Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] nvmem: imx-ocotp: add write support
From: Rob Herring @ 2017-04-03 13:18 UTC (permalink / raw)
  To: Richard Leitner
  Cc: linux-kernel, srinivas.kandagatla, maxime.ripard, mark.rutland,
	devicetree, dev
In-Reply-To: <1490621491-28247-2-git-send-email-richard.leitner@skidata.com>

On Mon, Mar 27, 2017 at 03:31:31PM +0200, Richard Leitner wrote:
> Implement write routine for OCOTP controller found in i.MX6 SoC's.
> Furthermore add locking to the read function to prevent race conditions.
> The write routine code is based on the fsl_otp driver from Freescale.
> 
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
>  .../devicetree/bindings/nvmem/imx-ocotp.txt        |   4 +

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/nvmem/imx-ocotp.c                          | 210 ++++++++++++++++++++-
>  2 files changed, 212 insertions(+), 2 deletions(-)

^ permalink raw reply

* [PATCH net-next] macb: Add hardware PTP support.
From: Rafal Ozieblo @ 2017-04-03 13:10 UTC (permalink / raw)
  To: David Miller, nicolas.ferre, netdev, linux-kernel, devicetree,
	linux-arm-kernel, harinikatakamlinux, harini.katakam,
	richardcochran, Andrei.Pistirica
  Cc: Rafal Ozieblo
In-Reply-To: <20170329.093914.152103359543418375.davem@davemloft.net>

This patch is based on original Harini's patch and Andrei's patch,
implemented in aseparate file to ease the review/maintanance
and integration with other platforms.

In case that macb is compiled as a module, it has been renamed to
cadence-macb.ko to avoid naming confusion in Makefile.

This driver does support GEM-GXL:
- Enable HW time stamp
- Register ptp clock framework
- Initialize PTP related registers
- Updated dma buffer descriptor read/write mechanism
- HW time stamp on the PTP Ethernet packets are received using the
  SO_TIMESTAMPING API. Where timers are obtained from the dma buffer
  descriptors
- Added tsu_clk to device tree

Note: Patch on net-next, on April 3rd.
Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
---
 Documentation/devicetree/bindings/net/macb.txt |   1 +
 drivers/net/ethernet/cadence/Kconfig           |  10 +-
 drivers/net/ethernet/cadence/Makefile          |   7 +-
 drivers/net/ethernet/cadence/macb.c            | 237 ++++++--
 drivers/net/ethernet/cadence/macb.h            | 176 +++++-
 drivers/net/ethernet/cadence/macb_ptp.c        | 724 +++++++++++++++++++++++++
 6 files changed, 1109 insertions(+), 46 deletions(-)
 create mode 100755 drivers/net/ethernet/cadence/macb_ptp.c

diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt
index 1506e94..27966ae 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -22,6 +22,7 @@ Required properties:
 	Required elements: 'pclk', 'hclk'
 	Optional elements: 'tx_clk'
 	Optional elements: 'rx_clk' applies to cdns,zynqmp-gem
+	Optional elements: 'tsu_clk'
 - clocks: Phandles to input clocks.
 
 Optional properties for PHY child node:
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index 608bea1..427d65a 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -29,7 +29,15 @@ config MACB
 	  support for the MACB/GEM chip.
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called macb.
+	  will be macb.
+
+config MACB_USE_HWSTAMP
+	bool "Use IEEE 1588 hwstamp"
+	depends on MACB
+	default y
+	imply PTP_1588_CLOCK
+	---help---
+	  Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
 
 config MACB_PCI
 	tristate "Cadence PCI MACB/GEM support"
diff --git a/drivers/net/ethernet/cadence/Makefile b/drivers/net/ethernet/cadence/Makefile
index 4ba7559..a7f6e04 100644
--- a/drivers/net/ethernet/cadence/Makefile
+++ b/drivers/net/ethernet/cadence/Makefile
@@ -1,6 +1,11 @@
 #
 # Makefile for the Atmel network device drivers.
 #
+cadence-macb-y	:= macb.o
 
-obj-$(CONFIG_MACB) += macb.o
+ifeq ($(CONFIG_MACB_USE_HWSTAMP),y)
+cadence-macb-y	+= macb_ptp.o
+endif
+
+obj-$(CONFIG_MACB) += cadence-macb.o
 obj-$(CONFIG_MACB_PCI) += macb_pci.o
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 30606b1..32af94e 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -79,33 +79,84 @@
 #define MACB_HALT_TIMEOUT	1230
 
 /* DMA buffer descriptor might be different size
- * depends on hardware configuration.
+ * depends on hardware configuration:
+ *
+ * 1. dma address width 32 bits:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *
+ * 2. dma address width 64 bits:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: upper 32 bit address of Data Buffer
+ *    word 4: unused
+ *
+ * 3. dma address width 32 bits with hardware timestamping:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: timestamp word 1
+ *    word 4: timestamp word 2
+ *
+ * 4. dma address width 64 bits with hardware timestamping:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: upper 32 bit address of Data Buffer
+ *    word 4: unused
+ *    word 5: timestamp word 1
+ *    word 6: timestamp word 2
  */
 static unsigned int macb_dma_desc_get_size(struct macb *bp)
 {
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
-		return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
+#ifdef MACB_EXT_DESC
+	unsigned int desc_size;
+
+	switch (bp->hw_dma_cap) {
+	case HW_DMA_CAP_64B:
+		desc_size = sizeof(struct macb_dma_desc)
+			+ sizeof(struct macb_dma_desc_64);
+		break;
+	case HW_DMA_CAP_PTP:
+		desc_size = sizeof(struct macb_dma_desc)
+			+ sizeof(struct macb_dma_desc_ptp);
+		break;
+	case HW_DMA_CAP_64B_PTP:
+		desc_size = sizeof(struct macb_dma_desc)
+			+ sizeof(struct macb_dma_desc_64)
+			+ sizeof(struct macb_dma_desc_ptp);
+		break;
+	default:
+		desc_size = sizeof(struct macb_dma_desc);
+	}
+	return desc_size;
 #endif
 	return sizeof(struct macb_dma_desc);
 }
 
-static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
+static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int desc_idx)
 {
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	/* Dma buffer descriptor is 4 words length (instead of 2 words)
-	 * for 64b GEM.
-	 */
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
-		idx <<= 1;
+#ifdef MACB_EXT_DESC
+	switch (bp->hw_dma_cap) {
+	case HW_DMA_CAP_64B:
+	case HW_DMA_CAP_PTP:
+		desc_idx <<= 1;
+		break;
+	case HW_DMA_CAP_64B_PTP:
+		desc_idx *= 3;
+		break;
+	default:
+		break;
+	}
+	return desc_idx;
 #endif
-	return idx;
+	return desc_idx;
 }
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
 {
-	return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+	if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+		return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+	return NULL;
 }
 #endif
 
@@ -600,7 +651,7 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 	struct macb_dma_desc_64 *desc_64;
 
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+	if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
 		desc_64 = macb_64b_desc(bp, desc);
 		desc_64->addrh = upper_32_bits(addr);
 	}
@@ -614,7 +665,7 @@ static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 	struct macb_dma_desc_64 *desc_64;
 
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+	if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
 		desc_64 = macb_64b_desc(bp, desc);
 		addr = ((u64)(desc_64->addrh) << 32);
 	}
@@ -713,7 +764,7 @@ static void macb_tx_error_task(struct work_struct *work)
 	/* Reinitialize the TX desc queue */
 	queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+	if (bp->hw_dma_cap & HW_DMA_CAP_64B)
 		queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
 	/* Make TX ring reflect state of hardware */
@@ -775,6 +826,16 @@ static void macb_tx_interrupt(struct macb_queue *queue)
 
 			/* First, update TX stats if needed */
 			if (skb) {
+#ifdef CONFIG_MACB_USE_HWSTAMP
+				if (gem_ptp_do_txstamp(queue, skb, desc) == 0) {
+					/* skb now belongs to timestamp buffer
+					 * and will be removed later
+					 */
+					tx_skb->skb = NULL;
+					schedule_work(&queue->tx_ts_task);
+
+				}
+#endif
 				netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
 					    macb_tx_ring_wrap(bp, tail),
 					    skb->data);
@@ -941,6 +1002,10 @@ static int gem_rx(struct macb *bp, int budget)
 		bp->stats.rx_packets++;
 		bp->stats.rx_bytes += skb->len;
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+		gem_ptp_do_rxstamp(bp, skb, desc);
+#endif
+
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
 		netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
 			    skb->len, skb->csum);
@@ -1263,6 +1328,11 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 				queue_writel(queue, ISR, MACB_BIT(HRESP));
 		}
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+		if (status & MACB_PTP_INT_MASK)
+			macb_ptp_int(queue, status);
+#endif
+
 		status = queue_readl(queue, ISR);
 	}
 
@@ -1592,8 +1662,10 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* Make newly initialized descriptor visible to hardware */
 	wmb();
-
-	skb_tx_timestamp(skb);
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	if (!bp->ptp_hw_support)
+#endif
+		skb_tx_timestamp(skb);
 
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
@@ -1921,9 +1993,13 @@ static void macb_configure_dma(struct macb *bp)
 			dmacfg &= ~GEM_BIT(TXCOEN);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+		if (bp->hw_dma_cap & HW_DMA_CAP_64B)
 			dmacfg |= GEM_BIT(ADDR64);
 #endif
+#ifdef CONFIG_MACB_USE_HWSTAMP
+		if (bp->hw_dma_cap & HW_DMA_CAP_PTP)
+			dmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);
+#endif
 		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
 			   dmacfg);
 		gem_writel(bp, DMACFG, dmacfg);
@@ -1971,21 +2047,22 @@ static void macb_init_hw(struct macb *bp)
 	/* Initialize TX and RX buffers */
 	macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+	if (bp->hw_dma_cap & HW_DMA_CAP_64B)
 		macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
 #endif
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 		queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		if (bp->hw_dma_cap == HW_DMA_CAP_64B)
-			queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
+		if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+			queue_writel(queue, TBQPH,
+					upper_32_bits(queue->tx_ring_dma));
 #endif
 
 		/* Enable interrupts */
 		queue_writel(queue, IER,
-			     MACB_RX_INT_FLAGS |
-			     MACB_TX_INT_FLAGS |
-			     MACB_BIT(HRESP));
+				MACB_RX_INT_FLAGS |
+				MACB_TX_INT_FLAGS |
+				MACB_BIT(HRESP));
 	}
 
 	/* Enable TX and RX */
@@ -2446,6 +2523,71 @@ static int macb_set_ringparam(struct net_device *netdev,
 	return 0;
 }
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+static unsigned int gem_get_tsu_rate(struct macb *bp)
+{
+	struct clk *tsu_clk;
+	unsigned int tsu_rate;
+
+	tsu_clk = devm_clk_get(&bp->pdev->dev, "tsu_clk");
+	if (!IS_ERR(tsu_clk))
+		tsu_rate = clk_get_rate(tsu_clk);
+	/* try pclk instead */
+	else if (!IS_ERR(bp->pclk)) {
+		tsu_clk = bp->pclk;
+		tsu_rate = clk_get_rate(tsu_clk);
+	} else
+		return -ENOTSUPP;
+	return tsu_rate;
+}
+
+static s32 gem_get_ptp_max_adj(void)
+{
+	return 64E6;
+}
+
+static int gem_get_ts_info(struct net_device *dev,
+			   struct ethtool_ts_info *info)
+{
+	struct macb *bp = netdev_priv(dev);
+
+	ethtool_op_get_ts_info(dev, info);
+	if (!bp->ptp_hw_support)
+		return 0;
+
+	info->so_timestamping =
+		SOF_TIMESTAMPING_TX_SOFTWARE |
+		SOF_TIMESTAMPING_RX_SOFTWARE |
+		SOF_TIMESTAMPING_SOFTWARE |
+		SOF_TIMESTAMPING_TX_HARDWARE |
+		SOF_TIMESTAMPING_RX_HARDWARE |
+		SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->tx_types =
+		(1 << HWTSTAMP_TX_ONESTEP_SYNC) |
+		(1 << HWTSTAMP_TX_OFF) |
+		(1 << HWTSTAMP_TX_ON);
+	info->rx_filters =
+		(1 << HWTSTAMP_FILTER_NONE) |
+		(1 << HWTSTAMP_FILTER_ALL);
+	info->phc_index = -1;
+
+	if (bp->ptp_clock)
+		info->phc_index = ptp_clock_index(bp->ptp_clock);
+
+	return 0;
+}
+
+static struct macb_ptp_info gem_ptp_info = {
+	.ptp_init	 = gem_ptp_init,
+	.ptp_remove	 = gem_ptp_remove,
+	.get_ptp_max_adj = gem_get_ptp_max_adj,
+	.get_tsu_rate	 = gem_get_tsu_rate,
+	.get_ts_info	 = gem_get_ts_info,
+	.get_hwtst	 = gem_get_hwtst,
+	.set_hwtst	 = gem_set_hwtst,
+};
+#endif
+
 static int macb_get_ts_info(struct net_device *netdev,
 			    struct ethtool_ts_info *info)
 {
@@ -2579,6 +2721,18 @@ static void macb_configure_caps(struct macb *bp,
 		dcfg = gem_readl(bp, DCFG2);
 		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
 			bp->caps |= MACB_CAPS_FIFO_MODE;
+		/* if HWSTAMP is configure and gem has the capability */
+#ifdef CONFIG_MACB_USE_HWSTAMP
+		bp->ptp_hw_support = false;
+		if (gem_has_ptp(bp)) {
+			if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
+				pr_err("GEM doesn't support hardware ptp.\n");
+			else {
+				bp->ptp_hw_support = true;
+				bp->ptp_info = &gem_ptp_info;
+			}
+		}
+#endif
 	}
 
 	dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps);
@@ -2716,7 +2870,7 @@ static int macb_init(struct platform_device *pdev)
 			queue->IMR  = GEM_IMR(hw_q - 1);
 			queue->TBQP = GEM_TBQP(hw_q - 1);
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-			if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+			if (bp->hw_dma_cap & HW_DMA_CAP_64B)
 				queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
 		} else {
@@ -2727,7 +2881,7 @@ static int macb_init(struct platform_device *pdev)
 			queue->IMR  = MACB_IMR;
 			queue->TBQP = MACB_TBQP;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-			if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+			if (bp->hw_dma_cap & HW_DMA_CAP_64B)
 				queue->TBQPH = MACB_TBQPH;
 #endif
 		}
@@ -3184,7 +3338,9 @@ static const struct macb_config np4_config = {
 };
 
 static const struct macb_config zynqmp_config = {
-	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+			MACB_CAPS_JUMBO |
+			MACB_CAPS_GEM_HAS_PTP,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
@@ -3218,7 +3374,9 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids);
 #endif /* CONFIG_OF */
 
 static const struct macb_config default_gem_config = {
-	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+			MACB_CAPS_JUMBO |
+			MACB_CAPS_GEM_HAS_PTP,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
@@ -3307,19 +3465,24 @@ static int macb_probe(struct platform_device *pdev)
 		bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
 	device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
-		dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
-		bp->hw_dma_cap = HW_DMA_CAP_64B;
-	} else
-		bp->hw_dma_cap = HW_DMA_CAP_32B;
-#endif
-
 	spin_lock_init(&bp->lock);
 
 	/* setup capabilities */
 	macb_configure_caps(bp, macb_config);
 
+#ifdef MACB_EXT_DESC
+	bp->hw_dma_cap = HW_DMA_CAP_32B;
+#endif
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
+		dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+		bp->hw_dma_cap |= HW_DMA_CAP_64B;
+	}
+#endif
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	if (bp->ptp_hw_support)
+		bp->hw_dma_cap |= HW_DMA_CAP_PTP;
+#endif
 	platform_set_drvdata(pdev, dev);
 
 	dev->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 234a49e..07a1e8e 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -11,6 +11,13 @@
 #define _MACB_H
 
 #include <linux/phy.h>
+#include <linux/ptp_clock.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/net_tstamp.h>
+
+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
+#define MACB_EXT_DESC
+#endif
 
 #define MACB_GREGS_NBR 16
 #define MACB_GREGS_VERSION 2
@@ -86,6 +93,10 @@
 #define GEM_SA3T		0x009C /* Specific3 Top */
 #define GEM_SA4B		0x00A0 /* Specific4 Bottom */
 #define GEM_SA4T		0x00A4 /* Specific4 Top */
+#define GEM_EFTSH		0x00e8 /* PTP Event Frame Transmitted Seconds Register 47:32 */
+#define GEM_EFRSH		0x00ec /* PTP Event Frame Received Seconds Register 47:32 */
+#define GEM_PEFTSH		0x00f0 /* PTP Peer Event Frame Transmitted Seconds Register 47:32 */
+#define GEM_PEFRSH		0x00f4 /* PTP Peer Event Frame Received Seconds Register 47:32 */
 #define GEM_OTX			0x0100 /* Octets transmitted */
 #define GEM_OCTTXL		0x0100 /* Octets transmitted [31:0] */
 #define GEM_OCTTXH		0x0104 /* Octets transmitted [47:32] */
@@ -155,6 +166,9 @@
 #define GEM_DCFG6		0x0294 /* Design Config 6 */
 #define GEM_DCFG7		0x0298 /* Design Config 7 */
 
+#define GEM_TXBDCTRL	0x04cc /* TX Buffer Descriptor control register */
+#define GEM_RXBDCTRL	0x04d0 /* RX Buffer Descriptor control register */
+
 #define GEM_ISR(hw_q)		(0x0400 + ((hw_q) << 2))
 #define GEM_TBQP(hw_q)		(0x0440 + ((hw_q) << 2))
 #define GEM_TBQPH(hw_q)		(0x04C8)
@@ -191,6 +205,8 @@
 #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
 #define MACB_TZQ_SIZE		1
 #define MACB_SRTSM_OFFSET	15
+#define MACB_OSSMODE_OFFSET 24 /* Enable One Step Synchro Mode */
+#define MACB_OSSMODE_SIZE	1
 
 /* Bitfields in NCFGR */
 #define MACB_SPD_OFFSET		0 /* Speed */
@@ -269,6 +285,10 @@
 #define GEM_RXBS_SIZE		8
 #define GEM_DDRP_OFFSET		24 /* disc_when_no_ahb */
 #define GEM_DDRP_SIZE		1
+#define GEM_RXEXT_OFFSET	28 /* RX extended Buffer Descriptor mode */
+#define GEM_RXEXT_SIZE		1
+#define GEM_TXEXT_OFFSET	29 /* TX extended Buffer Descriptor mode */
+#define GEM_TXEXT_SIZE		1
 #define GEM_ADDR64_OFFSET	30 /* Address bus width - 64b or 32b */
 #define GEM_ADDR64_SIZE		1
 
@@ -354,6 +374,16 @@
 #define MACB_PDRSFT_SIZE	1
 #define MACB_SRI_OFFSET		26 /* TSU Seconds Register Increment */
 #define MACB_SRI_SIZE		1
+#define MACB_TCI_OFFSET		29 /* TSU timer comparison interrupt */
+#define MACB_TCI_SIZE		1
+#define MACB_PTP_INT_MASK	(MACB_BIT(DRQFR) \
+							| MACB_BIT(SFR) \
+							| MACB_BIT(DRQFT) \
+							| MACB_BIT(SFT) \
+							| MACB_BIT(PDRQFR) \
+							| MACB_BIT(PDRSFR) \
+							| MACB_BIT(PDRQFT) \
+							| MACB_BIT(PDRSFT))
 
 /* Timer increment fields */
 #define MACB_TI_CNS_OFFSET	0
@@ -425,6 +455,11 @@
 #define GEM_TX_PKT_BUFF_OFFSET			21
 #define GEM_TX_PKT_BUFF_SIZE			1
 
+
+/* Bitfields in DCFG5. */
+#define GEM_TSU_OFFSET				8
+#define GEM_TSU_SIZE				1
+
 /* Bitfields in DCFG6. */
 #define GEM_PBUF_LSO_OFFSET			27
 #define GEM_PBUF_LSO_SIZE			1
@@ -439,6 +474,52 @@
 #define GEM_NSINCR_OFFSET			0
 #define GEM_NSINCR_SIZE				8
 
+/* Bitfields in TSH */
+#define GEM_TSH_OFFSET				0 /* TSU timer value (s). MSB [47:32] of seconds timer count */
+#define GEM_TSH_SIZE				16
+
+/* Bitfields in TSL */
+#define GEM_TSL_OFFSET				0 /* TSU timer value (s). LSB [31:0] of seconds timer count */
+#define GEM_TSL_SIZE				32
+
+/* Bitfields in TN */
+#define GEM_TN_OFFSET				0 /* TSU timer value (ns) */
+#define GEM_TN_SIZE					30
+
+/* Bitfields in TXBDCTRL */
+#define GEM_TXTSMODE_OFFSET			4 /* TX Descriptor Timestamp Insertion mode */
+#define GEM_TXTSMODE_SIZE			2
+
+/* Bitfields in RXBDCTRL */
+#define GEM_RXTSMODE_OFFSET			4 /* RX Descriptor Timestamp Insertion mode */
+#define GEM_RXTSMODE_SIZE			2
+
+/* Transmit DMA buffer descriptor Word 1 */
+#define GEM_DMA_TXVALID_OFFSET		23 /* timestamp has been captured in the Buffer Descriptor */
+#define GEM_DMA_TXVALID_SIZE		1
+
+/* Receive DMA buffer descriptor Word 0 */
+#define GEM_DMA_RXVALID_OFFSET		2 /* indicates a valid timestamp in the Buffer Descriptor */
+#define GEM_DMA_RXVALID_SIZE		1
+
+/* DMA buffer descriptor Word 2 (32 bit addressing) or Word 4 (64 bit addressing) */
+#define GEM_DMA_SECL_OFFSET			30 /* Timestamp seconds[1:0]  */
+#define GEM_DMA_SECL_SIZE			2
+#define GEM_DMA_NSEC_OFFSET			0 /* Timestamp nanosecs [29:0] */
+#define GEM_DMA_NSEC_SIZE			30
+
+/* DMA buffer descriptor Word 3 (32 bit addressing) or Word 5 (64 bit addressing) */
+
+/* New hardware supports 12 bit precision of timestamp in DMA buffer descriptor.
+ * Old hardware supports only 6 bit precision but it is enough for PTP.
+ * Less accuracy is used always instead of checking hardware version.
+ */
+#define GEM_DMA_SECH_OFFSET			0 /* Timestamp seconds[5:2] */
+#define GEM_DMA_SECH_SIZE			4
+#define GEM_DMA_SEC_WIDTH			(GEM_DMA_SECH_SIZE + GEM_DMA_SECL_SIZE)
+#define GEM_DMA_SEC_TOP				(1 << GEM_DMA_SEC_WIDTH)
+#define GEM_DMA_SEC_MASK			(GEM_DMA_SEC_TOP - 1)
+
 /* Bitfields in ADJ */
 #define GEM_ADDSUB_OFFSET			31
 #define GEM_ADDSUB_SIZE				1
@@ -514,6 +595,8 @@
 #define queue_readl(queue, reg)		(queue)->bp->macb_reg_readl((queue)->bp, (queue)->reg)
 #define queue_writel(queue, reg, value)	(queue)->bp->macb_reg_writel((queue)->bp, (queue)->reg, (value))
 
+#define PTP_TS_BUFFER_SIZE		128 /* must be power of 2 */
+
 /* Conditional GEM/MACB macros.  These perform the operation to the correct
  * register dependent on whether the device is a GEM or a MACB.  For registers
  * and bitfields that are common across both devices, use macb_{read,write}l
@@ -546,16 +629,21 @@ struct macb_dma_desc {
 	u32	ctrl;
 };
 
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-enum macb_hw_dma_cap {
-	HW_DMA_CAP_32B,
-	HW_DMA_CAP_64B,
-};
+#ifdef MACB_EXT_DESC
+#define HW_DMA_CAP_32B		0
+#define HW_DMA_CAP_64B		(1 << 0)
+#define HW_DMA_CAP_PTP		(1 << 1)
+#define HW_DMA_CAP_64B_PTP	(HW_DMA_CAP_64B | HW_DMA_CAP_PTP)
 
 struct macb_dma_desc_64 {
 	u32 addrh;
 	u32 resvd;
 };
+
+struct macb_dma_desc_ptp {
+	u32	ts_1;
+	u32	ts_2;
+};
 #endif
 
 /* DMA descriptor bitfields */
@@ -871,6 +959,18 @@ struct macb_config {
 	int	jumbo_max_len;
 };
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+struct tsu_incr {
+	u32 sub_ns;
+	u32 ns;
+};
+
+struct gem_tx_ts {
+	struct sk_buff *skb;
+	struct macb_dma_desc_ptp desc_ptp;
+};
+#endif
+
 struct macb_queue {
 	struct macb		*bp;
 	int			irq;
@@ -887,6 +987,12 @@ struct macb_queue {
 	struct macb_tx_skb	*tx_skb;
 	dma_addr_t		tx_ring_dma;
 	struct work_struct	tx_error_task;
+
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	struct work_struct	tx_ts_task;
+	unsigned int		tx_ts_head, tx_ts_tail;
+	struct gem_tx_ts	tx_timestamps[PTP_TS_BUFFER_SIZE];
+#endif
 };
 
 struct macb {
@@ -955,11 +1061,67 @@ struct macb {
 	u32			wol;
 
 	struct macb_ptp_info	*ptp_info;	/* macb-ptp interface */
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	enum macb_hw_dma_cap hw_dma_cap;
+#ifdef MACB_EXT_DESC
+	uint8_t hw_dma_cap;
+#endif
+
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	bool ptp_hw_support;
+	spinlock_t tsu_clk_lock; /* gem tsu clock locking */
+	unsigned int tsu_rate;
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_clock_info;
+	struct tsu_incr tsu_incr;
+	struct hwtstamp_config tstamp_config;
 #endif
 };
 
+#ifdef CONFIG_MACB_USE_HWSTAMP
+#define GEM_TSEC_SIZE  (GEM_TSH_SIZE + GEM_TSL_SIZE)
+#define TSU_SEC_MAX_VAL (((u64)1 << GEM_TSEC_SIZE) - 1)
+#define TSU_NSEC_MAX_VAL ((1 << GEM_TN_SIZE) - 1)
+
+enum macb_bd_control {
+	TSTAMP_DISABLED,
+	TSTAMP_FRAME_PTP_EVENT_ONLY,
+	TSTAMP_ALL_PTP_FRAMES,
+	TSTAMP_ALL_FRAMES,
+};
+
+void gem_ptp_init(struct net_device *ndev);
+void gem_ptp_remove(struct net_device *ndev);
+int gem_ptp_txstamp(struct macb_queue *queue, struct sk_buff *skb, struct macb_dma_desc *des);
+void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc);
+void macb_ptp_int(struct macb_queue *queue, u32 status);
+static inline int gem_ptp_do_txstamp(struct macb_queue *queue, struct sk_buff *skb, struct macb_dma_desc *desc)
+{
+	if (queue->bp->tstamp_config.tx_type == TSTAMP_DISABLED)
+		return -ENOTSUPP;
+
+	return gem_ptp_txstamp(queue, skb, desc);
+}
+
+static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc)
+{
+	if (bp->tstamp_config.rx_filter == TSTAMP_DISABLED)
+		return;
+
+	gem_ptp_rxstamp(bp, skb, desc);
+}
+int gem_get_hwtst(struct net_device *dev, struct ifreq *rq);
+int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd);
+#else
+static inline void gem_ptp_init(struct net_device *ndev) { }
+static inline void gem_ptp_remove(struct net_device *ndev) { }
+
+static inline int gem_ptp_do_txstamp(struct macb_queue *queue, struct sk_buff *skb, struct macb_dma_desc *desc)
+{
+	return 0;
+}
+
+static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc) { }
+#endif
+
 static inline bool macb_is_gem(struct macb *bp)
 {
 	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
new file mode 100755
index 0000000..72a79c4
--- /dev/null
+++ b/drivers/net/ethernet/cadence/macb_ptp.c
@@ -0,0 +1,724 @@
+/**
+ * 1588 PTP support for Cadence GEM device.
+ *
+ * Copyright (C) 2017 Cadence Design Systems - http://www.cadence.com
+ *
+ * Authors: Rafal Ozieblo <rafalo@cadence.com>
+ *          Bartosz Folta <bfolta@cadence.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/time64.h>
+#include <linux/ptp_classify.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
+#include <linux/circ_buf.h>
+#include <linux/spinlock.h>
+
+#include "macb.h"
+
+#define  GEM_PTP_TIMER_NAME "gem-ptp-timer"
+
+static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,
+		struct macb_dma_desc *desc)
+{
+	if (bp->hw_dma_cap == HW_DMA_CAP_PTP)
+		return (struct macb_dma_desc_ptp *)
+				((u8 *)desc + sizeof(struct macb_dma_desc));
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B_PTP)
+		return (struct macb_dma_desc_ptp *)
+				((u8 *)desc + sizeof(struct macb_dma_desc)
+				+ sizeof(struct macb_dma_desc_64));
+	return NULL;
+}
+
+static int gem_tsu_get_time(struct macb *bp, struct timespec64 *ts)
+{
+	long first, second;
+	u32 secl, sech;
+	unsigned long flags;
+
+	if (!bp || !ts)
+		return -EINVAL;
+
+	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
+	first = gem_readl(bp, TN);
+	secl = gem_readl(bp, TSL);
+	sech = gem_readl(bp, TSH);
+	second = gem_readl(bp, TN);
+
+	/* test for nsec rollover */
+	if (first > second) {
+		/* if so, use later read & re-read seconds
+		 * (assume all done within 1s)
+		 */
+		ts->tv_nsec = gem_readl(bp, TN);
+		secl = gem_readl(bp, TSL);
+		sech = gem_readl(bp, TSH);
+	} else
+		ts->tv_nsec = first;
+
+	ts->tv_sec = (((u64)sech << GEM_TSL_SIZE) | secl)
+			& TSU_SEC_MAX_VAL;
+
+	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
+	return 0;
+}
+
+static int gem_tsu_set_time(struct macb *bp, const struct timespec64 *ts)
+{
+	u32 ns, sech, secl;
+	unsigned long flags;
+
+	if (!bp || !ts)
+		return -EINVAL;
+
+	secl = (u32)ts->tv_sec;
+	sech = (ts->tv_sec >> GEM_TSL_SIZE) & ((1 << GEM_TSH_SIZE) - 1);
+	ns = ts->tv_nsec;
+
+	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
+
+	/* TSH doesn't latch the time and no atomicity! */
+	gem_writel(bp, TN, 0); /* clear to avoid overflow */
+	gem_writel(bp, TSH, sech);
+	/* write lower bits 2nd, for synchronized secs update */
+	gem_writel(bp, TSL, secl);
+	gem_writel(bp, TN, ns);
+
+	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
+
+	return 0;
+}
+
+static int gem_tsu_incr_set(struct macb *bp, struct tsu_incr *incr_spec)
+{
+	unsigned long flags;
+
+	if (!bp || !incr_spec)
+		return -EINVAL;
+
+	/* tsu_timer_incr register must be written after
+	 * the tsu_timer_incr_sub_ns register and the write operation
+	 * will cause the value written to the tsu_timer_incr_sub_ns register
+	 * to take effect.
+	 */
+	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
+	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, incr_spec->sub_ns));
+	gem_writel(bp, TI, GEM_BF(NSINCR, incr_spec->ns));
+	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
+
+	return 0;
+}
+
+static int gem_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct tsu_incr incr_spec;
+	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
+	u64 adj;
+	u32 word;
+	bool neg_adj = false;
+
+	if (!ptp)
+		return -EINVAL;
+
+	if (scaled_ppm < 0) {
+		neg_adj = true;
+		scaled_ppm = -scaled_ppm;
+	}
+
+	/* Adjustment is relative to base frequency */
+	incr_spec.sub_ns = bp->tsu_incr.sub_ns;
+	incr_spec.ns = bp->tsu_incr.ns;
+
+	/* scaling: unused(8bit) | ns(8bit) | fractions(16bit) */
+	word = ((u64)incr_spec.ns << GEM_SUBNSINCR_SIZE) + incr_spec.sub_ns;
+	adj = (u64)scaled_ppm * word;
+	/* Divide with rounding, equivalent to floating dividing:
+	 * (temp / USEC_PER_SEC) + 0.5
+	 */
+	adj += (USEC_PER_SEC >> 1);
+	adj >>= GEM_SUBNSINCR_SIZE; /* remove fractions */
+	adj = div_u64(adj, USEC_PER_SEC);
+	adj = neg_adj ? (word - adj) : (word + adj);
+
+	incr_spec.ns = (adj >> GEM_SUBNSINCR_SIZE)
+			& ((1 << GEM_NSINCR_SIZE) - 1);
+	incr_spec.sub_ns = adj & ((1 << GEM_SUBNSINCR_SIZE) - 1);
+	gem_tsu_incr_set(bp, &incr_spec);
+	return 0;
+}
+
+static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct timespec64 now, then = ns_to_timespec64(delta);
+	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
+	u32 adj, sign = 0;
+
+	if (!ptp)
+		return -EINVAL;
+
+	if (delta < 0) {
+		sign = 1;
+		delta = -delta;
+	}
+
+	if (delta > TSU_NSEC_MAX_VAL) {
+		gem_tsu_get_time(bp, &now);
+		if (sign)
+			now = timespec64_sub(now, then);
+		else
+			now = timespec64_add(now, then);
+
+		gem_tsu_set_time(bp, (const struct timespec64 *)&now);
+	} else {
+		adj = (sign << GEM_ADDSUB_OFFSET) | delta;
+
+		gem_writel(bp, TA, adj);
+	}
+
+	return 0;
+}
+
+static int gem_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
+
+	if (!ptp || !ts)
+		return -EINVAL;
+
+	gem_tsu_get_time(bp, ts);
+	return 0;
+}
+
+static int gem_ptp_settime(struct ptp_clock_info *ptp,
+		const struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
+
+	if (!ptp || !ts)
+		return -EINVAL;
+
+	gem_tsu_set_time(bp, ts);
+	return 0;
+}
+
+static int gem_ptp_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	struct macb *bp = container_of(ptp, struct macb, ptp_clock_info);
+
+	if (!ptp || !rq)
+		return -EINVAL;
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_EXTTS:	/* Toggle TSU match interrupt */
+		if (on)
+			macb_writel(bp, IER, MACB_BIT(TCI));
+		else
+			macb_writel(bp, IDR, MACB_BIT(TCI));
+		break;
+	case PTP_CLK_REQ_PEROUT: /* Toggle Periodic output */
+		return -EOPNOTSUPP;
+		/* break; */
+	case PTP_CLK_REQ_PPS:	/* Toggle TSU periodic (second) interrupt */
+		if (on)
+			macb_writel(bp, IER, MACB_BIT(SRI));
+		else
+			macb_writel(bp, IDR, MACB_BIT(SRI));
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static struct ptp_clock_info gem_ptp_caps_template = {
+	.owner		= THIS_MODULE,
+	.name		= GEM_PTP_TIMER_NAME,
+	.max_adj	= 0,
+	.n_alarm	= 1,
+	.n_ext_ts	= 1,
+	.n_per_out	= 0,
+	.n_pins		= 0,
+	.pps		= 1,
+	.adjfine	= gem_ptp_adjfine,
+	.adjtime	= gem_ptp_adjtime,
+	.gettime64	= gem_ptp_gettime,
+	.settime64	= gem_ptp_settime,
+	.enable		= gem_ptp_enable,
+};
+
+static void gem_ptp_init_timer(struct macb *bp)
+{
+	u32 rem = 0;
+
+	bp->tsu_incr.ns = div_u64_rem(NSEC_PER_SEC, bp->tsu_rate, &rem);
+	if (rem) {
+		u64 adj = rem;
+
+		adj <<= GEM_SUBNSINCR_SIZE;
+		bp->tsu_incr.sub_ns = div_u64(adj, bp->tsu_rate);
+	} else {
+		bp->tsu_incr.sub_ns = 0;
+	}
+}
+
+static void gem_ptp_init_tsu(struct macb *bp)
+{
+	struct timespec64 ts;
+
+	/* 1. get current system time */
+	ts = ns_to_timespec64(ktime_to_ns(ktime_get_real()));
+
+	/* 2. set ptp timer */
+	gem_tsu_set_time(bp, &ts);
+
+	/* 3. set PTP timer increment value to BASE_INCREMENT */
+	gem_tsu_incr_set(bp, &bp->tsu_incr);
+
+	gem_writel(bp, TA, 0);
+}
+
+static void gem_ptp_clear_timer(struct macb *bp)
+{
+	bp->tsu_incr.ns = 0;
+	bp->tsu_incr.sub_ns = 0;
+
+	gem_writel(bp, TISUBN, GEM_BF(SUBNSINCR, 0));
+	gem_writel(bp, TI, GEM_BF(NSINCR, 0));
+	gem_writel(bp, TA, 0);
+}
+
+static int gem_hw_timestamp(struct macb *bp,
+		u32 dma_desc_ts_1, u32 dma_desc_ts_2, struct timespec64 *ts)
+{
+	struct timespec64 tsu;
+
+	ts->tv_sec = (GEM_BFEXT(DMA_SECH, dma_desc_ts_2) << GEM_DMA_SECL_SIZE) |
+			GEM_BFEXT(DMA_SECL, dma_desc_ts_1);
+	ts->tv_nsec = GEM_BFEXT(DMA_NSEC, dma_desc_ts_1);
+
+	/* TSU overlaping workaround
+	 * The timestamp only contains lower few bits of seconds,
+	 * so add value from 1588 timer
+	 */
+	gem_tsu_get_time(bp, &tsu);
+
+	/* If the top bit is set in the timestamp,
+	 * but not in 1588 timer, it has rolled over,
+	 * so subtract max size
+	 */
+	if ((ts->tv_sec & (GEM_DMA_SEC_TOP >> 1)) &&
+		!(tsu.tv_sec & (GEM_DMA_SEC_TOP >> 1)))
+		ts->tv_sec -= GEM_DMA_SEC_TOP;
+
+	ts->tv_sec += ((~GEM_DMA_SEC_MASK) & (tsu.tv_sec));
+
+	return 0;
+}
+
+void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb,
+		struct macb_dma_desc *desc)
+{
+	struct timespec64 ts;
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+	struct macb_dma_desc_ptp *desc_ptp;
+
+	if (GEM_BFEXT(DMA_RXVALID, desc->addr)) {
+		desc_ptp = macb_ptp_desc(bp, desc);
+		gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
+		memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+		shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+	}
+}
+
+static void gem_tstamp_tx(struct macb *bp, struct sk_buff *skb,
+		struct macb_dma_desc_ptp *desc_ptp)
+{
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct timespec64 ts;
+
+	gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
+	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+	shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+	skb_tstamp_tx(skb, &shhwtstamps);
+}
+
+int gem_ptp_txstamp(struct macb_queue *queue, struct sk_buff *skb,
+		struct macb_dma_desc *desc)
+{
+	struct gem_tx_ts *tx_timestamp;
+	struct macb_dma_desc_ptp *desc_ptp;
+	unsigned long head = queue->tx_ts_head;
+	unsigned long tail = READ_ONCE(queue->tx_ts_tail);
+
+	if (!GEM_BFEXT(DMA_TXVALID, desc->ctrl))
+		return -EINVAL;
+
+	if (CIRC_SPACE(head, tail, PTP_TS_BUFFER_SIZE) == 0)
+		return -ENOMEM;
+
+	desc_ptp = macb_ptp_desc(queue->bp, desc);
+	tx_timestamp = &queue->tx_timestamps[head];
+	tx_timestamp->skb = skb;
+	tx_timestamp->desc_ptp.ts_1 = desc_ptp->ts_1;
+	tx_timestamp->desc_ptp.ts_2 = desc_ptp->ts_2;
+	/* move head */
+	smp_store_release(&queue->tx_ts_head,
+			(head + 1) & (PTP_TS_BUFFER_SIZE - 1));
+	return 0;
+}
+
+static void gem_tx_timestamp_flush(struct work_struct *work)
+{
+	struct macb_queue *queue =
+			container_of(work, struct macb_queue, tx_ts_task);
+	struct gem_tx_ts *tx_ts;
+	unsigned long head, tail;
+
+	/* take current head */
+	head = smp_load_acquire(&queue->tx_ts_head);
+	tail = queue->tx_ts_tail;
+
+	while (CIRC_CNT(head, tail, PTP_TS_BUFFER_SIZE)) {
+		tx_ts = &queue->tx_timestamps[tail];
+		gem_tstamp_tx(queue->bp, tx_ts->skb, &tx_ts->desc_ptp);
+		/* cleanup */
+		dev_kfree_skb_any(tx_ts->skb);
+		/* remove old tail */
+		smp_store_release(&queue->tx_ts_tail,
+				(tail + 1) & (PTP_TS_BUFFER_SIZE - 1));
+		tail = queue->tx_ts_tail;
+	}
+}
+
+void gem_ptp_init(struct net_device *dev)
+{
+	struct macb *bp = netdev_priv(dev);
+	unsigned int q;
+	struct macb_queue *queue;
+
+	bp->ptp_clock_info = gem_ptp_caps_template;
+
+	/* nominal frequency and maximum adjustment in ppb */
+	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
+	bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
+	gem_ptp_init_timer(bp);
+	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &dev->dev);
+	if (IS_ERR(&bp->ptp_clock)) {
+		bp->ptp_clock = NULL;
+		pr_err("ptp clock register failed\n");
+		return;
+	}
+
+	spin_lock_init(&bp->tsu_clk_lock);
+	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+		queue->tx_ts_head = 0;
+		queue->tx_ts_tail = 0;
+		INIT_WORK(&queue->tx_ts_task, gem_tx_timestamp_flush);
+		queue_writel(queue, IER, MACB_PTP_INT_MASK);
+	}
+
+	gem_ptp_init_tsu(bp);
+
+	dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
+		 GEM_PTP_TIMER_NAME);
+}
+
+void gem_ptp_remove(struct net_device *ndev)
+{
+	struct macb *bp = netdev_priv(ndev);
+
+	if (bp->ptp_clock)
+		ptp_clock_unregister(bp->ptp_clock);
+
+	gem_ptp_clear_timer(bp);
+
+	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
+		 GEM_PTP_TIMER_NAME);
+}
+
+static int gem_ptp_set_ts_mode(struct macb *bp,
+			     enum macb_bd_control tx_bd_control,
+			     enum macb_bd_control rx_bd_control)
+{
+	if (!bp)
+		return -EINVAL;
+
+	gem_writel(bp, TXBDCTRL, GEM_BF(TXTSMODE, tx_bd_control));
+	gem_writel(bp, RXBDCTRL, GEM_BF(RXTSMODE, rx_bd_control));
+
+	return 0;
+}
+
+int gem_get_hwtst(struct net_device *dev, struct ifreq *rq)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct hwtstamp_config *tstamp_config = &bp->tstamp_config;
+
+	if (!bp->ptp_hw_support)
+		return -EFAULT;
+
+	if (copy_to_user(rq->ifr_data, tstamp_config, sizeof(*tstamp_config)))
+		return -EFAULT;
+	else
+		return 0;
+}
+
+static int gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
+{
+	u32 reg_val;
+
+	if (!bp || enable > 1)
+		return -EINVAL;
+
+	reg_val = macb_readl(bp, NCR);
+
+	if (enable)
+		macb_writel(bp, NCR, reg_val | MACB_BIT(OSSMODE));
+	else
+		macb_writel(bp, NCR, reg_val & ~MACB_BIT(OSSMODE));
+
+	return 0;
+}
+
+int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct hwtstamp_config *tstamp_config = &bp->tstamp_config;
+	enum macb_bd_control tx_bd_control = TSTAMP_DISABLED;
+	enum macb_bd_control rx_bd_control = TSTAMP_DISABLED;
+	u32 regval;
+
+	if (!bp->ptp_hw_support)
+		return -EFAULT;
+
+	if (copy_from_user(tstamp_config, ifr->ifr_data,
+			sizeof(*tstamp_config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (tstamp_config->flags)
+		return -EINVAL;
+
+	switch (tstamp_config->tx_type) {
+	case HWTSTAMP_TX_OFF:
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		if (gem_ptp_set_one_step_sync(bp, 1) != 0)
+			return -ERANGE;
+	case HWTSTAMP_TX_ON:
+		tx_bd_control = TSTAMP_ALL_FRAMES;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (tstamp_config->rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		rx_bd_control =  TSTAMP_ALL_PTP_FRAMES;
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		regval = macb_readl(bp, NCR);
+		macb_writel(bp, NCR, (regval | MACB_BIT(SRTSM)));
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+		rx_bd_control = TSTAMP_ALL_FRAMES;
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_NONE;
+		return -ERANGE;
+	}
+
+	if (gem_ptp_set_ts_mode(bp, tx_bd_control, rx_bd_control) != 0)
+		return -ERANGE;
+
+	if (copy_to_user(ifr->ifr_data, tstamp_config, sizeof(*tstamp_config)))
+		return -EFAULT;
+	else
+		return 0;
+}
+
+static int gem_ptp_time_peer_frame_tx_get(struct macb *bp,
+		struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)gem_readl(bp, PEFTSH) << 32) |
+		gem_readl(bp, PEFTSL)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = gem_readl(bp, PEFTN);
+
+	return 0;
+}
+
+static int gem_ptp_time_peer_frame_rx_get(struct macb *bp,
+		struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)gem_readl(bp, PEFRSH) << 32) |
+		gem_readl(bp, PEFRSL)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = gem_readl(bp, PEFRN);
+
+	return 0;
+}
+
+static int gem_ptp_time_frame_tx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)gem_readl(bp, EFTSH) << 32) |
+		gem_readl(bp, EFTSL)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = gem_readl(bp, EFTN);
+
+	return 0;
+}
+
+static int gem_ptp_time_frame_rx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)gem_readl(bp, EFRSH) << 32) |
+		      gem_readl(bp, EFRSL)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = gem_readl(bp, EFRN);
+
+	return 0;
+}
+
+static int gem_ptp_event(struct macb *bp, struct timespec64 *ts)
+{
+	struct ptp_clock_event event;
+
+	event.type = PTP_CLOCK_EXTTS;
+	event.index = 0;
+	event.timestamp = ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
+
+	ptp_clock_event(bp->ptp_clock, &event);
+
+	return 0;
+}
+
+void macb_ptp_int(struct macb_queue *queue, u32 status)
+{
+	struct macb *bp = queue->bp;
+	struct timespec64 ts;
+
+	if (status & MACB_BIT(DRQFR)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(DRQFR));
+		if (gem_ptp_time_frame_rx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(SFR)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(SFR));
+		if (gem_ptp_time_frame_rx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(DRQFT)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(DRQFT));
+		if (gem_ptp_time_frame_tx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(SFT)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(SFT));
+		if (gem_ptp_time_frame_tx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(PDRQFR)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(PDRQFR));
+		if (gem_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(PDRSFR)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR, MACB_BIT(PDRSFR));
+		if (gem_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(PDRQFT)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR,
+					MACB_BIT(PDRQFT));
+		if (gem_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+
+	if (status & MACB_BIT(PDRSFT)) {
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			queue_writel(queue, ISR,
+					MACB_BIT(PDRSFT));
+		if (gem_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+		}
+		gem_ptp_event(bp, &ts);
+	}
+}
-- 
2.4.5

^ permalink raw reply related

* Re: [PATCH v3 01/20] net: stmmac: export stmmac_set_mac_addr/stmmac_get_mac_addr
From: Giuseppe CAVALLARO @ 2017-04-03 12:39 UTC (permalink / raw)
  To: Corentin Labbe, robh+dt, mark.rutland, maxime.ripard, wens, linux,
	catalin.marinas, will.deacon, alexandre.torgue
  Cc: devicetree, linux-kernel, linux-arm-kernel, netdev
In-Reply-To: <20170403091444.29876-2-clabbe.montjoie@gmail.com>

Hello Alex

do you can check if this has to be done for ST platforms?
I do not remember that it was necessary when build as module so
I cannot expect this should be only for dwmac-sun8i.

Regards
peppe



On 4/3/2017 11:14 AM, Corentin Labbe wrote:
> Thoses symbol will be needed for the dwmac-sun8i ethernet driver.
> For letting it to be build as module, they need to be exported.
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> ---
>   drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> index 38f9430..67af0bd 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
> @@ -248,6 +248,7 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
>   	data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
>   	writel(data, ioaddr + low);
>   }
> +EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
>   
>   /* Enable disable MAC RX/TX */
>   void stmmac_set_mac(void __iomem *ioaddr, bool enable)
> @@ -279,4 +280,4 @@ void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
>   	addr[4] = hi_addr & 0xff;
>   	addr[5] = (hi_addr >> 8) & 0xff;
>   }
> -
> +EXPORT_SYMBOL_GPL(stmmac_get_mac_addr);

^ permalink raw reply

* Re: [PATCH v3 02/20] net: stmmac: add optional setup function
From: Giuseppe CAVALLARO @ 2017-04-03 12:32 UTC (permalink / raw)
  To: Corentin Labbe, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, alexandre.torgue-qxv4g6HH51o
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170403091444.29876-3-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Hello Corentin

On 4/3/2017 11:14 AM, Corentin Labbe wrote:
> Instead of adding more ifthen logic for adding a new mac_device_info
> setup function, it is easier to add a function pointer to the function
> needed.
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>   drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++-
>   include/linux/stmmac.h                            | 3 +++
>   2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 43361f3..3beca41 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3508,7 +3508,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
>   	struct mac_device_info *mac;
>   
>   	/* Identify the MAC HW device */
> -	if (priv->plat->has_gmac) {
> +	if (priv->plat->setup) {
> +		mac = priv->plat->setup(priv);
> +	} else if (priv->plat->has_gmac) {
>   		priv->dev->priv_flags |= IFF_UNICAST_FLT;
>   		mac = dwmac1000_setup(priv->ioaddr,
>   				      priv->plat->multicast_filter_bins,
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index 3921cb9..dadd74b 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -144,6 +144,8 @@ struct stmmac_txq_cfg {
>   	u32 prio;
>   };
>   
> +struct stmmac_priv;
> +
>   struct plat_stmmacenet_data {
>   	int bus_id;
>   	int phy_addr;
> @@ -177,6 +179,7 @@ struct plat_stmmacenet_data {
>   	void (*fix_mac_speed)(void *priv, unsigned int speed);
>   	int (*init)(struct platform_device *pdev, void *priv);
>   	void (*exit)(struct platform_device *pdev, void *priv);
> +	struct mac_device_info *(*setup)(struct stmmac_priv *priv);

In that case  I prefer to have void *priv as done for the other callbacks.
I mean, keep the priv struct inside the driver part.

peppe

>   	void *bsp_priv;
>   	struct clk *stmmac_clk;
>   	struct clk *pclk;


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2] i2c/muxes/i2c-mux-ltc4306: LTC4306 and LTC4305 I2C multiplexer/switch
From: Peter Rosin @ 2017-04-03 12:03 UTC (permalink / raw)
  To: michael.hennerich, wsa, robh+dt, mark.rutland, linus.walleij
  Cc: linux-i2c, devicetree, linux-gpio, linux-kernel
In-Reply-To: <0d4c068f-d909-64be-421d-4500da7ebd4c@axentia.se>

On 2017-03-31 17:29, Peter Rosin wrote:
> Hi!
> 
> Sorry for my incremental reviewing...
> 

Another incremental...

> On 2017-03-29 12:15, michael.hennerich@analog.com wrote:
>> +
>> +	/* Now create an adapter for each channel */
>> +	for (num = 0; num < data->chip->nchans; num++) {
>> +		ret = i2c_mux_add_adapter(muxc, 0, num, 0);
>> +		if (ret) {
>> +			dev_err(&client->dev,
>> +				"failed to register multiplexed adapter %d\n",
>> +				num);

Just a heads up, I submitted a series to remove a bunch of dev_err calls
when i2c_mux_add_adapter fails. See https://lkml.org/lkml/2017/4/3/115

You can remove this one as well.

And please use a subject of the form:
i2c: mux: ltc4306: <message>

Cheers,
peda

>> +			goto add_adapter_failed;
>> +		}

^ permalink raw reply

* Re: [PATCH] ARM: sun7i: Cubietruck: enable ACIN und USB power supply subnode
From: Maxime Ripard @ 2017-04-03 11:48 UTC (permalink / raw)
  To: Alexander Syring
  Cc: Rob Herring, Mark Rutland, Russell King, Chen-Yu Tsai,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170403091245.9766-1-alex-a4LgQbPKaXiELgA04lAiVw@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]

Hi,

On Mon, Apr 03, 2017 at 11:12:45AM +0200, Alexander Syring wrote:
> The Cubietruck has an AXP209 PMIC and can be power-supplied by ACIN via
>  the CHG-IN pin or by USB.
> 
> This enables the ACIN and the USB power supply subnode in the DT.
> 
> Signed-off-by: Alexander Syring <alex-a4LgQbPKaXiELgA04lAiVw@public.gmane.org>
> ---
> 
> Send again to all relevant people
> 
> ---
>  arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> index feb995d29799..98431ef15bc9 100644
> --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
> @@ -267,6 +267,10 @@
> 
>  #include "axp209.dtsi"
> 
> +&ac_power_supply {
> +	status = "okay";
> +};
> +
>  &reg_dcdc2 {
>  	regulator-always-on;
>  	regulator-min-microvolt = <1000000>;
> @@ -323,6 +327,10 @@
>  	status = "okay";
>  };
> 
> +&usb_power_supply {
> +	status = "okay";
> +};
> +
>  &usbphy {
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
> @@ -333,3 +341,4 @@
>  	usb2_vbus-supply = <&reg_usb2_vbus>;
>  	status = "okay";
>  };
> +

You had a whitespace error here. I fixed it, and applied.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH v3 20/20] ARM: sunxi: Enable dwmac-sun8i driver on multi_v7_defconfig
From: Maxime Ripard @ 2017-04-03 11:39 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: robh+dt, mark.rutland, wens, linux, catalin.marinas, will.deacon,
	peppe.cavallaro, alexandre.torgue, devicetree, linux-kernel,
	netdev, linux-arm-kernel
In-Reply-To: <20170403091444.29876-21-clabbe.montjoie@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 290 bytes --]

On Mon, Apr 03, 2017 at 11:14:44AM +0200, Corentin Labbe wrote:
> Enable the dwmac-sun8i driver in the multi_v7 default configuration

Your prefix should be arm: multi_v7:

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH v3 16/20] ARM: dts: sun50i-a64: enable dwmac-sun8i on pine64
From: Maxime Ripard @ 2017-04-03 11:38 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	wens-jdAy2FN1RRM, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	peppe.cavallaro-qxv4g6HH51o, alexandre.torgue-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170403091444.29876-17-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 555 bytes --]

On Mon, Apr 03, 2017 at 11:14:40AM +0200, Corentin Labbe wrote:
> The dwmac-sun8i hardware is present on the pine64
> It uses an external PHY via RMII.
> 
> Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Looks fine, but please use "arm64: allwinner: pine64: " as your title
prefix. It applies to all your other patches (and the arm ones should
be "arm: <family>: <soc-or-board>:".

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH v3 12/20] ARM: dts: sun8i: Enable dwmac-sun8i on the Orange Pi plus
From: Maxime Ripard @ 2017-04-03 11:37 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: mark.rutland, devicetree, alexandre.torgue, catalin.marinas,
	will.deacon, linux, linux-kernel, wens, robh+dt, netdev,
	peppe.cavallaro, linux-arm-kernel
In-Reply-To: <20170403091444.29876-13-clabbe.montjoie@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 1693 bytes --]

On Mon, Apr 03, 2017 at 11:14:36AM +0200, Corentin Labbe wrote:
> The dwmac-sun8i hardware is present on the Orange PI plus.
> It uses an external PHY rtl8211e via RGMII.
> 
> This patch create the needed regulator, emac and phy nodes.
> 
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> ---
>  arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 36 ++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
> index 8c40ab7..6852006 100644
> --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
> +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
> @@ -58,6 +58,18 @@
>  		enable-active-high;
>  		gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>;
>  	};
> +
> +	reg_gmac_3v3: gmac-3v3 {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&gmac_power_pin_orangepi>;
> +		regulator-name = "gmac-3v3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <100000>;
> +		enable-active-high;
> +		gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
> +	};
>  };
>  
>  &ehci3 {
> @@ -86,8 +98,32 @@
>  		pins = "PG11";
>  		function = "gpio_out";
>  	};
> +
> +	gmac_power_pin_orangepi: gmac_power_pin@0 {
> +		pins = "PD6";
> +		function = "gpio_out";
> +		drive-strength = <10>;
> +	};

This is not needed, and will even harm the fixing of a bug that will
require to remove all the GPIO nodes. It works fine without it, please
remove it.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* RE: [PATCH 4/5] mtd: nand: add support for Micron on-die ECC
From: Bean Huo (beanhuo) @ 2017-04-03 11:31 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Thomas Petazzoni, richard-/L3Ra7n9ekc@public.gmane.org,
	marek.vasut-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	Cyrille Pitchen,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
	Campbell, pawel.moll-5wv7dgnIgG8@public.gmane.org, Mark Rutland,
	galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
In-Reply-To: <20170322155216.319efc3e@bbrezillon>

Hi, Boris and Thomas

>>
>> Ok, but I recommend that 70s should be the first choice on this single
>> solution, it doesn't need to read twice to detect its bitflips count.
>
>That's exactly why we need to differentiate the 2 chips.

Sorry for later this response. 
Below is the pseudo codes about how to differentiate these 2 series parallel
NAND with on-die ECC:

if (NAND == SLC ) { // on-die ECC only exists in SLC
//check device ID byte 4
     if ((ID.byte4 & 0x02) == 0x02) {// internal ECC level ==10b
	if (ID.byte4 & 0x80) {//on-Die ECC enabled
                    if (ONFI.byte112 == 4)
		 60s SLC NAND with on-die ECC
	    else if (ONFI.byte112 == 8)
     	              70s SLC NAND with on-die ECC
	    else
                          Doesn't support on-die ECC
	}	
	else
	  On-die ECC not enabled
     }
   else 
        Doesn't support on-die ECC
}
else
   Doesn't support on-die ECC.

//beanhuo

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 04/20] ARM: sun8i: dt: Add DT bindings documentation for Allwinner syscon
From: Maxime Ripard @ 2017-04-03 11:19 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	wens-jdAy2FN1RRM, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	peppe.cavallaro-qxv4g6HH51o, alexandre.torgue-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170403091444.29876-5-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1558 bytes --]

On Mon, Apr 03, 2017 at 11:14:28AM +0200, Corentin Labbe wrote:
> Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  .../devicetree/bindings/misc/allwinner,syscon.txt     | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/misc/allwinner,syscon.txt
> 
> diff --git a/Documentation/devicetree/bindings/misc/allwinner,syscon.txt b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt
> new file mode 100644
> index 0000000..9f5f1f5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/allwinner,syscon.txt
> @@ -0,0 +1,19 @@
> +* Allwinner sun8i system controller
> +
> +This file describes the bindings for the system controller present in
> +Allwinner SoC H3, A83T and A64.
> +The principal function of this syscon is to control EMAC PHY choice and
> +config.
> +
> +Required properties for the system controller:
> +- reg: address and length of the register for the device.
> +- compatible: should be "syscon" and one of the following string:
> +		"allwinner,sun8i-h3-system-controller"
> +		"allwinner,sun8i-a64-system-controller"
> +		"allwinner,sun8i-a83t-system-controller"
> +
> +Example:
> +syscon: syscon@01c00000 {
> +	compatible = "syscon", "allwinner,sun8i-h3-system-controller";

The syntax is the more specific first, so your compatibles should be
the other way around.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH v3 03/20] dt-bindings: net: Add DT bindings documentation for Allwinner dwmac-sun8i
From: Maxime Ripard @ 2017-04-03 11:19 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	wens-jdAy2FN1RRM, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	peppe.cavallaro-qxv4g6HH51o, alexandre.torgue-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170403091444.29876-4-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 2434 bytes --]

On Mon, Apr 03, 2017 at 11:14:27AM +0200, Corentin Labbe wrote:
> This patch adds documentation for Device-Tree bindings for the
> Allwinner dwmac-sun8i driver.
> 
> Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>  .../devicetree/bindings/net/dwmac-sun8i.txt        | 77 ++++++++++++++++++++++
>  1 file changed, 77 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/dwmac-sun8i.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
> new file mode 100644
> index 0000000..f01ef17
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
> @@ -0,0 +1,77 @@
> +* Allwinner sun8i GMAC ethernet controller
> +
> +This device is a platform glue layer for stmmac.
> +Please see stmmac.txt for the other unchanged properties.
> +
> +Required properties:
> +- compatible: should be one of the following string:
> +		"allwinner,sun8i-a83t-emac"
> +		"allwinner,sun8i-h3-emac"
> +		"allwinner,sun50i-a64-emac"
> +- reg: address and length of the register for the device.
> +- interrupts: interrupt for the device
> +- interrupt-names: should be "macirq"
> +- clocks: A phandle to the reference clock for this device
> +- clock-names: should be "stmmaceth"
> +- resets: A phandle to the reset control for this device
> +- reset-names: should be "stmmaceth"
> +- phy-mode: See ethernet.txt
> +- phy-handle: See ethernet.txt
> +- #address-cells: shall be 1
> +- #size-cells: shall be 0
> +- syscon: A phandle to the syscon of the SoC with one of the following
> + compatible string:
> +  - allwinner,sun8i-h3-system-controller
> +  - allwinner,sun8i-a64-system-controller
> +  - allwinner,sun8i-a83t-system-controller

I'm not sure you need to document those compatibles here.

> +Optional properties:
> +- allwinner,tx-delay: TX clock delay chain value. Range value is 0-0x07. Default is 0)
> +- allwinner,rx-delay: RX clock delay chain value. Range value is 0-0x1F. Default is 0)
> +Both delay properties are in 0.1ns step.

allwinner,tx-delay-ps and allwinner,rx-delay-ps, with the value in
picoseconds?

Looks good otherwise, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH v3 5/7] mfd: Add Device Tree bindings document for TI tps6105x chip
From: Lee Jones @ 2017-04-03 11:15 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland
In-Reply-To: <20170401071854.23198-6-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

On Sat, 01 Apr 2017, Javier Martinez Canillas wrote:

> There are Device Tree source files defining a device node for the
> tps61050/61052 I2C chip but there isn't a binding document for it.
> 
> Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>  Documentation/devicetree/bindings/mfd/tps6105x.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/tps6105x.txt
> 
> diff --git a/Documentation/devicetree/bindings/mfd/tps6105x.txt b/Documentation/devicetree/bindings/mfd/tps6105x.txt
> new file mode 100644
> index 000000000000..c076f28575fc
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/tps6105x.txt
> @@ -0,0 +1,17 @@
> +* Device tree bindings for TI TPS61050/61052 Boost Converters
> +
> +The TP61050/TPS61052 is a high-power "white LED driver". This boost converter
> +is also used for other things than white LEDs, and also contains a GPIO pin.

What functions does it offer?

> +Required properties:
> +- compatible:		"ti,tps61050" or "ti,tps61052"
> +- reg:			Specifies the I2C slave address
> +
> +Example:
> +
> +i2c0 {
> +	tps61052@33 {
> +		compatible = "ti,tps61052";
> +		reg = <0x33>;
> +	};
> +};

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 2/7] mfd: retu: Add OF device ID table
From: Lee Jones @ 2017-04-03 11:15 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring
In-Reply-To: <20170401071854.23198-3-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

On Sat, 01 Apr 2017, Javier Martinez Canillas wrote:

> The driver doesn't have a struct of_device_id table but supported devices
> are registered via Device Trees. This is working on the assumption that a
> I2C device registered via OF will always match a legacy I2C device ID and
> that the MODALIAS reported will always be of the form i2c:<device>.
> 
> But this could change in the future so the correct approach is to have a
> OF device ID table if the devices are registered via OF.
> 
> Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> 
> ---
> 
> Changes in v3:
> - Add a vendor prefix to the compatible string (Rob Herring).
> 
> Changes in v2:
> - Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
> 
>  drivers/mfd/retu-mfd.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
> index d4c114abeb75..937a1c21eec4 100644
> --- a/drivers/mfd/retu-mfd.c
> +++ b/drivers/mfd/retu-mfd.c
> @@ -308,9 +308,17 @@ static const struct i2c_device_id retu_id[] = {
>  };
>  MODULE_DEVICE_TABLE(i2c, retu_id);
>  
> +static const struct of_device_id retu_of_match[] = {
> +	{ .compatible = "nokia,retu-mfd" },
> +	{ .compatible = "nokia,tahvo-mfd" },

Please drop the "-mfd".

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, retu_of_match);
> +
>  static struct i2c_driver retu_driver = {
>  	.driver		= {
>  		.name = "retu-mfd",
> +		.of_match_table = retu_of_match,
>  	},
>  	.probe		= retu_probe,
>  	.remove		= retu_remove,

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 1/7] mfd: Add Device Tree bindings document for retu/tahvo ASIC chips
From: Lee Jones @ 2017-04-03 11:13 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland
In-Reply-To: <20170401071854.23198-2-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

On Sat, 01 Apr 2017, Javier Martinez Canillas wrote:

> There are Device Tree source files defining a device node for the
> retu/tahvo I2C chip, but there isn't a DT binding document for it.
> 
> Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>  Documentation/devicetree/bindings/mfd/retu.txt | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/retu.txt
> 
> diff --git a/Documentation/devicetree/bindings/mfd/retu.txt b/Documentation/devicetree/bindings/mfd/retu.txt
> new file mode 100644
> index 000000000000..2309e599a731
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/retu.txt
> @@ -0,0 +1,19 @@
> +* Device tree bindings for Nokia Retu and Tahvo multi-function device
> +
> +Retu and Tahvo are a multi-function devices found on Nokia Internet
> +Tablets (770, N800 and N810).

More information please.  What functions to they serve?

> +Required properties:
> +- compatible:		"nokia,retu-mfd" or "nokia,tahvo-mfd"
> +- reg:			Specifies the I2C slave address of the ASIC chip
> +
> +Example:
> +
> +i2c0 {
> +	retu_mfd: retu@1 {

Please avoid the term MFD at all times when using Device Tree.  DT is
meant to be OS agnostic and MFD is a Linuxisum.

> +		compatible = "nokia,retu-mfd";
> +		interrupt-parent = <&gpio4>;
> +		interrupts = <12 IRQ_TYPE_EDGE_RISING>;
> +		reg = <0x1>;
> +	};
> +};

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH RESEND v5 7/7] mfd: dt-bindings: Add RK805 device tree bindings document
From: Lee Jones @ 2017-04-03 11:06 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	chenjh-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	w.egorov-guT5V/WYfQezQB+pC5nmwQ
In-Reply-To: <1490597615-852-1-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

On Mon, 27 Mar 2017, Elaine Zhang wrote:

> Add device tree bindings documentation for Rockchip's RK805 PMIC.
> 
> Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/mfd/rk808.txt | 22 +++++++++++++++++++++-
>  1 file changed, 21 insertions(+), 1 deletion(-)

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  
> diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt
> index 9636ae8d8d41..91b65227afeb 100644
> --- a/Documentation/devicetree/bindings/mfd/rk808.txt
> +++ b/Documentation/devicetree/bindings/mfd/rk808.txt
> @@ -1,11 +1,14 @@
>  RK8XX Power Management Integrated Circuit
>  
>  The rk8xx family current members:
> +rk805
>  rk808
>  rk818
>  
>  Required properties:
> -- compatible: "rockchip,rk808", "rockchip,rk818"
> +- compatible: "rockchip,rk805"
> +- compatible: "rockchip,rk808"
> +- compatible: "rockchip,rk818"
>  - reg: I2C slave address
>  - interrupt-parent: The parent interrupt controller.
>  - interrupts: the interrupt outputs of the controller.
> @@ -18,6 +21,14 @@ Optional properties:
>  - rockchip,system-power-controller: Telling whether or not this pmic is controlling
>    the system power.
>  
> +Optional RK805 properties:
> +- vcc1-supply:  The input supply for DCDC_REG1
> +- vcc2-supply:  The input supply for DCDC_REG2
> +- vcc3-supply:  The input supply for DCDC_REG3
> +- vcc4-supply:  The input supply for DCDC_REG4
> +- vcc5-supply:  The input supply for LDO_REG1 and LDO_REG2
> +- vcc6-supply:  The input supply for LDO_REG3
> +
>  Optional RK808 properties:
>  - vcc1-supply:  The input supply for DCDC_REG1
>  - vcc2-supply:  The input supply for DCDC_REG2
> @@ -56,6 +67,15 @@ by a child node of the 'regulators' node.
>  		/* standard regulator bindings here */
>  	};
>  
> +Following regulators of the RK805 PMIC regulators are supported. Note that
> +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
> +number as described in RK805 datasheet.
> +
> +	- DCDC_REGn
> +		- valid values for n are 1 to 4.
> +	- LDO_REGn
> +		- valid values for n are 1 to 3
> +
>  Following regulators of the RK808 PMIC block are supported. Note that
>  the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO
>  number as described in RK808 datasheet.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 4/7] mfd: rk808: Add RK805 support
From: Lee Jones @ 2017-04-03 11:05 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: lgirdwood, broonie, huangtao, xxx, linux-rockchip, linux-kernel,
	chenjh, robh+dt, mark.rutland, devicetree, w.egorov
In-Reply-To: <1490595705-28844-5-git-send-email-zhangqing@rock-chips.com>

On Mon, 27 Mar 2017, Elaine Zhang wrote:

> The RK805 chip is a Power Management IC (PMIC) for multimedia and handheld
> devices. It contains the following components:
> 
>     - Regulators
>     - RTC
>     - Clocking
> 
> Both RK808 and RK805 chips are using a similar register map,
> so we can reuse the RTC and Clocking functionality.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  drivers/mfd/Kconfig |   4 +-
>  drivers/mfd/rk808.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 110 insertions(+), 2 deletions(-)

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
  
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 55ecdfb74d31..b410a348b756 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -892,13 +892,13 @@ config MFD_RC5T583
>  	  different functionality of the device.
>  
>  config MFD_RK808
> -	tristate "Rockchip RK808/RK818 Power Management Chip"
> +	tristate "Rockchip RK805/RK808/RK818 Power Management Chip"
>  	depends on I2C && OF
>  	select MFD_CORE
>  	select REGMAP_I2C
>  	select REGMAP_IRQ
>  	help
> -	  If you say yes here you get support for the RK808 and RK818
> +	  If you say yes here you get support for the RK805, RK808 and RK818
>  	  Power Management chips.
>  	  This driver provides common support for accessing the device
>  	  through I2C interface. The device supports multiple sub-devices
> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
> index 3334a2a7f3fb..7276555f0630 100644
> --- a/drivers/mfd/rk808.c
> +++ b/drivers/mfd/rk808.c
> @@ -70,6 +70,14 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  	.volatile_reg = rk808_is_volatile_reg,
>  };
>  
> +static const struct regmap_config rk805_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = RK805_OFF_SOURCE_REG,
> +	.cache_type = REGCACHE_RBTREE,
> +	.volatile_reg = rk808_is_volatile_reg,
> +};
> +
>  static const struct regmap_config rk808_regmap_config = {
>  	.reg_bits = 8,
>  	.val_bits = 8,
> @@ -86,6 +94,16 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  	}
>  };
>  
> +static const struct mfd_cell rk805s[] = {
> +	{ .name = "rk808-clkout", },
> +	{ .name = "rk808-regulator", },
> +	{
> +		.name = "rk808-rtc",
> +		.num_resources = ARRAY_SIZE(rtc_resources),
> +		.resources = &rtc_resources[0],
> +	},
> +};
> +
>  static const struct mfd_cell rk808s[] = {
>  	{ .name = "rk808-clkout", },
>  	{ .name = "rk808-regulator", },
> @@ -106,6 +124,20 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  	},
>  };
>  
> +static const struct rk808_reg_data rk805_pre_init_reg[] = {
> +	{RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
> +				 RK805_BUCK1_2_ILMAX_4000MA},
> +	{RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
> +				 RK805_BUCK1_2_ILMAX_4000MA},
> +	{RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
> +				 RK805_BUCK3_ILMAX_3000MA},
> +	{RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
> +				 RK805_BUCK4_ILMAX_3500MA},
> +	{RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
> +	{RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN},
> +	{RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
> +};
> +
>  static const struct rk808_reg_data rk808_pre_init_reg[] = {
>  	{ RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK,  BUCK_ILMIN_150MA },
>  	{ RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK,  BUCK_ILMIN_200MA },
> @@ -135,6 +167,41 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  						    VB_LO_SEL_3500MV },
>  };
>  
> +static const struct regmap_irq rk805_irqs[] = {
> +	[RK805_IRQ_PWRON_RISE] = {
> +		.mask = RK805_IRQ_PWRON_RISE_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_VB_LOW] = {
> +		.mask = RK805_IRQ_VB_LOW_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_PWRON] = {
> +		.mask = RK805_IRQ_PWRON_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_PWRON_LP] = {
> +		.mask = RK805_IRQ_PWRON_LP_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_HOTDIE] = {
> +		.mask = RK805_IRQ_HOTDIE_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_RTC_ALARM] = {
> +		.mask = RK805_IRQ_RTC_ALARM_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_RTC_PERIOD] = {
> +		.mask = RK805_IRQ_RTC_PERIOD_MSK,
> +		.reg_offset = 0,
> +	},
> +	[RK805_IRQ_PWRON_FALL] = {
> +		.mask = RK805_IRQ_PWRON_FALL_MSK,
> +		.reg_offset = 0,
> +	},
> +};
> +
>  static const struct regmap_irq rk808_irqs[] = {
>  	/* INT_STS */
>  	[RK808_IRQ_VOUT_LO] = {
> @@ -247,6 +314,17 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  	},
>  };
>  
> +static struct regmap_irq_chip rk805_irq_chip = {
> +	.name = "rk805",
> +	.irqs = rk805_irqs,
> +	.num_irqs = ARRAY_SIZE(rk805_irqs),
> +	.num_regs = 1,
> +	.status_base = RK805_INT_STS_REG,
> +	.mask_base = RK805_INT_STS_MSK_REG,
> +	.ack_base = RK805_INT_STS_REG,
> +	.init_ack_masked = true,
> +};
> +
>  static const struct regmap_irq_chip rk808_irq_chip = {
>  	.name = "rk808",
>  	.irqs = rk808_irqs,
> @@ -272,6 +350,25 @@ static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
>  };
>  
>  static struct i2c_client *rk808_i2c_client;
> +
> +static void rk805_device_shutdown(void)
> +{
> +	int ret;
> +	struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
> +
> +	if (!rk808) {
> +		dev_warn(&rk808_i2c_client->dev,
> +			 "have no rk805, so do nothing here\n");
> +		return;
> +	}
> +
> +	ret = regmap_update_bits(rk808->regmap,
> +				 RK805_DEV_CTRL_REG,
> +				 DEV_OFF, DEV_OFF);
> +	if (ret)
> +		dev_err(&rk808_i2c_client->dev, "power off error!\n");
> +}
> +
>  static void rk808_device_shutdown(void)
>  {
>  	int ret;
> @@ -309,6 +406,7 @@ static void rk818_device_shutdown(void)
>  }
>  
>  static const struct of_device_id rk808_of_match[] = {
> +	{ .compatible = "rockchip,rk805" },
>  	{ .compatible = "rockchip,rk808" },
>  	{ .compatible = "rockchip,rk818" },
>  	{ },
> @@ -352,6 +450,15 @@ static int rk808_probe(struct i2c_client *client,
>  	dev_info(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant);
>  
>  	switch (rk808->variant) {
> +	case RK805_ID:
> +		rk808->regmap_cfg = &rk805_regmap_config;
> +		rk808->regmap_irq_chip = &rk805_irq_chip;
> +		pre_init_reg = rk805_pre_init_reg;
> +		nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
> +		cells = rk805s;
> +		nr_cells = ARRAY_SIZE(rk805s);
> +		pm_pwroff_fn = rk805_device_shutdown;
> +		break;
>  	case RK808_ID:
>  		rk808->regmap_cfg = &rk808_regmap_config;
>  		rk808->regmap_irq_chip = &rk808_irq_chip;
> @@ -444,6 +551,7 @@ static int rk808_remove(struct i2c_client *client)
>  }
>  
>  static const struct i2c_device_id rk808_ids[] = {
> +	{ "rk805" },
>  	{ "rk808" },
>  	{ "rk818" },
>  	{ },

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v5 2/7] mfd: rk808: add rk805 regs addr and ID
From: Lee Jones @ 2017-04-03 11:04 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	chenjh-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	w.egorov-guT5V/WYfQezQB+pC5nmwQ
In-Reply-To: <1490595705-28844-3-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

On Mon, 27 Mar 2017, Elaine Zhang wrote:

> Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
>  include/linux/mfd/rk808.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 120 insertions(+)

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  
> diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
> index 54feb140c210..d3156594674c 100644
> --- a/include/linux/mfd/rk808.h
> +++ b/include/linux/mfd/rk808.h
> @@ -206,6 +206,97 @@ enum rk818_reg {
>  #define RK818_USB_ILMIN_2000MA		0x7
>  #define RK818_USB_CHG_SD_VSEL_MASK	0x70
>  
> +/* RK805 */
> +enum rk805_reg {
> +	RK805_ID_DCDC1,
> +	RK805_ID_DCDC2,
> +	RK805_ID_DCDC3,
> +	RK805_ID_DCDC4,
> +	RK805_ID_LDO1,
> +	RK805_ID_LDO2,
> +	RK805_ID_LDO3,
> +};
> +
> +/* CONFIG REGISTER */
> +#define RK805_VB_MON_REG		0x21
> +#define RK805_THERMAL_REG		0x22
> +
> +/* POWER CHANNELS ENABLE REGISTER */
> +#define RK805_DCDC_EN_REG		0x23
> +#define RK805_SLP_DCDC_EN_REG		0x25
> +#define RK805_SLP_LDO_EN_REG		0x26
> +#define RK805_LDO_EN_REG		0x27
> +
> +/* BUCK AND LDO CONFIG REGISTER */
> +#define RK805_BUCK_LDO_SLP_LP_EN_REG	0x2A
> +#define RK805_BUCK1_CONFIG_REG		0x2E
> +#define RK805_BUCK1_ON_VSEL_REG		0x2F
> +#define RK805_BUCK1_SLP_VSEL_REG	0x30
> +#define RK805_BUCK2_CONFIG_REG		0x32
> +#define RK805_BUCK2_ON_VSEL_REG		0x33
> +#define RK805_BUCK2_SLP_VSEL_REG	0x34
> +#define RK805_BUCK3_CONFIG_REG		0x36
> +#define RK805_BUCK4_CONFIG_REG		0x37
> +#define RK805_BUCK4_ON_VSEL_REG		0x38
> +#define RK805_BUCK4_SLP_VSEL_REG	0x39
> +#define RK805_LDO1_ON_VSEL_REG		0x3B
> +#define RK805_LDO1_SLP_VSEL_REG		0x3C
> +#define RK805_LDO2_ON_VSEL_REG		0x3D
> +#define RK805_LDO2_SLP_VSEL_REG		0x3E
> +#define RK805_LDO3_ON_VSEL_REG		0x3F
> +#define RK805_LDO3_SLP_VSEL_REG		0x40
> +
> +/* INTERRUPT REGISTER */
> +#define RK805_PWRON_LP_INT_TIME_REG	0x47
> +#define RK805_PWRON_DB_REG		0x48
> +#define RK805_DEV_CTRL_REG		0x4B
> +#define RK805_INT_STS_REG		0x4C
> +#define RK805_INT_STS_MSK_REG		0x4D
> +#define RK805_GPIO_IO_POL_REG		0x50
> +#define RK805_OUT_REG			0x52
> +#define RK805_ON_SOURCE_REG		0xAE
> +#define RK805_OFF_SOURCE_REG		0xAF
> +
> +#define RK805_NUM_REGULATORS		7
> +
> +#define RK805_PWRON_FALL_RISE_INT_EN	0x0
> +#define RK805_PWRON_FALL_RISE_INT_MSK	0x81
> +
> +/* RK805 IRQ Definitions */
> +#define RK805_IRQ_PWRON_RISE		0
> +#define RK805_IRQ_VB_LOW		1
> +#define RK805_IRQ_PWRON			2
> +#define RK805_IRQ_PWRON_LP		3
> +#define RK805_IRQ_HOTDIE		4
> +#define RK805_IRQ_RTC_ALARM		5
> +#define RK805_IRQ_RTC_PERIOD		6
> +#define RK805_IRQ_PWRON_FALL		7
> +
> +#define RK805_IRQ_PWRON_RISE_MSK	BIT(0)
> +#define RK805_IRQ_VB_LOW_MSK		BIT(1)
> +#define RK805_IRQ_PWRON_MSK		BIT(2)
> +#define RK805_IRQ_PWRON_LP_MSK		BIT(3)
> +#define RK805_IRQ_HOTDIE_MSK		BIT(4)
> +#define RK805_IRQ_RTC_ALARM_MSK		BIT(5)
> +#define RK805_IRQ_RTC_PERIOD_MSK	BIT(6)
> +#define RK805_IRQ_PWRON_FALL_MSK	BIT(7)
> +
> +#define RK805_PWR_RISE_INT_STATUS	BIT(0)
> +#define RK805_VB_LOW_INT_STATUS		BIT(1)
> +#define RK805_PWRON_INT_STATUS		BIT(2)
> +#define RK805_PWRON_LP_INT_STATUS	BIT(3)
> +#define RK805_HOTDIE_INT_STATUS		BIT(4)
> +#define RK805_ALARM_INT_STATUS		BIT(5)
> +#define RK805_PERIOD_INT_STATUS		BIT(6)
> +#define RK805_PWR_FALL_INT_STATUS	BIT(7)
> +
> +#define RK805_BUCK1_2_ILMAX_MASK	(3 << 6)
> +#define RK805_BUCK3_4_ILMAX_MASK        (3 << 3)
> +#define RK805_RTC_PERIOD_INT_MASK	(1 << 6)
> +#define RK805_RTC_ALARM_INT_MASK	(1 << 5)
> +#define RK805_INT_ALARM_EN		(1 << 3)
> +#define RK805_INT_TIMER_EN		(1 << 2)
> +
>  /* RK808 IRQ Definitions */
>  #define RK808_IRQ_VOUT_LO	0
>  #define RK808_IRQ_VB_LO		1
> @@ -298,7 +389,14 @@ enum rk818_reg {
>  #define VOUT_LO_INT	BIT(0)
>  #define CLK32KOUT2_EN	BIT(0)
>  
> +#define TEMP115C			0x0c
> +#define TEMP_HOTDIE_MSK			0x0c
> +#define SLP_SD_MSK			(0x3 << 2)
> +#define SHUTDOWN_FUN			(0x2 << 2)
> +#define SLEEP_FUN			(0x1 << 2)
>  #define RK8XX_ID_MSK			0xfff0
> +#define FPWM_MODE			BIT(7)
> +
>  enum {
>  	BUCK_ILMIN_50MA,
>  	BUCK_ILMIN_100MA,
> @@ -322,6 +420,28 @@ enum {
>  };
>  
>  enum {
> +	RK805_BUCK1_2_ILMAX_2500MA,
> +	RK805_BUCK1_2_ILMAX_3000MA,
> +	RK805_BUCK1_2_ILMAX_3500MA,
> +	RK805_BUCK1_2_ILMAX_4000MA,
> +};
> +
> +enum {
> +	RK805_BUCK3_ILMAX_1500MA,
> +	RK805_BUCK3_ILMAX_2000MA,
> +	RK805_BUCK3_ILMAX_2500MA,
> +	RK805_BUCK3_ILMAX_3000MA,
> +};
> +
> +enum {
> +	RK805_BUCK4_ILMAX_2000MA,
> +	RK805_BUCK4_ILMAX_2500MA,
> +	RK805_BUCK4_ILMAX_3000MA,
> +	RK805_BUCK4_ILMAX_3500MA,
> +};
> +
> +enum {
> +	RK805_ID = 0x8050,
>  	RK808_ID = 0x0000,
>  	RK818_ID = 0x8181,
>  };

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 1/7] mfd: rk808: fix up the chip id get failed
From: Lee Jones @ 2017-04-03 11:00 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	chenjh-TNX95d0MmH7DzftRWevZcw, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	w.egorov-guT5V/WYfQezQB+pC5nmwQ
In-Reply-To: <1490595705-28844-2-git-send-email-zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

On Mon, 27 Mar 2017, Elaine Zhang wrote:

> the rk8xx chip id is:
> ((MSB << 8) | LSB) & 0xfff0
> 
> Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---

It's usually helpful to keep a changelog here:

v3 => v4:
 - Stuff that happened

v2 => v3:
 - Stuff that happened

v1 => v2:
 - Stuff that happened
 
>  drivers/mfd/rk808.c       | 21 +++++++++++++++------
>  include/linux/mfd/rk808.h |  1 +
>  2 files changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
> index fd087cbb0bde..3334a2a7f3fb 100644
> --- a/drivers/mfd/rk808.c
> +++ b/drivers/mfd/rk808.c
> @@ -325,7 +325,7 @@ static int rk808_probe(struct i2c_client *client,
>  	void (*pm_pwroff_fn)(void);
>  	int nr_pre_init_regs;
>  	int nr_cells;
> -	int pm_off = 0;
> +	int pm_off = 0, msb, lsb;
>  	int ret;
>  	int i;
>  
> @@ -333,14 +333,23 @@ static int rk808_probe(struct i2c_client *client,
>  	if (!rk808)
>  		return -ENOMEM;
>  
> -	rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB);
> -	if (rk808->variant < 0) {
> -		dev_err(&client->dev, "Failed to read the chip id at 0x%02x\n",
> +	/* read Chip variant */

Please use correct grammar.

"Read chip variant"

> +	msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB);
> +	if (msb < 0) {
> +		dev_err(&client->dev, "failed to read the chip id at 0x%x\n",

Although this error messages makes the comment above redundant.

>  			RK808_ID_MSB);
> -		return rk808->variant;
> +		return msb;
>  	}
>  
> -	dev_dbg(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant);
> +	lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB);
> +	if (lsb < 0) {
> +		dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
> +			RK808_ID_LSB);
> +		return lsb;
> +	}
> +
> +	rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
> +	dev_info(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant);
>  
>  	switch (rk808->variant) {
>  	case RK808_ID:
> diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
> index 83701ef7d3c7..54feb140c210 100644
> --- a/include/linux/mfd/rk808.h
> +++ b/include/linux/mfd/rk808.h
> @@ -298,6 +298,7 @@ enum rk818_reg {
>  #define VOUT_LO_INT	BIT(0)
>  #define CLK32KOUT2_EN	BIT(0)
>  
> +#define RK8XX_ID_MSK			0xfff0
>  enum {
>  	BUCK_ILMIN_50MA,
>  	BUCK_ILMIN_100MA,

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2] clk/axs10x: introduce AXS10X pll driver
From: Jose Abreu @ 2017-04-03 10:54 UTC (permalink / raw)
  To: Vlad Zakharov, linux-clk-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-snps-arc-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Michael Turquette,
	Stephen Boyd, Mark Rutland, Rob Herring
In-Reply-To: <1487682670-4164-1-git-send-email-vzakhar-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>

Hi Vlad,


On 21-02-2017 13:11, Vlad Zakharov wrote:
> AXS10X boards manages it's clocks using various PLLs. These PLL has same
> dividers and corresponding control registers mapped to different addresses.
> So we add one common driver for such PLLs.
>
> Each PLL on AXS10X board consist of three dividers: IDIV, FBDIV and
> ODIV. Output clock value is managed using these dividers.
>
> We add pre-defined tables with supported rate values and appropriate
> configurations of IDIV, FBDIV and ODIV for each value.
>
> As of today we add support for PLLs that generate clock for the
> following devices:
>  * ARC core on AXC CPU tiles.
>  * ARC PGU on ARC SDP Mainboard.
> and more to come later.
>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Vlad Zakharov <vzakhar-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Jose Abreu <joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
> Cc: Michael Turquette <mturquette-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> Cc: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> ---
> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Changes v1..v2
>  - Replace '_' with '-' in device tree nodes
>
>  .../devicetree/bindings/clock/snps,pll-clock.txt   |  28 ++
>  MAINTAINERS                                        |   6 +
>  drivers/clk/axs10x/Makefile                        |   1 +
>  drivers/clk/axs10x/pll_clock.c                     | 384 +++++++++++++++++++++
>  4 files changed, 419 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/snps,pll-clock.txt
>  create mode 100644 drivers/clk/axs10x/pll_clock.c
>
> diff --git a/Documentation/devicetree/bindings/clock/snps,pll-clock.txt b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt
> new file mode 100644
> index 0000000..5706246
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt
> @@ -0,0 +1,28 @@
> +Binding for the AXS10X Generic PLL clock
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible: should be "snps,axs10x-<name>-pll-clock"
> +  "snps,axs10x-arc-pll-clock"
> +  "snps,axs10x-pgu-pll-clock"
> +- reg: should always contain 2 pairs address - length: first for PLL config
> +registers and second for corresponding LOCK CGU register.
> +- clocks: shall be the input parent clock phandle for the PLL.
> +- #clock-cells: from common clock binding; Should always be set to 0.
> +
> +Example:
> +	input-clk: input-clk {
> +		clock-frequency = <33333333>;
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +	};
> +
> +	core-clk: core-clk@80 {
> +		compatible = "snps,axs10x-arc-pll-clock";
> +		reg = <0x80 0x10 0x100 0x10>;
> +		#clock-cells = <0>;
> +		clocks = <&input-clk>;
> +	};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3960e7f..5805833 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11910,6 +11910,12 @@ F:	arch/arc/plat-axs10x
>  F:	arch/arc/boot/dts/ax*
>  F:	Documentation/devicetree/bindings/arc/axs10*
>  
> +SYNOPSYS ARC SDP clock driver
> +M:	Vlad Zakharov <vzakhar-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
> +S:	Supported
> +F:	drivers/clk/axs10x/*
> +F:	Documentation/devicetree/bindings/clock/snps,pll-clock.txt
> +
>  SYSTEM CONFIGURATION (SYSCON)
>  M:	Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>  M:	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile
> index 01996b8..d747dea 100644
> --- a/drivers/clk/axs10x/Makefile
> +++ b/drivers/clk/axs10x/Makefile
> @@ -1 +1,2 @@
>  obj-y += i2s_pll_clock.o
> +obj-y += pll_clock.o
> diff --git a/drivers/clk/axs10x/pll_clock.c b/drivers/clk/axs10x/pll_clock.c
> new file mode 100644
> index 0000000..784a0a2
> --- /dev/null
> +++ b/drivers/clk/axs10x/pll_clock.c
> @@ -0,0 +1,384 @@
> +/*
> + * Synopsys AXS10X SDP Generic PLL clock driver
> + *
> + * Copyright (C) 2017 Synopsys
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/of.h>
> +
> +/* PLL registers addresses */
> +#define PLL_REG_IDIV	0x0
> +#define PLL_REG_FBDIV	0x4
> +#define PLL_REG_ODIV	0x8
> +
> +/*
> + * Bit fields of the PLL IDIV/FBDIV/ODIV registers:
> + *  ________________________________________________________________________
> + * |31                15|    14    |   13   |  12  |11         6|5         0|
> + * |-------RESRVED------|-NOUPDATE-|-BYPASS-|-EDGE-|--HIGHTIME--|--LOWTIME--|
> + * |____________________|__________|________|______|____________|___________|
> + *
> + * Following macros detirmine the way of access to these registers
> + * They should be set up only using the macros.
> + * reg should be and uint32_t variable.
> + */
> +
> +#define PLL_REG_GET_LOW(reg)			\
> +	(((reg) & (0x3F << 0)) >> 0)
> +#define PLL_REG_GET_HIGH(reg)			\
> +	(((reg) & (0x3F << 6)) >> 6)
> +#define PLL_REG_GET_EDGE(reg)			\
> +	(((reg) & (BIT(12))) ? 1 : 0)
> +#define PLL_REG_GET_BYPASS(reg)			\
> +	(((reg) & (BIT(13))) ? 1 : 0)
> +#define PLL_REG_GET_NOUPD(reg)			\
> +	(((reg) & (BIT(14))) ? 1 : 0)
> +#define PLL_REG_GET_PAD(reg)			\
> +	(((reg) & (0x1FFFF << 15)) >> 15)
> +
> +#define PLL_REG_SET_LOW(reg, value)		\
> +	{ reg |= (((value) & 0x3F) << 0); }
> +#define PLL_REG_SET_HIGH(reg, value)	\
> +	{ reg |= (((value) & 0x3F) << 6); }
> +#define PLL_REG_SET_EDGE(reg, value)	\
> +	{ reg |= (((value) & 0x01) << 12); }
> +#define PLL_REG_SET_BYPASS(reg, value)	\
> +	{ reg |= (((value) & 0x01) << 13); }
> +#define PLL_REG_SET_NOUPD(reg, value)	\
> +	{ reg |= (((value) & 0x01) << 14); }
> +#define PLL_REG_SET_PAD(reg, value)		\
> +	{ reg |= (((value) & 0x1FFFF) << 15); }
> +
> +#define PLL_LOCK	0x1
> +#define PLL_MAX_LOCK_TIME 100 /* 100 us */
> +
> +struct pll_cfg {
> +	u32 rate;
> +	u32 idiv;
> +	u32 fbdiv;
> +	u32 odiv;
> +};
> +
> +struct pll_of_table {
> +	unsigned long prate;
> +	struct pll_cfg *pll_cfg_table;
> +};
> +
> +struct pll_of_data {
> +	struct pll_of_table *pll_table;
> +};
> +
> +static struct pll_of_data pgu_pll_data = {
> +	.pll_table = (struct pll_of_table []){
> +		{
> +			.prate = 27000000,
> +			.pll_cfg_table = (struct pll_cfg []){
> +				{ 25200000, 1, 84, 90 },
> +				{ 50000000, 1, 100, 54 },
> +				{ 74250000, 1, 44, 16 },
> +				{ },
> +			},
> +		},
> +		/* Used as list limiter */
> +		{ },
> +	},
> +};
> +
> +static struct pll_of_data arc_pll_data = {
> +	.pll_table = (struct pll_of_table []){
> +		{
> +			.prate = 33333333,
> +			.pll_cfg_table = (struct pll_cfg []){
> +				{ 33333333,  1, 1,  1 },
> +				{ 50000000,  1, 30, 20 },
> +				{ 75000000,  2, 45, 10 },
> +				{ 90000000,  2, 54, 10 },
> +				{ 100000000, 1, 30, 10 },
> +				{ 125000000, 2, 45, 6 },
> +				{ },
> +			},
> +		},
> +		/* Used as list limiter */
> +		{ },
> +	},
> +};
> +
> +struct pll_clk {
> +	void __iomem *base;
> +	void __iomem *lock;
> +	const struct pll_of_data *pll_data;
> +	struct clk_hw hw;
> +	struct device *dev;
> +};
> +
> +static inline void pll_write(struct pll_clk *clk, unsigned int reg,
> +		unsigned int val)
> +{
> +	iowrite32(val, clk->base + reg);
> +}
> +
> +static inline u32 pll_read(struct pll_clk *clk,
> +		unsigned int reg)
> +{
> +	return ioread32(clk->base + reg);
> +}
> +
> +static inline struct pll_clk *to_pll_clk(struct clk_hw *hw)
> +{
> +	return container_of(hw, struct pll_clk, hw);
> +}
> +
> +static inline u32 div_get_value(unsigned int reg)
> +{
> +	if (PLL_REG_GET_BYPASS(reg))
> +		return 1;
> +
> +	return (PLL_REG_GET_HIGH(reg) + PLL_REG_GET_LOW(reg));
> +}
> +
> +static inline u32 encode_div(unsigned int id, int upd)
> +{
> +	uint32_t div = 0;

"uint32_t" -> "u32"

> +
> +	PLL_REG_SET_LOW(div, (id%2 == 0) ? id >> 1 : (id >> 1) + 1);
> +	PLL_REG_SET_HIGH(div, id >> 1);
> +	PLL_REG_SET_EDGE(div, id%2);
> +	PLL_REG_SET_BYPASS(div, id == 1 ? 1 : 0);
> +	PLL_REG_SET_NOUPD(div, !upd);
> +
> +	return div;
> +}
> +
> +static const struct pll_cfg *pll_get_cfg(unsigned long prate,
> +		const struct pll_of_table *pll_table)
> +{
> +	int i;
> +
> +	for (i = 0; pll_table[i].prate != 0; i++)
> +		if (pll_table[i].prate == prate)
> +			return pll_table[i].pll_cfg_table;
> +
> +	return NULL;
> +}
> +
> +static unsigned long pll_recalc_rate(struct clk_hw *hw,
> +			unsigned long parent_rate)
> +{
> +	u64 rate;
> +	u32 idiv, fbdiv, odiv;
> +	struct pll_clk *clk = to_pll_clk(hw);
> +
> +	idiv = div_get_value(pll_read(clk, PLL_REG_IDIV));
> +	fbdiv = div_get_value(pll_read(clk, PLL_REG_FBDIV));
> +	odiv = div_get_value(pll_read(clk, PLL_REG_ODIV));
> +
> +	rate = (u64)parent_rate * fbdiv;
> +	do_div(rate, idiv * odiv);
> +
> +	return (unsigned long)rate;
> +}
> +
> +static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +			unsigned long *prate)
> +{
> +	int i;
> +	long best_rate;
> +	struct pll_clk *clk = to_pll_clk(hw);
> +	const struct pll_cfg *pll_cfg = pll_get_cfg(*prate,
> +			clk->pll_data->pll_table);
> +
> +	if (!pll_cfg) {
> +		dev_err(clk->dev, "invalid parent rate=%ld\n", *prate);
> +		return -EINVAL;
> +	}
> +
> +	if (pll_cfg[0].rate == 0)
> +		return -EINVAL;
> +
> +	best_rate = pll_cfg[0].rate;
> +
> +	for (i = 1; pll_cfg[i].rate != 0; i++) {
> +		if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate))
> +			best_rate = pll_cfg[i].rate;
> +	}
> +
> +	return best_rate;
> +}
> +
> +static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +			unsigned long parent_rate)
> +{
> +	int i;
> +	struct pll_clk *clk = to_pll_clk(hw);
> +	const struct pll_cfg *pll_cfg = pll_get_cfg(parent_rate,
> +			clk->pll_data->pll_table);
> +
> +	if (!pll_cfg) {
> +		dev_err(clk->dev, "invalid parent rate=%ld\n", parent_rate);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; pll_cfg[i].rate != 0; i++) {
> +		if (pll_cfg[i].rate == rate) {
> +			pll_write(clk, PLL_REG_IDIV,
> +					encode_div(pll_cfg[i].idiv, 0));
> +			pll_write(clk, PLL_REG_FBDIV,
> +					encode_div(pll_cfg[i].fbdiv, 0));
> +			pll_write(clk, PLL_REG_ODIV,
> +					encode_div(pll_cfg[i].odiv, 1));
> +
> +			/*
> +			 * Wait until CGU relocks.
> +			 * If after timeout CGU is unlocked yet return error
> +			 */
> +			udelay(PLL_MAX_LOCK_TIME);
> +			if (ioread32(clk->lock) & PLL_LOCK)
> +				return 0;
> +			else
> +				return -ETIMEDOUT;
> +		}
> +	}
> +
> +	dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate,
> +			parent_rate);
> +	return -EINVAL;
> +}
> +
> +static const struct clk_ops pll_ops = {
> +	.recalc_rate = pll_recalc_rate,
> +	.round_rate = pll_round_rate,
> +	.set_rate = pll_set_rate,
> +};
> +
> +static int pll_clk_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	const char *parent_name;
> +	struct clk *clk;
> +	struct pll_clk *pll_clk;
> +	struct resource *mem;
> +	struct clk_init_data init = { };
> +
> +	pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
> +	if (!pll_clk)
> +		return -ENOMEM;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	pll_clk->base = devm_ioremap_resource(dev, mem);
> +	if (IS_ERR(pll_clk->base))
> +		return PTR_ERR(pll_clk->base);
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	pll_clk->lock = devm_ioremap_resource(dev, mem);
> +	if (IS_ERR(pll_clk->lock))
> +		return PTR_ERR(pll_clk->base);

Typo: should be "return PTR_ERR(pll_clk->lock);"

> +
> +	init.name = dev->of_node->name;
> +	init.ops = &pll_ops;
> +	parent_name = of_clk_get_parent_name(dev->of_node, 0);
> +	init.parent_names = &parent_name;
> +	init.num_parents = 1;
> +	pll_clk->hw.init = &init;
> +	pll_clk->dev = dev;
> +	pll_clk->pll_data = of_device_get_match_data(dev);
> +
> +	if (!pll_clk->pll_data) {
> +		dev_err(dev, "No OF match data provided\n");
> +			return -EINVAL;
> +	}
> +
> +	clk = devm_clk_register(dev, &pll_clk->hw);
> +	if (IS_ERR(clk)) {
> +		dev_err(dev, "failed to register %s clock (%ld)\n",
> +				init.name, PTR_ERR(clk));
> +		return PTR_ERR(clk);
> +	}
> +
> +	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, clk);
> +}
> +
> +static int pll_clk_remove(struct platform_device *pdev)
> +{
> +	of_clk_del_provider(pdev->dev.of_node);
> +	return 0;
> +}
> +
> +static void __init of_pll_clk_setup(struct device_node *node)
> +{
> +	const char *parent_name;
> +	struct clk *clk;
> +	struct pll_clk *pll_clk;
> +	struct clk_init_data init = { };
> +
> +	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
> +	if (!pll_clk)
> +		return;
> +
> +	pll_clk->base = of_iomap(node, 0);
> +	if (!pll_clk->base) {
> +		pr_err("failed to map pll div registers\n");
> +		iounmap(pll_clk->base);
> +		return;
> +	}
> +
> +	pll_clk->lock = of_iomap(node, 1);
> +	if (!pll_clk->lock) {
> +		pr_err("failed to map pll lock register\n");
> +		iounmap(pll_clk->lock);
> +		return;
> +	}
> +
> +	init.name = node->name;
> +	init.ops = &pll_ops;
> +	parent_name = of_clk_get_parent_name(node, 0);
> +	init.parent_names = &parent_name;
> +	init.num_parents = parent_name ? 1 : 0;
> +	pll_clk->hw.init = &init;
> +	pll_clk->pll_data = &arc_pll_data;
> +
> +	clk = clk_register(NULL, &pll_clk->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("failed to register %s clock (%ld)\n",
> +				node->name, PTR_ERR(clk));
> +		kfree(pll_clk);
> +		return;
> +	}
> +
> +	of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +
> +CLK_OF_DECLARE(axs10x_pll_clock, "snps,axs10x-arc-pll-clock", of_pll_clk_setup);
> +
> +static const struct of_device_id pll_clk_id[] = {
> +	{ .compatible = "snps,axs10x-arc-pll-clock", .data = &arc_pll_data},
> +	{ .compatible = "snps,axs10x-pgu-pll-clock", .data = &pgu_pll_data},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, pll_clk_id);
> +
> +static struct platform_driver pll_clk_driver = {
> +	.driver = {
> +		.name = "axs10x-pll-clock",
> +		.of_match_table = pll_clk_id,
> +	},
> +	.probe = pll_clk_probe,
> +	.remove = pll_clk_remove,
> +};
> +builtin_platform_driver(pll_clk_driver);
> +
> +MODULE_AUTHOR("Vlad Zakharov <vzakhar-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>");
> +MODULE_DESCRIPTION("Synopsys AXS10X SDP Generic PLL Clock Driver");
> +MODULE_LICENSE("GPL v2");

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
From: Chen-Yu Tsai @ 2017-04-03 10:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Icenowy Zheng, Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi
In-Reply-To: <20170403081423.p6x4ytfoga2krygv@lukather>

On Mon, Apr 3, 2017 at 4:14 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi,
>
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       scrtc->tcon = tcon;
>>
>>       /* Create our layers */
>> -     scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +     scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>       if (IS_ERR(scrtc->layers)) {
>>               dev_err(drm->dev, "Couldn't create the planes\n");
>>               return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>       /* find primary and cursor planes for drm_crtc_init_with_planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             switch (layer->plane.type) {
>> +             switch (plane->type) {
>>               case DRM_PLANE_TYPE_PRIMARY:
>> -                     primary = &layer->plane;
>> +                     primary = plane;
>>                       break;
>>               case DRM_PLANE_TYPE_CURSOR:
>> -                     cursor = &layer->plane;
>> +                     cursor = plane;
>>                       break;
>>               default:
>>                       break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       /* Set possible_crtcs to this crtc for overlay planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>>               uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -                     layer->plane.possible_crtcs = possible_crtcs;
>> +             if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +                     plane->possible_crtcs = possible_crtcs;
>
> I think the logic should be reversed here, the CRTC shouldn't care
> (much) about the layers at all.

Correct. It shouldn't. However since the layers are tied to a specific
crtc, they get created as part of the crtc init sequence.

> We should modify sun4i_crtc_init to get the argument it needs (primary
> and cursor planes for example) through its parameters, and have the
> caller (which iirc is sun4i_drv) call it with the right parameters

The caller is (now) sun4i_crtc_init.

> depending on whether you're using DE or DE2.

Ack.

>
> If we're doing that, I don't think we even need the pointer to the
> array of layers in struct sun4i_crtc, which will make it easier to
> deal with.

Ack.

ChenYu

^ permalink raw reply

* Re: [PATCH v2 2/8] [media] stm32-dcmi: STM32 DCMI camera interface driver
From: Hans Verkuil @ 2017-04-03 10:37 UTC (permalink / raw)
  To: Hugues Fruchet, Rob Herring, Mark Rutland, Maxime Coquelin,
	Alexandre Torgue, Mauro Carvalho Chehab
  Cc: devicetree, linux-arm-kernel, linux-kernel, linux-media,
	Benjamin Gaignard, Yannick Fertre
In-Reply-To: <1490887667-8880-3-git-send-email-hugues.fruchet@st.com>

On 03/30/2017 05:27 PM, Hugues Fruchet wrote:
> This V4L2 subdev driver enables Digital Camera Memory Interface (DCMI)
> of STMicroelectronics STM32 SoC series.
> 
> Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
> Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
> ---
>  drivers/media/platform/Kconfig            |   12 +
>  drivers/media/platform/Makefile           |    2 +
>  drivers/media/platform/stm32/Makefile     |    1 +
>  drivers/media/platform/stm32/stm32-dcmi.c | 1417 +++++++++++++++++++++++++++++
>  4 files changed, 1432 insertions(+)
>  create mode 100644 drivers/media/platform/stm32/Makefile
>  create mode 100644 drivers/media/platform/stm32/stm32-dcmi.c

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Looks good!

Regards,

	Hans

^ permalink raw reply

* Re: [PATCH v4 06/14] MIPS: jz4740: DTS: Add nodes for ingenic pinctrl and gpio drivers
From: Sergei Shtylyov @ 2017-04-03 10:32 UTC (permalink / raw)
  To: Paul Cercueil
  Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
	Ralf Baechle, Boris Brezillon, Thierry Reding,
	Bartlomiej Zolnierkiewicz, Maarten ter Huurne, Lars-Peter Clausen,
	Paul Burton, james.hogan, linux-gpio, devicetree, linux-kernel,
	linux-mips, linux-mmc, linux-mtd, linux-pwm, linux-fbdev
In-Reply-To: <cf809000718514ba612b4f7b477586a9@crapouillou.net>

On 4/3/2017 1:20 PM, Paul Cercueil wrote:

>>> For a description of the pinctrl devicetree node, please read
>>> Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt
>>>
>>> For a description of the gpio devicetree nodes, please read
>>> Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
>>>
>>> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>> [...]
>>
>>> diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi
>>> b/arch/mips/boot/dts/ingenic/jz4740.dtsi
>>> index 3e1587f1f77a..9c23c877fc34 100644
>>> --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
>>> +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
>>> @@ -55,6 +55,67 @@
>>>          clock-names = "rtc";
>>>      };
>>>
>>> +    pinctrl: ingenic-pinctrl@10010000 {
>>
>>    The node name should be generic, so please rename it to something
>> like "pin-controller@..."
>
> OK.
>
>>> +        compatible = "ingenic,jz4740-pinctrl";
>>> +        reg = <0x10010000 0x400>;
>>> +
>>> +        gpa: gpio-controller@0 {
>>
>>    The name should be just "gpio@0", according to ePAPR and its
>> successor spec. Although, using the <unit-address> without the "reg"
>> prop isn't allowed either...
>
> ePAPR says: "If the node has no reg property, the unit-address may be

    My copy of ePAPR 1.1 says "must be omitted". :-)

> omitted if the node name alone differentiates the node from other nodes at
> the same level in the tree."

> I could use 'gpio@bank-a', it is allowed by the spec. Or do you prefer 'gpio@0'?

    Hm... maybe you should just use the "reg" prop.

> I'll wait from some feedback on the other patches then send a v5.
>
> Thanks,
> -Paul

MBR, Sergei


^ permalink raw reply

* Re: [PATCHv5] mfd: cpcap: implement irq sense helper
From: Lee Jones @ 2017-04-03 10:26 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Tony Lindgren, Dmitry Torokhov, Rob Herring, Mark Rutland,
	linux-input, devicetree, linux-kernel
In-Reply-To: <20170329121820.14237-1-sre@kernel.org>

On Wed, 29 Mar 2017, Sebastian Reichel wrote:

> CPCAP can sense if IRQ is currently set or not. This
> functionality is required for a few subdevices, such
> as the power button and usb phy modules.
> 
> Acked-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Changes since PATCHv3:
>  - add extern to function definition
>  - use BIT macro for mask variable
>  - avoid magic numbers
> Changes since PATCHv4:
>  - rename base to irq_base
> ---
>  drivers/mfd/motorola-cpcap.c       | 28 ++++++++++++++++++++++++++++
>  include/linux/mfd/motorola-cpcap.h |  2 ++
>  2 files changed, 30 insertions(+)

Applied, thanks.

> diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
> index 6aeada7d7ce5..a9097efcefa5 100644
> --- a/drivers/mfd/motorola-cpcap.c
> +++ b/drivers/mfd/motorola-cpcap.c
> @@ -23,6 +23,8 @@
>  
>  #define CPCAP_NR_IRQ_REG_BANKS	6
>  #define CPCAP_NR_IRQ_CHIPS	3
> +#define CPCAP_REGISTER_SIZE	4
> +#define CPCAP_REGISTER_BITS	16
>  
>  struct cpcap_ddata {
>  	struct spi_device *spi;
> @@ -32,6 +34,32 @@ struct cpcap_ddata {
>  	struct regmap *regmap;
>  };
>  
> +static int cpcap_sense_irq(struct regmap *regmap, int irq)
> +{
> +	int regnum = irq / CPCAP_REGISTER_BITS;
> +	int mask = BIT(irq % CPCAP_REGISTER_BITS);
> +	int reg = CPCAP_REG_INTS1 + (regnum * CPCAP_REGISTER_SIZE);
> +	int err, val;
> +
> +	if (reg < CPCAP_REG_INTS1 || reg > CPCAP_REG_INTS4)
> +		return -EINVAL;
> +
> +	err = regmap_read(regmap, reg, &val);
> +	if (err)
> +		return err;
> +
> +	return !!(val & mask);
> +}
> +
> +int cpcap_sense_virq(struct regmap *regmap, int virq)
> +{
> +	struct regmap_irq_chip_data *d = irq_get_chip_data(virq);
> +	int irq_base = regmap_irq_chip_get_base(d);
> +
> +	return cpcap_sense_irq(regmap, virq - irq_base);
> +}
> +EXPORT_SYMBOL_GPL(cpcap_sense_virq);
> +
>  static int cpcap_check_revision(struct cpcap_ddata *cpcap)
>  {
>  	u16 vendor, rev;
> diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
> index b4031c2b2214..793aa695faa0 100644
> --- a/include/linux/mfd/motorola-cpcap.h
> +++ b/include/linux/mfd/motorola-cpcap.h
> @@ -290,3 +290,5 @@ static inline int cpcap_get_vendor(struct device *dev,
>  
>  	return 0;
>  }
> +
> +extern int cpcap_sense_virq(struct regmap *regmap, int virq);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH 3/3] dt-bindings: Document Phytec phyCORE-RK3288 RDK
From: Wadim Egorov @ 2017-04-03 10:23 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	heiko-4mtYJXux2i+zQB+pC5nmwQ, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1491214985-18331-1-git-send-email-w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>

Add documentation for the PCM-947 carrier board, a RK3288 based
development board made by PHYTEC.

Signed-off-by: Wadim Egorov <w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/rockchip.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index cc4ace6..e079a62 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -103,6 +103,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "mqmaker,miqi", "rockchip,rk3288";
 
+- Phytec phyCORE-RK3288: Rapid Development Kit
+    Required root node properties:
+     - compatible = "phytec,rk3288-pcm-947", "phytec,rk3288-phycore-som", "rockchip,rk3288";
+
 - Rockchip PX3 Evaluation board:
     Required root node properties:
       - compatible = "rockchip,px3-evb", "rockchip,px3", "rockchip,rk3188";
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ 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