* 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";
> +};
> +
> ®_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 = <®_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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox