Devicetree
 help / color / mirror / Atom feed
* [v2, 04/10] powerpc/mpc85xx: move ptp timer out of fman in dts
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi   |   14 ++++++++------
 arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi   |   14 ++++++++------
 arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi  |   14 ++++++++------
 arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi  |   14 ++++++++------
 arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi |   14 ++++++++------
 5 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
index abd01d4..6b124f7 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
 	#size-cells = <1>;
 	cell-index = <0>;
 	compatible = "fsl,fman";
-	ranges = <0 0x400000 0x100000>;
-	reg = <0x400000 0x100000>;
+	ranges = <0 0x400000 0xfe000>;
+	reg = <0x400000 0xfe000>;
 	interrupts = <96 2 0 0>, <16 2 1 1>;
 	clocks = <&clockgen 3 0>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x40 0xc>;
+	ptimer-handle = <&ptp_timer0>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman0: fman@400000 {
 		reg = <0x87000 0x1000>;
 		status = "disabled";
 	};
+};
 
-	ptp_timer0: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer0: ptp-timer@4fe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x4fe000 0x1000>;
+	interrupts = <96 2 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
index debea75..b80aaf5 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman@500000 {
 	#size-cells = <1>;
 	cell-index = <1>;
 	compatible = "fsl,fman";
-	ranges = <0 0x500000 0x100000>;
-	reg = <0x500000 0x100000>;
+	ranges = <0 0x500000 0xfe000>;
+	reg = <0x500000 0xfe000>;
 	interrupts = <97 2 0 0>, <16 2 1 0>;
 	clocks = <&clockgen 3 1>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x60 0xc>;
+	ptimer-handle = <&ptp_timer1>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -93,9 +94,10 @@ fman1: fman@500000 {
 		reg = <0x87000 0x1000>;
 		status = "disabled";
 	};
+};
 
-	ptp_timer1: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer1: ptp-timer@5fe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x5fe000 0x1000>;
+	interrupts = <97 2 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
index 3a20e0d..d3720fd 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
 	#size-cells = <1>;
 	cell-index = <0>;
 	compatible = "fsl,fman";
-	ranges = <0 0x400000 0x100000>;
-	reg = <0x400000 0x100000>;
+	ranges = <0 0x400000 0xfe000>;
+	reg = <0x400000 0xfe000>;
 	interrupts = <96 2 0 0>, <16 2 1 1>;
 	clocks = <&clockgen 3 0>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x800 0x10>;
+	ptimer-handle = <&ptp_timer0>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman0: fman@400000 {
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfd000 0x1000>;
 	};
+};
 
-	ptp_timer0: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer0: ptp-timer@4fe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x4fe000 0x1000>;
+	interrupts = <96 2 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
index 82750ac..ae34c20 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-1.dtsi
@@ -37,12 +37,13 @@ fman1: fman@500000 {
 	#size-cells = <1>;
 	cell-index = <1>;
 	compatible = "fsl,fman";
-	ranges = <0 0x500000 0x100000>;
-	reg = <0x500000 0x100000>;
+	ranges = <0 0x500000 0xfe000>;
+	reg = <0x500000 0xfe000>;
 	interrupts = <97 2 0 0>, <16 2 1 0>;
 	clocks = <&clockgen 3 1>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x820 0x10>;
+	ptimer-handle = <&ptp_timer1>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -98,9 +99,10 @@ fman1: fman@500000 {
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfd000 0x1000>;
 	};
+};
 
-	ptp_timer1: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer1: ptp-timer@5fe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x5fe000 0x1000>;
+	interrupts = <97 2 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
index 7f60b60..02f2755 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
@@ -37,12 +37,13 @@ fman0: fman@400000 {
 	#size-cells = <1>;
 	cell-index = <0>;
 	compatible = "fsl,fman";
-	ranges = <0 0x400000 0x100000>;
-	reg = <0x400000 0x100000>;
+	ranges = <0 0x400000 0xfe000>;
+	reg = <0x400000 0xfe000>;
 	interrupts = <96 2 0 0>, <16 2 1 1>;
 	clocks = <&clockgen 3 0>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x800 0x10>;
+	ptimer-handle = <&ptp_timer0>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -86,9 +87,10 @@ fman0: fman@400000 {
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfd000 0x1000>;
 	};
+};
 
-	ptp_timer0: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer0: ptp-timer@4fe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x4fe000 0x1000>;
+	interrupts = <96 2 0 0>;
 };
-- 
1.7.1

^ permalink raw reply related

* [v2, 05/10] arm64: dts: fsl: move ptp timer out of fman
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

This patch is to move ptp timer node out of fman.
Because ptp timer will be probed by ptp_qoriq driver,
it should be an independent device in case of conflict
memory mapping.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Fixed address-cells for ptp-timer.
---
 arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
index 4dd0676..a56a408 100644
--- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
+++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
@@ -11,13 +11,14 @@ fman0: fman@1a00000 {
 	#size-cells = <1>;
 	cell-index = <0>;
 	compatible = "fsl,fman";
-	ranges = <0x0 0x0 0x1a00000 0x100000>;
-	reg = <0x0 0x1a00000 0x0 0x100000>;
+	ranges = <0x0 0x0 0x1a00000 0xfe000>;
+	reg = <0x0 0x1a00000 0x0 0xfe000>;
 	interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
 		     <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 	clocks = <&clockgen 3 0>;
 	clock-names = "fmanclk";
 	fsl,qman-channel-range = <0x800 0x10>;
+	ptimer-handle = <&ptp_timer0>;
 
 	muram@0 {
 		compatible = "fsl,fman-muram";
@@ -73,9 +74,10 @@ fman0: fman@1a00000 {
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfd000 0x1000>;
 	};
+};
 
-	ptp_timer0: ptp-timer@fe000 {
-		compatible = "fsl,fman-ptp-timer";
-		reg = <0xfe000 0x1000>;
-	};
+ptp_timer0: ptp-timer@1afe000 {
+	compatible = "fsl,fman-ptp-timer";
+	reg = <0x0 0x1afe000 0x0 0x1000>;
+	interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
 };
-- 
1.7.1

^ permalink raw reply related

* [v2, 06/10] fsl/fman: add set_tstamp interface
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

This patch is to add set_tstamp interface for memac,
dtsec, and 10GEC controllers to configure HW timestamping.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/net/ethernet/freescale/fman/fman_dtsec.c |   27 ++++++++++++++++++++++
 drivers/net/ethernet/freescale/fman/fman_dtsec.h |    1 +
 drivers/net/ethernet/freescale/fman/fman_memac.c |    5 ++++
 drivers/net/ethernet/freescale/fman/fman_memac.h |    1 +
 drivers/net/ethernet/freescale/fman/fman_tgec.c  |   21 +++++++++++++++++
 drivers/net/ethernet/freescale/fman/fman_tgec.h  |    1 +
 drivers/net/ethernet/freescale/fman/mac.c        |    3 ++
 drivers/net/ethernet/freescale/fman/mac.h        |    1 +
 8 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 57b1e2b..1ca543a 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -123,11 +123,13 @@
 #define DTSEC_ECNTRL_R100M		0x00000008
 #define DTSEC_ECNTRL_QSGMIIM		0x00000001
 
+#define TCTRL_TTSE			0x00000040
 #define TCTRL_GTS			0x00000020
 
 #define RCTRL_PAL_MASK			0x001f0000
 #define RCTRL_PAL_SHIFT			16
 #define RCTRL_GHTX			0x00000400
+#define RCTRL_RTSE			0x00000040
 #define RCTRL_GRS			0x00000020
 #define RCTRL_MPROM			0x00000008
 #define RCTRL_RSF			0x00000004
@@ -1136,6 +1138,31 @@ int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
 	return 0;
 }
 
+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable)
+{
+	struct dtsec_regs __iomem *regs = dtsec->regs;
+	u32 rctrl, tctrl;
+
+	if (!is_init_done(dtsec->dtsec_drv_param))
+		return -EINVAL;
+
+	rctrl = ioread32be(&regs->rctrl);
+	tctrl = ioread32be(&regs->tctrl);
+
+	if (enable) {
+		rctrl |= RCTRL_RTSE;
+		tctrl |= TCTRL_TTSE;
+	} else {
+		rctrl &= ~RCTRL_RTSE;
+		tctrl &= ~TCTRL_TTSE;
+	}
+
+	iowrite32be(rctrl, &regs->rctrl);
+	iowrite32be(tctrl, &regs->tctrl);
+
+	return 0;
+}
+
 int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
 {
 	struct dtsec_regs __iomem *regs = dtsec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index 1a689ad..5149d96 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -56,5 +56,6 @@ int dtsec_set_exception(struct fman_mac *dtsec,
 int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
 int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version);
 int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable);
+int dtsec_set_tstamp(struct fman_mac *dtsec, bool enable);
 
 #endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 446a97b..bc6eb30 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -964,6 +964,11 @@ int memac_set_allmulti(struct fman_mac *memac, bool enable)
 	return 0;
 }
 
+int memac_set_tstamp(struct fman_mac *memac, bool enable)
+{
+	return 0; /* Always enabled. */
+}
+
 int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
 {
 	struct memac_regs __iomem *regs = memac->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h
index b5a5033..b2c671e 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -58,5 +58,6 @@ int memac_set_exception(struct fman_mac *memac,
 int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
 int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
 int memac_set_allmulti(struct fman_mac *memac, bool enable);
+int memac_set_tstamp(struct fman_mac *memac, bool enable);
 
 #endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 284735d..4070593 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -44,6 +44,7 @@
 #define TGEC_TX_IPG_LENGTH_MASK	0x000003ff
 
 /* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP		0x00100000
 #define CMD_CFG_NO_LEN_CHK		0x00020000
 #define CMD_CFG_PAUSE_IGNORE		0x00000100
 #define CMF_CFG_CRC_FWD			0x00000040
@@ -588,6 +589,26 @@ int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
 	return 0;
 }
 
+int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
+{
+	struct tgec_regs __iomem *regs = tgec->regs;
+	u32 tmp;
+
+	if (!is_init_done(tgec->cfg))
+		return -EINVAL;
+
+	tmp = ioread32be(&regs->command_config);
+
+	if (enable)
+		tmp |= CMD_CFG_EN_TIMESTAMP;
+	else
+		tmp &= ~CMD_CFG_EN_TIMESTAMP;
+
+	iowrite32be(tmp, &regs->command_config);
+
+	return 0;
+}
+
 int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
 {
 	struct tgec_regs __iomem *regs = tgec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index cbbd3b4..3bfd106 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -52,5 +52,6 @@ int tgec_set_exception(struct fman_mac *tgec,
 int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
 int tgec_get_version(struct fman_mac *tgec, u32 *mac_version);
 int tgec_set_allmulti(struct fman_mac *tgec, bool enable);
+int tgec_set_tstamp(struct fman_mac *tgec, bool enable);
 
 #endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index 7b5b95f..a847b9c 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -471,6 +471,7 @@ static void setup_dtsec(struct mac_device *mac_dev)
 	mac_dev->set_rx_pause		= dtsec_accept_rx_pause_frames;
 	mac_dev->set_exception		= dtsec_set_exception;
 	mac_dev->set_allmulti		= dtsec_set_allmulti;
+	mac_dev->set_tstamp		= dtsec_set_tstamp;
 	mac_dev->set_multi		= set_multi;
 	mac_dev->start			= start;
 	mac_dev->stop			= stop;
@@ -490,6 +491,7 @@ static void setup_tgec(struct mac_device *mac_dev)
 	mac_dev->set_rx_pause		= tgec_accept_rx_pause_frames;
 	mac_dev->set_exception		= tgec_set_exception;
 	mac_dev->set_allmulti		= tgec_set_allmulti;
+	mac_dev->set_tstamp		= tgec_set_tstamp;
 	mac_dev->set_multi		= set_multi;
 	mac_dev->start			= start;
 	mac_dev->stop			= stop;
@@ -509,6 +511,7 @@ static void setup_memac(struct mac_device *mac_dev)
 	mac_dev->set_rx_pause		= memac_accept_rx_pause_frames;
 	mac_dev->set_exception		= memac_set_exception;
 	mac_dev->set_allmulti		= memac_set_allmulti;
+	mac_dev->set_tstamp		= memac_set_tstamp;
 	mac_dev->set_multi		= set_multi;
 	mac_dev->start			= start;
 	mac_dev->stop			= stop;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
index b520cec..824a81a 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -68,6 +68,7 @@ struct mac_device {
 	int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
 	int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr);
 	int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
+	int (*set_tstamp)(struct fman_mac *mac_dev, bool enable);
 	int (*set_multi)(struct net_device *net_dev,
 			 struct mac_device *mac_dev);
 	int (*set_rx_pause)(struct fman_mac *mac_dev, bool en);
-- 
1.7.1

^ permalink raw reply related

* [v2, 07/10] fsl/fman_port: support getting timestamp field
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

This patch is to add fman_port_get_tstamp_field() interface
to get timestamp field data.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/net/ethernet/freescale/fman/fman_port.c |   12 ++++++++++++
 drivers/net/ethernet/freescale/fman/fman_port.h |    3 +++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c
index ce6e24c..86f0094 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1731,6 +1731,18 @@ int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset)
 }
 EXPORT_SYMBOL(fman_port_get_hash_result_offset);
 
+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+			       u64 *tstamp)
+{
+	if (port->buffer_offsets.time_stamp_offset == ILLEGAL_BASE)
+		return -EINVAL;
+
+	*tstamp = *(u64 *)(data + port->buffer_offsets.time_stamp_offset);
+
+	return 0;
+}
+EXPORT_SYMBOL(fman_port_get_tstamp_field);
+
 static int fman_port_probe(struct platform_device *of_dev)
 {
 	struct fman_port *port;
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h b/drivers/net/ethernet/freescale/fman/fman_port.h
index e86ca6a..d10e48d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -153,6 +153,9 @@ int fman_port_cfg_buf_prefix_content(struct fman_port *port,
 
 int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset);
 
+int fman_port_get_tstamp_field(struct fman_port *port, const void *data,
+			       u64 *tstamp);
+
 struct fman_port *fman_port_bind(struct device *dev);
 
 #endif /* __FMAN_PORT_H */
-- 
1.7.1

^ permalink raw reply related

* [v2, 08/10] fsl/fman: define frame description command UPD
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

Defined frame description command FM_FD_CMD_UPD for
prepended data updating.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/net/ethernet/freescale/fman/fman.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h
index bfa02e0..935c317 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -41,6 +41,7 @@
 /* Frame queue Context Override */
 #define FM_FD_CMD_FCO                   0x80000000
 #define FM_FD_CMD_RPD                   0x40000000  /* Read Prepended Data */
+#define FM_FD_CMD_UPD			0x20000000  /* Update Prepended Data */
 #define FM_FD_CMD_DTC                   0x10000000  /* Do L4 Checksum */
 
 /* TX-Port: Unsupported Format */
-- 
1.7.1

^ permalink raw reply related

* [v2, 09/10] dpaa_eth: add support for hardware timestamping
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

This patch is to add hardware timestamping support
for dpaa_eth. On Rx, timestamping is enabled for
all frames. On Tx, we only instruct the hardware
to timestamp the frames marked accordingly by the
stack.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Removed ifdef for timestamp code.
	- Minor fixes for code style.
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c |  101 ++++++++++++++++++++++-
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.h |    3 +
 2 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index fd43f98..bd589ac 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct fman_port *port, struct dpaa_fq *errq,
 	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
 	buf_prefix_content.pass_prs_result = true;
 	buf_prefix_content.pass_hash_result = true;
-	buf_prefix_content.pass_time_stamp = false;
+	buf_prefix_content.pass_time_stamp = true;
 	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
 
 	params.specific_params.non_rx_params.err_fqid = errq->fqid;
@@ -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp **bps,
 	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
 	buf_prefix_content.pass_prs_result = true;
 	buf_prefix_content.pass_hash_result = true;
-	buf_prefix_content.pass_time_stamp = false;
+	buf_prefix_content.pass_time_stamp = true;
 	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
 
 	rx_p = &params.specific_params.rx_params;
@@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
 	return 0;
 }
 
+static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
+			      struct fman_port *port, const void *data)
+{
+	if (!fman_port_get_tstamp_field(port, data, ns)) {
+		be64_to_cpus(ns);
+		return 0;
+	}
+	return -EINVAL;
+}
+
 /* Cleanup function for outgoing frame descriptors that were built on Tx path,
  * either contiguous frames or scatter/gather ones.
  * Skb freeing is not handled here.
@@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
 {
 	const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
 	struct device *dev = priv->net_dev->dev.parent;
+	struct skb_shared_hwtstamps shhwtstamps;
 	dma_addr_t addr = qm_fd_addr(fd);
 	const struct qm_sg_entry *sgt;
 	struct sk_buff **skbh, *skb;
 	int nr_frags, i;
+	u64 ns;
 
 	skbh = (struct sk_buff **)phys_to_virt(addr);
 	skb = *skbh;
 
+	if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+		if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+					priv->mac_dev->port[TX],
+					(void *)skbh)) {
+			shhwtstamps.hwtstamp = ns_to_ktime(ns);
+			skb_tstamp_tx(skb, &shhwtstamps);
+		} else {
+			dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
+		}
+	}
+
 	if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
 		nr_frags = skb_shinfo(skb)->nr_frags;
 		dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
@@ -2086,6 +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
 	if (unlikely(err < 0))
 		goto skb_to_fd_failed;
 
+	if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		fd.cmd |= FM_FD_CMD_UPD;
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+	}
+
 	if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
 		return NETDEV_TX_OK;
 
@@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
 						struct qman_fq *fq,
 						const struct qm_dqrr_entry *dq)
 {
+	struct skb_shared_hwtstamps *shhwtstamps;
 	struct rtnl_link_stats64 *percpu_stats;
 	struct dpaa_percpu_priv *percpu_priv;
 	const struct qm_fd *fd = &dq->fd;
@@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
 	struct sk_buff *skb;
 	int *count_ptr;
 	void *vaddr;
+	u64 ns;
 
 	fd_status = be32_to_cpu(fd->status);
 	fd_format = qm_fd_get_format(fd);
@@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
 	if (!skb)
 		return qman_cb_dqrr_consume;
 
+	if (priv->rx_tstamp) {
+		shhwtstamps = skb_hwtstamps(skb);
+		memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+		if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
+					priv->mac_dev->port[RX],
+					vaddr))
+			shhwtstamps->hwtstamp = ns_to_ktime(ns);
+		else
+			dev_warn(net_dev->dev.parent, "dpaa_get_tstamp_ns failed!\n");
+	}
+
 	skb->protocol = eth_type_trans(skb, net_dev);
 
 	if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use &&
@@ -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device *net_dev)
 	return err;
 }
 
+static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct dpaa_priv *priv = netdev_priv(dev);
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		/* Couldn't disable rx/tx timestamping separately.
+		 * Do nothing here.
+		 */
+		priv->tx_tstamp = false;
+		break;
+	case HWTSTAMP_TX_ON:
+		priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+		priv->tx_tstamp = true;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
+		/* Couldn't disable rx/tx timestamping separately.
+		 * Do nothing here.
+		 */
+		priv->rx_tstamp = false;
+	} else {
+		priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac, true);
+		priv->rx_tstamp = true;
+		/* TS is set for all frame types, not only those requested */
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+	}
+
+	return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
+			-EFAULT : 0;
+}
+
 static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
 {
-	if (!net_dev->phydev)
-		return -EINVAL;
-	return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+	int ret = -EINVAL;
+
+	if (cmd == SIOCGMIIREG) {
+		if (net_dev->phydev)
+			return phy_mii_ioctl(net_dev->phydev, rq, cmd);
+	}
+
+	if (cmd == SIOCSHWTSTAMP)
+		return dpaa_ts_ioctl(net_dev, rq, cmd);
+
+	return ret;
 }
 
 static const struct net_device_ops dpaa_ops = {
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
index bd94220..af320f8 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
@@ -182,6 +182,9 @@ struct dpaa_priv {
 
 	struct dpaa_buffer_layout buf_layout[2];
 	u16 rx_headroom;
+
+	bool tx_tstamp; /* Tx timestamping enabled */
+	bool rx_tstamp; /* Rx timestamping enabled */
 };
 
 /* from dpaa_ethtool.c */
-- 
1.7.1

^ permalink raw reply related

* [v2, 10/10] dpaa_eth: add the get_ts_info interface for ethtool
From: Yangbo Lu @ 2018-06-07  3:22 UTC (permalink / raw)
  To: netdev, madalin.bucur, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree, linuxppc-dev, linux-arm-kernel, linux-kernel,
	Yangbo Lu
In-Reply-To: <20180607032256.39802-1-yangbo.lu@nxp.com>

Added the get_ts_info interface for ethtool to check
the timestamping capability.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- Removed ifdef for hw timestamp.
---
 drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c |   39 ++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
index 2f933b6..3184c8f 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -32,6 +32,9 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/string.h>
+#include <linux/of_platform.h>
+#include <linux/net_tstamp.h>
+#include <linux/fsl/ptp_qoriq.h>
 
 #include "dpaa_eth.h"
 #include "mac.h"
@@ -515,6 +518,41 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 	return ret;
 }
 
+static int dpaa_get_ts_info(struct net_device *net_dev,
+			    struct ethtool_ts_info *info)
+{
+	struct device *dev = net_dev->dev.parent;
+	struct device_node *mac_node = dev->of_node;
+	struct device_node *fman_node = NULL, *ptp_node = NULL;
+	struct platform_device *ptp_dev = NULL;
+	struct qoriq_ptp *ptp = NULL;
+
+	info->phc_index = -1;
+
+	fman_node = of_get_parent(mac_node);
+	if (fman_node)
+		ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
+
+	if (ptp_node)
+		ptp_dev = of_find_device_by_node(ptp_node);
+
+	if (ptp_dev)
+		ptp = platform_get_drvdata(ptp_dev);
+
+	if (ptp)
+		info->phc_index = ptp->phc_index;
+
+	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+			 (1 << HWTSTAMP_TX_ON);
+	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+			   (1 << HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 const struct ethtool_ops dpaa_ethtool_ops = {
 	.get_drvinfo = dpaa_get_drvinfo,
 	.get_msglevel = dpaa_get_msglevel,
@@ -530,4 +568,5 @@ static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 	.set_link_ksettings = dpaa_set_link_ksettings,
 	.get_rxnfc = dpaa_get_rxnfc,
 	.set_rxnfc = dpaa_set_rxnfc,
+	.get_ts_info = dpaa_get_ts_info,
 };
-- 
1.7.1

^ permalink raw reply related

* [PATCH v4 1/2] dt-bindings: Add bindings for AKM ak7375 voice coil lens
From: bingbu.cao @ 2018-06-07  3:50 UTC (permalink / raw)
  To: linux-media, devicetree
  Cc: sakari.ailus, tfiga, jacopo, rajmohan.mani, bingbu.cao,
	tian.shu.qiu, jian.xu.zheng

From: Bingbu Cao <bingbu.cao@intel.com>

Add device tree bindings for AKM ak7375 voice coil lens
driver. This chip is used to drive a lens in a camera module.

Signed-off-by: Tianshu Qiu <tian.shu.qiu@intel.com>
Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>

---
Changes since v1:
    - add the MAINTAINERS change
    - correct the vendor prefix from akm to asahi-kasei
---
---
 Documentation/devicetree/bindings/media/i2c/ak7375.txt | 8 ++++++++
 MAINTAINERS                                            | 8 ++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/ak7375.txt

diff --git a/Documentation/devicetree/bindings/media/i2c/ak7375.txt b/Documentation/devicetree/bindings/media/i2c/ak7375.txt
new file mode 100644
index 000000000000..aa3e24b41241
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ak7375.txt
@@ -0,0 +1,8 @@
+Asahi Kasei Microdevices AK7375 voice coil lens driver
+
+AK7375 is a camera voice coil lens.
+
+Mandatory properties:
+
+- compatible: "asahi-kasei,ak7375"
+- reg: I2C slave address
diff --git a/MAINTAINERS b/MAINTAINERS
index ea362219c4aa..ad68d75abc84 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2258,6 +2258,14 @@ L:	linux-leds@vger.kernel.org
 S:	Maintained
 F:	drivers/leds/leds-as3645a.c
 
+ASAHI KASEI AK7375 LENS VOICE COIL DRIVER
+M:	Tianshu Qiu <tian.shu.qiu@intel.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/i2c/ak7375.c
+F:	Documentation/devicetree/bindings/media/i2c/ak7375.txt
+
 ASAHI KASEI AK8974 DRIVER
 M:	Linus Walleij <linus.walleij@linaro.org>
 L:	linux-iio@vger.kernel.org
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 2/2] media: ak7375: Add ak7375 lens voice coil driver
From: bingbu.cao @ 2018-06-07  3:50 UTC (permalink / raw)
  To: linux-media, devicetree
  Cc: sakari.ailus, tfiga, jacopo, rajmohan.mani, bingbu.cao,
	tian.shu.qiu, jian.xu.zheng
In-Reply-To: <1528343433-2475-1-git-send-email-bingbu.cao@intel.com>

From: Bingbu Cao <bingbu.cao@intel.com>

Add a v4l2 sub-device driver for the ak7375 lens voice coil.
This is a voice coil module using the i2c bus to control the
focus position.

ak7375 can write multiple bytes of data at a time. If more
data is received instead of the stop condition after receiving
one byte of data, the address inside the chip is automatically
incremented and the data is written into the next address.

The ak7375 can control the position with 12 bits value and
consists of two 8 bit registers show as below:
register 0x00(AK7375_REG_POSITION):
    +---+---+---+---+---+---+---+---+
    |D11|D10|D09|D08|D07|D06|D05|D04|
    +---+---+---+---+---+---+---+---+
register 0x01:
    +---+---+---+---+---+---+---+---+
    |D03|D02|D01|D00|---|---|---|---|
    +---+---+---+---+---+---+---+---+

This driver support :
    - set ak7375 to standby mode once suspend and
      turn it back to active if resume
    - set the position via V4L2_CID_FOCUS_ABSOLUTE ctrl

Signed-off-by: Tianshu Qiu <tian.shu.qiu@intel.com>
Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>

---
Changes from v1 -> v3:
    - correct i2c write
    - add media_entity_pads_init() into probe
    - move the MAINTAINERs change into dt-binding change
    - correct the compatible stringa
Changes since v3:
    - add active flag to indicate the mode
---
---
 drivers/media/i2c/Kconfig  |  10 ++
 drivers/media/i2c/Makefile |   1 +
 drivers/media/i2c/ak7375.c | 289 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+)
 create mode 100644 drivers/media/i2c/ak7375.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 341452fe98df..ff3cb5afb0e1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -326,6 +326,16 @@ config VIDEO_AD5820
 	  This is a driver for the AD5820 camera lens voice coil.
 	  It is used for example in Nokia N900 (RX-51).
 
+config VIDEO_AK7375
+	tristate "AK7375 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	depends on VIDEO_V4L2_SUBDEV_API
+	help
+	  This is a driver for the AK7375 camera lens voice coil.
+	  AK7375 is a 12 bit DAC with 120mA output current sink
+	  capability. This is designed for linear control of
+	  voice coil motors, controlled via I2C serial interface.
+
 config VIDEO_DW9714
 	tristate "DW9714 lens voice coil support"
 	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index d679d57cd3b3..05b97e319ea9 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
 obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
+obj-$(CONFIG_VIDEO_AK7375)  += ak7375.o
 obj-$(CONFIG_VIDEO_DW9714)  += dw9714.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c
new file mode 100644
index 000000000000..e716821cf438
--- /dev/null
+++ b/drivers/media/i2c/ak7375.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#define AK7375_MAX_FOCUS_POS	4095
+/*
+ * This sets the minimum granularity for the focus positions.
+ * A value of 1 gives maximum accuracy for a desired focus position
+ */
+#define AK7375_FOCUS_STEPS	1
+/*
+ * This acts as the minimum granularity of lens movement.
+ * Keep this value power of 2, so the control steps can be
+ * uniformly adjusted for gradual lens movement, with desired
+ * number of control steps.
+ */
+#define AK7375_CTRL_STEPS	64
+#define AK7375_CTRL_DELAY_US	1000
+
+#define AK7375_REG_POSITION	0x0
+#define AK7375_REG_CONT		0x2
+#define AK7375_MODE_ACTIVE	0x0
+#define AK7375_MODE_STANDBY	0x40
+
+/* ak7375 device structure */
+struct ak7375_device {
+	struct v4l2_ctrl_handler ctrls_vcm;
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl *focus;
+	/* active or standby mode */
+	bool active;
+};
+
+static inline struct ak7375_device *to_ak7375_vcm(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct ak7375_device, ctrls_vcm);
+}
+
+static inline struct ak7375_device *sd_to_ak7375_vcm(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct ak7375_device, sd);
+}
+
+static int ak7375_i2c_write(struct ak7375_device *ak7375,
+	u8 addr, u16 data, int size)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&ak7375->sd);
+	int ret;
+	u8 buf[3];
+
+	if (size != 1 && size != 2)
+		return -EINVAL;
+	buf[0] = addr;
+	buf[size] = data & 0xff;
+	if (size == 2)
+		buf[1] = (data >> 8) & 0xff;
+	ret = i2c_master_send(client, (const char *)buf, size + 1);
+	if (ret < 0)
+		return ret;
+	if (ret != size + 1)
+		return -EIO;
+	return 0;
+}
+
+static int ak7375_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ak7375_device *dev_vcm = to_ak7375_vcm(ctrl);
+
+	if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
+		return ak7375_i2c_write(dev_vcm, AK7375_REG_POSITION,
+					ctrl->val << 4, 2);
+
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops ak7375_vcm_ctrl_ops = {
+	.s_ctrl = ak7375_set_ctrl,
+};
+
+static int ak7375_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	int rval;
+
+	rval = pm_runtime_get_sync(sd->dev);
+	if (rval < 0) {
+		pm_runtime_put_noidle(sd->dev);
+		return rval;
+	}
+
+	return 0;
+}
+
+static int ak7375_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	pm_runtime_put(sd->dev);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops ak7375_int_ops = {
+	.open = ak7375_open,
+	.close = ak7375_close,
+};
+
+static const struct v4l2_subdev_ops ak7375_ops = { };
+
+static void ak7375_subdev_cleanup(struct ak7375_device *ak7375_dev)
+{
+	v4l2_async_unregister_subdev(&ak7375_dev->sd);
+	v4l2_ctrl_handler_free(&ak7375_dev->ctrls_vcm);
+	media_entity_cleanup(&ak7375_dev->sd.entity);
+}
+
+static int ak7375_init_controls(struct ak7375_device *dev_vcm)
+{
+	struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm;
+	const struct v4l2_ctrl_ops *ops = &ak7375_vcm_ctrl_ops;
+
+	v4l2_ctrl_handler_init(hdl, 1);
+
+	dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
+		0, AK7375_MAX_FOCUS_POS, AK7375_FOCUS_STEPS, 0);
+
+	if (hdl->error)
+		dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n",
+			__func__, hdl->error);
+	dev_vcm->sd.ctrl_handler = hdl;
+	return hdl->error;
+}
+
+static int ak7375_probe(struct i2c_client *client)
+{
+	struct ak7375_device *ak7375_dev;
+	int val;
+
+	ak7375_dev = devm_kzalloc(&client->dev, sizeof(*ak7375_dev),
+				  GFP_KERNEL);
+	if (!ak7375_dev)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&ak7375_dev->sd, client, &ak7375_ops);
+	ak7375_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	ak7375_dev->sd.internal_ops = &ak7375_int_ops;
+	ak7375_dev->sd.entity.function = MEDIA_ENT_F_LENS;
+
+	val = ak7375_init_controls(ak7375_dev);
+	if (val)
+		goto err_cleanup;
+
+	val = media_entity_pads_init(&ak7375_dev->sd.entity, 0, NULL);
+	if (val < 0)
+		goto err_cleanup;
+
+	val = v4l2_async_register_subdev(&ak7375_dev->sd);
+	if (val < 0)
+		goto err_cleanup;
+
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_enable(&client->dev);
+	pm_runtime_idle(&client->dev);
+
+	return 0;
+
+err_cleanup:
+	v4l2_ctrl_handler_free(&ak7375_dev->ctrls_vcm);
+	media_entity_cleanup(&ak7375_dev->sd.entity);
+	dev_err(&client->dev, "Probe failed: %d\n", val);
+	return val;
+}
+
+static int ak7375_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd);
+
+	ak7375_subdev_cleanup(ak7375_dev);
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+
+	return 0;
+}
+
+/*
+ * This function sets the vcm position, so it consumes least current
+ * The lens position is gradually moved in units of AK7375_CTRL_STEPS,
+ * to make the movements smoothly.
+ */
+static int __maybe_unused ak7375_vcm_suspend(struct device *dev)
+{
+
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd);
+	int ret, val;
+
+	if (!ak7375_dev->active)
+		return 0;
+
+	for (val = ak7375_dev->focus->val & ~(AK7375_CTRL_STEPS - 1);
+	     val >= 0; val -= AK7375_CTRL_STEPS) {
+		ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION,
+				       val << 4, 2);
+		if (ret)
+			dev_err_once(dev, "%s I2C failure: %d\n",
+				     __func__, ret);
+		usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10);
+	}
+
+	ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT,
+			       AK7375_MODE_STANDBY, 1);
+	if (ret)
+		dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
+
+	ak7375_dev->active = false;
+	return 0;
+}
+
+/*
+ * This function sets the vcm position to the value set by the user
+ * through v4l2_ctrl_ops s_ctrl handler
+ * The lens position is gradually moved in units of AK7375_CTRL_STEPS,
+ * to make the movements smoothly.
+ */
+static int __maybe_unused ak7375_vcm_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd);
+	int ret, val;
+
+	if (ak7375_dev->active)
+		return 0;
+
+	ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT,
+		AK7375_MODE_ACTIVE, 1);
+	if (ret) {
+		dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
+		return ret;
+	}
+
+	for (val = ak7375_dev->focus->val % AK7375_CTRL_STEPS;
+	     val <= ak7375_dev->focus->val;
+	     val += AK7375_CTRL_STEPS) {
+		ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION,
+				       val << 4, 2);
+		if (ret)
+			dev_err_ratelimited(dev, "%s I2C failure: %d\n",
+						__func__, ret);
+		usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10);
+	}
+
+	ak7375_dev->active = true;
+
+	return 0;
+}
+
+static const struct of_device_id ak7375_of_table[] = {
+	{ .compatible = "asahi-kasei,ak7375" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ak7375_of_table);
+
+static const struct dev_pm_ops ak7375_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ak7375_vcm_suspend, ak7375_vcm_resume)
+	SET_RUNTIME_PM_OPS(ak7375_vcm_suspend, ak7375_vcm_resume, NULL)
+};
+
+static struct i2c_driver ak7375_i2c_driver = {
+	.driver = {
+		.name = "ak7375",
+		.pm = &ak7375_pm_ops,
+		.of_match_table = ak7375_of_table,
+	},
+	.probe_new = ak7375_probe,
+	.remove = ak7375_remove,
+};
+module_i2c_driver(ak7375_i2c_driver);
+
+MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
+MODULE_DESCRIPTION("AK7375 VCM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH] remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
From: Vinod @ 2018-06-07  4:11 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Sricharan R, ohad, robh+dt, mark.rutland, andy.gross, david.brown,
	linux-remoteproc, devicetree, linux-kernel, linux-arm-msm,
	linux-soc, sibis
In-Reply-To: <20180606161733.GE510@tuxbook-pro>

On 06-06-18, 09:17, Bjorn Andersson wrote:
> On Tue 05 Jun 05:56 PDT 2018, Sricharan R wrote:
> 
> > Hi Vinod,
> > 
> > On 6/5/2018 11:49 AM, Vinod wrote:
> > > On 05-06-18, 11:12, Sricharan R wrote:
> > > 
> > >> +config QCOM_Q6V5_WCSS
> > >> +	tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
> > >> +	depends on OF && ARCH_QCOM
> > >> +	depends on QCOM_SMEM
> > >> +	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
> > >> +	depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
> > > 
> > > Is there a reason why it depends on RPMSG_QCOM_GLINK_SMEM=n? What would
> > > happen if distro wants both this and RPMSG_QCOM_GLINK_SMEM
> > > 
> 
> It says that QCOM_Q6V5_WCSS either must have a compatible state (i.e.
> builtin vs builtin, module vs builtin, but not builtin vs module) or
> that it's disabled, in which case we will hit the stub functions in
> qcom_glink.h.
> 
> I.e. this prevents QCOM_Q6V5_WCSS to be compiled builtin when
> RPMSG_QCOM_GLINK_SMEM is module, as this would give us both stubs and
> the module.

IIUC, you want to have QCOM_Q6V5_WCSS and RPMSG_QCOM_GLINK_SMEM as
modules or builtin

So, wouldn't Kconfig syntax something like where we say:
        M if RPMSG_QCOM_GLINK_SMEM=m
        bool if RPMSG_QCOM_GLINK_SMEM=y

Which makes it clear that both these have to be same type?

-- 
~Vinod

^ permalink raw reply

* Re: [PATCH] remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
From: Bjorn Andersson @ 2018-06-07  4:24 UTC (permalink / raw)
  To: Vinod
  Cc: Sricharan R, ohad, robh+dt, mark.rutland, andy.gross, david.brown,
	linux-remoteproc, devicetree, linux-kernel, linux-arm-msm,
	linux-soc, sibis
In-Reply-To: <20180607041134.GF16230@vkoul-mobl>

On Wed 06 Jun 21:11 PDT 2018, Vinod wrote:

> On 06-06-18, 09:17, Bjorn Andersson wrote:
> > On Tue 05 Jun 05:56 PDT 2018, Sricharan R wrote:
> > 
> > > Hi Vinod,
> > > 
> > > On 6/5/2018 11:49 AM, Vinod wrote:
> > > > On 05-06-18, 11:12, Sricharan R wrote:
> > > > 
> > > >> +config QCOM_Q6V5_WCSS
> > > >> +	tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
> > > >> +	depends on OF && ARCH_QCOM
> > > >> +	depends on QCOM_SMEM
> > > >> +	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
> > > >> +	depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
> > > > 
> > > > Is there a reason why it depends on RPMSG_QCOM_GLINK_SMEM=n? What would
> > > > happen if distro wants both this and RPMSG_QCOM_GLINK_SMEM
> > > > 
> > 
> > It says that QCOM_Q6V5_WCSS either must have a compatible state (i.e.
> > builtin vs builtin, module vs builtin, but not builtin vs module) or
> > that it's disabled, in which case we will hit the stub functions in
> > qcom_glink.h.
> > 
> > I.e. this prevents QCOM_Q6V5_WCSS to be compiled builtin when
> > RPMSG_QCOM_GLINK_SMEM is module, as this would give us both stubs and
> > the module.
> 
> IIUC, you want to have QCOM_Q6V5_WCSS and RPMSG_QCOM_GLINK_SMEM as
> modules or builtin
> 

RPMSG_QCOM_SMD, RPMSG_QCOM_GLINK_SMEM and QCOM_Q6V5_WCSS are all
tristate.

> So, wouldn't Kconfig syntax something like where we say:
>         M if RPMSG_QCOM_GLINK_SMEM=m
>         bool if RPMSG_QCOM_GLINK_SMEM=y
> 

If we ignore SMD for a while we have the following combinations:

glink/wcss
y     y - valid
y     m - valid
y     n - valid
m     y - link failure (invalid)
m     m - valid
m     n - valid
n     y - valid (platform uses wcss, but not glink)
n     m - valid (-----"-----)
n     n - valid

So to distill this we have the two valid cases:
module/no if RPMSG_QCOM_GLINK_SMEM=m
yes/module/no if RPMSG_QCOM_GLINK_SMEM=y

and the way you express that in Kconfig is the somewhat awkward

  depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n

> Which makes it clear that both these have to be same type?
> 

They don't have to be of the same type, only of a compatible type.

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH] remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
From: Sricharan R @ 2018-06-07  5:29 UTC (permalink / raw)
  To: Bjorn Andersson, Vinod
  Cc: ohad, robh+dt, mark.rutland, andy.gross, david.brown,
	linux-remoteproc, devicetree, linux-kernel, linux-arm-msm,
	linux-soc, sibis
In-Reply-To: <20180607042443.GK510@tuxbook-pro>

Hi Bjorn,

On 6/7/2018 9:54 AM, Bjorn Andersson wrote:
> On Wed 06 Jun 21:11 PDT 2018, Vinod wrote:
> 
>> On 06-06-18, 09:17, Bjorn Andersson wrote:
>>> On Tue 05 Jun 05:56 PDT 2018, Sricharan R wrote:
>>>
>>>> Hi Vinod,
>>>>
>>>> On 6/5/2018 11:49 AM, Vinod wrote:
>>>>> On 05-06-18, 11:12, Sricharan R wrote:
>>>>>
>>>>>> +config QCOM_Q6V5_WCSS
>>>>>> +	tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
>>>>>> +	depends on OF && ARCH_QCOM
>>>>>> +	depends on QCOM_SMEM
>>>>>> +	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
>>>>>> +	depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
>>>>>
>>>>> Is there a reason why it depends on RPMSG_QCOM_GLINK_SMEM=n? What would
>>>>> happen if distro wants both this and RPMSG_QCOM_GLINK_SMEM
>>>>>
>>>
>>> It says that QCOM_Q6V5_WCSS either must have a compatible state (i.e.
>>> builtin vs builtin, module vs builtin, but not builtin vs module) or
>>> that it's disabled, in which case we will hit the stub functions in
>>> qcom_glink.h.
>>>
>>> I.e. this prevents QCOM_Q6V5_WCSS to be compiled builtin when
>>> RPMSG_QCOM_GLINK_SMEM is module, as this would give us both stubs and
>>> the module.
>>
>> IIUC, you want to have QCOM_Q6V5_WCSS and RPMSG_QCOM_GLINK_SMEM as
>> modules or builtin
>>
> 
> RPMSG_QCOM_SMD, RPMSG_QCOM_GLINK_SMEM and QCOM_Q6V5_WCSS are all
> tristate.
> 
>> So, wouldn't Kconfig syntax something like where we say:
>>         M if RPMSG_QCOM_GLINK_SMEM=m
>>         bool if RPMSG_QCOM_GLINK_SMEM=y
>>
> 
> If we ignore SMD for a while we have the following combinations:
> 
> glink/wcss
> y     y - valid
> y     m - valid
> y     n - valid
> m     y - link failure (invalid)
> m     m - valid
> m     n - valid
> n     y - valid (platform uses wcss, but not glink)
> n     m - valid (-----"-----)
> n     n - valid
> 
> So to distill this we have the two valid cases:
> module/no if RPMSG_QCOM_GLINK_SMEM=m
> yes/module/no if RPMSG_QCOM_GLINK_SMEM=y
> 
> and the way you express that in Kconfig is the somewhat awkward
> 
>   depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
> 

 ok, Having "depends on RPMSG_QCOM_GLINK_SMEM" takes care of the
 first 6 cases in the above list.

 But just was thinking that by allowing the last three combinations,
 there is a chance that some config that really needs GLINK_SMEM and WCSS,
 but selects only Q6V5_WCSS and misses to select GLINK_SMEM,
 would still built and make it non-functional, right ?

Regards,
 Sricharan

>> Which makes it clear that both these have to be same type?
>>
> 
> They don't have to be of the same type, only of a compatible type.
> 

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

^ permalink raw reply

* Re: [PATCH] remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
From: Bjorn Andersson @ 2018-06-07  5:48 UTC (permalink / raw)
  To: Sricharan R
  Cc: Vinod, ohad, robh+dt, mark.rutland, andy.gross, david.brown,
	linux-remoteproc, devicetree, linux-kernel, linux-arm-msm,
	linux-soc, sibis
In-Reply-To: <d01d6819-3f95-0b65-1251-aead88fe86cc@codeaurora.org>

On Wed 06 Jun 22:29 PDT 2018, Sricharan R wrote:

> Hi Bjorn,
> 
> On 6/7/2018 9:54 AM, Bjorn Andersson wrote:
> > On Wed 06 Jun 21:11 PDT 2018, Vinod wrote:
> > 
> >> On 06-06-18, 09:17, Bjorn Andersson wrote:
> >>> On Tue 05 Jun 05:56 PDT 2018, Sricharan R wrote:
> >>>
> >>>> Hi Vinod,
> >>>>
> >>>> On 6/5/2018 11:49 AM, Vinod wrote:
> >>>>> On 05-06-18, 11:12, Sricharan R wrote:
[..]
> > If we ignore SMD for a while we have the following combinations:
> > 
> > glink/wcss
> > y     y - valid
> > y     m - valid
> > y     n - valid
> > m     y - link failure (invalid)
> > m     m - valid
> > m     n - valid
> > n     y - valid (platform uses wcss, but not glink)
> > n     m - valid (-----"-----)
> > n     n - valid
> > 
> > So to distill this we have the two valid cases:
> > module/no if RPMSG_QCOM_GLINK_SMEM=m
> > yes/module/no if RPMSG_QCOM_GLINK_SMEM=y
> > 
> > and the way you express that in Kconfig is the somewhat awkward
> > 
> >   depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
> > 
> 
>  ok, Having "depends on RPMSG_QCOM_GLINK_SMEM" takes care of the
>  first 6 cases in the above list.
> 
>  But just was thinking that by allowing the last three combinations,
>  there is a chance that some config that really needs GLINK_SMEM and WCSS,
>  but selects only Q6V5_WCSS and misses to select GLINK_SMEM,
>  would still built and make it non-functional, right ?
> 

It would allow you to compile a kernel with GLINk disabled that in
runtime loads a firmware that depends on GLINK being there.

As it would be convenient to thereby state that "WCSS always depends on
GLINK" we can make the analog to 410 where "MSS always depends on SMD",
which isn't true when the same driver is reused on e.g. 845 - which
uses GLINK.


So my recommendation is that we stick with Kconfig options that
describes the build time dependencies of this particular driver, rather
than its runtime dependencies in a particular platform.

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH] remoteproc: qcom: Introduce Hexagon V5 based WCSS driver
From: Sricharan R @ 2018-06-07  6:36 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Vinod, ohad, robh+dt, mark.rutland, andy.gross, david.brown,
	linux-remoteproc, devicetree, linux-kernel, linux-arm-msm,
	linux-soc, sibis
In-Reply-To: <20180607054838.GM510@tuxbook-pro>

Hi Bjorn,

On 6/7/2018 11:18 AM, Bjorn Andersson wrote:
> On Wed 06 Jun 22:29 PDT 2018, Sricharan R wrote:
> 
>> Hi Bjorn,
>>
>> On 6/7/2018 9:54 AM, Bjorn Andersson wrote:
>>> On Wed 06 Jun 21:11 PDT 2018, Vinod wrote:
>>>
>>>> On 06-06-18, 09:17, Bjorn Andersson wrote:
>>>>> On Tue 05 Jun 05:56 PDT 2018, Sricharan R wrote:
>>>>>
>>>>>> Hi Vinod,
>>>>>>
>>>>>> On 6/5/2018 11:49 AM, Vinod wrote:
>>>>>>> On 05-06-18, 11:12, Sricharan R wrote:
> [..]
>>> If we ignore SMD for a while we have the following combinations:
>>>
>>> glink/wcss
>>> y     y - valid
>>> y     m - valid
>>> y     n - valid
>>> m     y - link failure (invalid)
>>> m     m - valid
>>> m     n - valid
>>> n     y - valid (platform uses wcss, but not glink)
>>> n     m - valid (-----"-----)
>>> n     n - valid
>>>
>>> So to distill this we have the two valid cases:
>>> module/no if RPMSG_QCOM_GLINK_SMEM=m
>>> yes/module/no if RPMSG_QCOM_GLINK_SMEM=y
>>>
>>> and the way you express that in Kconfig is the somewhat awkward
>>>
>>>   depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
>>>
>>
>>  ok, Having "depends on RPMSG_QCOM_GLINK_SMEM" takes care of the
>>  first 6 cases in the above list.
>>
>>  But just was thinking that by allowing the last three combinations,
>>  there is a chance that some config that really needs GLINK_SMEM and WCSS,
>>  but selects only Q6V5_WCSS and misses to select GLINK_SMEM,
>>  would still built and make it non-functional, right ?
>>
> 
> It would allow you to compile a kernel with GLINk disabled that in
> runtime loads a firmware that depends on GLINK being there.
> 
> As it would be convenient to thereby state that "WCSS always depends on
> GLINK" we can make the analog to 410 where "MSS always depends on SMD",
> which isn't true when the same driver is reused on e.g. 845 - which
> uses GLINK.
> 
> 
> So my recommendation is that we stick with Kconfig options that
> describes the build time dependencies of this particular driver, rather
> than its runtime dependencies in a particular platform.
> 

ok thanks. It sort of gave an impression that the last three combinations in
the above list was only for "compile testing". Hence was thinking to have
(COMPILE_TEST && RPMSG_QCOM_GLINK_SMEM=n). Anyways for WCSS, would drop 
the dependency on SMD and just have RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n.

Regards,
 Sricharan

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

^ permalink raw reply

* RE: [PATCH v4 2/3] arm: shmobile: Add the R9A06G032 SMP enabler driver
From: Michel Pollet @ 2018-06-07  6:59 UTC (permalink / raw)
  To: Frank Rowand, linux-renesas-soc@vger.kernel.org, Simon Horman
  Cc: Michel Pollet, Mark Rutland, Phil Edworthy, Florian Fainelli,
	Rajendra Nayak, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Stefan Wahren, Magnus Damm,
	Russell King, Douglas Anderson, Chen-Yu Tsai, Rob Herring,
	Carlo Caione, Andreas Färber, Frank Rowand,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <79c0899e-7df1-1fe7-9681-ad3bd51feda7@gmail.com>

On 06 June 2018 22:53, Frank wrote:
> On 06/06/18 14:48, Frank Rowand wrote:
> > On 06/05/18 23:36, Michel Pollet wrote:
> >> Hi Frank,
> >>
> >> On 05 June 2018 18:34, Frank wrote:
> >>> On 06/05/18 04:28, Michel Pollet wrote:
> >>>> The Renesas R9A06G032 second CA7 is parked in a ROM pen at boot
> >>>> time, it requires a special enable method to get it started.
> >>>>
> >>>> Signed-off-by: Michel Pollet <michel.pollet@bp.renesas.com>
> >>>> ---
> >>>>  arch/arm/mach-shmobile/Makefile        |  1 +
> >>>>  arch/arm/mach-shmobile/smp-r9a06g032.c | 79
> >>>> ++++++++++++++++++++++++++++++++++
> >>>>  2 files changed, 80 insertions(+)
> >>>>  create mode 100644 arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>>
> >>>> diff --git a/arch/arm/mach-shmobile/Makefile
> >>>> b/arch/arm/mach-shmobile/Makefile index 1939f52..d7fc98f 100644
> >>>> --- a/arch/arm/mach-shmobile/Makefile
> >>>> +++ b/arch/arm/mach-shmobile/Makefile
> >>>> @@ -34,6 +34,7 @@ smp-$(CONFIG_ARCH_SH73A0)+= smp-sh73a0.o
> >>> headsmp-scu.o platsmp-scu.o
> >>>>  smp-$(CONFIG_ARCH_R8A7779)+= smp-r8a7779.o headsmp-scu.o
> >>> platsmp-scu.o
> >>>>  smp-$(CONFIG_ARCH_R8A7790)+= smp-r8a7790.o
> >>>> smp-$(CONFIG_ARCH_R8A7791)+= smp-r8a7791.o
> >>>> +smp-$(CONFIG_ARCH_R9A06G032)+= smp-r9a06g032.o
> >>>>  smp-$(CONFIG_ARCH_EMEV2)+= smp-emev2.o headsmp-scu.o
> >>> platsmp-scu.o
> >>>>
> >>>>  # PM objects
> >>>> diff --git a/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> b/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> new file mode 100644
> >>>> index 0000000..cd40e6e
> >>>> --- /dev/null
> >>>> +++ b/arch/arm/mach-shmobile/smp-r9a06g032.c
> >>>> @@ -0,0 +1,79 @@
> >>>> +// SPDX-License-Identifier: GPL-2.0
> >>>> +/*
> >>>> + * R9A06G032 Second CA7 enabler.
> >>>> + *
> >>>> + * Copyright (C) 2018 Renesas Electronics Europe Limited
> >>>> + *
> >>>> + * Michel Pollet <michel.pollet@bp.renesas.com>,
> >>> <buserror@gmail.com>
> >>>> + * Derived from action,s500-smp
> >>>> + */
> >>>> +
> >>>> +#include <linux/io.h>
> >>>> +#include <linux/of.h>
> >>>> +#include <linux/of_address.h>
> >>>> +#include <linux/smp.h>
> >>>> +
> >>>> +/*
> >>>> + * The second CPU is parked in ROM at boot time. It requires
> >>>> +waking it after
> >>>> + * writing an address into the BOOTADDR register of sysctrl.
> >>>> + *
> >>>> + * So the default value of the "cpu-release-addr" corresponds to
> >>> BOOTADDR...
> >>>> + *
> >>>> + * *However* the BOOTADDR register is not available when the
> >>>> +kernel
> >>>> + * starts in NONSEC mode.
> >>>> + *
> >>>> + * So for NONSEC mode, the bootloader re-parks the second CPU into
> >>>> +a pen
> >>>> + * in SRAM, and changes the "cpu-release-addr" of linux's DT to a
> >>>> +SRAM address,
> >>>> + * which is not restricted.
> >>>
> >>> The binding document for cpu-release-addr does not have a definition
> >>> for 32 bit arm.  The existing definition is only 64 bit arm.  Please
> >>> add the definition for 32 bit arm to patch 1.
> >>
> >> Hmmm I do find a definition in
> >> Documentation/devicetree/bindings/arm/cpus.txt -- just under where I
> >> added my 'enable-method' -- And it is already used as 32 bits in at
> >> least arch/arm/boot/dts/stih407-family.dtsi.
> >
> > If the correct answer is for cpu-release-addr to be 64 bits in certain
> > cases (that discussion is ongoing further downthread) then one
> > approach to maintain compatibility _and_ to fix the devicetree source
> > files is to change the source code that currently gets
> > cpu-release-addr as a
> > 32 bit object to check the size of the property and get it as either a
> > 32 bit or 64 bit object, based on the actual size of the property in
> > the device tree and then change the value in the devicetree source
> > files to be two cells.  BUT this does not consider the bootloader
> > complication.  arch/arm/boot/dts/axm5516-cpus.dtsi has a note "//
> > Fixed by the boot loader", so the boot loader also has to be modified
> > to be able to handle the possibility that the property could be either
> > 32 bits or 64 bits.  I don't know how to maintain compatibility with
> > the boot loader since we can't force it to change synchronously with
> > changes in the kernel.
> >
> > You can consider this comment to be a drive-by observation.  I think
> > Rob and Geert and people like that are likely to be more helpful with
> > what to actually do, and you can treat my comment more as pointing out
> > the issue than as providing the perfect solution.
>
> Darn it, hit <send> too quickly.
>
> I meant to mention that there are several devicetree source files that have a
> single cell value for cpu-release-addr, and thus potentially face the same
> situation, depending on what the final decision is on the proper size for cpu-
> release-addr. As of v4.17, a git grep shows one cell values in:
>
>   arch/arm/boot/dts/axm5516-cpus.dtsi
>   arch/arm/boot/dts/stih407-family.dtsi
>   arch/arm/boot/dts/stih418.dtsi

Yes, I had grepped before I used 32 bits on mine...

Now, what is the decision here? Our bootloader is already modified to set it to 32 bits, so I propose that

+ I change the driver to handle 32 and 64 bits properties
+ I add this to the cpu.txt, as a separate patch:
# On other systems, the property can be either
  32 bits or 64 bits, it is the driver's responsibility
  to deal with either sizes.

Michel

>
> -Frank
>
> > -Frnak
> >
> >
> >>
> >> What do you want me to add to this exactly? Do you want me to just
> >> change "required for systems that have an "enable-method" property
> >> value of "spin-table" to also specify renesas,r9a06g032 ?
> >>
> >> Thanks!
> >> Michel
> >>
> >>>
> >>> -Frank
> >>>
> >>>
> >>>> + */
> >>>> +
> >>>> +static void __iomem *cpu_bootaddr;
> >>>> +
> >>>> +static DEFINE_SPINLOCK(cpu_lock);
> >>>> +
> >>>> +static int r9a06g032_smp_boot_secondary(unsigned int cpu, struct
> >>>> +task_struct *idle) { if (!cpu_bootaddr) return -ENODEV;
> >>>> +
> >>>> +spin_lock(&cpu_lock);
> >>>> +
> >>>> +writel(__pa_symbol(secondary_startup), cpu_bootaddr);
> >>>> +arch_send_wakeup_ipi_mask(cpumask_of(cpu));
> >>>> +
> >>>> +spin_unlock(&cpu_lock);
> >>>> +
> >>>> +return 0;
> >>>> +}
> >>>> +
> >>>> +static void __init r9a06g032_smp_prepare_cpus(unsigned int
> >>>> +max_cpus) { struct device_node *dn; int ret;
> >>>> +u32 bootaddr;
> >>>> +
> >>>> +dn = of_get_cpu_node(1, NULL);
> >>>> +if (!dn) {
> >>>> +pr_err("CPU#1: missing device tree node\n"); return; }
> >>>> +/*
> >>>> + * Determine the address from which the CPU is polling.
> >>>> + * The bootloader *does* change this property  */ ret =
> >>>> +of_property_read_u32(dn, "cpu-release-addr", &bootaddr);
> >>>> +of_node_put(dn); if (ret) {
> >>>> +pr_err("CPU#1: invalid cpu-release-addr property\n"); return; }
> >>>> +pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
> >>>> +
> >>>> +cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr)); }
> >>>> +
> >>>> +static const struct smp_operations r9a06g032_smp_ops __initconst =
> >>>> +{ .smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
> >>>> +.smp_boot_secondary = r9a06g032_smp_boot_secondary, };
> >>>> +CPU_METHOD_OF_DECLARE(r9a06g032_smp, "renesas,r9a06g032-
> smp",
> >>>> +&r9a06g032_smp_ops);
> >>>>
> >>
> >>
> >>
> >>
> >> Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne
> End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under
> Registered No. 04586709.
> >>
> >
> >




Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered No. 04586709.

^ permalink raw reply

* Re: [PATCH 2/2] cpufreq: qcom-fw: Add support for QCOM cpufreq FW driver
From: Taniya Das @ 2018-06-07  7:18 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, linux-kernel, linux-pm, Stephen Boyd, robh,
	Rajendra Nayak, devicetree, skannan
In-Reply-To: <20180606060119.yzl24vhqff6btvrk@vireshk-i7>

Hello Viresh,

Thank you for the review comments.

On 6/6/2018 11:31 AM, Viresh Kumar wrote:
> On 04-06-18, 16:16, Taniya Das wrote:
>> The CPUfreq FW present in some QCOM chipsets offloads the steps necessary
>> for changing the frequency of CPUs. The driver implements the cpufreq
>> driver interface for this firmware.
>>
>> Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
>> Signed-off-by: Taniya Das <tdas@codeaurora.org>
>> ---
>>   drivers/cpufreq/Kconfig.arm       |   9 ++
>>   drivers/cpufreq/Makefile          |   1 +
>>   drivers/cpufreq/qcom-cpufreq-fw.c | 316 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 326 insertions(+)
>>   create mode 100644 drivers/cpufreq/qcom-cpufreq-fw.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index c7ce928..82c391e 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -312,3 +312,12 @@ config ARM_PXA2xx_CPUFREQ
>>   	  This add the CPUFreq driver support for Intel PXA2xx SOCs.
>>
>>   	  If in doubt, say N.
>> +
>> +config ARM_QCOM_CPUFREQ_FW
>> +	bool "QCOM CPUFreq FW driver"
>> +	help
>> +	 Support for the CPUFreq FW driver.
>> +	 The CPUfreq FW preset in some QCOM chipsets offloads the steps
>> +	 necessary for changing the frequency of CPUs. The driver
>> +	 implements the cpufreq driver interface for this firmware.
>> +	 Say Y if you want to support CPUFreq FW.
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index fb4a2ec..34691a2 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -86,6 +86,7 @@ obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)	+= tegra124-cpufreq.o
>>   obj-$(CONFIG_ARM_TEGRA186_CPUFREQ)	+= tegra186-cpufreq.o
>>   obj-$(CONFIG_ARM_TI_CPUFREQ)		+= ti-cpufreq.o
>>   obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)	+= vexpress-spc-cpufreq.o
>> +obj-$(CONFIG_ARM_QCOM_CPUFREQ_FW)	+= qcom-cpufreq-fw.o
>>
>>
>>   ##################################################################################
>> diff --git a/drivers/cpufreq/qcom-cpufreq-fw.c b/drivers/cpufreq/qcom-cpufreq-fw.c
>> new file mode 100644
>> index 0000000..2135a08
>> --- /dev/null
>> +++ b/drivers/cpufreq/qcom-cpufreq-fw.c
>> @@ -0,0 +1,316 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#include <linux/cpufreq.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +
>> +#define INIT_RATE			300000000UL
>> +#define XO_RATE				19200000UL
>> +#define LUT_MAX_ENTRIES			40U
>> +#define CORE_COUNT_VAL(val)		(((val) & (GENMASK(18, 16))) >> 16)
>> +#define LUT_ROW_SIZE			32
>> +
>> +struct cpufreq_qcom {
>> +	struct cpufreq_frequency_table *table;
>> +	struct device *dev;
>> +	void __iomem *perf_base;
>> +	void __iomem *lut_base;
>> +	cpumask_t related_cpus;
>> +	unsigned int max_cores;
>> +};
>> +
>> +static struct cpufreq_qcom *qcom_freq_domain_map[NR_CPUS];
>> +
>> +static int
>> +qcom_cpufreq_fw_target_index(struct cpufreq_policy *policy,
>> +			     unsigned int index)
>> +{
>> +	struct cpufreq_qcom *c = policy->driver_data;
>> +
>> +	writel_relaxed(index, c->perf_base);
>> +
>> +	return 0;
>> +}
>> +
>> +static unsigned int qcom_cpufreq_fw_get(unsigned int cpu)
>> +{
>> +	struct cpufreq_qcom *c;
>> +	unsigned int index;
>> +
>> +	c = qcom_freq_domain_map[cpu];
>> +	if (!c)
>> +		return 0;
>> +
>> +	index = readl_relaxed(c->perf_base);
>> +	index = min(index, LUT_MAX_ENTRIES - 1);
>> +
>> +	return c->table[index].frequency;
>> +}
>> +
>> +static int qcom_cpufreq_fw_cpu_init(struct cpufreq_policy *policy)
>> +{
>> +	struct cpufreq_qcom *c;
>> +
>> +	c = qcom_freq_domain_map[policy->cpu];
>> +	if (!c) {
>> +		pr_err("No scaling support for CPU%d\n", policy->cpu);
>> +		return -ENODEV;
>> +	}
>> +
>> +	cpumask_copy(policy->cpus, &c->related_cpus);
>> +
>> +	policy->freq_table = c->table;
>> +	policy->driver_data = c;
> 
> What about fast cpufreq switching ? I think you can enable that option as well
> here..
> 
Sure I will take a look and update.

>> +
>> +	return 0;
>> +}
>> +
>> +static struct freq_attr *qcom_cpufreq_fw_attr[] = {
>> +	&cpufreq_freq_attr_scaling_available_freqs,
>> +	&cpufreq_freq_attr_scaling_boost_freqs,
>> +	NULL
>> +};
>> +
>> +static struct cpufreq_driver cpufreq_qcom_fw_driver = {
>> +	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
>> +			  CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
>> +	.verify		= cpufreq_generic_frequency_table_verify,
>> +	.target_index	= qcom_cpufreq_fw_target_index,
>> +	.get		= qcom_cpufreq_fw_get,
>> +	.init		= qcom_cpufreq_fw_cpu_init,
> 
> What about CPU hotplug ? We can still do that, right ? So what will happen if
> all CPUs of a freq-domain are removed (hence cpufreq policy is removed) and then
> someone calls qcom_cpufreq_fw_get() ? You should really work on cpufreq_policy
> there to get 'c'.
> 

You want the _get to do something as below.
Please correct me if my understanding is wrong.
....

  policy = cpufreq_cpu_get_raw(cpu);
  if (!policy)
     return 0;

  c = policy->driver_data;

  index = readl_relaxed(c->perf_base);
  index = min(index, LUT_MAX_ENTRIES - 1);

  return c->table[index].frequency;

....

>> +	.name		= "qcom-cpufreq-fw",
>> +	.attr		= qcom_cpufreq_fw_attr,
>> +	.boost_enabled	= true,
>> +};
>> +
>> +static int qcom_read_lut(struct platform_device *pdev,
>> +			 struct cpufreq_qcom *c)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	u32 data, src, lval, i, core_count, prev_cc, prev_freq, cur_freq;
>> +
>> +	c->table = devm_kcalloc(dev, LUT_MAX_ENTRIES + 1,
>> +				sizeof(*c->table), GFP_KERNEL);
>> +	if (!c->table)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < LUT_MAX_ENTRIES; i++) {
>> +		data = readl_relaxed(c->lut_base + i * LUT_ROW_SIZE);
>> +		src = ((data & GENMASK(31, 30)) >> 30);
>> +		lval = (data & GENMASK(7, 0));
>> +		core_count = CORE_COUNT_VAL(data);
>> +
>> +		if (!src)
>> +			c->table[i].frequency = INIT_RATE / 1000;
>> +		else
>> +			c->table[i].frequency = XO_RATE * lval / 1000;
>> +
>> +		cur_freq = c->table[i].frequency;
>> +
>> +		dev_dbg(dev, "index=%d freq=%d, core_count %d\n",
>> +			i, c->table[i].frequency, core_count);
>> +
>> +		if (core_count != c->max_cores)
>> +			cur_freq = CPUFREQ_ENTRY_INVALID;
>> +
>> +		/*
>> +		 * Two of the same frequencies with the same core counts means
>> +		 * end of table.
>> +		 */
>> +		if (i > 0 && c->table[i - 1].frequency ==
>> +		   c->table[i].frequency && prev_cc == core_count) {
>> +			struct cpufreq_frequency_table *prev = &c->table[i - 1];
>> +
>> +			if (prev_freq == CPUFREQ_ENTRY_INVALID)
>> +				prev->flags = CPUFREQ_BOOST_FREQ;
>> +			break;
>> +		}
>> +		prev_cc = core_count;
>> +		prev_freq = cur_freq;
>> +	}
>> +
>> +	c->table[i].frequency = CPUFREQ_TABLE_END;
>> +
>> +	return 0;
>> +}
> 
> Looks like there are many problems here.
> - You are assigning prev_freq with cur_freq (which may be uninitialized local
>    variable here).
> - In this version, you never write CPUFREQ_ENTRY_INVALID to table[i].frequency,
>    which looks wrong as well.
> 

- The code to detect boost, would only enter for i > 0 and the prev_freq 
   would be initialized with the cur_freq.
- In the case where the core_count != max_cores, the cur_freq is marked 
INVALID, and when both prev_freq == cur_freq && prev_cc && cur_cc match, 
that is the time the prev table flags need to be updated. Marking the 
table[i].frequency as INVALID is not required as cur_freq is already 
marked with the same. Please correct me if you think otherwise.

>> +
>> +static int qcom_get_related_cpus(struct device_node *np, struct cpumask *m)
>> +{
>> +	struct device_node  *cpu_dev;
> 
> s/cpu_dev/cpu_np/
> 
>> +	int cpu;
>> +
>> +	for_each_possible_cpu(cpu) {
>> +		cpu_dev = of_cpu_device_node_get(cpu);
>> +		if (!cpu_dev)
>> +			continue;
>> +		cpu_dev = of_parse_phandle(cpu_dev, "qcom,freq-domain", 0);
> 
> What's returned here is a pointer to the qcom,freq-domain node, and you assign
> that to a variable named cpu_dev. Either use two variables for different node
> types, or rename it to temp_np or something similar.
> 

I would use a different node.

>> +		if (!cpu_dev)
>> +			continue;
>> +		if (cpu_dev == np)
>> +			cpumask_set_cpu(cpu, m);
>> +	}
>> +
>> +	if (cpumask_empty(m))
>> +		return -ENOENT;
>> +
>> +	return 0;
>> +}
>> +
>> +static int qcom_cpu_resources_init(struct platform_device *pdev,
>> +				   struct device_node *np)
>> +{
>> +	struct cpufreq_qcom *c;
>> +	struct resource res;
>> +	struct device *dev = &pdev->dev;
>> +	void __iomem *en_base;
>> +	int cpu, index, ret;
>> +
>> +	c = devm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
>> +	if (!c)
>> +		return -ENOMEM;
>> +
>> +	index = of_property_match_string(np, "reg-names", "enable");
>> +	if (index < 0)
>> +		return index;
>> +
>> +	if (of_address_to_resource(np, index, &res))
>> +		return -ENOMEM;
>> +
>> +	en_base = devm_ioremap(dev, res.start, resource_size(&res));
>> +	if (!en_base) {
>> +		dev_err(dev, "Unable to map %s enable-base\n", np->name);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	/* FW should be in enabled state to proceed */
>> +	if (!(readl_relaxed(en_base) & 0x1)) {
>> +		dev_err(dev, "%s firmware not enabled\n", np->name);
>> +		return -ENODEV;
>> +	}
>> +	devm_iounmap(&pdev->dev, en_base);
>> +
>> +	index = of_property_match_string(np, "reg-names", "perf");
>> +	if (index < 0)
>> +		return index;
>> +
>> +	if (of_address_to_resource(np, index, &res))
>> +		return -ENOMEM;
>> +
>> +	c->perf_base = devm_ioremap(dev, res.start, resource_size(&res));
>> +	if (!c->perf_base) {
>> +		dev_err(dev, "Unable to map %s perf-base\n", np->name);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	index = of_property_match_string(np, "reg-names", "lut");
>> +	if (index < 0)
>> +		return index;
>> +
>> +	if (of_address_to_resource(np, index, &res))
>> +		return -ENOMEM;
>> +
>> +	c->lut_base = devm_ioremap(dev, res.start, resource_size(&res));
>> +	if (!c->lut_base) {
>> +		dev_err(dev, "Unable to map %s lut-base\n", np->name);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	ret = qcom_get_related_cpus(np, &c->related_cpus);
>> +	if (ret) {
>> +		dev_err(dev, "%s failed to get core phandles\n", np->name);
> 
> Maybe write a more relevant error message here ?
> 

Sure, would take care of it in the next patch.

>> +		return ret;
>> +	}
>> +
>> +	c->max_cores = cpumask_weight(&c->related_cpus);
> 
> Maybe remove the error checking conditional from qcom_get_related_cpus() and
> check !c->max_cores here for the same.
> 

I would update it in the next patch.

>> +
>> +	ret = qcom_read_lut(pdev, c);
>> +	if (ret) {
>> +		dev_err(dev, "%s failed to read LUT\n", np->name);
>> +		return ret;
>> +	}
> 
> Enter a blank line here.

I would update in the next patch.
> 
>> +	for_each_cpu(cpu, &c->related_cpus)
>> +		qcom_freq_domain_map[cpu] = c;
> 
> This whole setup looks a bit confusing to me. This is what you are doing
> essentially:
> 
> qcom_resources_init()
> {
>          for_each_possible_cpu() {
>                  qcom_cpu_resources_init()
>                  {
>                          populate c->related_cpus;
> 
>                          for_each_related_cpu() {
>                                  qcom_freq_domain_map[cpu] = c;
>                          }
>                  }
>          }
> }
> 
> So if there are 4 CPUs that share a freq domain, then you are allocating 'c' 4
> times and (over)writing qcom_freq_domain_map[] for all these CPUs 4 times and
> finally keeping value of 'c' only once.
> 
> You must be running most of the work done in qcom_resources_init() only once per
> freq-domain.
> 

Thanks, you are correct, I carried the earlier logic, would cleanup in 
the next patch.

>> +
>> +	return 0;
>> +}
>> +
>> +static int qcom_resources_init(struct platform_device *pdev)
>> +{
>> +	struct device_node *np, *cpu_dev;
> 
> cpu_dev is normally used in kernel for struct device *, maybe use cpu_np ?

I would update it in the next patch.
> 
>> +	unsigned int cpu;
>> +	int ret;
>> +
>> +	for_each_possible_cpu(cpu) {
>> +		cpu_dev = of_cpu_device_node_get(cpu);
>> +		if (!cpu_dev) {
>> +			dev_err(&pdev->dev, "Failed to get cpu %d device\n",
>> +				cpu);
>> +			continue;
>> +		}
>> +
>> +		np = of_parse_phandle(cpu_dev, "qcom,freq-domain", 0);
>> +		if (!np) {
>> +			dev_err(&pdev->dev, "Failed to get freq-domain device\n");
>> +			continue;
> 
> I am not sure if we should continue or error out here. Why would you want only a
> group of CPUs to have this property set ? Or if you really have a case for that
> currently ?
> 

I don't have any usecase, but I was of the opinion in case there is no 
freq domains attached to a cluster. But it might be better I error out.

>> +		}
>> +
>> +		of_node_put(cpu_dev);
>> +
>> +		ret = qcom_cpu_resources_init(pdev, np);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int qcom_cpufreq_fw_driver_probe(struct platform_device *pdev)
>> +{
>> +	int rc;
>> +
>> +	/* Get the bases of cpufreq for domains */
>> +	rc = qcom_resources_init(pdev);
>> +	if (rc) {
>> +		dev_err(&pdev->dev, "CPUFreq resource init failed\n");
>> +		return rc;
>> +	}
>> +
>> +	rc = cpufreq_register_driver(&cpufreq_qcom_fw_driver);
>> +	if (rc) {
>> +		dev_err(&pdev->dev, "CPUFreq FW driver failed to register\n");
>> +		return rc;
>> +	}
>> +
>> +	dev_info(&pdev->dev, "QCOM CPUFreq FW driver inited\n");
> 
> s/inited/initialized/ ?
> 

Sure, will fix in the next patch.

>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id match_table[] = {
>> +	{ .compatible = "qcom,cpufreq-fw" },
>> +	{}
>> +};
>> +
>> +static struct platform_driver qcom_cpufreq_fw_driver = {
>> +	.probe = qcom_cpufreq_fw_driver_probe,
>> +	.driver = {
>> +		.name = "qcom-cpufreq-fw",
>> +		.of_match_table = match_table,
>> +		.owner = THIS_MODULE,
>> +	},
>> +};
>> +
>> +static int __init qcom_cpufreq_fw_init(void)
>> +{
>> +	return platform_driver_register(&qcom_cpufreq_fw_driver);
>> +}
>> +subsys_initcall(qcom_cpufreq_fw_init);
>> +
>> +MODULE_DESCRIPTION("QCOM CPU Frequency FW");
>> +MODULE_LICENSE("GPL v2");
>> --
>> Qualcomm INDIA, on behalf of Qualcomm Innovation Center, Inc.is a member
>> of the Code Aurora Forum, hosted by the  Linux Foundation.
> 

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation.

--

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: cpufreq: Introduce QCOM CPUFREQ FW bindings
From: Taniya Das @ 2018-06-07  7:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Rafael J. Wysocki, Viresh Kumar, linux-kernel, linux-pm,
	Stephen Boyd, robh, Rajendra Nayak, devicetree, skannan
In-Reply-To: <20180604105531.GB13977@e107155-lin>

Hello Sudeep,

Thanks for the review comments.

On 6/4/2018 4:25 PM, Sudeep Holla wrote:
> On Mon, Jun 04, 2018 at 04:16:33PM +0530, Taniya Das wrote:
>> Add QCOM cpufreq firmware device bindings for Qualcomm Technology Inc's
>> SoCs. This is required for managing the cpu frequency transitions which are
>> controlled by firmware.
>>
>> Signed-off-by: Taniya Das <tdas@codeaurora.org>
>> ---
>>   .../bindings/cpufreq/cpufreq-qcom-fw.txt           | 173 +++++++++++++++++++++
>>   1 file changed, 173 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
>> new file mode 100644
>> index 0000000..e3087ec
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
>> @@ -0,0 +1,173 @@
>> +Qualcomm Technologies, Inc. CPUFREQ Bindings
>> +
>> +CPUFREQ FW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
>> +SoCs to manage frequency in hardware. It is capable of controlling frequency
>> +for multiple clusters.
>> +
>> +Properties:
>> +- compatible
>> +	Usage:		required
>> +	Value type:	<string>
>> +	Definition:	must be "qcom,cpufreq-fw".
>> +
>> +* Property qcom,freq-domain
>> +Devices supporting freq-domain must set their "qcom,freq-domain" property with
>> +phandle to a freq_domain_table in their DT node.
>> +
>> +* Frequency Domain Table Node
>> +
>> +This describes the frequency domain belonging to a device.
>> +This node can have following properties:
>> +
>> +- reg
>> +	Usage:		required
>> +	Value type:	<prop-encoded-array>
>> +	Definition:	Addresses and sizes for the memory of the perf
>> +			, lut and enable bases.
>> +			perf - indicates the base address for the desired
>> +			performance state to be set.
>> +			lut - indicates the look up table base address for the
>> +			cpufreq	driver to read frequencies.
>> +			enable - indicates the enable register for firmware.
>> +- reg-names
>> +	Usage:		required
>> +	Value type:	<stringlist>
>> +	Definition:	Address names. Must be "perf", "lut", "enable".
>> +			Must be specified in the same order as the reg property.
>> +
> 
> [...]
> 
>> +
>> +	qcom,cpufreq-fw {
>> +		compatible = "qcom,cpufreq-fw";
>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +
>> +		freq_domain_table0 : freq_table0 {
>> +			reg = <0x17d43920 0x4>, <0x17d43110 0x500>,
>> +				 <0x17d41000 0x4>;
> 
> Are "perf", "lut", "enable" registers part of single IP block / share memory ?
> I am just trying to understand the reason for separate entries in this fashion
> as part of DT register property. I am wondering if there will be multiple
> entries that fall with the page size.
> 

They are part of the same IP block and these are the only register 
offsets which is required to be accessed by HLOS.

> --
> Regards,
> Sudeep
> 

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation.

--

^ permalink raw reply

* Re: USB role switches, usb-connector, typec and device trees
From: Hans de Goede @ 2018-06-07  7:22 UTC (permalink / raw)
  To: Mats Karrman, Heikki Krogerus, Andrzej Hajda
  Cc: Greg Kroah-Hartman, linux-usb, devicetree
In-Reply-To: <6c379a23-5c63-9b49-9444-e16d6a8082a6@gmail.com>

Hi,

On 06-06-18 23:36, Mats Karrman wrote:
> Hello Gentlemen,
> 
> I'm trying to get my head around USB role switches in connection with Type-C ports
> and device-trees. So far I have not found much documentation, e.g. there are no
> device-tree bindings documented and really no good examples in existing device
> trees, although there has been some attempts, e.g. [1] and [2]. Anyway, so I send
> you a couple of questions instead:
> 
> 1) tcpm uses the port device struct to find a single usb_role_switch but there is
> room for three USB busses in the Type-C connector; one high speed and two (?) super-
> speed. These would not all come from the same controller (there might even be
> separate controllers for host and device mode for each bus).

AFAIK the 2nd superspeed USB bus is never used as such. There really is only 1
USB bus on the Type-C connector, the combined USB-2 + the 1st superspeed bus,
physically these are 2 separate busses but that is purely for compatibility
reasons, logically there really only is 1 bus, just like a superspeed Type-A
connector has both busses physically but logically represents a single bus/port.

> The case I am working on now only have a single USB2 otg controller so it should
> be possible to make that driver register a role switch but for other cases?

I guess theoretically a device could use separate role switches / muxes for
the USB-2 and USB-3 busses, but that would be weird. So lets cross that bridge
when we reach it.

> I imagine it would be possible to create a composite driver as a proxy for all role
> switches but that would probably be different for every platform/product - not
> very elegant. Could the role switch infrastructure be extended to handle arbitrary
> sets of coordinated switches?

As said lets cross that bridge when we reach it.

> 2) How should the connection between the Type-C port and the switches best be
> expressed in a device tree? Using graph I presume, but should it be mixed into the
> existing "usb-connector" or should this be a separate block?
> I think it is unfortunate that the graph use numeric addresses that need to be
> fixed by documentation and already I see problems with the current assignment
> (0=HS, 1=SS, 2=SBU), e.g. if the host and device mode are handled by different
> controllers. Graph do support multiple endpoints for one port but then we have
> another level of magic numbers which does not exactly make things easier
> (e.g. 0=dual or host controller, 1=device controller, 2=mode switch).

The graph stuff is more Heikki's specialty so I will let Heikki answer this.

Regards,

Hans


^ permalink raw reply

* Re: [PATCH v3 4/6] bus: ti-sysc: Add support for software reset
From: Tony Lindgren @ 2018-06-07  7:35 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: linux-kernel, devicetree, linux-omap, linux-arm-kernel, linux-clk,
	mark.rutland, paul, t-kristo, robh+dt, bcousson
In-Reply-To: <20180606060826.14671-5-faiz_abbas@ti.com>

* Faiz Abbas <faiz_abbas@ti.com> [180606 06:14]:
> +static int sysc_reset(struct sysc *ddata)
> +{
> +	int offset = ddata->offsets[SYSC_SYSCONFIG];
> +	int val = sysc_read(ddata, offset);
> +
> +	val |= (0x1 << ddata->cap->regbits->srst_shift);
> +	sysc_write(ddata, offset, val);
> +
> +	/* Poll on reset status */
> +	if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
> +		offset = ddata->offsets[SYSC_SYSSTATUS];
> +
> +		return readl_poll_timeout(ddata->module_va + offset, val,
> +				(val & ddata->cfg.syss_mask) == 0x0,
> +				100, MAX_MODULE_SOFTRESET_WAIT);
> +	}
> +
> +	return 0;
> +}

I wonder if we should also add SYSS_QUIRK_RESET_STATUS in
addition to SYSC_QUIRK_RESET status to make it easy to
read the right register?

Then we can add support for SYSC_QUIRK_RESET_STATUS later on
when tested and return error for now.

Regards,

Tony

^ permalink raw reply

* Re: [PATCH v1 2/4] clk: rockchip: add dt-binding header for px30
From: Heiko Stübner @ 2018-06-07  7:56 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: sboyd, robh+dt, mark.rutland, mturquette, linux-clk, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel, cl, xxx, xf,
	huangtao
In-Reply-To: <1528340786-462-3-git-send-email-zhangqing@rock-chips.com>

Am Donnerstag, 7. Juni 2018, 05:06:24 CEST schrieb Elaine Zhang:
> Add the dt-bindings header for the px30, that gets shared between
> the clock controller and the clock references in the dts.
> Add softreset ID for px30.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  include/dt-bindings/clock/px30-cru.h | 402
> +++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+)
>  create mode 100644 include/dt-bindings/clock/px30-cru.h
> 
> diff --git a/include/dt-bindings/clock/px30-cru.h
> b/include/dt-bindings/clock/px30-cru.h new file mode 100644
> index 000000000000..db9fc2a0bb21
> --- /dev/null
> +++ b/include/dt-bindings/clock/px30-cru.h
> @@ -0,0 +1,402 @@
> +/*
> + * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
> + * Author: Elaine <zhangqing@rock-chips.com>

				^^ full name maybe?

Otherwise looks good.


Heiko

^ permalink raw reply

* RE: [v2, 09/10] dpaa_eth: add support for hardware timestamping
From: Madalin-cristian Bucur @ 2018-06-07  8:24 UTC (permalink / raw)
  To: netdev@vger.kernel.org, Richard Cochran, Rob Herring, Shawn Guo,
	David S . Miller
  Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Y.b. Lu
In-Reply-To: <20180607032256.39802-10-yangbo.lu@nxp.com>

> -----Original Message-----
> From: Yangbo Lu [mailto:yangbo.lu@nxp.com]
> Sent: Thursday, June 7, 2018 6:23 AM
> Subject: [v2, 09/10] dpaa_eth: add support for hardware timestamping
> 
> This patch is to add hardware timestamping support
> for dpaa_eth. On Rx, timestamping is enabled for
> all frames. On Tx, we only instruct the hardware
> to timestamp the frames marked accordingly by the
> stack.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- Removed ifdef for timestamp code.
> 	- Minor fixes for code style.
> ---
>  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c |  101
> ++++++++++++++++++++++-
>  drivers/net/ethernet/freescale/dpaa/dpaa_eth.h |    3 +
>  2 files changed, 99 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index fd43f98..bd589ac 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -1168,7 +1168,7 @@ static int dpaa_eth_init_tx_port(struct fman_port
> *port, struct dpaa_fq *errq,
>  	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
>  	buf_prefix_content.pass_prs_result = true;
>  	buf_prefix_content.pass_hash_result = true;
> -	buf_prefix_content.pass_time_stamp = false;
> +	buf_prefix_content.pass_time_stamp = true;
>  	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
> 
>  	params.specific_params.non_rx_params.err_fqid = errq->fqid;
> @@ -1210,7 +1210,7 @@ static int dpaa_eth_init_rx_port(struct fman_port
> *port, struct dpaa_bp **bps,
>  	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
>  	buf_prefix_content.pass_prs_result = true;
>  	buf_prefix_content.pass_hash_result = true;
> -	buf_prefix_content.pass_time_stamp = false;
> +	buf_prefix_content.pass_time_stamp = true;
>  	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
> 
>  	rx_p = &params.specific_params.rx_params;
> @@ -1592,6 +1592,16 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv
> *priv)
>  	return 0;
>  }
> 
> +static int dpaa_get_tstamp_ns(struct net_device *net_dev, u64 *ns,
> +			      struct fman_port *port, const void *data)
> +{
> +	if (!fman_port_get_tstamp_field(port, data, ns)) {
> +		be64_to_cpus(ns);

Please move this endianness conversion in the fman API.

> +		return 0;
> +	}
> +	return -EINVAL;
> +}
> +
>  /* Cleanup function for outgoing frame descriptors that were built on Tx
> path,
>   * either contiguous frames or scatter/gather ones.
>   * Skb freeing is not handled here.
> @@ -1607,14 +1617,29 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv
> *priv)
>  {
>  	const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
>  	struct device *dev = priv->net_dev->dev.parent;
> +	struct skb_shared_hwtstamps shhwtstamps;
>  	dma_addr_t addr = qm_fd_addr(fd);
>  	const struct qm_sg_entry *sgt;
>  	struct sk_buff **skbh, *skb;
>  	int nr_frags, i;
> +	u64 ns;
> 
>  	skbh = (struct sk_buff **)phys_to_virt(addr);
>  	skb = *skbh;
> 
> +	if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> SKBTX_HW_TSTAMP) {
> +		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> +
> +		if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> +					priv->mac_dev->port[TX],
> +					(void *)skbh)) {
> +			shhwtstamps.hwtstamp = ns_to_ktime(ns);
> +			skb_tstamp_tx(skb, &shhwtstamps);
> +		} else {
> +			dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
> +		}
> +	}
> +
>  	if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
>  		nr_frags = skb_shinfo(skb)->nr_frags;
>  		dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
> @@ -2086,6 +2111,11 @@ static int dpaa_start_xmit(struct sk_buff *skb,
> struct net_device *net_dev)
>  	if (unlikely(err < 0))
>  		goto skb_to_fd_failed;
> 
> +	if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags &
> SKBTX_HW_TSTAMP) {
> +		fd.cmd |= FM_FD_CMD_UPD;

The fd.cmd field is big endian, please use this:

+		fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);

> +		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> +	}
> +
>  	if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
>  		return NETDEV_TX_OK;
> 
> @@ -2227,6 +2257,7 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
>  						struct qman_fq *fq,
>  						const struct qm_dqrr_entry
> *dq)
>  {
> +	struct skb_shared_hwtstamps *shhwtstamps;
>  	struct rtnl_link_stats64 *percpu_stats;
>  	struct dpaa_percpu_priv *percpu_priv;
>  	const struct qm_fd *fd = &dq->fd;
> @@ -2240,6 +2271,7 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
>  	struct sk_buff *skb;
>  	int *count_ptr;
>  	void *vaddr;
> +	u64 ns;
> 
>  	fd_status = be32_to_cpu(fd->status);
>  	fd_format = qm_fd_get_format(fd);
> @@ -2304,6 +2336,18 @@ static enum qman_cb_dqrr_result
> rx_default_dqrr(struct qman_portal *portal,
>  	if (!skb)
>  		return qman_cb_dqrr_consume;
> 
> +	if (priv->rx_tstamp) {
> +		shhwtstamps = skb_hwtstamps(skb);
> +		memset(shhwtstamps, 0, sizeof(*shhwtstamps));
> +
> +		if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> +					priv->mac_dev->port[RX],
> +					vaddr))
> +			shhwtstamps->hwtstamp = ns_to_ktime(ns);
> +		else
> +			dev_warn(net_dev->dev.parent,
> "dpaa_get_tstamp_ns failed!\n");
> +	}
> +
>  	skb->protocol = eth_type_trans(skb, net_dev);
> 
>  	if (net_dev->features & NETIF_F_RXHASH && priv->keygen_in_use
> &&
> @@ -2523,11 +2567,58 @@ static int dpaa_eth_stop(struct net_device
> *net_dev)
>  	return err;
>  }
> 
> +static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> +	struct dpaa_priv *priv = netdev_priv(dev);
> +	struct hwtstamp_config config;
> +
> +	if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
> +		return -EFAULT;
> +
> +	switch (config.tx_type) {
> +	case HWTSTAMP_TX_OFF:
> +		/* Couldn't disable rx/tx timestamping separately.
> +		 * Do nothing here.
> +		 */
> +		priv->tx_tstamp = false;
> +		break;
> +	case HWTSTAMP_TX_ON:
> +		priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> true);
> +		priv->tx_tstamp = true;
> +		break;
> +	default:
> +		return -ERANGE;
> +	}
> +
> +	if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
> +		/* Couldn't disable rx/tx timestamping separately.
> +		 * Do nothing here.
> +		 */
> +		priv->rx_tstamp = false;
> +	} else {
> +		priv->mac_dev->set_tstamp(priv->mac_dev->fman_mac,
> true);
> +		priv->rx_tstamp = true;
> +		/* TS is set for all frame types, not only those requested */
> +		config.rx_filter = HWTSTAMP_FILTER_ALL;
> +	}
> +
> +	return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
> +			-EFAULT : 0;
> +}
> +
>  static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
>  {
> -	if (!net_dev->phydev)
> -		return -EINVAL;
> -	return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> +	int ret = -EINVAL;
> +
> +	if (cmd == SIOCGMIIREG) {
> +		if (net_dev->phydev)
> +			return phy_mii_ioctl(net_dev->phydev, rq, cmd);
> +	}
> +
> +	if (cmd == SIOCSHWTSTAMP)
> +		return dpaa_ts_ioctl(net_dev, rq, cmd);
> +
> +	return ret;
>  }
> 
>  static const struct net_device_ops dpaa_ops = {
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> index bd94220..af320f8 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
> @@ -182,6 +182,9 @@ struct dpaa_priv {
> 
>  	struct dpaa_buffer_layout buf_layout[2];
>  	u16 rx_headroom;
> +
> +	bool tx_tstamp; /* Tx timestamping enabled */
> +	bool rx_tstamp; /* Rx timestamping enabled */
>  };
> 
>  /* from dpaa_ethtool.c */
> --
> 1.7.1

^ permalink raw reply

* Re: [PATCH v2] arm64: dts: msm8996: Use dwc3-qcom glue driver for USB
From: Vivek Gautam @ 2018-06-07  8:30 UTC (permalink / raw)
  To: Manu Gautam, andy.gross
  Cc: linux-soc, devicetree, linux-arm-msm, dianders, linux-usb,
	felipe.balbi, gregkh, bjorn.andersson
In-Reply-To: <20180531104710.23965-1-mgautam@codeaurora.org>



On 5/31/2018 4:17 PM, Manu Gautam wrote:
> Move from dwc3-of-simple to dwc3-qcom glue driver to
> support peripheral mode which requires qscratch wrapper
> programming on VBUS event.
>
> Fixes: a4333c3a6ba9 ("usb: dwc3: Add Qualcomm DWC3 glue driver")
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
>
> Changes since v1:
>   - Update unit address of DT node as per Doug's comment
>
>   arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi |  6 ++++--
>   arch/arm64/boot/dts/qcom/msm8996.dtsi        | 10 ++++++----
>   2 files changed, 10 insertions(+), 6 deletions(-)

Tested on DB820c. Works fine.
Tested-by: Vivek Gautam <vivek.gautam@codeaurora.org>

BRs
Vivek
>
> diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> index f45a0ab30d30..00be0d53891a 100644
> --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
> @@ -106,8 +106,9 @@
>   			status = "okay";
>   		};
>   
> -		usb@6a00000 {
> +		usb@6af8800 {
>   			status = "okay";
> +			extcon = <&usb3_id>;
>   
>   			dwc3@6a00000 {
>   				extcon = <&usb3_id>;
> @@ -122,8 +123,9 @@
>   			pinctrl-0 = <&usb3_vbus_det_gpio>;
>   		};
>   
> -		usb@7600000 {
> +		usb@76f8800 {
>   			status = "okay";
> +			extcon = <&usb2_id>;
>   
>   			dwc3@7600000 {
>   				extcon = <&usb2_id>;
> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> index 26292027ba9b..8b6dd5443524 100644
> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
> @@ -776,8 +776,9 @@
>   			status = "disabled";
>   		};
>   
> -		usb2: usb@7600000 {
> -			compatible = "qcom,dwc3";
> +		usb2: usb@76f8800 {
> +			compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
> +			reg = <0x76f8800 0x400>;
>   			#address-cells = <1>;
>   			#size-cells = <1>;
>   			ranges;
> @@ -804,8 +805,9 @@
>   			};
>   		};
>   
> -		usb3: usb@6a00000 {
> -			compatible = "qcom,dwc3";
> +		usb3: usb@6af8800 {
> +			compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
> +			reg = <0x6af8800 0x400>;
>   			#address-cells = <1>;
>   			#size-cells = <1>;
>   			ranges;


^ permalink raw reply

* [PATCH 0/4] Fix suspend resume on at91sam9261 and at91sam9263
From: Alexandre Belloni @ 2018-06-07  8:41 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Rob Herring, devicetree, linux-clk, Stephen Boyd, linux-kernel,
	linux-arm-kernel, Alexandre Belloni

USB clock detection may not work properly on at91sam9261 and at91sam9263
because they currently use the same bit mask as at91rm9200 instead of
the one for at91sam9260.

Take the opportunity to also change the PMC compatible strings for all
the other SoCs in preparation for the new clock bindings.

Alexandre Belloni (4):
  dt-bindings: arm: remove PMC bindings
  dt-bindings: clk: at91: Document all the PMC compatibles
  ARM: at91: fix USB clock detection handling
  ARM: dts: fix PMC compatible

 .../devicetree/bindings/arm/atmel-pmc.txt          | 14 --------------
 .../devicetree/bindings/clock/at91-clock.txt       |  9 ++++-----
 arch/arm/boot/dts/at91sam9261.dtsi                 |  2 +-
 arch/arm/boot/dts/at91sam9263.dtsi                 |  2 +-
 arch/arm/boot/dts/at91sam9rl.dtsi                  |  2 +-
 arch/arm/boot/dts/sama5d4.dtsi                     |  2 +-
 arch/arm/mach-at91/pm.c                            |  5 +++++
 7 files changed, 13 insertions(+), 23 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/arm/atmel-pmc.txt

-- 
2.17.1

^ permalink raw reply

* [PATCH 1/4] dt-bindings: arm: remove PMC bindings
From: Alexandre Belloni @ 2018-06-07  8:41 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: devicetree, Alexandre Belloni, Stephen Boyd, linux-kernel,
	Rob Herring, linux-clk, linux-arm-kernel
In-Reply-To: <20180607084107.4461-1-alexandre.belloni@bootlin.com>

The PMC bindings are fully described in
Documentation/devicetree/bindings/clock/at91-clock.txt. Remove the
duplicate and incomplete documentation.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 .../devicetree/bindings/arm/atmel-pmc.txt          | 14 --------------
 1 file changed, 14 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/arm/atmel-pmc.txt

diff --git a/Documentation/devicetree/bindings/arm/atmel-pmc.txt b/Documentation/devicetree/bindings/arm/atmel-pmc.txt
deleted file mode 100644
index 795cc78543fe..000000000000
--- a/Documentation/devicetree/bindings/arm/atmel-pmc.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-* Power Management Controller (PMC)
-
-Required properties:
-- compatible: Should be "atmel,<chip>-pmc".
-	<chip> can be: at91rm9200, at91sam9260, at91sam9g45, at91sam9n12,
-	at91sam9x5, sama5d3
-
-- reg: Should contain PMC registers location and length
-
-Examples:
-	pmc: pmc@fffffc00 {
-		compatible = "atmel,at91rm9200-pmc";
-		reg = <0xfffffc00 0x100>;
-	};
-- 
2.17.1

^ permalink raw reply related

* [PATCH 2/4] dt-bindings: clk: at91: Document all the PMC compatibles
From: Alexandre Belloni @ 2018-06-07  8:41 UTC (permalink / raw)
  To: Nicolas Ferre
  Cc: Rob Herring, devicetree, linux-clk, Stephen Boyd, linux-kernel,
	linux-arm-kernel, Alexandre Belloni
In-Reply-To: <20180607084107.4461-1-alexandre.belloni@bootlin.com>

Add missing PMC compatibles to the list of available compatibles.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 Documentation/devicetree/bindings/clock/at91-clock.txt | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
index 51c259a92d02..a1f591969538 100644
--- a/Documentation/devicetree/bindings/clock/at91-clock.txt
+++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
@@ -17,14 +17,13 @@ Required properties:
 	"atmel,at91sam9x5-clk-slow-rc-osc":
 		at91 internal slow RC oscillator
 
-	"atmel,at91rm9200-pmc" or
-	"atmel,at91sam9g45-pmc" or
-	"atmel,at91sam9n12-pmc" or
-	"atmel,at91sam9x5-pmc" or
-	"atmel,sama5d3-pmc":
+	"atmel,<chip>-pmc":
 		at91 PMC (Power Management Controller)
 		All at91 specific clocks (clocks defined below) must be child
 		node of the PMC node.
+		<chip> can be: at91rm9200, at91sam9260, at91sam9261,
+		at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9x5,
+		sama5d2, sama5d3 or sama5d4.
 
 	"atmel,at91sam9x5-clk-slow" (under sckc node)
 	or
-- 
2.17.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox