Re: [PATCH] media: Fix compilation error

2021-04-07 Thread Mikko Perttunen

On 7.4.2021 16.29, Hans Verkuil wrote:

On 02/04/2021 09:40, Bixuan Cui wrote:

Fix the error:

drivers/staging/media/tegra-video/vi.c:1180:4:
error: implicit declaration of function 'host1x_syncpt_free' 
[-Werror,-Wimplicit-function-declaration]


Against what tree is this being built? The mainline kernel doesn't have
host1x_syncpt_put, only host1x_syncpt_free.


This change was done only very recently, it's in linux-next and 
submitted for 5.13. I missed this one host1x_syncpt_free call in vi.c, 
but Thierry has already applied an equivalent patch on his end so the 
issue should be resolved.


Thanks,
Mikko



Also, the subject line is very vague, something like this is much more 
descriptive:

[PATCH] media: tegra-video: replace host1x_syncpt_free by host1x_syncpt_put

Regards,

Hans



Fixes: 3028a00c55bf ('gpu: host1x: Cleanup and refcounting for syncpoints')
Reported-by: Hulk Robot 
Signed-off-by: Bixuan Cui 
---
  drivers/staging/media/tegra-video/vi.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 7e0cb5529b49..df5ca3596470 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1177,7 +1177,7 @@ static int tegra_channel_host1x_syncpt_init(struct 
tegra_vi_channel *chan)
mw_sp = host1x_syncpt_request(>client, flags);
if (!mw_sp) {
dev_err(vi->dev, "failed to request memory ack 
syncpoint\n");
-   host1x_syncpt_free(fs_sp);
+   host1x_syncpt_put(fs_sp);
ret = -ENOMEM;
goto free_syncpts;
}





Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure

2021-02-16 Thread Mikko Perttunen

On 2/16/21 2:47 PM, Robin Murphy wrote:

Hi Mikko,

On 2021-02-08 16:38, Mikko Perttunen wrote:

To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.


I'd suggest taking a closer look at the patches that made this 
of_dma_configure_id() in the first place, and the corresponding bus code 
in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
in terms of being a bus of logical devices composed from bits of 
implicit behind-the-scenes hardware. I mean, compare your series title 
to the fact that their identifiers are literally named "Isolation 
Context ID" ;)


Please just use the existing mechanisms to describe a mapping between 
Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
giant hacky mess here.


(This also reminds me I wanted to rip out all the PCI special-cases and 
convert pci_dma_configure() over to passing its own IDs too, so thanks 
for the memory-jog...)


Thanks Robin, not sure how I missed that the first time :) Maybe because 
Host1x doesn't have a concept of its own "IDs" for these per se - the 
hardware just uses stream IDs as is. I would need to count the number of 
mapped IDs from the iommu-map property and introduce some 0..N range of 
IDs at the software level. But maybe that's not too bad if we're able to 
use the existing paths and bindings then.


I'll take a look at switching to iommu-map.

Thanks,
Mikko



Robin.


Signed-off-by: Mikko Perttunen 
---
  drivers/iommu/of_iommu.c  | 12 
  drivers/of/device.c   |  9 +
  include/linux/of_device.h | 34 +++---
  include/linux/of_iommu.h  |  6 --
  4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const 
char *prefix, int index,

  }
  EXPORT_SYMBOL_GPL(of_get_dma_window);
-static int of_iommu_xlate(struct device *dev,
-  struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args 
*iommu_spec)

  {
  const struct iommu_ops *ops;
  struct fwnode_handle *fwnode = _spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
  module_put(ops->owner);
  return ret;
  }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
  static int of_iommu_configure_dev_id(struct device_node *master_np,
   struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct 
device_node *master_np,

  const struct iommu_ops *of_iommu_configure(struct device *dev,
 struct device_node *master_np,
-   const u32 *id)
+   const u32 *id,
+   struct of_phandle_args *iommu_spec)
  {
  const struct iommu_ops *ops = NULL;
  struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct 
device *dev,

  err = pci_for_each_dma_alias(to_pci_dev(dev),
   of_pci_iommu_init, );
  } else {
-    err = of_iommu_configure_device(master_np, dev, id);
+    if (iommu_spec)
+    err = of_iommu_xlate(dev, iommu_spec);
+    else
+    err = of_iommu_configure_device(master_np, dev, id);
  fwspec = dev_iommu_fwspec_get(dev);
  if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
   * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE 
events

   * to fix up DMA configuration.
   */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-    bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+    bool force_dma, const u32 *id,
+    struct of_phandle_args *iommu_spec)
  {
  const struct iommu_ops *iommu;
  const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
device_node *np,

  dev_dbg(dev, "device is%sdma coherent\n",
  coherent ? " " : " not ");
-    iommu = of_iommu_configure(dev, np, id);
+    iommu = of_iommu_configure(dev, np, id, iommu_spec);
  if (PTR_ERR(iommu) == -EPROBE_DEFER) {
  kfree(map);
  return -EPROBE_DE

Re: [PATCH] tty: serial: Add earlycon driver for Tegra Combined UART

2021-02-16 Thread Mikko Perttunen

On 2/15/21 2:09 PM, Thierry Reding wrote:

On Mon, Feb 15, 2021 at 12:35:31PM +0200, Mikko Perttunen wrote:

On 2/15/21 12:25 PM, Thierry Reding wrote:

On Sat, Feb 13, 2021 at 01:58:24PM +0200, Mikko Perttunen wrote:

Add an earlycon driver for platforms with TCU, namely Tegra194.
The driver is compatible with boot parameters passed by NVIDIA
boot chains.


I'm not sure I understand the latter part of this description. What boot
parameters is this compatible with? Looking at the setup function there
doesn't seem to be anything out of the ordinary here, so I'm wondering
if that's just confusing. If there's anything special, it might be worth
specifically pointing out what that is. Perhaps both in the commit
message and in a code comment, so it's properly documented.


It's that the name of the driver 'tegra_comb_uart' matches what the boot
chain passes; and that OF_EARLYCON_DECLARE is not used. (OF_EARLYCON_DECLARE
cannot anyway be used due to the mailbox indirection in device tree).


This is all not immediately obvious. Perhaps you can add more of this
into the commit message and perhaps provide an example of how this would
be used on the kernel command-line.


Will do.



You say "mailbox indirection" and looking at the implementation this
does seem to use the mailbox's base address as a sort of TX FIFO, which
I think is all good. However, I'm wondering if we couldn't somehow
detect this all dynamically at runtime. Don't we have access to the
device tree node at this point? If so, couldn't we parse all the
necessary information from the DT instead of relying on the user
providing the mailbox address on the command-line?


Sure, I will look at parsing the address from DT manually at init time.



I realize that this would all make things a bit more complicated in this
driver, but at the same time it'd make life so much easier for users, so
I think it's worth at least considering.

To elaborate on this a bit, I think it'd be much more useful if users
could specify something like this:

earlycon=tegra-tcu

rather than:

earlycon=tegra_comb_uart,0xc15

Note that I'm not even sure if that's a correct address. It'd be even
better if all of this can just be derived from the device tree. My
recollection is that earlycon always needs to be explicitly enabled, but
I thought it was also possible to derive which console to use from the
/chose/stdout-path property in device tree.


The reason I don't think this is that complicated is that that is what 
cboot is already passing to the kernel. Maybe we could support both 
options since it's just 2 or 3 extra lines.





Signed-off-by: Mikko Perttunen 
---
   drivers/tty/serial/Kconfig  | 12 +
   drivers/tty/serial/Makefile |  1 +
   drivers/tty/serial/tegra-tcu-earlycon.c | 72 +
   3 files changed, 85 insertions(+)
   create mode 100644 drivers/tty/serial/tegra-tcu-earlycon.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 34a2899e69c0..d941785e3f46 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -331,6 +331,18 @@ config SERIAL_TEGRA_TCU_CONSOLE
  If unsure, say Y.
+config SERIAL_TEGRA_TCU_EARLYCON
+   bool "Earlycon on NVIDIA Tegra Combined UART"
+   depends on ARCH_TEGRA || COMPILE_TEST
+   select SERIAL_EARLYCON
+   select SERIAL_CORE_CONSOLE
+   default y if SERIAL_TEGRA_TCU_CONSOLE
+   help
+ If you say Y here, TCU output will be supported during the earlycon
+ phase of the boot.
+
+ If unsure, say Y.
+
   config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index b85d53f9e9ff..408144326fed 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
   obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
   obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
   obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU_EARLYCON) += tegra-tcu-earlycon.o
   obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
   obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
   obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu-earlycon.c 
b/drivers/tty/serial/tegra-tcu-earlycon.c
new file mode 100644
index ..9decfbced0a7
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu-earlycon.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2021, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+
+#define NUM_BYTES_FIELD_BIT24
+#define FLUSH_BIT  26


This one seems to be unused.


True, I'll remove it.




+#define INTR_TRIGGER_BIT   31


I wonder if this could somehow be integrated with the existing TCU
driver since we have these bits defined there already. And reall

Re: [PATCH] tty: serial: Add earlycon driver for Tegra Combined UART

2021-02-15 Thread Mikko Perttunen

On 2/15/21 12:25 PM, Thierry Reding wrote:

On Sat, Feb 13, 2021 at 01:58:24PM +0200, Mikko Perttunen wrote:

Add an earlycon driver for platforms with TCU, namely Tegra194.
The driver is compatible with boot parameters passed by NVIDIA
boot chains.


I'm not sure I understand the latter part of this description. What boot
parameters is this compatible with? Looking at the setup function there
doesn't seem to be anything out of the ordinary here, so I'm wondering
if that's just confusing. If there's anything special, it might be worth
specifically pointing out what that is. Perhaps both in the commit
message and in a code comment, so it's properly documented.


It's that the name of the driver 'tegra_comb_uart' matches what the boot 
chain passes; and that OF_EARLYCON_DECLARE is not used. 
(OF_EARLYCON_DECLARE cannot anyway be used due to the mailbox 
indirection in device tree).






Signed-off-by: Mikko Perttunen 
---
  drivers/tty/serial/Kconfig  | 12 +
  drivers/tty/serial/Makefile |  1 +
  drivers/tty/serial/tegra-tcu-earlycon.c | 72 +
  3 files changed, 85 insertions(+)
  create mode 100644 drivers/tty/serial/tegra-tcu-earlycon.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 34a2899e69c0..d941785e3f46 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -331,6 +331,18 @@ config SERIAL_TEGRA_TCU_CONSOLE
  
  	  If unsure, say Y.
  
+config SERIAL_TEGRA_TCU_EARLYCON

+   bool "Earlycon on NVIDIA Tegra Combined UART"
+   depends on ARCH_TEGRA || COMPILE_TEST
+   select SERIAL_EARLYCON
+   select SERIAL_CORE_CONSOLE
+   default y if SERIAL_TEGRA_TCU_CONSOLE
+   help
+ If you say Y here, TCU output will be supported during the earlycon
+ phase of the boot.
+
+ If unsure, say Y.
+
  config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index b85d53f9e9ff..408144326fed 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
  obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
  obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
  obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU_EARLYCON) += tegra-tcu-earlycon.o
  obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
  obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
  obj-$(CONFIG_SERIAL_ARC)  += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu-earlycon.c 
b/drivers/tty/serial/tegra-tcu-earlycon.c
new file mode 100644
index ..9decfbced0a7
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu-earlycon.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2021, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+
+#define NUM_BYTES_FIELD_BIT24
+#define FLUSH_BIT  26


This one seems to be unused.


True, I'll remove it.




+#define INTR_TRIGGER_BIT   31


I wonder if this could somehow be integrated with the existing TCU
driver since we have these bits defined there already. And really this
is basically a skeleton version of the same driver.


+/*
+ * This function splits the string to be printed (const char *s) into multiple
+ * packets. Each packet contains a max of 3 characters. Packets are sent to the
+ * SPE-based combined UART server for printing. Communication with SPE is done
+ * through mailbox registers which can generate interrupts for SPE.
+ */
+static void early_tcu_write(struct console *console, const char *s, unsigned 
int count)
+{
+   struct earlycon_device *device = console->data;
+   u8 __iomem *addr = device->port.membase;
+   u32 mbox_val = BIT(INTR_TRIGGER_BIT);
+   unsigned int i;
+
+   /* Loop for processing each 3 char packet */
+   for (i = 0; i < count; i++) {
+   if (s[i] == '\n')
+   mbox_val = update_and_send_mbox(addr, mbox_val, '\r');
+   mbox_val = update_and_send_mbox(addr, mbox_val, s[i]);
+   }
+
+   if ((mbox_val >> NUM_BYTES_FIELD_BIT) & 0x3) {
+   while (readl(addr) & BIT(INTR_TRIGGER_BIT))
+   cpu_relax();
+   writel(mbox_val, addr);
+   }
+}


For example this function already exists in the Tegra TCU driver and
perhaps some of that could be refactored to work for both cases.


This is very similar to the main tegra_tcu driver, but considering how 
simple this driver is, and the main driver using the mailbox framework 
making the actual implementation incompatible, I was thinking that it's 
easier to just have this be independent.




Thierry



Thanks,
Mikko


[PATCH] tty: serial: Add earlycon driver for Tegra Combined UART

2021-02-13 Thread Mikko Perttunen
Add an earlycon driver for platforms with TCU, namely Tegra194.
The driver is compatible with boot parameters passed by NVIDIA
boot chains.

Signed-off-by: Mikko Perttunen 
---
 drivers/tty/serial/Kconfig  | 12 +
 drivers/tty/serial/Makefile |  1 +
 drivers/tty/serial/tegra-tcu-earlycon.c | 72 +
 3 files changed, 85 insertions(+)
 create mode 100644 drivers/tty/serial/tegra-tcu-earlycon.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 34a2899e69c0..d941785e3f46 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -331,6 +331,18 @@ config SERIAL_TEGRA_TCU_CONSOLE
 
  If unsure, say Y.
 
+config SERIAL_TEGRA_TCU_EARLYCON
+   bool "Earlycon on NVIDIA Tegra Combined UART"
+   depends on ARCH_TEGRA || COMPILE_TEST
+   select SERIAL_EARLYCON
+   select SERIAL_CORE_CONSOLE
+   default y if SERIAL_TEGRA_TCU_CONSOLE
+   help
+ If you say Y here, TCU output will be supported during the earlycon
+ phase of the boot.
+
+ If unsure, say Y.
+
 config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index b85d53f9e9ff..408144326fed 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
 obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
 obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
 obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU_EARLYCON) += tegra-tcu-earlycon.o
 obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
 obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
 obj-$(CONFIG_SERIAL_ARC)   += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu-earlycon.c 
b/drivers/tty/serial/tegra-tcu-earlycon.c
new file mode 100644
index ..9decfbced0a7
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu-earlycon.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2021, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+
+#define NUM_BYTES_FIELD_BIT24
+#define FLUSH_BIT  26
+#define INTR_TRIGGER_BIT   31
+
+static u32 update_and_send_mbox(u8 __iomem *addr, u32 mbox_val, char c)
+{
+   int bytes = bytes = (mbox_val >> NUM_BYTES_FIELD_BIT) & 0x3;
+
+   mbox_val |= BIT(INTR_TRIGGER_BIT);
+   mbox_val |= c << (bytes * 8);
+   bytes++;
+   mbox_val = (mbox_val & ~(3 << NUM_BYTES_FIELD_BIT)) |
+   (bytes << NUM_BYTES_FIELD_BIT);
+
+   if (bytes == 3) {
+   /* Send current packet to SPE */
+   while (readl(addr) & BIT(INTR_TRIGGER_BIT))
+   cpu_relax();
+   writel(mbox_val, addr);
+   mbox_val = BIT(INTR_TRIGGER_BIT);
+   }
+
+   return mbox_val;
+}
+
+/*
+ * This function splits the string to be printed (const char *s) into multiple
+ * packets. Each packet contains a max of 3 characters. Packets are sent to the
+ * SPE-based combined UART server for printing. Communication with SPE is done
+ * through mailbox registers which can generate interrupts for SPE.
+ */
+static void early_tcu_write(struct console *console, const char *s, unsigned 
int count)
+{
+   struct earlycon_device *device = console->data;
+   u8 __iomem *addr = device->port.membase;
+   u32 mbox_val = BIT(INTR_TRIGGER_BIT);
+   unsigned int i;
+
+   /* Loop for processing each 3 char packet */
+   for (i = 0; i < count; i++) {
+   if (s[i] == '\n')
+   mbox_val = update_and_send_mbox(addr, mbox_val, '\r');
+   mbox_val = update_and_send_mbox(addr, mbox_val, s[i]);
+   }
+
+   if ((mbox_val >> NUM_BYTES_FIELD_BIT) & 0x3) {
+   while (readl(addr) & BIT(INTR_TRIGGER_BIT))
+   cpu_relax();
+   writel(mbox_val, addr);
+   }
+}
+
+int __init early_tegra_combined_uart_setup(struct earlycon_device *device, 
const char *options)
+{
+   if (!(device->port.membase))
+   return -ENODEV;
+
+   device->con->write = early_tcu_write;
+
+   return 0;
+}
+
+EARLYCON_DECLARE(tegra_comb_uart, early_tegra_combined_uart_setup);
-- 
2.30.0



[PATCH] mailbox: tegra-hsp: Set lockdep class dynamically

2021-02-10 Thread Mikko Perttunen
On Tegra194, due to both BPMP and TCU using mailboxes, we get a
lockdep spew at boot. Both are using different instances of HSP,
so this is harmless. As such give each HSP instance a different
lockdep class.

Signed-off-by: Mikko Perttunen 
---
 drivers/mailbox/tegra-hsp.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index e07091d71986..acd0675da681 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -98,7 +98,9 @@ struct tegra_hsp {
unsigned int num_ss;
unsigned int num_db;
unsigned int num_si;
+
spinlock_t lock;
+   struct lock_class_key lock_key;
 
struct list_head doorbells;
struct tegra_hsp_mailbox *mailboxes;
@@ -775,6 +777,18 @@ static int tegra_hsp_probe(struct platform_device *pdev)
return err;
}
 
+   lockdep_register_key(>lock_key);
+   lockdep_set_class(>lock, >lock_key);
+
+   return 0;
+}
+
+static int tegra_hsp_remove(struct platform_device *pdev)
+{
+   struct tegra_hsp *hsp = platform_get_drvdata(pdev);
+
+   lockdep_unregister_key(>lock_key);
+
return 0;
 }
 
@@ -834,6 +848,7 @@ static struct platform_driver tegra_hsp_driver = {
.pm = _hsp_pm_ops,
},
.probe = tegra_hsp_probe,
+   .remove = tegra_hsp_remove,
 };
 
 static int __init tegra_hsp_init(void)
-- 
2.30.0



Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure

2021-02-08 Thread Mikko Perttunen

On 2/8/21 6:38 PM, Mikko Perttunen wrote:

...
-static int of_iommu_xlate(struct device *dev,
- struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
...
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
  


These two chunks should not be needed.. looks like I left them in from 
some earlier experiments.


Sending patches out is really the best way to notice mistakes, even 
after reading through them 5 times before.. :)


Mikko


[RFC PATCH 0/8] Host1x context isolation support

2021-02-08 Thread Mikko Perttunen
Hi all,

this series adds support for Host1x 'context isolation'. Since
when programming engines through Host1x, userspace can program in
any addresses it wants, we need some way to isolate the engines'
memory spaces. Traditionally this has either been done imperfectly
with a single shared IOMMU domain, or by copying and verifying the
programming command stream at submit time (Host1x firewall).

Since Tegra186 there is a privileged (only usable by kernel)
Host1x opcode that allows setting the stream ID sent by the engine
to the SMMU. So, by allocating a number of context banks and stream
IDs for this purpose, and using this opcode at the beginning of
each job, we can implement isolation. Due to the limited number of
context banks only each process gets its own context, and not
each channel.

This feature also allows sharing engines among multiple VMs when
used with Host1x's hardware virtualization support - up to 8 VMs
can be configured with a subset of allowed stream IDs, enforced
at hardware level.

To implement this, this series adds a new host1x context bus, which
will contain the 'struct device's corresponding to each context
bank / stream ID, changes to device tree and SMMU code to allow
registering the devices and using the bus, as well as the Host1x
stream ID programming code and support in TegraDRM.

The series is based on v5 of the "Host1x/TegraDRM UAPI" series,
which still hasn't quite settled. Also, I haven't updated the
device tree bindings (or converted them to YAML) yet, so this
is RFC for now.

Thanks!

Mikko

Mikko Perttunen (8):
  of/device: Allow specifying a custom iommu_spec to of_dma_configure
  gpu: host1x: Add context bus
  gpu: host1x: Add context device management code
  gpu: host1x: Program context stream ID on submission
  iommu/arm-smmu: Attach to host1x context device bus
  arm64: tegra: Add Host1x context stream IDs on Tegra186+
  drm/tegra: Support context isolation
  drm/tegra: vic: Implement get_streamid_offset

 arch/arm64/boot/dts/nvidia/tegra186.dtsi  |   9 ++
 drivers/gpu/Makefile  |   3 +-
 drivers/gpu/drm/tegra/drm.h   |   1 +
 drivers/gpu/drm/tegra/uapi.h  |   1 +
 drivers/gpu/drm/tegra/uapi/submit.c   |  13 ++
 drivers/gpu/drm/tegra/uapi/uapi.c |  34 -
 drivers/gpu/drm/tegra/vic.c   |  38 +
 drivers/gpu/host1x/Kconfig|   5 +
 drivers/gpu/host1x/Makefile   |   2 +
 drivers/gpu/host1x/context.c  | 161 ++
 drivers/gpu/host1x/context.h  |  27 
 drivers/gpu/host1x/context_bus.c  |  31 +
 drivers/gpu/host1x/dev.c  |  12 +-
 drivers/gpu/host1x/dev.h  |   2 +
 drivers/gpu/host1x/hw/channel_hw.c|  52 ++-
 drivers/gpu/host1x/hw/host1x06_hardware.h |  10 ++
 drivers/gpu/host1x/hw/host1x07_hardware.h |  10 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c |  13 ++
 drivers/iommu/of_iommu.c  |  12 +-
 drivers/of/device.c   |   9 +-
 include/linux/host1x.h|  21 +++
 include/linux/host1x_context_bus.h|  15 ++
 include/linux/of_device.h |  34 -
 include/linux/of_iommu.h  |   6 +-
 24 files changed, 495 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

-- 
2.30.0



[RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission

2021-02-08 Thread Mikko Perttunen
Add code to do stream ID switching at the beginning of a job. The
stream ID is switched to the stream ID specified by the context
passed in the job structure.

Before switching the stream ID, an OP_DONE wait is done on the
channel's engine to ensure that there is no residual ongoing
work that might do DMA using the new stream ID.

Signed-off-by: Mikko Perttunen 
---
 drivers/gpu/host1x/hw/channel_hw.c| 52 +--
 drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +
 drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +
 include/linux/host1x.h|  4 ++
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c 
b/drivers/gpu/host1x/hw/channel_hw.c
index d88a32f73f5e..f97296864da8 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -129,6 +129,45 @@ static void host1x_channel_set_streamid(struct 
host1x_channel *channel)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+   u32 fence;
+
+   if (!job->context)
+   return;
+
+   fence = host1x_syncpt_incr_max(job->syncpt, 1);
+
+   /* First, increment a syncpoint on OP_DONE condition.. */
+
+   host1x_cdma_push(>channel->cdma,
+   host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1),
+   HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) |
+   HOST1X_UCLASS_INCR_SYNCPT_COND_F(1));
+
+   /* Wait for syncpoint to increment */
+
+   host1x_cdma_push(>channel->cdma,
+   host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
+   host1x_uclass_wait_syncpt_r(), 1),
+   host1x_class_host_wait_syncpt(job->syncpt->id, fence));
+
+   /*
+* Now that we know the engine is idle, return to class and
+* change stream ID.
+*/
+
+   host1x_cdma_push(>channel->cdma,
+   host1x_opcode_setclass(job->class, 0, 0),
+   HOST1X_OPCODE_NOP);
+
+   host1x_cdma_push(>channel->cdma,
+   host1x_opcode_setpayload(job->context->stream_id),
+   host1x_opcode_setstreamid(job->engine_streamid_offset / 4));
+#endif
+}
+
 static int channel_submit(struct host1x_job *job)
 {
struct host1x_channel *ch = job->channel;
@@ -184,18 +223,23 @@ static int channel_submit(struct host1x_job *job)
if (sp->base)
synchronize_syncpt_base(job);
 
-   syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
-
host1x_hw_syncpt_assign_to_channel(host, sp, ch);
 
-   job->syncpt_end = syncval;
-
/* add a setclass for modules that require it */
if (job->class)
host1x_cdma_push(>cdma,
 host1x_opcode_setclass(job->class, 0, 0),
 HOST1X_OPCODE_NOP);
 
+   /*
+* Ensure engine DMA is idle and set new stream ID. May increment
+* syncpt max.
+*/
+   host1x_channel_program_engine_streamid(job);
+
+   syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
+   job->syncpt_end = syncval;
+
submit_gathers(job);
 
/* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h 
b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned 
offset, unsigned count)
return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+   return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+   return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h 
b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned 
offset, unsigned count)
return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+   return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+   return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3cf3c6a0b225..3bf19080f1c1 100644
--- a/include/lin

[RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure

2021-02-08 Thread Mikko Perttunen
To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.

Signed-off-by: Mikko Perttunen 
---
 drivers/iommu/of_iommu.c  | 12 
 drivers/of/device.c   |  9 +
 include/linux/of_device.h | 34 +++---
 include/linux/of_iommu.h  |  6 --
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-static int of_iommu_xlate(struct device *dev,
- struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
const struct iommu_ops *ops;
struct fwnode_handle *fwnode = _spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
module_put(ops->owner);
return ret;
 }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
 
 static int of_iommu_configure_dev_id(struct device_node *master_np,
 struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node 
*master_np,
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
   struct device_node *master_np,
-  const u32 *id)
+  const u32 *id,
+  struct of_phandle_args *iommu_spec)
 {
const struct iommu_ops *ops = NULL;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
err = pci_for_each_dma_alias(to_pci_dev(dev),
 of_pci_iommu_init, );
} else {
-   err = of_iommu_configure_device(master_np, dev, id);
+   if (iommu_spec)
+   err = of_iommu_xlate(dev, iommu_spec);
+   else
+   err = of_iommu_configure_device(master_np, dev, id);
 
fwspec = dev_iommu_fwspec_get(dev);
if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-   bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+   bool force_dma, const u32 *id,
+   struct of_phandle_args *iommu_spec)
 {
const struct iommu_ops *iommu;
const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
device_node *np,
dev_dbg(dev, "device is%sdma coherent\n",
coherent ? " " : " not ");
 
-   iommu = of_iommu_configure(dev, np, id);
+   iommu = of_iommu_configure(dev, np, id, iommu_spec);
if (PTR_ERR(iommu) == -EPROBE_DEFER) {
kfree(map);
return -EPROBE_DEFER;
@@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct 
device_node *np,
dev->dma_range_map = map;
return 0;
 }
-EXPORT_SYMBOL_GPL(of_dma_configure_id);
+EXPORT_SYMBOL_GPL(__of_dma_configure);
 
 int of_device_register(struct platform_device *pdev)
 {
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 07ca187fc5e4..40cc3e788cb9 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,14 +55,27 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
return of_node_get(cpu_dev->of_node);
 }
 
-int of_dma_configure_id(struct device *dev,
+int __of_dma_configure(struct device *dev,
 struct device_node *np,
-bool force_dma, const u32 *id);
+bool force_dma, const u32 *id,
+struct of_phandle_args *iommu_spec);
 static inline int of_dma_configure(struct device *dev,
   struct device_node *np,
   bool force_dma)
 {
-   return of_dma_configure_id(dev, np, force_

[RFC PATCH 3/8] gpu: host1x: Add context device management code

2021-02-08 Thread Mikko Perttunen
Add code to register context devices from device tree, allocate them
out and manage their refcounts.

Signed-off-by: Mikko Perttunen 
---
 drivers/gpu/host1x/Makefile  |   1 +
 drivers/gpu/host1x/context.c | 161 +++
 drivers/gpu/host1x/context.h |  27 ++
 drivers/gpu/host1x/dev.c |  12 ++-
 drivers/gpu/host1x/dev.h |   2 +
 include/linux/host1x.h   |  17 
 6 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index d9fea2885658..9f6797e39057 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -11,6 +11,7 @@ host1x-y = \
mipi.o \
uapi.o \
fence.o \
+   context.o \
hw/host1x01.o \
hw/host1x02.o \
hw/host1x04.o \
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
new file mode 100644
index ..c3bbdb5484c3
--- /dev/null
+++ b/drivers/gpu/host1x/context.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "context.h"
+#include "dev.h"
+
+int host1x_context_list_init(struct host1x *host1x)
+{
+   struct host1x_context_list *cdl = >context_list;
+   struct host1x_context *ctx;
+   struct of_phandle_args iommu_spec;
+   int index;
+   int err;
+
+   cdl->devs = NULL;
+   cdl->len = 0;
+   mutex_init(>lock);
+
+   err = of_count_phandle_with_args(host1x->dev->of_node,
+"nvidia,context-iommus",
+"#iommu-cells");
+   if (err < 0)
+   return 0;
+
+   cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL);
+   if (!cdl->devs)
+   return -ENOMEM;
+   cdl->len = err;
+
+   for (index = 0; index < cdl->len; index++) {
+   err = of_parse_phandle_with_args(host1x->dev->of_node,
+"nvidia,context-iommus",
+"#iommu-cells", index,
+_spec);
+   if (err) {
+   dev_err(host1x->dev, "could not parse context device %d 
from device tree: %d\n",
+   index, err);
+   goto del_devices;
+   }
+
+   ctx = >devs[index];
+
+   ctx->host = host1x;
+
+   device_initialize(>dev);
+
+   ctx->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
+   ctx->dev.dma_mask = >dev.coherent_dma_mask;
+   dev_set_name(>dev, "host1x-ctx.%d", index);
+   ctx->dev.bus = _context_device_bus_type;
+   ctx->dev.parent = host1x->dev;
+
+   dma_set_max_seg_size(>dev, UINT_MAX);
+
+   err = device_add(>dev);
+   if (err) {
+   dev_err(host1x->dev, "could not add context device %d: 
%d\n", index, err);
+   of_node_put(iommu_spec.np);
+   goto del_devices;
+   }
+
+   err = of_dma_configure_iommu_spec(
+   >dev, host1x->dev->of_node, false, _spec);
+   of_node_put(iommu_spec.np);
+   if (err) {
+   dev_err(host1x->dev, "IOMMU configuration failed for 
context device %d: %d\n",
+   index, err);
+   device_del(>dev);
+   goto del_devices;
+   }
+
+   ctx->stream_id = iommu_spec.args[0] & 0x;
+   }
+
+   return 0;
+
+del_devices:
+   while (--index >= 0)
+   device_del(>devs[index].dev);
+
+   kfree(cdl->devs);
+   cdl->len = 0;
+
+   return err;
+}
+
+void host1x_context_list_free(struct host1x_context_list *cdl)
+{
+   int i;
+
+   for (i = 0; i < cdl->len; i++)
+   device_del(>devs[i].dev);
+
+   kfree(cdl->devs);
+   cdl->len = 0;
+}
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+   struct pid *pid)
+{
+   struct host1x_context_list *cdl = >context_list;
+   struct host1x_context *free = NULL;
+   int i;
+
+   if (!cdl->len)
+   return ERR_PTR(-EOPNOTSUPP);
+
+   mutex_lock(>lock);
+
+   for (i = 0; i < cdl->len; i++) {
+   struct host1x_context *cd = >devs[i];
+
+   if (cd->owner == 

[RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset

2021-02-08 Thread Mikko Perttunen
Implement the get_streamid_offset required for supporting context
isolation. Since old firmware cannot support context isolation
without hacks that we don't want to implement, check the firmware
binary to see if context isolation should be enabled.

Signed-off-by: Mikko Perttunen 
---
 drivers/gpu/drm/tegra/vic.c | 38 +
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 6c2f03faec24..f8d5f381904d 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -37,6 +37,8 @@ struct vic {
struct clk *clk;
struct reset_control *rst;
 
+   bool can_use_context;
+
/* Platform configuration */
const struct vic_config *config;
 };
@@ -218,6 +220,7 @@ static int vic_load_firmware(struct vic *vic)
 {
struct host1x_client *client = >client.base;
struct tegra_drm *tegra = vic->client.drm;
+   u32 fce_bin_data_offset;
dma_addr_t iova;
size_t size;
void *virt;
@@ -266,6 +269,25 @@ static int vic_load_firmware(struct vic *vic)
vic->falcon.firmware.phys = phys;
}
 
+   /*
+* Check if firmware is new enough to not require mapping firmware
+* to data buffer domains.
+*/
+   fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+   if (!vic->config->supports_sid) {
+   vic->can_use_context = false;
+   } else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 
0xa5a5a5a5) {
+   /*
+* Firmware will access FCE through STREAMID0, so context
+* isolation cannot be used.
+*/
+   vic->can_use_context = false;
+   dev_warn_once(vic->dev, "context isolation disabled due to old 
firmware\n");
+   } else {
+   vic->can_use_context = true;
+   }
+
return 0;
 
 cleanup:
@@ -357,10 +379,26 @@ static void vic_close_channel(struct tegra_drm_context 
*context)
pm_runtime_put(vic->dev);
 }
 
+static int vic_get_streamid_offset(struct tegra_drm_client *client)
+{
+   struct vic *vic = to_vic(client);
+   int err;
+
+   err = vic_load_firmware(vic);
+   if (err < 0)
+   return err;
+
+   if (vic->can_use_context)
+   return 0x30;
+   else
+   return -ENOTSUPP;
+}
+
 static const struct tegra_drm_client_ops vic_ops = {
.open_channel = vic_open_channel,
.close_channel = vic_close_channel,
.submit = tegra_drm_submit,
+   .get_streamid_offset = vic_get_streamid_offset,
 };
 
 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
-- 
2.30.0



[RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+

2021-02-08 Thread Mikko Perttunen
Add Host1x context stream IDs on systems that support Host1x context
isolation. Host1x and attached engines can use these stream IDs to
allow isolation between memory used by different processes.

The specified stream IDs must match those configured by the hypervisor,
if one is present.

Signed-off-by: Mikko Perttunen 
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index c567aa65418b..25a8cb1a97a6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1176,6 +1176,15 @@ host1x@13e0 {
interconnect-names = "dma-mem";
 
iommus = < TEGRA186_SID_HOST1X>;
+   nvidia,context-iommus = <
+TEGRA186_SID_HOST1X_CTX0
+TEGRA186_SID_HOST1X_CTX1
+TEGRA186_SID_HOST1X_CTX2
+TEGRA186_SID_HOST1X_CTX3
+TEGRA186_SID_HOST1X_CTX4
+TEGRA186_SID_HOST1X_CTX5
+TEGRA186_SID_HOST1X_CTX6
+TEGRA186_SID_HOST1X_CTX7>;
 
dpaux1: dpaux@1504 {
compatible = "nvidia,tegra186-dpaux";
-- 
2.30.0



[RFC PATCH 7/8] drm/tegra: Support context isolation

2021-02-08 Thread Mikko Perttunen
For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

Signed-off-by: Mikko Perttunen 
---
 drivers/gpu/drm/tegra/drm.h |  1 +
 drivers/gpu/drm/tegra/uapi.h|  1 +
 drivers/gpu/drm/tegra/uapi/submit.c | 13 +++
 drivers/gpu/drm/tegra/uapi/uapi.c   | 34 +++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 1af57c2016eb..5d3903372041 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -81,6 +81,7 @@ struct tegra_drm_client_ops {
int (*submit)(struct tegra_drm_context *context,
  struct drm_tegra_submit *args, struct drm_device *drm,
  struct drm_file *file);
+   int (*get_streamid_offset)(struct tegra_drm_client *client);
 };
 
 int tegra_drm_submit(struct tegra_drm_context *context,
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
index 5c422607e8fa..8efb30bbdb4b 100644
--- a/drivers/gpu/drm/tegra/uapi.h
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -26,6 +26,7 @@ struct tegra_drm_file {
 struct tegra_drm_channel_ctx {
struct tegra_drm_client *client;
struct host1x_channel *channel;
+   struct host1x_context *context;
struct xarray mappings;
 };
 
diff --git a/drivers/gpu/drm/tegra/uapi/submit.c 
b/drivers/gpu/drm/tegra/uapi/submit.c
index 8633844ae3d7..1d0dd28af99f 100644
--- a/drivers/gpu/drm/tegra/uapi/submit.c
+++ b/drivers/gpu/drm/tegra/uapi/submit.c
@@ -337,6 +337,9 @@ static void release_job(struct host1x_job *job)
struct tegra_drm_submit_data *job_data = job->user_data;
u32 i;
 
+   if (job->context)
+   host1x_context_put(job->context);
+
for (i = 0; i < job_data->num_used_mappings; i++)
tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
 
@@ -398,6 +401,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, 
void *data,
job->release = release_job;
job->timeout = 1;
 
+   if (ctx->context && ctx->client->ops->get_streamid_offset) {
+   int offset = ctx->client->ops->get_streamid_offset(ctx->client);
+
+   if (offset >= 0) {
+   job->context = ctx->context;
+   job->engine_streamid_offset = offset;
+   host1x_context_get(job->context);
+   }
+   }
+
/*
 * job_data is now part of job reference counting, so don't release
 * it from here.
diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c 
b/drivers/gpu/drm/tegra/uapi/uapi.c
index d503b5e817c4..e2e0c88b858d 100644
--- a/drivers/gpu/drm/tegra/uapi/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi/uapi.c
@@ -49,6 +49,9 @@ static void tegra_drm_channel_ctx_close(struct 
tegra_drm_channel_ctx *ctx)
unsigned long mapping_id;
struct tegra_drm_mapping *mapping;
 
+   if (ctx->context)
+   host1x_context_put(ctx->context);
+
xa_for_each(>mappings, mapping_id, mapping)
tegra_drm_mapping_put(mapping);
 
@@ -82,6 +85,7 @@ void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 struct drm_file *file)
 {
+   struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
struct tegra_drm_file *fpriv = file->driver_priv;
struct tegra_drm *tegra = drm->dev_private;
struct drm_tegra_channel_open *args = data;
@@ -116,10 +120,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, 
void *data,
}
}
 
+   /* Only allocate context if the engine supports context isolation. */
+   if (client->ops->get_streamid_offset &&
+   client->ops->get_streamid_offset(client) >= 0) {
+   ctx->context =
+   host1x_context_alloc(host, get_task_pid(current, 
PIDTYPE_TGID));
+   if (IS_ERR(ctx->context)) {
+   if (PTR_ERR(ctx->context) != -EOPNOTSUPP) {
+   err = PTR_ERR(ctx->context);
+   goto put_channel;
+   } else {
+   /*
+* OK, HW does not support contexts or contexts
+* are disabled.
+*/
+   ctx->context = NULL;
+   }
+   }
+   }
+
err = xa_alloc(>contexts, >channel_ctx, ctx,
   XA_LIMIT(1, U32_MAX), GFP_KERNEL);
if (err < 0)
-   goto put_channel;
+   goto put_context;
 
ctx->

[RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus

2021-02-08 Thread Mikko Perttunen
Set itself as the IOMMU for the host1x context device bus, containing
"dummy" devices used for Host1x context isolation.

Signed-off-by: Mikko Perttunen 
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..ec746c2a08ae 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -40,6 +40,7 @@
 
 #include 
 #include 
+#include 
 
 #include "arm-smmu.h"
 
@@ -2087,8 +2088,20 @@ static int arm_smmu_bus_init(struct iommu_ops *ops)
goto err_reset_pci_ops;
}
 #endif
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+   if (!iommu_present(_context_device_bus_type)) {
+   err = bus_set_iommu(_context_device_bus_type, ops);
+   if (err)
+   goto err_reset_fsl_mc_ops;
+   }
+#endif
+
return 0;
 
+err_reset_fsl_mc_ops: __maybe_unused;
+#ifdef CONFIG_FSL_MC_BUS
+   bus_set_iommu(_mc_bus_type, NULL);
+#endif
 err_reset_pci_ops: __maybe_unused;
 #ifdef CONFIG_PCI
bus_set_iommu(_bus_type, NULL);
-- 
2.30.0



[RFC PATCH 2/8] gpu: host1x: Add context bus

2021-02-08 Thread Mikko Perttunen
The context bus is a "dummy" bus that contains struct devices that
correspond to IOMMU contexts assigned through Host1x to processes.

Even when host1x itself is built as a module, the bus is registered
in built-in code so that the built-in ARM SMMU driver is able to
reference it.

Signed-off-by: Mikko Perttunen 
---
 drivers/gpu/Makefile   |  3 +--
 drivers/gpu/host1x/Kconfig |  5 +
 drivers/gpu/host1x/Makefile|  1 +
 drivers/gpu/host1x/context_bus.c   | 31 ++
 include/linux/host1x_context_bus.h | 15 +++
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 835c88318cec..8997f0096545 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,6 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-$(CONFIG_TEGRA_HOST1X) += host1x/
-obj-y  += drm/ vga/
+obj-y  += host1x/ drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)   += ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)+= trace/
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..8546dde3acc8 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,7 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config TEGRA_HOST1X_CONTEXT_BUS
+   bool
+
 config TEGRA_HOST1X
tristate "NVIDIA Tegra host1x driver"
depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+   select TEGRA_HOST1X_CONTEXT_BUS
select IOMMU_IOVA
help
  Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a48af2cefae1..d9fea2885658 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -19,3 +19,4 @@ host1x-y = \
hw/host1x07.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
new file mode 100644
index ..2625914f3c7d
--- /dev/null
+++ b/drivers/gpu/host1x/context_bus.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include 
+#include 
+
+struct bus_type host1x_context_device_bus_type = {
+   .name = "host1x-context",
+};
+EXPORT_SYMBOL(host1x_context_device_bus_type);
+
+static int __init host1x_context_device_bus_init(void)
+{
+   int err;
+
+   if (!of_machine_is_compatible("nvidia,tegra186") &&
+   !of_machine_is_compatible("nvidia,tegra194") &&
+   !of_machine_is_compatible("nvidia,tegra234"))
+   return 0;
+
+   err = bus_register(_context_device_bus_type);
+   if (err < 0) {
+   pr_err("bus type registration failed: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+postcore_initcall(host1x_context_device_bus_init);
diff --git a/include/linux/host1x_context_bus.h 
b/include/linux/host1x_context_bus.h
new file mode 100644
index ..72462737a6db
--- /dev/null
+++ b/include/linux/host1x_context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __LINUX_HOST1X_CONTEXT_BUS_H
+#define __LINUX_HOST1X_CONTEXT_BUS_H
+
+#include 
+
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+extern struct bus_type host1x_context_device_bus_type;
+#endif
+
+#endif
-- 
2.30.0



Re: [PATCH v3] i2c: bpmp-tegra: Ignore unknown I2C_M flags

2021-01-18 Thread Mikko Perttunen

On 1/17/21 1:20 PM, Wolfram Sang wrote:

On Tue, Jan 12, 2021 at 12:22:25PM +0200, Mikko Perttunen wrote:

In order to not to start returning errors when new I2C_M flags are
added, change behavior to just ignore all flags that we don't know
about. This includes the I2C_M_DMA_SAFE flag that already exists.

Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Mikko Perttunen 


Applied to for-current, thanks! I added also this sentence from v2 to
the description to justify stable: "but causes -EINVAL to be returned
for valid transactions."


Thanks!



Also, this driver has no dedicated maintainer. Is there someone up for
this task? There is probably little to do and it will speed up patch
acceptance because I pick patches once the driver maintainer is happy.



I think it falls under the 'TEGRA ARCHITECTURE SUPPORT' wildcard 
(Thierry and Jon). Do we need a more specific maintainer entry?


If it's helpful to Thierry and Jon, I guess I could pick it up.

Mikko


Re: [PATCH v2] i2c: tegra-bpmp: ignore DMA safe buffer flag

2021-01-12 Thread Mikko Perttunen

On 1/12/21 12:26 PM, Wolfram Sang wrote:



I wonder if bailing out on an unknown flag shouldn't be revisited in
general? I mean this will happen again when a new I2C_M_* flag is
introduced.



If it's guaranteed that any new flags are optional to handle by the driver,
than that is certainly better. I'll post a v3 with that approach.


If there will be a new flag, it is highly likely that it will handle
some corner case which only gets applied when there is a I2C_FUNC_* flag
guarding it. If the new flag turns out to be mandatory, the (poor)
author needs to check with all existing drivers anyhow.



Yep, I suppose that is true :)

I just sent out the v3.

thanks!
Mikko


[PATCH v3] i2c: bpmp-tegra: Ignore unknown I2C_M flags

2021-01-12 Thread Mikko Perttunen
In order to not to start returning errors when new I2C_M flags are
added, change behavior to just ignore all flags that we don't know
about. This includes the I2C_M_DMA_SAFE flag that already exists.

Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Mikko Perttunen 
---
v3:
- Ignore all unknown flags instead of just I2C_M_DMA_SAFE
---
 drivers/i2c/busses/i2c-tegra-bpmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c 
b/drivers/i2c/busses/i2c-tegra-bpmp.c
index ec7a7e917edd..c0c7d01473f2 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -80,7 +80,7 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
flags &= ~I2C_M_RECV_LEN;
}
 
-   return (flags != 0) ? -EINVAL : 0;
+   return 0;
 }
 
 /**
-- 
2.30.0



Re: [PATCH v2] i2c: tegra-bpmp: ignore DMA safe buffer flag

2021-01-12 Thread Mikko Perttunen

On 1/11/21 11:42 PM, Wolfram Sang wrote:

On Mon, Jan 11, 2021 at 05:58:16PM +0200, Mikko Perttunen wrote:

From: Muhammed Fazal 

Ignore I2C_M_DMA_SAFE flag as it does not make a difference
for bpmp-i2c, but causes -EINVAL to be returned for valid
transactions.


I wonder if bailing out on an unknown flag shouldn't be revisited in
general? I mean this will happen again when a new I2C_M_* flag is
introduced.



If it's guaranteed that any new flags are optional to handle by the 
driver, than that is certainly better. I'll post a v3 with that approach.


thanks,
Mikko


[PATCH v2] i2c: tegra: Wait for config load atomically while in ISR

2021-01-11 Thread Mikko Perttunen
Upon a communication error, the interrupt handler can call
tegra_i2c_disable_packet_mode. This causes a sleeping poll to happen
unless the current transaction was marked atomic. Fix this by
making the poll happen atomically if we are in an IRQ.

This matches the behavior prior to the patch mentioned
in the Fixes tag.

Fixes: ede2299f7101 ("i2c: tegra: Support atomic transfers")
Cc: sta...@vger.kernel.org
Signed-off-by: Mikko Perttunen 
---
v2:
* Use in_irq() instead of passing a flag from the ISR.
  Thanks to Dmitry for the suggestion.
* Update commit message.
---
 drivers/i2c/busses/i2c-tegra.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6f08c0c3238d..0727383f4940 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -533,7 +533,7 @@ static int tegra_i2c_poll_register(struct tegra_i2c_dev 
*i2c_dev,
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;
 
-   if (!i2c_dev->atomic_mode)
+   if (!i2c_dev->atomic_mode && !in_irq())
return readl_relaxed_poll_timeout(addr, val, !(val & mask),
  delay_us, timeout_us);
 
-- 
2.30.0



[PATCH v2] i2c: tegra-bpmp: ignore DMA safe buffer flag

2021-01-11 Thread Mikko Perttunen
From: Muhammed Fazal 

Ignore I2C_M_DMA_SAFE flag as it does not make a difference
for bpmp-i2c, but causes -EINVAL to be returned for valid
transactions.

Signed-off-by: Muhammed Fazal 
Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Mikko Perttunen 
---
v2:
- Remove unnecessary check for if the bit is set
---
 drivers/i2c/busses/i2c-tegra-bpmp.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c 
b/drivers/i2c/busses/i2c-tegra-bpmp.c
index ec7a7e917edd..aa6685cabde3 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -80,6 +80,8 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
flags &= ~I2C_M_RECV_LEN;
}
 
+   flags &= ~I2C_M_DMA_SAFE;
+
return (flags != 0) ? -EINVAL : 0;
 }
 
-- 
2.30.0



Re: [PATCH] i2c: tegra: Wait for config load atomically while in ISR

2021-01-11 Thread Mikko Perttunen

On 1/11/21 5:14 PM, Dmitry Osipenko wrote:

11.01.2021 16:55, Mikko Perttunen пишет:

Upon a communication error, the interrupt handler can call
tegra_i2c_disable_packet_mode. This causes a sleeping poll to happen
unless the current transaction was marked atomic. Since
tegra_i2c_disable_packet_mode is only called from the interrupt path,
make it use atomic waiting always.

Fixes: ede2299f7101 ("i2c: tegra: Support atomic transfers")
Cc: sta...@vger.kernel.org
Signed-off-by: Mikko Perttunen 
---
This fixes constant spew for me while HDMI is connected to a
powered off television.

  drivers/i2c/busses/i2c-tegra.c | 16 
  1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6f08c0c3238d..4a7ff1840565 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -528,12 +528,12 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev 
*i2c_dev)
  
  static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,

   u32 reg, u32 mask, u32 delay_us,
-  u32 timeout_us)
+  u32 timeout_us, bool force_atomic)
  {
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;
  
-	if (!i2c_dev->atomic_mode)

+   if (!i2c_dev->atomic_mode && !force_atomic)
return readl_relaxed_poll_timeout(addr, val, !(val & mask),
  delay_us, timeout_us);
  
@@ -560,7 +560,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)

val |= mask;
i2c_writel(i2c_dev, val, offset);
  
-	err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 100);

+   err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 100, 
false);
if (err) {
dev_err(i2c_dev->dev, "failed to flush FIFO\n");
return err;
@@ -569,7 +569,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev 
*i2c_dev)
return 0;
  }
  
-static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)

+static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev, bool 
force_atomic)
  {
int err;
  
@@ -579,7 +579,7 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)

i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
  
  	err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0x,

- 1000, I2C_CONFIG_LOAD_TIMEOUT);
+ 1000, I2C_CONFIG_LOAD_TIMEOUT, 
force_atomic);
if (err) {
dev_err(i2c_dev->dev, "failed to load config\n");
return err;
@@ -684,7 +684,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
  
-	err = tegra_i2c_wait_for_config_load(i2c_dev);

+   err = tegra_i2c_wait_for_config_load(i2c_dev, false);
if (err)
return err;
  
@@ -707,7 +707,7 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)

if (cnfg & I2C_CNFG_PACKET_MODE_EN)
i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
  
-	return tegra_i2c_wait_for_config_load(i2c_dev);

+   return tegra_i2c_wait_for_config_load(i2c_dev, true);
  }
  
  static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)

@@ -1090,7 +1090,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter 
*adap)
  I2C_BC_TERMINATE;
i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
  
-	err = tegra_i2c_wait_for_config_load(i2c_dev);

+   err = tegra_i2c_wait_for_config_load(i2c_dev, false);
if (err)
return err;
  



What about a simpler variant:

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6f08c0c3238d..0727383f4940 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -533,7 +533,7 @@ static int tegra_i2c_poll_register(struct
tegra_i2c_dev *i2c_dev,
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;

-   if (!i2c_dev->atomic_mode)
+   if (!i2c_dev->atomic_mode && !in_irq())
return readl_relaxed_poll_timeout(addr, val, !(val & mask),
  delay_us, timeout_us);



Yep, I'll post a v2 with that.

Mikko


Re: [PATCH] i2c: tegra-bpmp: ignore DMA safe buffer flag

2021-01-11 Thread Mikko Perttunen

On 1/11/21 5:04 PM, Ben Dooks wrote:

On 11/01/2021 14:27, Mikko Perttunen wrote:

From: Muhammed Fazal 

Ignore I2C_M_DMA_SAFE flag as it does not make a difference
for bpmp-i2c, but causes -EINVAL to be returned for valid
transactions.

Signed-off-by: Muhammed Fazal 
Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Mikko Perttunen 
---
This fixes failures seen with PMIC probing tools on
Tegra186+ boards.

  drivers/i2c/busses/i2c-tegra-bpmp.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c 
b/drivers/i2c/busses/i2c-tegra-bpmp.c

index ec7a7e917edd..998d4b21fb59 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -80,6 +80,9 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
  flags &= ~I2C_M_RECV_LEN;
  }
+    if (flags & I2C_M_DMA_SAFE)
+    flags &= ~I2C_M_DMA_SAFE;
+


Just a comment, you can do without the test here.
Just doing this would have been fine:

 flags &= ~I2C_M_DMA_SAFE;





Yep, I'll send a v2.

thanks,
Mikko


Re: [PATCH] i2c: tegra: Wait for config load atomically while in ISR

2021-01-11 Thread Mikko Perttunen
Agreed that this is possibly not optimal, but this patch simply returns 
the behavior to what it was before "i2c: tegra: Support atomic 
transfers", fixing the overt issue.


Design fixes can be considered later, in a non-stable patch.

Mikko

On 1/11/21 4:31 PM, David Laight wrote:

From: Mikko Perttunen

Sent: 11 January 2021 13:56

Upon a communication error, the interrupt handler can call
tegra_i2c_disable_packet_mode. This causes a sleeping poll to happen
unless the current transaction was marked atomic. Since
tegra_i2c_disable_packet_mode is only called from the interrupt path,
make it use atomic waiting always.


Spin-waiting in an ISR for anything that it makes sense to do
a sleep-wait for at other times is badly broken design.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)



[PATCH] i2c: tegra-bpmp: ignore DMA safe buffer flag

2021-01-11 Thread Mikko Perttunen
From: Muhammed Fazal 

Ignore I2C_M_DMA_SAFE flag as it does not make a difference
for bpmp-i2c, but causes -EINVAL to be returned for valid
transactions.

Signed-off-by: Muhammed Fazal 
Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Mikko Perttunen 
---
This fixes failures seen with PMIC probing tools on
Tegra186+ boards.

 drivers/i2c/busses/i2c-tegra-bpmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c 
b/drivers/i2c/busses/i2c-tegra-bpmp.c
index ec7a7e917edd..998d4b21fb59 100644
--- a/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -80,6 +80,9 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
flags &= ~I2C_M_RECV_LEN;
}
 
+   if (flags & I2C_M_DMA_SAFE)
+   flags &= ~I2C_M_DMA_SAFE;
+
return (flags != 0) ? -EINVAL : 0;
 }
 
-- 
2.30.0



[PATCH] i2c: tegra: Wait for config load atomically while in ISR

2021-01-11 Thread Mikko Perttunen
Upon a communication error, the interrupt handler can call
tegra_i2c_disable_packet_mode. This causes a sleeping poll to happen
unless the current transaction was marked atomic. Since
tegra_i2c_disable_packet_mode is only called from the interrupt path,
make it use atomic waiting always.

Fixes: ede2299f7101 ("i2c: tegra: Support atomic transfers")
Cc: sta...@vger.kernel.org
Signed-off-by: Mikko Perttunen 
---
This fixes constant spew for me while HDMI is connected to a
powered off television.

 drivers/i2c/busses/i2c-tegra.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6f08c0c3238d..4a7ff1840565 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -528,12 +528,12 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev 
*i2c_dev)
 
 static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
   u32 reg, u32 mask, u32 delay_us,
-  u32 timeout_us)
+  u32 timeout_us, bool force_atomic)
 {
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;
 
-   if (!i2c_dev->atomic_mode)
+   if (!i2c_dev->atomic_mode && !force_atomic)
return readl_relaxed_poll_timeout(addr, val, !(val & mask),
  delay_us, timeout_us);
 
@@ -560,7 +560,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev 
*i2c_dev)
val |= mask;
i2c_writel(i2c_dev, val, offset);
 
-   err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 100);
+   err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 100, 
false);
if (err) {
dev_err(i2c_dev->dev, "failed to flush FIFO\n");
return err;
@@ -569,7 +569,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev 
*i2c_dev)
return 0;
 }
 
-static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
+static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev, bool 
force_atomic)
 {
int err;
 
@@ -579,7 +579,7 @@ static int tegra_i2c_wait_for_config_load(struct 
tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
 
err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0x,
- 1000, I2C_CONFIG_LOAD_TIMEOUT);
+ 1000, I2C_CONFIG_LOAD_TIMEOUT, 
force_atomic);
if (err) {
dev_err(i2c_dev->dev, "failed to load config\n");
return err;
@@ -684,7 +684,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
 
-   err = tegra_i2c_wait_for_config_load(i2c_dev);
+   err = tegra_i2c_wait_for_config_load(i2c_dev, false);
if (err)
return err;
 
@@ -707,7 +707,7 @@ static int tegra_i2c_disable_packet_mode(struct 
tegra_i2c_dev *i2c_dev)
if (cnfg & I2C_CNFG_PACKET_MODE_EN)
i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
 
-   return tegra_i2c_wait_for_config_load(i2c_dev);
+   return tegra_i2c_wait_for_config_load(i2c_dev, true);
 }
 
 static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
@@ -1090,7 +1090,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter 
*adap)
  I2C_BC_TERMINATE;
i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
 
-   err = tegra_i2c_wait_for_config_load(i2c_dev);
+   err = tegra_i2c_wait_for_config_load(i2c_dev, false);
if (err)
return err;
 
-- 
2.30.0



Re: [PATCH v2 34/48] gpu: host1x: Support power management

2020-12-17 Thread Mikko Perttunen

On 12/17/20 8:06 PM, Dmitry Osipenko wrote:

Add suspend/resume and generic power domain support to the Host1x driver.
This is required for enabling system-wide DVFS and supporting dynamic
power management using a generic power domain.

Tested-by: Peter Geis 
Tested-by: Nicolas Chauvet 
Signed-off-by: Dmitry Osipenko 
---
  drivers/gpu/host1x/dev.c | 102 ++-
  1 file changed, 91 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index d0ebb70e2fdd..c1525cffe7b1 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -12,6 +12,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  
  #define CREATE_TRACE_POINTS

@@ -417,7 +418,7 @@ static int host1x_probe(struct platform_device *pdev)
return err;
}
  
-	host->rst = devm_reset_control_get(>dev, "host1x");

+   host->rst = devm_reset_control_get_exclusive_released(>dev, 
"host1x");
if (IS_ERR(host->rst)) {
err = PTR_ERR(host->rst);
dev_err(>dev, "failed to get reset: %d\n", err);
@@ -437,16 +438,15 @@ static int host1x_probe(struct platform_device *pdev)
goto iommu_exit;
}
  
-	err = clk_prepare_enable(host->clk);

-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock\n");
-   goto free_channels;
-   }
+   pm_runtime_enable(>dev);
+   err = pm_runtime_get_sync(>dev);
+   if (err < 0)
+   goto rpm_disable;
  
  	err = reset_control_deassert(host->rst);

if (err < 0) {
dev_err(>dev, "failed to deassert reset: %d\n", err);
-   goto unprepare_disable;
+   goto rpm_disable;
}
  
  	err = host1x_syncpt_init(host);

@@ -485,9 +485,10 @@ static int host1x_probe(struct platform_device *pdev)
host1x_syncpt_deinit(host);
  reset_assert:
reset_control_assert(host->rst);
-unprepare_disable:
-   clk_disable_unprepare(host->clk);
-free_channels:
+rpm_disable:
+   pm_runtime_put(>dev);
+   pm_runtime_disable(>dev);
+
host1x_channel_list_free(>channel_list);
  iommu_exit:
host1x_iommu_exit(host);
@@ -504,16 +505,95 @@ static int host1x_remove(struct platform_device *pdev)
host1x_intr_deinit(host);
host1x_syncpt_deinit(host);
reset_control_assert(host->rst);
-   clk_disable_unprepare(host->clk);
+   pm_runtime_put(>dev);
+   pm_runtime_disable(>dev);
host1x_iommu_exit(host);
  
  	return 0;

  }
  
+static int __maybe_unused host1x_runtime_suspend(struct device *dev)

+{
+   struct host1x *host = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(host->clk);
+   reset_control_release(host->rst);
+
+   return 0;
+}
+
+static int __maybe_unused host1x_runtime_resume(struct device *dev)
+{
+   struct host1x *host = dev_get_drvdata(dev);
+   int err;
+
+   err = reset_control_acquire(host->rst);
+   if (err) {
+   dev_err(dev, "failed to acquire reset: %d\n", err);
+   return err;
+   }
+
+   err = clk_prepare_enable(host->clk);
+   if (err) {
+   dev_err(dev, "failed to enable clock: %d\n", err);
+   goto release_reset;
+   }
+
+   return 0;
+
+release_reset:
+   reset_control_release(host->rst);
+
+   return err;
+}
+
+static __maybe_unused int host1x_suspend(struct device *dev)
+{
+   struct host1x *host = dev_get_drvdata(dev);
+   int err;
+
+   host1x_syncpt_save(host);
+
+   err = pm_runtime_force_suspend(dev);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+
+static __maybe_unused int host1x_resume(struct device *dev)
+{
+   struct host1x *host = dev_get_drvdata(dev);
+   struct host1x_channel *channel;
+   unsigned int index;
+   int err;
+
+   err = pm_runtime_force_resume(dev);
+   if (err < 0)
+   return err;
+
+   host1x_syncpt_restore(host);


We also need to execute 'host1x_setup_sid_table' upon resume.

cheers,
Mikko


+
+   for_each_set_bit(index, host->channel_list.allocated_channels,
+host->info->nb_channels) {
+   channel = >channel_list.channels[index];
+   host1x_hw_channel_init(host, channel, channel->id);
+   }
+
+   return 0;
+}
+
+static const struct dev_pm_ops host1x_pm = {
+   SET_RUNTIME_PM_OPS(host1x_runtime_suspend, host1x_runtime_resume,
+  NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(host1x_suspend, host1x_resume)
+};
+
  static struct platform_driver tegra_host1x_driver = {
.driver = {
.name = "tegra-host1x",
.of_match_table = host1x_of_match,
+   .pm = _pm,
},
.probe = host1x_probe,
.remove = host1x_remove,



Re: [PATCH -next] gpu: host1x: simplify the return expression of host1x_cdma_init()

2020-09-21 Thread Mikko Perttunen

On 9/21/20 4:10 PM, Qinglang Miao wrote:

Simplify the return expression.

Signed-off-by: Qinglang Miao 
---
  drivers/gpu/host1x/cdma.c | 8 +---
  1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index e8d3fda91..08a0f9e10 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -448,8 +448,6 @@ void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma,
   */
  int host1x_cdma_init(struct host1x_cdma *cdma)
  {
-   int err;
-
mutex_init(>lock);
init_completion(>complete);
  
@@ -459,11 +457,7 @@ int host1x_cdma_init(struct host1x_cdma *cdma)

cdma->running = false;
cdma->torndown = false;
  
-	err = host1x_pushbuffer_init(>push_buffer);

-   if (err)
-   return err;
-
-   return 0;
+   return host1x_pushbuffer_init(>push_buffer);


IMHO, this makes it less readable since now it kind of looks like 
host1x_pushbuffer_init is returning some meaningful value, instead of 
the code just handling error values in a sequence.


Mikko


  }
  
  /*




Re: [PATCH v3 08/16] irqchip/gic: Configure SGIs as standard interrupts

2020-09-16 Thread Mikko Perttunen
Not sure which boards this issue is happening on, but looking at my 
hobby kernel's git history (from a couple of years ago, memory is a bit 
hazy), the commit labeled "Add support for TX2" adds code to drop from 
EL2 to EL1 at boot.


Mikko

On 9/16/20 10:06 PM, Jon Hunter wrote:

On 16/09/2020 17:22, Marc Zyngier wrote:

Do you boot form EL2?


Not that I am aware of. There is no hypervisor that we are using.

Jon



Re: [PATCH] soc/tegra: Add Tegra Soc Version support

2020-06-26 Thread Mikko Perttunen

On 6/26/20 1:29 PM, Sandipan Patra wrote:

Add the chip IDs for NVIDIA Tegra186, Tegra194 and Tegra234
SoC family.


families



Signed-off-by: Sandipan Patra 
---
  include/soc/tegra/fuse.h | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
index 252ea20..4a5236b 100644
--- a/include/soc/tegra/fuse.h
+++ b/include/soc/tegra/fuse.h
@@ -1,6 +1,6 @@
  /* SPDX-License-Identifier: GPL-2.0-only */
  /*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2020, NVIDIA CORPORATION.  All rights reserved.
   */
  
  #ifndef __SOC_TEGRA_FUSE_H__

@@ -12,6 +12,9 @@
  #define TEGRA124  0x40
  #define TEGRA132  0x13
  #define TEGRA210  0x21
+#define TEGRA186   0x18
+#define TEGRA194   0x19
+#define TEGRA234   0x23
  
  #define TEGRA_FUSE_SKU_CALIB_0	0xf0

  #define TEGRA30_FUSE_SATA_CALIB   0x124



Also, can you make the commit message something like "soc/tegra: Add 
defines for Tegra186+ chip IDs"?


thanks,
Mikko


Re: [PATCH net-next 3/3] net: stmmac: Introducing support for Page Pool

2019-07-29 Thread Mikko Perttunen
My understanding is that Tegra186 does not have DMA coherency, but 
Tegra194 does.


Mikko

On 23.7.2019 16.34, Jon Hunter wrote:


On 23/07/2019 13:51, Jose Abreu wrote:

From: Jon Hunter 
Date: Jul/23/2019, 12:58:55 (UTC+00:00)



On 23/07/2019 11:49, Jose Abreu wrote:

From: Jon Hunter 
Date: Jul/23/2019, 11:38:33 (UTC+00:00)



On 23/07/2019 11:07, Jose Abreu wrote:

From: Jon Hunter 
Date: Jul/23/2019, 11:01:24 (UTC+00:00)


This appears to be a winner and by disabling the SMMU for the ethernet
controller and reverting commit 954a03be033c7cef80ddc232e7cbdb17df735663
this worked! So yes appears to be related to the SMMU being enabled. We
had to enable the SMMU for ethernet recently due to commit
954a03be033c7cef80ddc232e7cbdb17df735663.


Finally :)

However, from "git show 954a03be033c7cef80ddc232e7cbdb17df735663":

+ There are few reasons to allow unmatched stream bypass, and
+ even fewer good ones.  If saying YES here breaks your board
+ you should work on fixing your board.

So, how can we fix this ? Is your ethernet DT node marked as
"dma-coherent;" ?


TBH I have no idea. I can't say I fully understand your change or how it
is breaking things for us.

Currently, the Tegra DT binding does not have 'dma-coherent' set. I see
this is optional, but I am not sure how you determine whether or not
this should be set.


 From my understanding it means that your device / IP DMA accesses are coherent 
regarding the CPU point of view. I think it will be the case if GMAC is not 
behind any kind of IOMMU in the HW arch.


I understand what coherency is, I just don't know how you tell if this
implementation of the ethernet controller is coherent or not.


Do you have any detailed diagram of your HW ? Such as blocks / IPs
connection, address space wiring , ...


Yes, this can be found in the Tegra X2 Technical Reference Manual [0].
Unfortunately, you need to create an account to download it.

Jon

[0] https://developer.nvidia.com/embedded/dlc/parker-series-trm



Re: [PATCH] [v2] gpu: host1x: avoid IOMMU_API build error

2019-03-06 Thread Mikko Perttunen

On 6.3.2019 15.57, Arnd Bergmann wrote:

When the iommu API is disabled, the host1x driver fails to build:

drivers/gpu/host1x/hw/channel_hw.c: In function 'host1x_channel_set_streamid':
drivers/gpu/host1x/hw/channel_hw.c:118:30: error: implicit declaration of 
function 'dev_iommu_fwspec_get'; did you mean 'iommu_fwspec_free'? 
[-Werror=implicit-function-declaration]
   struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
   ^~~~
   iommu_fwspec_free
drivers/gpu/host1x/hw/channel_hw.c:118:30: error: initialization of 'struct 
iommu_fwspec *' from 'int' makes pointer from integer without a cast 
[-Werror=int-conversion]
drivers/gpu/host1x/hw/channel_hw.c:119:23: error: 'struct iommu_fwspec' has no 
member named 'ids'
   u32 sid = spec ? spec->ids[0] & 0x : 0x7f;
^~
cc1: all warnings being treated as errors

As Mikko explains, we should program SMMU bypass (0x7f) if that
happens.

Fixes: de5469c21ff9 ("gpu: host1x: Program the channel stream ID")
Suggested-by: Mikko Perttunen 
Signed-off-by: Arnd Bergmann 

v2: fall back to 0x7f sid
---
  drivers/gpu/host1x/hw/channel_hw.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c 
b/drivers/gpu/host1x/hw/channel_hw.c
index 27101c04a827..0c0eb43abf65 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -115,8 +115,12 @@ static inline void synchronize_syncpt_base(struct 
host1x_job *job)
  static void host1x_channel_set_streamid(struct host1x_channel *channel)
  {
  #if HOST1X_HW >= 6
+   u32 sid = 0x7f;
+#ifdef CONFIG_IOMMU_API
struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
-   u32 sid = spec ? spec->ids[0] & 0x : 0x7f;
+   if (spec)
+   sid = spec->ids[0] & 0x;
+#endif
  
  	host1x_ch_writel(channel, sid, HOST1X_CHANNEL_SMMU_STREAMID);

  #endif



Reviewed-by: Mikko Perttunen 


Re: [PATCH] gpu: host1x: avoid IOMMU_API build error

2019-03-05 Thread Mikko Perttunen

On 4.3.2019 21.53, Arnd Bergmann wrote:

drivers/gpu/host1x/hw/channel_hw.c: In function 'host1x_channel_set_streamid':
drivers/gpu/host1x/hw/channel_hw.c:118:30: error: implicit declaration of 
function 'dev_iommu_fwspec_get'; did you mean 'iommu_fwspec_free'? 
[-Werror=implicit-function-declaration]
   struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
   ^~~~
   iommu_fwspec_free
drivers/gpu/host1x/hw/channel_hw.c:118:30: error: initialization of 'struct 
iommu_fwspec *' from 'int' makes pointer from integer without a cast 
[-Werror=int-conversion]
drivers/gpu/host1x/hw/channel_hw.c:119:23: error: 'struct iommu_fwspec' has no 
member named 'ids'
   u32 sid = spec ? spec->ids[0] & 0x : 0x7f;
^~
cc1: all warnings being treated as errors

Fixes: de5469c21ff9 ("gpu: host1x: Program the channel stream ID")
Signed-off-by: Arnd Bergmann 
---
  drivers/gpu/host1x/hw/channel_hw.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c 
b/drivers/gpu/host1x/hw/channel_hw.c
index 27101c04a827..738dccf4ee3f 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -114,7 +114,7 @@ static inline void synchronize_syncpt_base(struct 
host1x_job *job)
  
  static void host1x_channel_set_streamid(struct host1x_channel *channel)

  {
-#if HOST1X_HW >= 6
+#if HOST1X_HW >= 6 && defined(CONFIG_IOMMU_API)
struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
u32 sid = spec ? spec->ids[0] & 0x : 0x7f;
  



We should always program the stream ID - if IOMMU API is not enabled 
then 0x7f (SMMU bypass) should always be programmed.


Mikko


Re: [PATCH 7/9] dt-bindings: tegra186-gpio: Add wakeup parent support

2018-09-21 Thread Mikko Perttunen

On 21/09/2018 19.25, Thierry Reding wrote:

From: Thierry Reding 

Tegra186 and later have some top-level controls for wake events in the
power management controller (PMC). In order to enable the system to wake
up from low power states, additional registers in the PMC need to be
programmed. Add a wakeup-parent property to establish this relationship
between the GPIO controller and the PMC.

Signed-off-by: Thierry Reding 
---
  .../devicetree/bindings/gpio/nvidia,tegra186-gpio.txt  | 7 +++
  1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt 
b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
index adff16c71d21..cbb51a8990c3 100644
--- a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
@@ -127,6 +127,11 @@ Required properties:
  - 8: Active low level-sensitive.
  Valid combinations are 1, 2, 3, 4, 8.
  
+Optional properties:

+- wake-parent


wakeup-parent

Cheers,
Mikko


+A phandle to the Power Management Controller (PMC) that contains top-
+level controls to enable the wake-up capabilities of some GPIOs.
+
  Example:
  
  #include 

@@ -148,6 +153,7 @@ gpio@220 {
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+   wakeup-parent = <>;
  };
  
  gpio@c2f {

@@ -162,4 +168,5 @@ gpio@c2f {
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+   wakeup-parent = <>;
  };



Re: [PATCH 7/9] dt-bindings: tegra186-gpio: Add wakeup parent support

2018-09-21 Thread Mikko Perttunen

On 21/09/2018 19.25, Thierry Reding wrote:

From: Thierry Reding 

Tegra186 and later have some top-level controls for wake events in the
power management controller (PMC). In order to enable the system to wake
up from low power states, additional registers in the PMC need to be
programmed. Add a wakeup-parent property to establish this relationship
between the GPIO controller and the PMC.

Signed-off-by: Thierry Reding 
---
  .../devicetree/bindings/gpio/nvidia,tegra186-gpio.txt  | 7 +++
  1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt 
b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
index adff16c71d21..cbb51a8990c3 100644
--- a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
@@ -127,6 +127,11 @@ Required properties:
  - 8: Active low level-sensitive.
  Valid combinations are 1, 2, 3, 4, 8.
  
+Optional properties:

+- wake-parent


wakeup-parent

Cheers,
Mikko


+A phandle to the Power Management Controller (PMC) that contains top-
+level controls to enable the wake-up capabilities of some GPIOs.
+
  Example:
  
  #include 

@@ -148,6 +153,7 @@ gpio@220 {
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+   wakeup-parent = <>;
  };
  
  gpio@c2f {

@@ -162,4 +168,5 @@ gpio@c2f {
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+   wakeup-parent = <>;
  };



Re: [PATCH 3/9] soc/tegra: pmc: Add wake event support

2018-09-21 Thread Mikko Perttunen

On 21/09/2018 19.25, Thierry Reding wrote:

...
+   /* route wake to tier 2 (XXX conditionally enable this) */
+   value = readl(pmc->wake + WAKE_AOWAKE_TIER2_CTRL);
+   writel(0x1, pmc->wake + WAKE_AOWAKE_TIER2_CTRL);


This doesn't seem right

Cheers,
Mikko


Re: [PATCH 3/9] soc/tegra: pmc: Add wake event support

2018-09-21 Thread Mikko Perttunen

On 21/09/2018 19.25, Thierry Reding wrote:

...
+   /* route wake to tier 2 (XXX conditionally enable this) */
+   value = readl(pmc->wake + WAKE_AOWAKE_TIER2_CTRL);
+   writel(0x1, pmc->wake + WAKE_AOWAKE_TIER2_CTRL);


This doesn't seem right

Cheers,
Mikko


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-09 Thread Mikko Perttunen

Here's my current code:

https://github.com/cyndis/linux/commits/wip/t194-tcu-4

"fixup! mailbox: tegra-hsp: Add support for shared mailboxes" splits up 
the controller into two. "tegra-hsp: use polling" changes it to use polling.


There are two lines in the top patch with comments:

- at the end of tegra_hsp_mailbox_send_data, I left a "while 
(!tegra_hsp_mailbox_last_tx_done(chan));". Without it I wasn't able to 
see even a few garbled characters in the output.


- as mentioned, if I enable tx_block on the client side, I get a BUG: 
scheduling while atomic. I assume this gets printed through the earlycon 
as it's printing out correctly.


Thanks,
Mikko

On 08.08.2018 17:46, Mikko Perttunen wrote:

On 08/08/2018 05:39 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 8:04 PM, Mikko Perttunen  wrote:



On 08/08/2018 05:10 PM, Jassi Brar wrote:


On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  
wrote:




On 04.08.2018 13:45, Mikko Perttunen wrote:



On 08/03/2018 03:54 PM, Jassi Brar wrote:



On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 


wrote:



Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when
transmitting
data.


1) TXDONE_BY_BLOCK flag :-
   Have you tried setting the flag
mbox_chan->mbox_client->tx_block
?




No - I suppose I should have done that. I'm a bit concerned about
overhead
as send_data may be called thousands of times per second, so I 
tried to

make
it as close as possible to the downstream driver that just pokes the
mailbox
register directly.




I tried using polling in the mailbox framework. Some printing is done
from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic
context.
I also tried without tx_block, in which case I got some horribly 
garbled

output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the 
controllers. The

SM controller has txdone_poll = true. I didn't adjust txpoll_period so I
guess it's zero.


Can you please share your code (controller and client) ? Maybe offline
if you wish.



I'll upload a git branch tomorrow -- I'm not at the machine with the 
code now.


Mikko
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-09 Thread Mikko Perttunen

Here's my current code:

https://github.com/cyndis/linux/commits/wip/t194-tcu-4

"fixup! mailbox: tegra-hsp: Add support for shared mailboxes" splits up 
the controller into two. "tegra-hsp: use polling" changes it to use polling.


There are two lines in the top patch with comments:

- at the end of tegra_hsp_mailbox_send_data, I left a "while 
(!tegra_hsp_mailbox_last_tx_done(chan));". Without it I wasn't able to 
see even a few garbled characters in the output.


- as mentioned, if I enable tx_block on the client side, I get a BUG: 
scheduling while atomic. I assume this gets printed through the earlycon 
as it's printing out correctly.


Thanks,
Mikko

On 08.08.2018 17:46, Mikko Perttunen wrote:

On 08/08/2018 05:39 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 8:04 PM, Mikko Perttunen  wrote:



On 08/08/2018 05:10 PM, Jassi Brar wrote:


On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  
wrote:




On 04.08.2018 13:45, Mikko Perttunen wrote:



On 08/03/2018 03:54 PM, Jassi Brar wrote:



On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 


wrote:



Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when
transmitting
data.


1) TXDONE_BY_BLOCK flag :-
   Have you tried setting the flag
mbox_chan->mbox_client->tx_block
?




No - I suppose I should have done that. I'm a bit concerned about
overhead
as send_data may be called thousands of times per second, so I 
tried to

make
it as close as possible to the downstream driver that just pokes the
mailbox
register directly.




I tried using polling in the mailbox framework. Some printing is done
from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic
context.
I also tried without tx_block, in which case I got some horribly 
garbled

output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the 
controllers. The

SM controller has txdone_poll = true. I didn't adjust txpoll_period so I
guess it's zero.


Can you please share your code (controller and client) ? Maybe offline
if you wish.



I'll upload a git branch tomorrow -- I'm not at the machine with the 
code now.


Mikko
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen

On 08/08/2018 05:39 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 8:04 PM, Mikko Perttunen  wrote:



On 08/08/2018 05:10 PM, Jassi Brar wrote:


On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  wrote:




On 04.08.2018 13:45, Mikko Perttunen wrote:



On 08/03/2018 03:54 PM, Jassi Brar wrote:



On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
wrote:



Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when
transmitting
data.


1) TXDONE_BY_BLOCK flag :-
   Have you tried setting the flag
mbox_chan->mbox_client->tx_block
?




No - I suppose I should have done that. I'm a bit concerned about
overhead
as send_data may be called thousands of times per second, so I tried to
make
it as close as possible to the downstream driver that just pokes the
mailbox
register directly.




I tried using polling in the mailbox framework. Some printing is done
from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic
context.
I also tried without tx_block, in which case I got some horribly garbled
output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the controllers. The
SM controller has txdone_poll = true. I didn't adjust txpoll_period so I
guess it's zero.


Can you please share your code (controller and client) ? Maybe offline
if you wish.



I'll upload a git branch tomorrow -- I'm not at the machine with the 
code now.


Mikko


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen

On 08/08/2018 05:39 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 8:04 PM, Mikko Perttunen  wrote:



On 08/08/2018 05:10 PM, Jassi Brar wrote:


On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  wrote:




On 04.08.2018 13:45, Mikko Perttunen wrote:



On 08/03/2018 03:54 PM, Jassi Brar wrote:



On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
wrote:



Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when
transmitting
data.


1) TXDONE_BY_BLOCK flag :-
   Have you tried setting the flag
mbox_chan->mbox_client->tx_block
?




No - I suppose I should have done that. I'm a bit concerned about
overhead
as send_data may be called thousands of times per second, so I tried to
make
it as close as possible to the downstream driver that just pokes the
mailbox
register directly.




I tried using polling in the mailbox framework. Some printing is done
from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic
context.
I also tried without tx_block, in which case I got some horribly garbled
output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the controllers. The
SM controller has txdone_poll = true. I didn't adjust txpoll_period so I
guess it's zero.


Can you please share your code (controller and client) ? Maybe offline
if you wish.



I'll upload a git branch tomorrow -- I'm not at the machine with the 
code now.


Mikko


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen




On 08/08/2018 05:10 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  wrote:



On 04.08.2018 13:45, Mikko Perttunen wrote:


On 08/03/2018 03:54 PM, Jassi Brar wrote:


On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
wrote:


Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
  Have you tried setting the flag mbox_chan->mbox_client->tx_block
?



No - I suppose I should have done that. I'm a bit concerned about overhead
as send_data may be called thousands of times per second, so I tried to make
it as close as possible to the downstream driver that just pokes the mailbox
register directly.



I tried using polling in the mailbox framework. Some printing is done from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic context.
I also tried without tx_block, in which case I got some horribly garbled
output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the controllers. 
The SM controller has txdone_poll = true. I didn't adjust txpoll_period 
so I guess it's zero.


Mikko


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen




On 08/08/2018 05:10 PM, Jassi Brar wrote:

On Wed, Aug 8, 2018 at 5:08 PM, Mikko Perttunen  wrote:



On 04.08.2018 13:45, Mikko Perttunen wrote:


On 08/03/2018 03:54 PM, Jassi Brar wrote:


On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
wrote:


Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
  Have you tried setting the flag mbox_chan->mbox_client->tx_block
?



No - I suppose I should have done that. I'm a bit concerned about overhead
as send_data may be called thousands of times per second, so I tried to make
it as close as possible to the downstream driver that just pokes the mailbox
register directly.



I tried using polling in the mailbox framework. Some printing is done from
atomic context so it seems tx_block cannot be used -
wait_for_completion_timeout understandably does not work in atomic context.
I also tried without tx_block, in which case I got some horribly garbled
output, but "Try increasing MBOX_TX_QUEUE_LEN" was readable there.

Any opinions?


The problems arise because your hardware (SM) supports TXDONE_BY_POLL,
but your client drives it by TXDONE_BY_ACK because the older DB
channels are so.

Please populate SM channels as a separate controller than DB.
The DB controller, as is, run by ACK method.
The SM controller should be run by polling, i.e, set txdone_poll =
true and the poll period small enough. The virtual tty client driver
should be able to safely set tx_block from appropriate context.



Sorry, I should have clarified that I already split up the controllers. 
The SM controller has txdone_poll = true. I didn't adjust txpoll_period 
so I guess it's zero.


Mikko


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen




On 04.08.2018 13:45, Mikko Perttunen wrote:

On 08/03/2018 03:54 PM, Jassi Brar wrote:
On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
 wrote:

Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
 Have you tried setting the flag 
mbox_chan->mbox_client->tx_block ?


No - I suppose I should have done that. I'm a bit concerned about 
overhead as send_data may be called thousands of times per second, so I 
tried to make it as close as possible to the downstream driver that just 
pokes the mailbox register directly.


I tried using polling in the mailbox framework. Some printing is done 
from atomic context so it seems tx_block cannot be used - 
wait_for_completion_timeout understandably does not work in atomic 
context. I also tried without tx_block, in which case I got some 
horribly garbled output, but "Try increasing MBOX_TX_QUEUE_LEN" was 
readable there.


Any opinions?

Thanks,
Mikko





2) Implementing TEGRA_HSP_MBOX_TYPE_SM :-
    In mailbox framework, a controller is a collection of identical
channels. That is, instances of the same class.
    So ideally, in probe you should populate a controller for each
type of channel, i.e, DB, SM, SS and AS.


Hmm, yes, I guess this would be possible if I change the mailbox core to 
allow registering multiple controllers per device.


Thanks!
Mikko


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


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


Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-08 Thread Mikko Perttunen




On 04.08.2018 13:45, Mikko Perttunen wrote:

On 08/03/2018 03:54 PM, Jassi Brar wrote:
On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen 
 wrote:

Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
 Have you tried setting the flag 
mbox_chan->mbox_client->tx_block ?


No - I suppose I should have done that. I'm a bit concerned about 
overhead as send_data may be called thousands of times per second, so I 
tried to make it as close as possible to the downstream driver that just 
pokes the mailbox register directly.


I tried using polling in the mailbox framework. Some printing is done 
from atomic context so it seems tx_block cannot be used - 
wait_for_completion_timeout understandably does not work in atomic 
context. I also tried without tx_block, in which case I got some 
horribly garbled output, but "Try increasing MBOX_TX_QUEUE_LEN" was 
readable there.


Any opinions?

Thanks,
Mikko





2) Implementing TEGRA_HSP_MBOX_TYPE_SM :-
    In mailbox framework, a controller is a collection of identical
channels. That is, instances of the same class.
    So ideally, in probe you should populate a controller for each
type of channel, i.e, DB, SM, SS and AS.


Hmm, yes, I guess this would be possible if I change the mailbox core to 
allow registering multiple controllers per device.


Thanks!
Mikko


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


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


Re: [RFC PATCH v1] memory: tegra: Block DMA for clients HW on a faulty memory access

2018-08-04 Thread Mikko Perttunen
One potential issue is with host1x clients where userspace processes can 
submit jobs with invalid memory accesses (addresses not mapped to 
IOMMU). If when such a failure happens, we disable the DMA for the whole 
host1x client, unrelated userspace processes may see failures even 
though there is no problem with their jobs.


Mikko

On 08/04/2018 02:53 PM, Dmitry Osipenko wrote:

On Tuesday, 8 May 2018 19:58:41 MSK Dmitry Osipenko wrote:

Currently Memory Controller informs about erroneous memory accesses done
by memory clients and that's it. Let's make it to block whole HW unit
that corresponds to the misbehaving memory client in order to try to avoid
memory corruptions and to stop deliberate attempts of manipulation by a
misbehaving client.


Guys, any comments? That is a kinda useful feature, in worst case only some of
memory could get corrupted instead of trashing the whole memory. In my
experience with T20/30, the interrupt handling latency is low and blocking
happens immediately after the first page fault.





Re: [RFC PATCH v1] memory: tegra: Block DMA for clients HW on a faulty memory access

2018-08-04 Thread Mikko Perttunen
One potential issue is with host1x clients where userspace processes can 
submit jobs with invalid memory accesses (addresses not mapped to 
IOMMU). If when such a failure happens, we disable the DMA for the whole 
host1x client, unrelated userspace processes may see failures even 
though there is no problem with their jobs.


Mikko

On 08/04/2018 02:53 PM, Dmitry Osipenko wrote:

On Tuesday, 8 May 2018 19:58:41 MSK Dmitry Osipenko wrote:

Currently Memory Controller informs about erroneous memory accesses done
by memory clients and that's it. Let's make it to block whole HW unit
that corresponds to the misbehaving memory client in order to try to avoid
memory corruptions and to stop deliberate attempts of manipulation by a
misbehaving client.


Guys, any comments? That is a kinda useful feature, in worst case only some of
memory could get corrupted instead of trashing the whole memory. In my
experience with T20/30, the interrupt handling latency is low and blocking
happens immediately after the first page fault.





Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-04 Thread Mikko Perttunen

On 08/03/2018 03:54 PM, Jassi Brar wrote:

On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen  wrote:

Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
 Have you tried setting the flag mbox_chan->mbox_client->tx_block ?


No - I suppose I should have done that. I'm a bit concerned about 
overhead as send_data may be called thousands of times per second, so I 
tried to make it as close as possible to the downstream driver that just 
pokes the mailbox register directly.




2) Implementing TEGRA_HSP_MBOX_TYPE_SM :-
In mailbox framework, a controller is a collection of identical
channels. That is, instances of the same class.
So ideally, in probe you should populate a controller for each
type of channel, i.e, DB, SM, SS and AS.


Hmm, yes, I guess this would be possible if I change the mailbox core to 
allow registering multiple controllers per device.


Thanks!
Mikko


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



Re: [PATCH v3 3/8] mailbox: Add transmit done by blocking option

2018-08-04 Thread Mikko Perttunen

On 08/03/2018 03:54 PM, Jassi Brar wrote:

On Mon, Jul 2, 2018 at 5:10 PM, Mikko Perttunen  wrote:

Add a new TXDONE option, TXDONE_BY_BLOCK. With this option, the
send_data function of the mailbox driver is expected to block until
the message has been sent. The new option is used with the Tegra
Combined UART driver to minimize unnecessary overhead when transmitting
data.


1) TXDONE_BY_BLOCK flag :-
 Have you tried setting the flag mbox_chan->mbox_client->tx_block ?


No - I suppose I should have done that. I'm a bit concerned about 
overhead as send_data may be called thousands of times per second, so I 
tried to make it as close as possible to the downstream driver that just 
pokes the mailbox register directly.




2) Implementing TEGRA_HSP_MBOX_TYPE_SM :-
In mailbox framework, a controller is a collection of identical
channels. That is, instances of the same class.
So ideally, in probe you should populate a controller for each
type of channel, i.e, DB, SM, SS and AS.


Hmm, yes, I guess this would be possible if I change the mailbox core to 
allow registering multiple controllers per device.


Thanks!
Mikko


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



Re: [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch

2018-07-25 Thread Mikko Perttunen




On 24.07.2018 17:34, Aapo Vienamo wrote:

Run the automatic pad calibration after voltage switching if
tegra_host->pad_calib_required is set.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 78781bd..529aa4e7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -537,6 +537,8 @@ static int sdhci_tegra_start_signal_voltage_switch(struct 
mmc_host *mmc,
   struct mmc_ios *ios)
  {
struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
int ret = 0;
  
  	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {

@@ -551,6 +553,9 @@ static int sdhci_tegra_start_signal_voltage_switch(struct 
mmc_host *mmc,
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
}
  
+	if (tegra_host->pad_calib_required)

+   tegra_sdhci_pad_autocalib(host);


What if the autocalibration fails? Should we return an error?


+
return ret;
  }
  



Re: [PATCH 09/10] mmc: tegra: Perform pad calibration after voltage switch

2018-07-25 Thread Mikko Perttunen




On 24.07.2018 17:34, Aapo Vienamo wrote:

Run the automatic pad calibration after voltage switching if
tegra_host->pad_calib_required is set.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 78781bd..529aa4e7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -537,6 +537,8 @@ static int sdhci_tegra_start_signal_voltage_switch(struct 
mmc_host *mmc,
   struct mmc_ios *ios)
  {
struct sdhci_host *host = mmc_priv(mmc);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
int ret = 0;
  
  	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {

@@ -551,6 +553,9 @@ static int sdhci_tegra_start_signal_voltage_switch(struct 
mmc_host *mmc,
ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
}
  
+	if (tegra_host->pad_calib_required)

+   tegra_sdhci_pad_autocalib(host);


What if the autocalibration fails? Should we return an error?


+
return ret;
  }
  



Re: [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Parse the pad drive strength calibration offsets from the device tree.
Program the calibration offsets in accordance with the current signaling
mode.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 147 -
  1 file changed, 146 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0de74f4..78781bd 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -48,6 +48,7 @@
  #define SDHCI_TEGRA_AUTO_CAL_CONFIG   0x1e4
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
+#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK0x
  
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0

  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK  0x000f
@@ -71,6 +72,22 @@ struct sdhci_tegra_soc_data {
u32 nvquirks;
  };
  
+/* Magic pull up and pull down pad calibration offsets */

+struct sdhci_tegra_autocal_offsets {
+   u8 pull_up_3v3;
+   u8 pull_down_3v3;
+   u8 pull_up_3v3_timeout;
+   u8 pull_down_3v3_timeout;
+   u8 pull_up_1v8;
+   u8 pull_down_1v8;
+   u8 pull_up_1v8_timeout;
+   u8 pull_down_1v8_timeout;
+   u8 pull_up_sdr104;
+   u8 pull_down_sdr104;
+   u8 pull_up_hs400;
+   u8 pull_down_hs400;
+}; > +
  struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
struct gpio_desc *power_gpio;
@@ -82,6 +99,8 @@ struct sdhci_tegra {
struct pinctrl *pinctrl_sdmmc;
struct pinctrl_state *pinctrl_state_3v3;
struct pinctrl_state *pinctrl_state_1v8;
+
+   struct sdhci_tegra_autocal_offsets autocal_offsets;
  };
  
  static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)

@@ -248,12 +267,45 @@ static bool tegra_sdhci_configure_card_clk(struct 
sdhci_host *host, bool enable)
return orig_enabled;
  }
  
+static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,

+  u16 pdpu)
+{
+   u32 reg;
+
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg &= ~SDHCI_AUTO_CAL_PDPU_OFFSET_MASK;
+   reg |= pdpu;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_tegra_autocal_offsets offsets =
+   tegra_host->autocal_offsets;
+   struct mmc_ios *ios = >mmc->ios;
unsigned timeout = 10;
bool card_clk_enabled;
+   u16 pdpu;
u32 reg;
  
+	switch (ios->timing) {

+   case MMC_TIMING_UHS_SDR104:
+   pdpu = offsets.pull_down_sdr104 << 8 | offsets.pull_up_sdr104;
+   break;
+   case MMC_TIMING_MMC_HS400:
+   pdpu = offsets.pull_down_hs400 << 8 | offsets.pull_up_hs400;
+   break;
+   default:
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+   pdpu = offsets.pull_down_1v8 << 8 | offsets.pull_up_1v8;
+   else
+   pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
+   }
+
+   tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+
card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
  
  	tegra_sdhci_configure_cal_pad(host, true);

@@ -275,8 +327,99 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
  
  	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
  
-	if (timeout == 0)

+   if (timeout == 0) {
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
+
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+   pdpu = offsets.pull_down_1v8_timeout << 8 |
+  offsets.pull_up_1v8_timeout;
+   else
+   pdpu = offsets.pull_down_3v3_timeout << 8 |
+  offsets.pull_up_3v3_timeout;
+
+   tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+   }
+}
+
+static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_tegra_autocal_offsets *autocal =
+   _host->autocal_offsets;
+   int err;
+
+   err = device_property_read_u8(host->mmc->parent,
+ "pad-autocal-pull-up-offset-3v3",
+ >pull_up_3v3);
+   if (err)
+   autocal->pull_up_3v3 = 0;
+


If you read these properties using read_u8, they'll need to be specified 
in the device tree as "property = /bits/ 8 <...>;", which might not be 
desirable.




Re: [PATCH 06/10] mmc: tegra: Program pad autocal offsets from dt

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Parse the pad drive strength calibration offsets from the device tree.
Program the calibration offsets in accordance with the current signaling
mode.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 147 -
  1 file changed, 146 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0de74f4..78781bd 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -48,6 +48,7 @@
  #define SDHCI_TEGRA_AUTO_CAL_CONFIG   0x1e4
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
+#define SDHCI_AUTO_CAL_PDPU_OFFSET_MASK0x
  
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0

  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK  0x000f
@@ -71,6 +72,22 @@ struct sdhci_tegra_soc_data {
u32 nvquirks;
  };
  
+/* Magic pull up and pull down pad calibration offsets */

+struct sdhci_tegra_autocal_offsets {
+   u8 pull_up_3v3;
+   u8 pull_down_3v3;
+   u8 pull_up_3v3_timeout;
+   u8 pull_down_3v3_timeout;
+   u8 pull_up_1v8;
+   u8 pull_down_1v8;
+   u8 pull_up_1v8_timeout;
+   u8 pull_down_1v8_timeout;
+   u8 pull_up_sdr104;
+   u8 pull_down_sdr104;
+   u8 pull_up_hs400;
+   u8 pull_down_hs400;
+}; > +
  struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
struct gpio_desc *power_gpio;
@@ -82,6 +99,8 @@ struct sdhci_tegra {
struct pinctrl *pinctrl_sdmmc;
struct pinctrl_state *pinctrl_state_3v3;
struct pinctrl_state *pinctrl_state_1v8;
+
+   struct sdhci_tegra_autocal_offsets autocal_offsets;
  };
  
  static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)

@@ -248,12 +267,45 @@ static bool tegra_sdhci_configure_card_clk(struct 
sdhci_host *host, bool enable)
return orig_enabled;
  }
  
+static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,

+  u16 pdpu)
+{
+   u32 reg;
+
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg &= ~SDHCI_AUTO_CAL_PDPU_OFFSET_MASK;
+   reg |= pdpu;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_tegra_autocal_offsets offsets =
+   tegra_host->autocal_offsets;
+   struct mmc_ios *ios = >mmc->ios;
unsigned timeout = 10;
bool card_clk_enabled;
+   u16 pdpu;
u32 reg;
  
+	switch (ios->timing) {

+   case MMC_TIMING_UHS_SDR104:
+   pdpu = offsets.pull_down_sdr104 << 8 | offsets.pull_up_sdr104;
+   break;
+   case MMC_TIMING_MMC_HS400:
+   pdpu = offsets.pull_down_hs400 << 8 | offsets.pull_up_hs400;
+   break;
+   default:
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+   pdpu = offsets.pull_down_1v8 << 8 | offsets.pull_up_1v8;
+   else
+   pdpu = offsets.pull_down_3v3 << 8 | offsets.pull_up_3v3;
+   }
+
+   tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+
card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);
  
  	tegra_sdhci_configure_cal_pad(host, true);

@@ -275,8 +327,99 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
  
  	tegra_sdhci_configure_card_clk(host, card_clk_enabled);
  
-	if (timeout == 0)

+   if (timeout == 0) {
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
+
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+   pdpu = offsets.pull_down_1v8_timeout << 8 |
+  offsets.pull_up_1v8_timeout;
+   else
+   pdpu = offsets.pull_down_3v3_timeout << 8 |
+  offsets.pull_up_3v3_timeout;
+
+   tegra_sdhci_set_pad_autocal_offset(host, pdpu);
+   }
+}
+
+static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_tegra_autocal_offsets *autocal =
+   _host->autocal_offsets;
+   int err;
+
+   err = device_property_read_u8(host->mmc->parent,
+ "pad-autocal-pull-up-offset-3v3",
+ >pull_up_3v3);
+   if (err)
+   autocal->pull_up_3v3 = 0;
+


If you read these properties using read_u8, they'll need to be specified 
in the device tree as "property = /bits/ 8 <...>;", which might not be 
desirable.




Re: [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Add bindings documentation for pad pull up and pull down offset values to be
programmed before executing automatic pad drive strength calibration.

Signed-off-by: Aapo Vienamo 
---
  .../bindings/mmc/nvidia,tegra20-sdhci.txt  | 32 ++
  1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 90c214d..949f616 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -24,6 +24,7 @@ Required properties:
  Optional properties:
  - power-gpios : Specify GPIOs for power control
  
+Optional properties for Tegra210 and Tegra186:

  Example:
  
  sdhci@c8000200 {

@@ -45,6 +46,33 @@ Optional properties for Tegra210 and Tegra186:
for controllers supporting multiple voltage levels. The order of names
should correspond to the pin configuration states in pinctrl-0 and
pinctrl-1.
+- pad-autocal-pull-up-offset-3v3, pad-autocal-pull-down-offset-3v3 :
+  Specify drive strength calibration offsets for 3.3 V signaling modes.
+- pad-autocal-pull-up-offset-1v8, pad-autocal-pull-down-offset-1v8 :
+  Specify drive strength calibration offsets for 1.8 V signaling modes.
+- pad-autocal-pull-up-offset-3v3-timeout,
+  pad-autocal-pull-down-offset-3v3-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  3.3 V signaling mode.
+- pad-autocal-pull-up-offset-1v8-timeout,
+  pad-autocal-pull-down-offset-1v8-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  1.8 V signaling mode.
+- pad-autocal-pull-up-offset-sdr104,
+  pad-autocal-pull-down-offset-sdr104 : Specify drive strength
+  calibration offsets for SDR104 mode.
+- pad-autocal-pull-up-offset-hs400,
+  pad-autocal-pull-down-offset-hs400 : Specify drive strength
+  calibration offsets for HS400 mode.


All of these need an "nvidia," prefix.


+
+  Notes on the pad calibration pull up and pulldown offset values:
+- The property values are drive codes which are programmed into the
+  PD_OFFSET and PU_OFFSET sections of the
+  SDHCI_TEGRA_AUTO_CAL_CONFIG register.
+- A higher value corresponds to higher drive strength. Please refer
+  to the reference manual of the SoC for correct values.
+- The SDR104 and HS400 timing specific values are used in
+  corresponding modes if specified.
  
  Example:

  sdhci@700b {
@@ -58,5 +86,9 @@ sdhci@700b {
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   pad-autocal-pull-up-offset-3v3 = <0x00>;
+   pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
  };



Re: [PATCH 05/10] dt-bindings: Add Tegra SDHCI pad pdpu offset bindings

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Add bindings documentation for pad pull up and pull down offset values to be
programmed before executing automatic pad drive strength calibration.

Signed-off-by: Aapo Vienamo 
---
  .../bindings/mmc/nvidia,tegra20-sdhci.txt  | 32 ++
  1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 90c214d..949f616 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -24,6 +24,7 @@ Required properties:
  Optional properties:
  - power-gpios : Specify GPIOs for power control
  
+Optional properties for Tegra210 and Tegra186:

  Example:
  
  sdhci@c8000200 {

@@ -45,6 +46,33 @@ Optional properties for Tegra210 and Tegra186:
for controllers supporting multiple voltage levels. The order of names
should correspond to the pin configuration states in pinctrl-0 and
pinctrl-1.
+- pad-autocal-pull-up-offset-3v3, pad-autocal-pull-down-offset-3v3 :
+  Specify drive strength calibration offsets for 3.3 V signaling modes.
+- pad-autocal-pull-up-offset-1v8, pad-autocal-pull-down-offset-1v8 :
+  Specify drive strength calibration offsets for 1.8 V signaling modes.
+- pad-autocal-pull-up-offset-3v3-timeout,
+  pad-autocal-pull-down-offset-3v3-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  3.3 V signaling mode.
+- pad-autocal-pull-up-offset-1v8-timeout,
+  pad-autocal-pull-down-offset-1v8-timeout : Specify drive strength
+  used as a fallback in case the automatic calibration times out on a
+  1.8 V signaling mode.
+- pad-autocal-pull-up-offset-sdr104,
+  pad-autocal-pull-down-offset-sdr104 : Specify drive strength
+  calibration offsets for SDR104 mode.
+- pad-autocal-pull-up-offset-hs400,
+  pad-autocal-pull-down-offset-hs400 : Specify drive strength
+  calibration offsets for HS400 mode.


All of these need an "nvidia," prefix.


+
+  Notes on the pad calibration pull up and pulldown offset values:
+- The property values are drive codes which are programmed into the
+  PD_OFFSET and PU_OFFSET sections of the
+  SDHCI_TEGRA_AUTO_CAL_CONFIG register.
+- A higher value corresponds to higher drive strength. Please refer
+  to the reference manual of the SoC for correct values.
+- The SDR104 and HS400 timing specific values are used in
+  corresponding modes if specified.
  
  Example:

  sdhci@700b {
@@ -58,5 +86,9 @@ sdhci@700b {
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
pinctrl-0 = <_3v3>;
pinctrl-1 = <_1v8>;
+   pad-autocal-pull-up-offset-3v3 = <0x00>;
+   pad-autocal-pull-down-offset-3v3 = <0x7d>;
+   pad-autocal-pull-up-offset-1v8 = <0x7b>;
+   pad-autocal-pull-down-offset-1v8 = <0x7b>;
status = "disabled";
  };



Re: [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Disable the card clock during automatic pad drive strength calibration
and re-enable it aftewards.


s/aftewards/afterwards/.



Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 27 +++
  1 file changed, 27 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 61067b7..0de74f4 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -52,6 +52,7 @@
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL0x1e0
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK  0x000f
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL   0x7
+#define SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD  BIT(31)


Looks like this should be in the previous patch.

  
  #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec

  #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
@@ -226,11 +227,35 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
udelay(1);
  }
  
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)

+{
+   bool orig_enabled;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   orig_enabled = reg & SDHCI_CLOCK_CARD_EN;


I would do !!(reg & SDHCI_CLOCK_CARD_EN) here.


+
+   if (orig_enabled == enable)
+   return orig_enabled;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return orig_enabled;
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
unsigned timeout = 10;
+   bool card_clk_enabled;
u32 reg;
  
+	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);

+
tegra_sdhci_configure_cal_pad(host, true);
  
  	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);

@@ -248,6 +273,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
  
  	tegra_sdhci_configure_cal_pad(host, false);
  
+	tegra_sdhci_configure_card_clk(host, card_clk_enabled);

+
if (timeout == 0)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }



Re: [PATCH 04/10] mmc: tegra: Disable card clock during pad calibration

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Disable the card clock during automatic pad drive strength calibration
and re-enable it aftewards.


s/aftewards/afterwards/.



Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 27 +++
  1 file changed, 27 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 61067b7..0de74f4 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -52,6 +52,7 @@
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL0x1e0
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK  0x000f
  #define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL   0x7
+#define SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD  BIT(31)


Looks like this should be in the previous patch.

  
  #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec

  #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
@@ -226,11 +227,35 @@ static void tegra_sdhci_configure_cal_pad(struct 
sdhci_host *host, bool enable)
udelay(1);
  }
  
+static bool tegra_sdhci_configure_card_clk(struct sdhci_host *host, bool enable)

+{
+   bool orig_enabled;
+   u32 reg;
+
+   reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+   orig_enabled = reg & SDHCI_CLOCK_CARD_EN;


I would do !!(reg & SDHCI_CLOCK_CARD_EN) here.


+
+   if (orig_enabled == enable)
+   return orig_enabled;
+
+   if (enable)
+   reg |= SDHCI_CLOCK_CARD_EN;
+   else
+   reg &= ~SDHCI_CLOCK_CARD_EN;
+
+   sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+   return orig_enabled;
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
unsigned timeout = 10;
+   bool card_clk_enabled;
u32 reg;
  
+	card_clk_enabled = tegra_sdhci_configure_card_clk(host, false);

+
tegra_sdhci_configure_cal_pad(host, true);
  
  	reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);

@@ -248,6 +273,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
  
  	tegra_sdhci_configure_cal_pad(host, false);
  
+	tegra_sdhci_configure_card_clk(host, card_clk_enabled);

+
if (timeout == 0)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }



Re: [PATCH 03/10] mmc: tegra: Power on the calibration pad

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 24.07.2018 17:34, Aapo Vienamo wrote:

Automatic pad drive strength calibration is performed on a separate pad
identical to the ones used for driving the actual bus. Power on the
calibration pad during the calibration procedure and power it off
afterwards to save power.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 21 +
  1 file changed, 21 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6008e2f..61067b7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -209,11 +209,30 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
tegra_host->ddr_signaling = false;
  }
  
+static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)

+{
+   u32 reg;
+
+   /*
+* Enable or disable the additional I/O pad used by the drive strength
+* calibration process.
+*/
+   reg = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   if (enable)
+   reg |= SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+   else
+   reg &= ~SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+   sdhci_writel(host, reg, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   udelay(1);
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
unsigned timeout = 10;
u32 reg;
  
+	tegra_sdhci_configure_cal_pad(host, true);

+
reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
@@ -227,6 +246,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
timeout--;
} while (timeout);
  
+	tegra_sdhci_configure_cal_pad(host, false);

+
if (timeout == 0)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }



Re: [PATCH 03/10] mmc: tegra: Power on the calibration pad

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 24.07.2018 17:34, Aapo Vienamo wrote:

Automatic pad drive strength calibration is performed on a separate pad
identical to the ones used for driving the actual bus. Power on the
calibration pad during the calibration procedure and power it off
afterwards to save power.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 21 +
  1 file changed, 21 insertions(+)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 6008e2f..61067b7 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -209,11 +209,30 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
tegra_host->ddr_signaling = false;
  }
  
+static void tegra_sdhci_configure_cal_pad(struct sdhci_host *host, bool enable)

+{
+   u32 reg;
+
+   /*
+* Enable or disable the additional I/O pad used by the drive strength
+* calibration process.
+*/
+   reg = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   if (enable)
+   reg |= SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+   else
+   reg &= ~SDHCI_TEGRA_PAD_E_INPUT_OR_E_PWRD;
+   sdhci_writel(host, reg, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   udelay(1);
+}
+
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
  {
unsigned timeout = 10;
u32 reg;
  
+	tegra_sdhci_configure_cal_pad(host, true);

+
reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
@@ -227,6 +246,8 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host 
*host)
timeout--;
} while (timeout);
  
+	tegra_sdhci_configure_cal_pad(host, false);

+
if (timeout == 0)
dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }



Re: [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Configure the voltage reference used by the automatic pad drive strength
calibration procedure. The value is a magic number from the TRM.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 14 --
  1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e40ca43..6008e2f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,10 @@
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
  
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0

+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+
  #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec
  #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
  
@@ -152,7 +156,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)

struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
-   u32 misc_ctrl, clk_ctrl;
+   u32 misc_ctrl, clk_ctrl, pad_ctrl;
  
  	sdhci_reset(host, mask);
  
@@ -193,8 +197,14 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)

sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
  
-	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)

+   if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
+   pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
+   pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
+   sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+


Will this happen to only eMMC controllers or for all controllers? My 
docs are saying this should be set to 0x7 for SDMMC2/4 and 0x1 or 0x2 
for SDMMC1/3 depending on voltage. Not sure how downstream is 
programming it, though.



tegra_host->pad_calib_required = true;
+   }
  
  	tegra_host->ddr_signaling = false;

  }



Re: [PATCH 02/10] mmc: tegra: Set calibration pad voltage reference

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:34, Aapo Vienamo wrote:

Configure the voltage reference used by the automatic pad drive strength
calibration procedure. The value is a magic number from the TRM.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 14 --
  1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e40ca43..6008e2f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,10 @@
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
  
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL			0x1e0

+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK   0x000f
+#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL0x7
+
  #define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec
  #define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
  
@@ -152,7 +156,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)

struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
-   u32 misc_ctrl, clk_ctrl;
+   u32 misc_ctrl, clk_ctrl, pad_ctrl;
  
  	sdhci_reset(host, mask);
  
@@ -193,8 +197,14 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)

sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
  
-	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)

+   if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB) {
+   pad_ctrl = sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+   pad_ctrl &= ~SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK;
+   pad_ctrl |= SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL;
+   sdhci_writel(host, pad_ctrl, SDHCI_TEGRA_SDMEM_COMP_PADCTRL);
+


Will this happen to only eMMC controllers or for all controllers? My 
docs are saying this should be set to 0x7 for SDMMC2/4 and 0x1 or 0x2 
for SDMMC1/3 depending on voltage. Not sure how downstream is 
programming it, though.



tegra_host->pad_calib_required = true;
+   }
  
  	tegra_host->ddr_signaling = false;

  }



Re: [PATCH 01/10] mmc: tegra: Poll for calibration completion

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:29, Aapo Vienamo wrote:

Implement polling with 10 ms timeout for automatic pad drive strength
calibration.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 24 +++-
  1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f108c48..e40ca43 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,9 @@
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
  
+#define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec

+#define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)


Please align the definition value with tabs. Also it looks like the 
alignments for the defines here are all over the place, would be nice to 
fix those up so they line up.



+
  #define NVQUIRK_FORCE_SDHCI_SPEC_200  BIT(0)
  #define NVQUIRK_ENABLE_BLOCK_GAP_DET  BIT(1)
  #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
@@ -198,13 +201,24 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
  
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)

  {
-   u32 val;
+   unsigned timeout = 10;


I prefer "unsigned int" instead of just "unsigned", but I guess that's 
just a personal preference..



+   u32 reg;
  
-	mdelay(1);

+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   udelay(1);
+
+   do {
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_STATUS);
+   if (!(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE))
+   break;
+   mdelay(1);
+   timeout--;
+   } while (timeout);


Can we use readl_poll_timeout here? We'll need to calculate the address 
directly but it'd still look nicer.


Cheers,
Mikko

  
-	val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);

-   val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
-   sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   if (timeout == 0)
+   dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }
  
  static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)




Re: [PATCH 01/10] mmc: tegra: Poll for calibration completion

2018-07-25 Thread Mikko Perttunen

On 24.07.2018 17:29, Aapo Vienamo wrote:

Implement polling with 10 ms timeout for automatic pad drive strength
calibration.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 24 +++-
  1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f108c48..e40ca43 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -49,6 +49,9 @@
  #define SDHCI_AUTO_CAL_START  BIT(31)
  #define SDHCI_AUTO_CAL_ENABLE BIT(29)
  
+#define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec

+#define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)


Please align the definition value with tabs. Also it looks like the 
alignments for the defines here are all over the place, would be nice to 
fix those up so they line up.



+
  #define NVQUIRK_FORCE_SDHCI_SPEC_200  BIT(0)
  #define NVQUIRK_ENABLE_BLOCK_GAP_DET  BIT(1)
  #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
@@ -198,13 +201,24 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 
mask)
  
  static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)

  {
-   u32 val;
+   unsigned timeout = 10;


I prefer "unsigned int" instead of just "unsigned", but I guess that's 
just a personal preference..



+   u32 reg;
  
-	mdelay(1);

+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   reg |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
+   sdhci_writel(host, reg, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   udelay(1);
+
+   do {
+   reg = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_STATUS);
+   if (!(reg & SDHCI_TEGRA_AUTO_CAL_ACTIVE))
+   break;
+   mdelay(1);
+   timeout--;
+   } while (timeout);


Can we use readl_poll_timeout here? We'll need to calculate the address 
directly but it'd still look nicer.


Cheers,
Mikko

  
-	val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);

-   val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
-   sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG);
+   if (timeout == 0)
+   dev_err(mmc_dev(host->mmc), "Pad autocal timed out\n");
  }
  
  static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)




Re: [PATCH 7/7] arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1

2018-07-25 Thread Mikko Perttunen
Looks like patch 6 will probably cause tegra-sdhci to start advertising 
faster modes (see " if (!IS_ERR(host->mmc->supply.vqmmc))" in 
sdhci-tegra.c). With that patch and this, will the SDHCI core start to 
try putting us into these higher modes? Clearly that won't work yet 
before the upcoming patches.


Mikko

On 20.07.2018 15:45, Aapo Vienamo wrote:

Allow sdmmc1 to set the signaling voltage to 1.8 V in order to support
faster signaling modes.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 1 -
  1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 9d5a0e6..365726d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1452,7 +1452,6 @@
sdhci@700b {
status = "okay";
bus-width = <4>;
-   no-1-8-v;
  
  		cd-gpios = < TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
  



Re: [PATCH 7/7] arm64: dts: tegra210-p2597: Remove no-1-8-v from sdmmc1

2018-07-25 Thread Mikko Perttunen
Looks like patch 6 will probably cause tegra-sdhci to start advertising 
faster modes (see " if (!IS_ERR(host->mmc->supply.vqmmc))" in 
sdhci-tegra.c). With that patch and this, will the SDHCI core start to 
try putting us into these higher modes? Clearly that won't work yet 
before the upcoming patches.


Mikko

On 20.07.2018 15:45, Aapo Vienamo wrote:

Allow sdmmc1 to set the signaling voltage to 1.8 V in order to support
faster signaling modes.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 1 -
  1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 9d5a0e6..365726d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1452,7 +1452,6 @@
sdhci@700b {
status = "okay";
bus-width = <4>;
-   no-1-8-v;
  
  		cd-gpios = < TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
  



Re: [PATCH 6/7] arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply

2018-07-25 Thread Mikko Perttunen
Technically this shouldn't be required since VDD_1V8 is always on 
anyway, but I think it's nicer to specify regulators anyway, so +1!


Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

On p2180 sdmmc4 is powered from a fixed 1.8 V regulator.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 1 +
  1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 8496101..053458a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -273,6 +273,7 @@
status = "okay";
bus-width = <8>;
non-removable;
+   vqmmc-supply = <_1v8>;
};
  
  	clocks {




Re: [PATCH 6/7] arm64: dts: tegra210-p2180: Correct sdmmc4 vqmmc-supply

2018-07-25 Thread Mikko Perttunen
Technically this shouldn't be required since VDD_1V8 is always on 
anyway, but I think it's nicer to specify regulators anyway, so +1!


Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

On p2180 sdmmc4 is powered from a fixed 1.8 V regulator.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 1 +
  1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 8496101..053458a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -273,6 +273,7 @@
status = "okay";
bus-width = <8>;
non-removable;
+   vqmmc-supply = <_1v8>;
};
  
  	clocks {




Re: [PATCH 5/7] arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Set regulator-min-microvolt property of ldo2 to 1.8 V in
tegra210-p2180.dtsi. ldo2 is used by the sdmmc1 SDHCI controller and its
voltage needs to be adjusted down to 1.8 V to support faster signaling
modes. It appears that the comment about the SDHCI driver requesting
invalid voltages no longer applies.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 11 +--
  1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 212e663..8496101 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -178,16 +178,7 @@
  
  vddio_sdmmc: ldo2 {

regulator-name = "VDDIO_SDMMC";
-   /*
-* Technically this supply should have
-* a supported range from 1.8 - 3.3 V.
-* However, that would cause the SDHCI
-* driver to request 2.7 V upon access
-* and that in turn will cause traffic
-* to be broken. Leave it at 3.3 V for
-* now.
-*/
-   regulator-min-microvolt = <330>;
+   regulator-min-microvolt = <180>;
regulator-max-microvolt = <330>;
regulator-always-on;
regulator-boot-on;



Re: [PATCH 5/7] arm64: dts: tegra210-p2180: Allow ldo2 to go down to 1.8 V

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Set regulator-min-microvolt property of ldo2 to 1.8 V in
tegra210-p2180.dtsi. ldo2 is used by the sdmmc1 SDHCI controller and its
voltage needs to be adjusted down to 1.8 V to support faster signaling
modes. It appears that the comment about the SDHCI driver requesting
invalid voltages no longer applies.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 11 +--
  1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 212e663..8496101 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -178,16 +178,7 @@
  
  vddio_sdmmc: ldo2 {

regulator-name = "VDDIO_SDMMC";
-   /*
-* Technically this supply should have
-* a supported range from 1.8 - 3.3 V.
-* However, that would cause the SDHCI
-* driver to request 2.7 V upon access
-* and that in turn will cause traffic
-* to be broken. Leave it at 3.3 V for
-* now.
-*/
-   regulator-min-microvolt = <330>;
+   regulator-min-microvolt = <180>;
regulator-max-microvolt = <330>;
regulator-always-on;
regulator-boot-on;



Re: [PATCH 4/7] arm64: dts: Add Tegra186 sdmmc pinctrl voltage states

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra186.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra186.dtsi | 40 
  1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b762227..7669756 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -4,6 +4,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -236,6 +237,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC1>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -247,6 +251,9 @@

clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC2>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -258,6 +265,9 @@

clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC3>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -368,6 +378,36 @@

  <0 0x0c38 0 0x1>,
  <0 0x0c39 0 0x1>;
reg-names = "pmc", "wake", "aotag", "scratch";
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc2_3v3: sdmmc2-3v3 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc2_1v8: sdmmc2-1v8 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
};
  
  	ccplex@e00 {




Re: [PATCH 4/7] arm64: dts: Add Tegra186 sdmmc pinctrl voltage states

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra186.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra186.dtsi | 40 
  1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b762227..7669756 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -4,6 +4,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -236,6 +237,9 @@
clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC1>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -247,6 +251,9 @@

clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC2>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -258,6 +265,9 @@

clock-names = "sdhci";
resets = < TEGRA186_RESET_SDMMC3>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -368,6 +378,36 @@

  <0 0x0c38 0 0x1>,
  <0 0x0c39 0 0x1>;
reg-names = "pmc", "wake", "aotag", "scratch";
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1-hv";
+   power-source = ;
+   };
+
+   sdmmc2_3v3: sdmmc2-3v3 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc2_1v8: sdmmc2-1v8 {
+   pins = "sdmmc2-hv";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3-hv";
+   power-source = ;
+   };
};
  
  	ccplex@e00 {




Re: [PATCH 3/7] arm64: dts: Add Tegra210 sdmmc pinctrl voltage states

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra210.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210.dtsi | 27 +++
  1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 3be920e..bc1918e 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -3,6 +3,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  
@@ -776,6 +777,26 @@

#power-domain-cells = <0>;
};
};
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
};
  
  	fuse@7000f800 {

@@ -1027,6 +1048,9 @@
clock-names = "sdhci";
resets = <_car 14>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -1049,6 +1073,9 @@

clock-names = "sdhci";
resets = <_car 69>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  



Re: [PATCH 3/7] arm64: dts: Add Tegra210 sdmmc pinctrl voltage states

2018-07-25 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Add pad voltage configuration nodes for sdmmc pads with configurable
voltages on Tegra210.

Signed-off-by: Aapo Vienamo 
---
  arch/arm64/boot/dts/nvidia/tegra210.dtsi | 27 +++
  1 file changed, 27 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 3be920e..bc1918e 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -3,6 +3,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  
@@ -776,6 +777,26 @@

#power-domain-cells = <0>;
};
};
+
+   sdmmc1_3v3: sdmmc1-3v3 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc1_1v8: sdmmc1-1v8 {
+   pins = "sdmmc1";
+   power-source = ;
+   };
+
+   sdmmc3_3v3: sdmmc3-3v3 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
+
+   sdmmc3_1v8: sdmmc3-1v8 {
+   pins = "sdmmc3";
+   power-source = ;
+   };
};
  
  	fuse@7000f800 {

@@ -1027,6 +1048,9 @@
clock-names = "sdhci";
resets = <_car 14>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  
@@ -1049,6 +1073,9 @@

clock-names = "sdhci";
resets = <_car 69>;
reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
status = "disabled";
};
  



Re: [PATCH 1/7] dt-bindings: Document Tegra SDHCI pinctrl bindings

2018-07-25 Thread Mikko Perttunen
I would maybe say "dt-bindings: mmc: tegra: Add pad voltage control 
properties" or similar for the subject - the current kind of looks like 
the SDHCI controller is a pinctrl device :)


Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Document the pinctrl bindings used by the SDHCI driver to reconfigure
pad voltages on controllers supporting multiple voltage levels.

Signed-off-by: Aapo Vienamo 
---
  .../bindings/mmc/nvidia,tegra20-sdhci.txt  | 22 ++
  1 file changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9bce578..90c214d 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -38,3 +38,25 @@ sdhci@c8000200 {
power-gpios = < 155 0>; /* gpio PT3 */
bus-width = <8>;
  };
+
+Optional properties for Tegra210 and Tegra186:
+- pinctrl-names, pinctrl-0, pinctrl-1 : Specify pad voltage
+  configurations. Valid pinctrl-names are "sdmmc-3v3" and "sdmmc-1v8"
+  for controllers supporting multiple voltage levels. The order of names
+  should correspond to the pin configuration states in pinctrl-0 and
+  pinctrl-1.
+
+Example:
+sdhci@700b {
+   compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
+   reg = <0x0 0x700b 0x0 0x200>;
+   interrupts = ;
+   clocks = <_car TEGRA210_CLK_SDMMC1>;
+   clock-names = "sdhci";
+   resets = <_car 14>;
+   reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   status = "disabled";
+};



Re: [PATCH 1/7] dt-bindings: Document Tegra SDHCI pinctrl bindings

2018-07-25 Thread Mikko Perttunen
I would maybe say "dt-bindings: mmc: tegra: Add pad voltage control 
properties" or similar for the subject - the current kind of looks like 
the SDHCI controller is a pinctrl device :)


Reviewed-by: Mikko Perttunen 

On 20.07.2018 15:45, Aapo Vienamo wrote:

Document the pinctrl bindings used by the SDHCI driver to reconfigure
pad voltages on controllers supporting multiple voltage levels.

Signed-off-by: Aapo Vienamo 
---
  .../bindings/mmc/nvidia,tegra20-sdhci.txt  | 22 ++
  1 file changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt 
b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 9bce578..90c214d 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -38,3 +38,25 @@ sdhci@c8000200 {
power-gpios = < 155 0>; /* gpio PT3 */
bus-width = <8>;
  };
+
+Optional properties for Tegra210 and Tegra186:
+- pinctrl-names, pinctrl-0, pinctrl-1 : Specify pad voltage
+  configurations. Valid pinctrl-names are "sdmmc-3v3" and "sdmmc-1v8"
+  for controllers supporting multiple voltage levels. The order of names
+  should correspond to the pin configuration states in pinctrl-0 and
+  pinctrl-1.
+
+Example:
+sdhci@700b {
+   compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
+   reg = <0x0 0x700b 0x0 0x200>;
+   interrupts = ;
+   clocks = <_car TEGRA210_CLK_SDMMC1>;
+   clock-names = "sdhci";
+   resets = <_car 14>;
+   reset-names = "sdhci";
+   pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+   pinctrl-0 = <_3v3>;
+   pinctrl-1 = <_1v8>;
+   status = "disabled";
+};



Re: [PATCH 2/7] mmc: tegra: Reconfigure pad voltages during voltage switching

2018-07-25 Thread Mikko Perttunen

On 20.07.2018 15:45, Aapo Vienamo wrote:

Parse the pinctrl states from the device tree and implement pad voltage
state reconfiguration in the mmc start_signal_voltage_switch() callback.
This is done in the mmc callback because the order of pad
reconfiguration and sdhci voltage switch depend on the voltage to which
the transition occurs.

Add NVQUIRK_NEEDS_PAD_CONTROL and add set it for Tegra210 and Tegra186.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 91 +++---
  1 file changed, 85 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ddf00166..f108c48 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -21,6 +21,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -55,6 +56,7 @@
  #define NVQUIRK_ENABLE_SDR104 BIT(4)
  #define NVQUIRK_ENABLE_DDR50  BIT(5)
  #define NVQUIRK_HAS_PADCALIB  BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
  
  struct sdhci_tegra_soc_data {

const struct sdhci_pltfm_data *pdata;
@@ -66,8 +68,12 @@ struct sdhci_tegra {
struct gpio_desc *power_gpio;
bool ddr_signaling;
bool pad_calib_required;
+   bool pad_control_required;
  
  	struct reset_control *rst;

+   struct pinctrl *pinctrl_sdmmc;
+   struct pinctrl_state *pinctrl_state_3v3;
+   struct pinctrl_state *pinctrl_state_1v8;
  };
  
  static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)

@@ -286,14 +292,80 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host 
*host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
  }
  
-static void tegra_sdhci_voltage_switch(struct sdhci_host *host)

+static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
  {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-   const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+   int ret;
+
+   if (!tegra_host->pad_control_required)
+   return 0;
+
+   if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_1v8);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 1.8V failed, ret: %d\n", ret);
+   } else {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_3v3);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 3.3V failed, ret: %d\n", ret);
+   }
  
-	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)

-   tegra_host->pad_calib_required = true;
+   return ret;
+}
+
+static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
+  struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   int ret = 0;
+
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+   ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+   if (ret < 0)
+   return ret;
+   ret = sdhci_start_signal_voltage_switch(mmc, ios);
+   } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = sdhci_start_signal_voltage_switch(mmc, ios);
+   if (ret < 0)
+   return ret;
+   ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+   }
+
+   return ret;
+}
+
+static void tegra_sdhci_init_pinctrl_info(struct device *dev,
+ struct sdhci_tegra *tegra_host)
+{
+   tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev);
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_sdmmc)) {


Can this ever return NULL, considering ARCH_TEGRA selects PINCTRL? 
IS_ERR is probably better. Same for the two other checks in this function.



+   dev_dbg(dev, "No pinctrl info, err: %ld\n",
+   PTR_ERR(tegra_host->pinctrl_sdmmc));
+   return;
+   }
+
+   tegra_host->pinctrl_state_3v3 =
+   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3");
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_state_3v3)) {
+   dev_err(dev, "Missing 3.3V pad state, err: %ld\n",
+   PTR_ERR(tegra_host->pinctrl_state_3v3));
+   return;
+   }
+
+   tegra_host->pinctrl_state_1v8 =
+   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8");
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_state_1v8)) {
+   dev_err(dev, "Missing 1.8V pad state, err: %ld\n",
+ 

Re: [PATCH 2/7] mmc: tegra: Reconfigure pad voltages during voltage switching

2018-07-25 Thread Mikko Perttunen

On 20.07.2018 15:45, Aapo Vienamo wrote:

Parse the pinctrl states from the device tree and implement pad voltage
state reconfiguration in the mmc start_signal_voltage_switch() callback.
This is done in the mmc callback because the order of pad
reconfiguration and sdhci voltage switch depend on the voltage to which
the transition occurs.

Add NVQUIRK_NEEDS_PAD_CONTROL and add set it for Tegra210 and Tegra186.

Signed-off-by: Aapo Vienamo 
---
  drivers/mmc/host/sdhci-tegra.c | 91 +++---
  1 file changed, 85 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ddf00166..f108c48 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -21,6 +21,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -55,6 +56,7 @@
  #define NVQUIRK_ENABLE_SDR104 BIT(4)
  #define NVQUIRK_ENABLE_DDR50  BIT(5)
  #define NVQUIRK_HAS_PADCALIB  BIT(6)
+#define NVQUIRK_NEEDS_PAD_CONTROL  BIT(7)
  
  struct sdhci_tegra_soc_data {

const struct sdhci_pltfm_data *pdata;
@@ -66,8 +68,12 @@ struct sdhci_tegra {
struct gpio_desc *power_gpio;
bool ddr_signaling;
bool pad_calib_required;
+   bool pad_control_required;
  
  	struct reset_control *rst;

+   struct pinctrl *pinctrl_sdmmc;
+   struct pinctrl_state *pinctrl_state_3v3;
+   struct pinctrl_state *pinctrl_state_1v8;
  };
  
  static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)

@@ -286,14 +292,80 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host 
*host, u32 opcode)
return mmc_send_tuning(host->mmc, opcode, NULL);
  }
  
-static void tegra_sdhci_voltage_switch(struct sdhci_host *host)

+static int tegra_sdhci_set_padctrl(struct sdhci_host *host, int voltage)
  {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
-   const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+   int ret;
+
+   if (!tegra_host->pad_control_required)
+   return 0;
+
+   if (voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_1v8);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 1.8V failed, ret: %d\n", ret);
+   } else {
+   ret = pinctrl_select_state(tegra_host->pinctrl_sdmmc,
+  tegra_host->pinctrl_state_3v3);
+   if (ret < 0)
+   dev_err(mmc_dev(host->mmc),
+   "setting 3.3V failed, ret: %d\n", ret);
+   }
  
-	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)

-   tegra_host->pad_calib_required = true;
+   return ret;
+}
+
+static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
+  struct mmc_ios *ios)
+{
+   struct sdhci_host *host = mmc_priv(mmc);
+   int ret = 0;
+
+   if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+   ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+   if (ret < 0)
+   return ret;
+   ret = sdhci_start_signal_voltage_switch(mmc, ios);
+   } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+   ret = sdhci_start_signal_voltage_switch(mmc, ios);
+   if (ret < 0)
+   return ret;
+   ret = tegra_sdhci_set_padctrl(host, ios->signal_voltage);
+   }
+
+   return ret;
+}
+
+static void tegra_sdhci_init_pinctrl_info(struct device *dev,
+ struct sdhci_tegra *tegra_host)
+{
+   tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev);
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_sdmmc)) {


Can this ever return NULL, considering ARCH_TEGRA selects PINCTRL? 
IS_ERR is probably better. Same for the two other checks in this function.



+   dev_dbg(dev, "No pinctrl info, err: %ld\n",
+   PTR_ERR(tegra_host->pinctrl_sdmmc));
+   return;
+   }
+
+   tegra_host->pinctrl_state_3v3 =
+   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-3v3");
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_state_3v3)) {
+   dev_err(dev, "Missing 3.3V pad state, err: %ld\n",
+   PTR_ERR(tegra_host->pinctrl_state_3v3));
+   return;
+   }
+
+   tegra_host->pinctrl_state_1v8 =
+   pinctrl_lookup_state(tegra_host->pinctrl_sdmmc, "sdmmc-1v8");
+   if (IS_ERR_OR_NULL(tegra_host->pinctrl_state_1v8)) {
+   dev_err(dev, "Missing 1.8V pad state, err: %ld\n",
+ 

Re: [PATCH] Revert "ata: ahci_platform: convert kcalloc to devm_kcalloc"

2018-07-17 Thread Mikko Perttunen

Thanks!

Reviewed-by: Mikko Perttunen 

On 17.07.2018 13:49, Corentin Labbe wrote:

Since ahci_platform_put_resources() use target_pwrs after "devm_" freed
it, we cannot use devm_kcalloc for allocating target_pwrs.

This reverts commit bd0038b1b4f499d814d8f33a55b1df5ea6cf3b85.

Reported-by: Mikko Perttunen 
Signed-off-by: Corentin Labbe 
---
  drivers/ata/libahci_platform.c | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index fe8939e161ea..2ceebaf2ed56 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -271,6 +271,8 @@ static void ahci_platform_put_resources(struct device *dev, 
void *res)
for (c = 0; c < hpriv->nports; c++)
if (hpriv->target_pwrs && hpriv->target_pwrs[c])
regulator_put(hpriv->target_pwrs[c]);
+
+   kfree(hpriv->target_pwrs);
  }
  
  static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,

@@ -406,7 +408,11 @@ struct ahci_host_priv *ahci_platform_get_resources(struct 
platform_device *pdev)
rc = -ENOMEM;
goto err_out;
}
-   hpriv->target_pwrs = devm_kcalloc(dev, hpriv->nports, 
sizeof(*hpriv->target_pwrs), GFP_KERNEL);
+   /*
+* We cannot use devm_ here, since ahci_platform_put_resources() uses
+* target_pwrs after devm_ have freed memory
+*/
+   hpriv->target_pwrs = kcalloc(hpriv->nports, 
sizeof(*hpriv->target_pwrs), GFP_KERNEL);
if (!hpriv->target_pwrs) {
rc = -ENOMEM;
goto err_out;



Re: [PATCH] Revert "ata: ahci_platform: convert kcalloc to devm_kcalloc"

2018-07-17 Thread Mikko Perttunen

Thanks!

Reviewed-by: Mikko Perttunen 

On 17.07.2018 13:49, Corentin Labbe wrote:

Since ahci_platform_put_resources() use target_pwrs after "devm_" freed
it, we cannot use devm_kcalloc for allocating target_pwrs.

This reverts commit bd0038b1b4f499d814d8f33a55b1df5ea6cf3b85.

Reported-by: Mikko Perttunen 
Signed-off-by: Corentin Labbe 
---
  drivers/ata/libahci_platform.c | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index fe8939e161ea..2ceebaf2ed56 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -271,6 +271,8 @@ static void ahci_platform_put_resources(struct device *dev, 
void *res)
for (c = 0; c < hpriv->nports; c++)
if (hpriv->target_pwrs && hpriv->target_pwrs[c])
regulator_put(hpriv->target_pwrs[c]);
+
+   kfree(hpriv->target_pwrs);
  }
  
  static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,

@@ -406,7 +408,11 @@ struct ahci_host_priv *ahci_platform_get_resources(struct 
platform_device *pdev)
rc = -ENOMEM;
goto err_out;
}
-   hpriv->target_pwrs = devm_kcalloc(dev, hpriv->nports, 
sizeof(*hpriv->target_pwrs), GFP_KERNEL);
+   /*
+* We cannot use devm_ here, since ahci_platform_put_resources() uses
+* target_pwrs after devm_ have freed memory
+*/
+   hpriv->target_pwrs = kcalloc(hpriv->nports, 
sizeof(*hpriv->target_pwrs), GFP_KERNEL);
if (!hpriv->target_pwrs) {
rc = -ENOMEM;
goto err_out;



Boot WARN with patch "regulator: core: Link consumer with regulator driver"

2018-07-11 Thread Mikko Perttunen

Hi,

I'm seeing the following spew during boot with Tegra210 with the patch 
"regulator: core: Link consumer with regulator driver", recently applied 
to linux-next:


[1.196664] [ cut here ]
[1.201480] kobject: '(null)' ((ptrval)): is not initialized, 
yet kobject_put() is being called.
[1.219186] WARNING: CPU: 2 PID: 23 at lib/kobject.c:688 
kobject_put+0xa4/0xe8

[1.230026] Modules linked in:
[1.241081] CPU: 2 PID: 23 Comm: kworker/2:0 Not tainted 
4.18.0-rc4-next-20180711 #66

[1.258637] Hardware name: NVIDIA Jetson TX1 Developer Kit (DT)
[1.258651] Workqueue: rcu_gp srcu_invoke_callbacks
[1.272055] pstate: 6005 (nZCv daif -PAN -UAO)
[1.272064] pc : kobject_put+0xa4/0xe8
[1.272071] lr : kobject_put+0xa4/0xe8
[1.272078] sp : 09be3cf0
[1.279387] console [ttyS0] disabled
[1.283662] x29: 09be3cf0 x28: 
[1.283673] x27: 8000fb30aeb8 x26: 08e20690
[1.283686] x25: 093e2118 x24: 8000fff7b480
[1.314668] x23: 08135358 x22: 8000fff7b4c0
[1.325719] x21: 8000fff7b4c8 x20: 8000fafae600
[1.325727] x19: 8000faa54850 x18: 0010
[1.346022] x17:  x16: 
[1.346022] x17:  x16: 
[1.356805] x15:  x14: 75705f7463656a62
[1.356805] x15:  x14: 75705f7463656a62
[1.356813] x13: 6f6b20746579202c x12: 64657a696c616974
[1.356813] x13: 6f6b20746579202c x12: 64657a696c616974
[1.374670] x11: 696e6920746f6e20 x10: 7369203a29295f5f
[1.374670] x11: 696e6920746f6e20 x10: 7369203a29295f5f
[1.374678] x9 : 5f5f6c6176727470 x8 : 085c9810
[1.404186] x7 : 6220736920292874 x6 : 000d
[1.414785] x5 :  x4 : 
[1.414793] x3 :  x2 : 09301010
[1.414801] x1 : a7cf02699fb4fa00 x0 : 
[1.424623] Call trace:
[1.424632]  kobject_put+0xa4/0xe8
[1.424645]  __device_link_free_srcu+0x24/0x48
[1.435235]  srcu_invoke_callbacks+0xf0/0x170
[1.435242]  process_one_work+0x1e0/0x318
[1.435247]  worker_thread+0x40/0x428
[1.435259]  kthread+0x124/0x128
[1.445628] loop: module loaded
[1.449599] ---[ end trace ce0b4f0828c5eeaf ]---
[1.449619] [ cut here ]

After reverting the patch, the kernel boots without the warning.

Thanks,
Mikko


Boot WARN with patch "regulator: core: Link consumer with regulator driver"

2018-07-11 Thread Mikko Perttunen

Hi,

I'm seeing the following spew during boot with Tegra210 with the patch 
"regulator: core: Link consumer with regulator driver", recently applied 
to linux-next:


[1.196664] [ cut here ]
[1.201480] kobject: '(null)' ((ptrval)): is not initialized, 
yet kobject_put() is being called.
[1.219186] WARNING: CPU: 2 PID: 23 at lib/kobject.c:688 
kobject_put+0xa4/0xe8

[1.230026] Modules linked in:
[1.241081] CPU: 2 PID: 23 Comm: kworker/2:0 Not tainted 
4.18.0-rc4-next-20180711 #66

[1.258637] Hardware name: NVIDIA Jetson TX1 Developer Kit (DT)
[1.258651] Workqueue: rcu_gp srcu_invoke_callbacks
[1.272055] pstate: 6005 (nZCv daif -PAN -UAO)
[1.272064] pc : kobject_put+0xa4/0xe8
[1.272071] lr : kobject_put+0xa4/0xe8
[1.272078] sp : 09be3cf0
[1.279387] console [ttyS0] disabled
[1.283662] x29: 09be3cf0 x28: 
[1.283673] x27: 8000fb30aeb8 x26: 08e20690
[1.283686] x25: 093e2118 x24: 8000fff7b480
[1.314668] x23: 08135358 x22: 8000fff7b4c0
[1.325719] x21: 8000fff7b4c8 x20: 8000fafae600
[1.325727] x19: 8000faa54850 x18: 0010
[1.346022] x17:  x16: 
[1.346022] x17:  x16: 
[1.356805] x15:  x14: 75705f7463656a62
[1.356805] x15:  x14: 75705f7463656a62
[1.356813] x13: 6f6b20746579202c x12: 64657a696c616974
[1.356813] x13: 6f6b20746579202c x12: 64657a696c616974
[1.374670] x11: 696e6920746f6e20 x10: 7369203a29295f5f
[1.374670] x11: 696e6920746f6e20 x10: 7369203a29295f5f
[1.374678] x9 : 5f5f6c6176727470 x8 : 085c9810
[1.404186] x7 : 6220736920292874 x6 : 000d
[1.414785] x5 :  x4 : 
[1.414793] x3 :  x2 : 09301010
[1.414801] x1 : a7cf02699fb4fa00 x0 : 
[1.424623] Call trace:
[1.424632]  kobject_put+0xa4/0xe8
[1.424645]  __device_link_free_srcu+0x24/0x48
[1.435235]  srcu_invoke_callbacks+0xf0/0x170
[1.435242]  process_one_work+0x1e0/0x318
[1.435247]  worker_thread+0x40/0x428
[1.435259]  kthread+0x124/0x128
[1.445628] loop: module loaded
[1.449599] ---[ end trace ce0b4f0828c5eeaf ]---
[1.449619] [ cut here ]

After reverting the patch, the kernel boots without the warning.

Thanks,
Mikko


[PATCH] clk: core: Potentially free connection id

2018-07-11 Thread Mikko Perttunen
Patch "clk: core: Copy connection id" made it so that the connector
id (con_id) is kstrdup_const'ed to cater to drivers that pass non-
constant connection ids. The patch added the corresponding kfree_const
to __clk_free_clk, but struct clk's can be freed also via __clk_put.
Add the kfree_const call to __clk_put and add comments to both
functions to remind that the logic in them should be kept in sync.

Fixes: 253160a8ad06 ("clk: core: Copy connection id")
Signed-off-by: Mikko Perttunen 
---
 drivers/clk/clk.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ac96caab0523..d31055ae6ec6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3132,6 +3132,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const 
char *dev_id,
return clk;
 }
 
+/* keep in sync with __clk_put */
 void __clk_free_clk(struct clk *clk)
 {
clk_prepare_lock();
@@ -3511,6 +3512,7 @@ int __clk_get(struct clk *clk)
return 1;
 }
 
+/* keep in sync with __clk_free_clk */
 void __clk_put(struct clk *clk)
 {
struct module *owner;
@@ -3544,6 +3546,7 @@ void __clk_put(struct clk *clk)
 
module_put(owner);
 
+   kfree_const(clk->con_id);
kfree(clk);
 }
 
-- 
2.16.1



[PATCH] clk: core: Potentially free connection id

2018-07-11 Thread Mikko Perttunen
Patch "clk: core: Copy connection id" made it so that the connector
id (con_id) is kstrdup_const'ed to cater to drivers that pass non-
constant connection ids. The patch added the corresponding kfree_const
to __clk_free_clk, but struct clk's can be freed also via __clk_put.
Add the kfree_const call to __clk_put and add comments to both
functions to remind that the logic in them should be kept in sync.

Fixes: 253160a8ad06 ("clk: core: Copy connection id")
Signed-off-by: Mikko Perttunen 
---
 drivers/clk/clk.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ac96caab0523..d31055ae6ec6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3132,6 +3132,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const 
char *dev_id,
return clk;
 }
 
+/* keep in sync with __clk_put */
 void __clk_free_clk(struct clk *clk)
 {
clk_prepare_lock();
@@ -3511,6 +3512,7 @@ int __clk_get(struct clk *clk)
return 1;
 }
 
+/* keep in sync with __clk_free_clk */
 void __clk_put(struct clk *clk)
 {
struct module *owner;
@@ -3544,6 +3546,7 @@ void __clk_put(struct clk *clk)
 
module_put(owner);
 
+   kfree_const(clk->con_id);
kfree(clk);
 }
 
-- 
2.16.1



Re: [PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-03 Thread Mikko Perttunen

On 02.07.2018 16:47, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 04:30:07PM +0300, Mikko Perttunen wrote:

On 02.07.2018 16:18, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 02:40:31PM +0300, Mikko Perttunen wrote:

The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
  v2:
  - Removed (void) casts for unused variables.
  - Changed the uart_set_options() call to be on one line, even if its
over 80 characters.
  - Added defines for magic numbers.
  - Style fixes.
  - Changed Kconfig entry to depend on the Tegra HSP driver instead of
just the mailbox framework.
  v3:
  - Removed FLUSH bit, as it's unnecessary and slows down printing
  - Removed call to uart_set_options
  - Added mbox_free_channel calls to remove()

   drivers/tty/serial/Kconfig   |   9 ++
   drivers/tty/serial/Makefile  |   1 +
   drivers/tty/serial/tegra-tcu.c   | 291 
+++
   include/uapi/linux/serial_core.h |   3 +
   4 files changed, 304 insertions(+)
   create mode 100644 drivers/tty/serial/tegra-tcu.c


The driver looks good to me. But for my own understanding, is there some
way we can make use of the multiplexing? That is, could we add a
mechanism to have the driver filter out only a specific stream? Could we
also specify which stream to send data back to? What happens by default?
Which stream is data sent to?


There is no multiplexing on the producer/device side (i.e. what this driver
does). The mailbox specified in device tree specifies the stream we send
stuff to. The mailboxes are per-CPU (we use the CCPLEX mailbox here), so it
cannot really be changed.


Oh, I see, so there is one stream per pair of mailboxes? That is, the
mailboxes we specify in the DT define which stream we receive from and
send to?


Correct.

Mikko



Thierry



Re: [PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-03 Thread Mikko Perttunen

On 02.07.2018 16:47, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 04:30:07PM +0300, Mikko Perttunen wrote:

On 02.07.2018 16:18, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 02:40:31PM +0300, Mikko Perttunen wrote:

The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
  v2:
  - Removed (void) casts for unused variables.
  - Changed the uart_set_options() call to be on one line, even if its
over 80 characters.
  - Added defines for magic numbers.
  - Style fixes.
  - Changed Kconfig entry to depend on the Tegra HSP driver instead of
just the mailbox framework.
  v3:
  - Removed FLUSH bit, as it's unnecessary and slows down printing
  - Removed call to uart_set_options
  - Added mbox_free_channel calls to remove()

   drivers/tty/serial/Kconfig   |   9 ++
   drivers/tty/serial/Makefile  |   1 +
   drivers/tty/serial/tegra-tcu.c   | 291 
+++
   include/uapi/linux/serial_core.h |   3 +
   4 files changed, 304 insertions(+)
   create mode 100644 drivers/tty/serial/tegra-tcu.c


The driver looks good to me. But for my own understanding, is there some
way we can make use of the multiplexing? That is, could we add a
mechanism to have the driver filter out only a specific stream? Could we
also specify which stream to send data back to? What happens by default?
Which stream is data sent to?


There is no multiplexing on the producer/device side (i.e. what this driver
does). The mailbox specified in device tree specifies the stream we send
stuff to. The mailboxes are per-CPU (we use the CCPLEX mailbox here), so it
cannot really be changed.


Oh, I see, so there is one stream per pair of mailboxes? That is, the
mailboxes we specify in the DT define which stream we receive from and
send to?


Correct.

Mikko



Thierry



Re: [PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen

On 02.07.2018 16:18, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 02:40:31PM +0300, Mikko Perttunen wrote:

The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
 v2:
 - Removed (void) casts for unused variables.
 - Changed the uart_set_options() call to be on one line, even if its
   over 80 characters.
 - Added defines for magic numbers.
 - Style fixes.
 - Changed Kconfig entry to depend on the Tegra HSP driver instead of
   just the mailbox framework.
 
 v3:

 - Removed FLUSH bit, as it's unnecessary and slows down printing
 - Removed call to uart_set_options
 - Added mbox_free_channel calls to remove()

  drivers/tty/serial/Kconfig   |   9 ++
  drivers/tty/serial/Makefile  |   1 +
  drivers/tty/serial/tegra-tcu.c   | 291 +++
  include/uapi/linux/serial_core.h |   3 +
  4 files changed, 304 insertions(+)
  create mode 100644 drivers/tty/serial/tegra-tcu.c


The driver looks good to me. But for my own understanding, is there some
way we can make use of the multiplexing? That is, could we add a
mechanism to have the driver filter out only a specific stream? Could we
also specify which stream to send data back to? What happens by default?
Which stream is data sent to?


There is no multiplexing on the producer/device side (i.e. what this 
driver does). The mailbox specified in device tree specifies the stream 
we send stuff to. The mailboxes are per-CPU (we use the CCPLEX mailbox 
here), so it cannot really be changed.


The consumer then sees the multiplexing in that it can receive from and 
transmit to all of the various CPUs in the system at the same time. AIUI 
there is also a secondary form of multiplexing where the outputs of 
different VMs can be multiplexed by the hypervisor, but I'm not very 
familiar with that.


Mikko



Thierry



Re: [PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen

On 02.07.2018 16:18, Thierry Reding wrote:

On Mon, Jul 02, 2018 at 02:40:31PM +0300, Mikko Perttunen wrote:

The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
 v2:
 - Removed (void) casts for unused variables.
 - Changed the uart_set_options() call to be on one line, even if its
   over 80 characters.
 - Added defines for magic numbers.
 - Style fixes.
 - Changed Kconfig entry to depend on the Tegra HSP driver instead of
   just the mailbox framework.
 
 v3:

 - Removed FLUSH bit, as it's unnecessary and slows down printing
 - Removed call to uart_set_options
 - Added mbox_free_channel calls to remove()

  drivers/tty/serial/Kconfig   |   9 ++
  drivers/tty/serial/Makefile  |   1 +
  drivers/tty/serial/tegra-tcu.c   | 291 +++
  include/uapi/linux/serial_core.h |   3 +
  4 files changed, 304 insertions(+)
  create mode 100644 drivers/tty/serial/tegra-tcu.c


The driver looks good to me. But for my own understanding, is there some
way we can make use of the multiplexing? That is, could we add a
mechanism to have the driver filter out only a specific stream? Could we
also specify which stream to send data back to? What happens by default?
Which stream is data sent to?


There is no multiplexing on the producer/device side (i.e. what this 
driver does). The mailbox specified in device tree specifies the stream 
we send stuff to. The mailboxes are per-CPU (we use the CCPLEX mailbox 
here), so it cannot really be changed.


The consumer then sees the multiplexing in that it can receive from and 
transmit to all of the various CPUs in the system at the same time. AIUI 
there is also a secondary form of multiplexing where the outputs of 
different VMs can be multiplexed by the hypervisor, but I'm not very 
familiar with that.


Mikko



Thierry



[PATCH v3 2/8] dt-bindings: serial: Add bindings for nvidia,tegra194-tcu

2018-07-02 Thread Mikko Perttunen
Add bindings for the Tegra Combined UART device used to talk to the
UART console on Tegra194 systems.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Rob Herring 
Acked-by: Jon Hunter 
---

Notes:
v2:
- Added Rob's Reviewed-by.

v3:
- Added Jon's Acked-by.

 .../bindings/serial/nvidia,tegra194-tcu.txt| 35 ++
 1 file changed, 35 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt

diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt 
b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
new file mode 100644
index ..a8becf6efd2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
@@ -0,0 +1,35 @@
+NVIDIA Tegra Combined UART (TCU)
+
+The TCU is a system for sharing a hardware UART instance among multiple
+systems within the Tegra SoC. It is implemented through a mailbox-
+based protocol where each "virtual UART" has a pair of mailboxes, one
+for transmitting and one for receiving, that is used to communicate
+with the hardware implementing the TCU.
+
+Required properties:
+- name : Should be tcu
+- compatible
+Array of strings
+One of:
+- "nvidia,tegra194-tcu"
+- mbox-names:
+"rx" - Mailbox for receiving data from hardware UART
+"tx" - Mailbox for transmitting data to hardware UART
+- mboxes: Mailboxes corresponding to the mbox-names. 
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+Example bindings:
+-
+
+tcu: tcu {
+   compatible = "nvidia,tegra194-tcu";
+   mboxes = <_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
+<_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
+   mbox-names = "rx", "tx";
+};
-- 
2.16.1



[PATCH v3 0/8] Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen
Hi, here's v3. Changes are in individual patches. Acks are still
missing from the following patches:

mailbox: Add transmit done by blocking option
mailbox: tegra-hsp: Refactor in preparation of mailboxes
mailbox: tegra-hsp: Add support for shared mailboxes
serial: Add Tegra Combined UART driver

Thanks,
Mikko

Original message:

Hi all,

on Tegra194, the primary console UART is the "Tegra Combined UART",
or TCU. This is a "virtual UART", where each consumer communicates
with a central implementation over mailboxes. The central
implementation then multiplexes the streams and arbitrates use of
a hardware serial port. This driver implements the consumer portion
to allow using the primary console.

The series is split into the following parts:
* patches 1 and 2 add the device tree bindings for mailbox and tcu
  itself.
* patch 3 adds a blocking transmission option to the mailbox
  framework.
* patches 4 and 5 add support for the "shared mailbox" primitive
  to the Tegra HSP driver.
* patch 6 adds the TCU driver itself
* patches 7 and 8 do the necessary device tree changes.

The series has been tested on the Tegra194 P2972 board.

Mikko Perttunen (8):
  dt-bindings: tegra186-hsp: Add shared interrupts
  dt-bindings: serial: Add bindings for nvidia,tegra194-tcu
  mailbox: Add transmit done by blocking option
  mailbox: tegra-hsp: Refactor in preparation of mailboxes
  mailbox: tegra-hsp: Add support for shared mailboxes
  serial: Add Tegra Combined UART driver
  arm64: tegra: Add nodes for tcu on Tegra194
  arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888

 .../bindings/mailbox/nvidia,tegra186-hsp.txt   |   3 +
 .../bindings/serial/nvidia,tegra194-tcu.txt|  35 +++
 arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi |   2 +-
 arch/arm64/boot/dts/nvidia/tegra194.dtsi   |  34 ++-
 drivers/mailbox/mailbox.c  |  30 +-
 drivers/mailbox/mailbox.h  |   1 +
 drivers/mailbox/tegra-hsp.c| 320 +
 drivers/tty/serial/Kconfig |   9 +
 drivers/tty/serial/Makefile|   1 +
 drivers/tty/serial/tegra-tcu.c | 291 +++
 include/uapi/linux/serial_core.h   |   3 +
 11 files changed, 661 insertions(+), 68 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
 create mode 100644 drivers/tty/serial/tegra-tcu.c

-- 
2.16.1



[PATCH v3 2/8] dt-bindings: serial: Add bindings for nvidia,tegra194-tcu

2018-07-02 Thread Mikko Perttunen
Add bindings for the Tegra Combined UART device used to talk to the
UART console on Tegra194 systems.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Rob Herring 
Acked-by: Jon Hunter 
---

Notes:
v2:
- Added Rob's Reviewed-by.

v3:
- Added Jon's Acked-by.

 .../bindings/serial/nvidia,tegra194-tcu.txt| 35 ++
 1 file changed, 35 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt

diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt 
b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
new file mode 100644
index ..a8becf6efd2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
@@ -0,0 +1,35 @@
+NVIDIA Tegra Combined UART (TCU)
+
+The TCU is a system for sharing a hardware UART instance among multiple
+systems within the Tegra SoC. It is implemented through a mailbox-
+based protocol where each "virtual UART" has a pair of mailboxes, one
+for transmitting and one for receiving, that is used to communicate
+with the hardware implementing the TCU.
+
+Required properties:
+- name : Should be tcu
+- compatible
+Array of strings
+One of:
+- "nvidia,tegra194-tcu"
+- mbox-names:
+"rx" - Mailbox for receiving data from hardware UART
+"tx" - Mailbox for transmitting data to hardware UART
+- mboxes: Mailboxes corresponding to the mbox-names. 
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+Example bindings:
+-
+
+tcu: tcu {
+   compatible = "nvidia,tegra194-tcu";
+   mboxes = <_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
+<_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
+   mbox-names = "rx", "tx";
+};
-- 
2.16.1



[PATCH v3 0/8] Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen
Hi, here's v3. Changes are in individual patches. Acks are still
missing from the following patches:

mailbox: Add transmit done by blocking option
mailbox: tegra-hsp: Refactor in preparation of mailboxes
mailbox: tegra-hsp: Add support for shared mailboxes
serial: Add Tegra Combined UART driver

Thanks,
Mikko

Original message:

Hi all,

on Tegra194, the primary console UART is the "Tegra Combined UART",
or TCU. This is a "virtual UART", where each consumer communicates
with a central implementation over mailboxes. The central
implementation then multiplexes the streams and arbitrates use of
a hardware serial port. This driver implements the consumer portion
to allow using the primary console.

The series is split into the following parts:
* patches 1 and 2 add the device tree bindings for mailbox and tcu
  itself.
* patch 3 adds a blocking transmission option to the mailbox
  framework.
* patches 4 and 5 add support for the "shared mailbox" primitive
  to the Tegra HSP driver.
* patch 6 adds the TCU driver itself
* patches 7 and 8 do the necessary device tree changes.

The series has been tested on the Tegra194 P2972 board.

Mikko Perttunen (8):
  dt-bindings: tegra186-hsp: Add shared interrupts
  dt-bindings: serial: Add bindings for nvidia,tegra194-tcu
  mailbox: Add transmit done by blocking option
  mailbox: tegra-hsp: Refactor in preparation of mailboxes
  mailbox: tegra-hsp: Add support for shared mailboxes
  serial: Add Tegra Combined UART driver
  arm64: tegra: Add nodes for tcu on Tegra194
  arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888

 .../bindings/mailbox/nvidia,tegra186-hsp.txt   |   3 +
 .../bindings/serial/nvidia,tegra194-tcu.txt|  35 +++
 arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi |   2 +-
 arch/arm64/boot/dts/nvidia/tegra194.dtsi   |  34 ++-
 drivers/mailbox/mailbox.c  |  30 +-
 drivers/mailbox/mailbox.h  |   1 +
 drivers/mailbox/tegra-hsp.c| 320 +
 drivers/tty/serial/Kconfig |   9 +
 drivers/tty/serial/Makefile|   1 +
 drivers/tty/serial/tegra-tcu.c | 291 +++
 include/uapi/linux/serial_core.h   |   3 +
 11 files changed, 661 insertions(+), 68 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
 create mode 100644 drivers/tty/serial/tegra-tcu.c

-- 
2.16.1



[PATCH v3 5/8] mailbox: tegra-hsp: Add support for shared mailboxes

2018-07-02 Thread Mikko Perttunen
The Tegra HSP block supports 'shared mailboxes' that are simple 32-bit
registers consisting of a FULL bit in MSB position and 31 bits of data.
The hardware can be configured to trigger interrupts when a mailbox
is empty or full. Add support for these shared mailboxes to the HSP
driver.

The initial use for the mailboxes is the Tegra Combined UART. For this
purpose, we use interrupts to receive data, and spinning to wait for
the transmit mailbox to be emptied to minimize unnecessary overhead.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Jon Hunter 
---

Notes:
v3:
- Added define HSP_INT0_IE_FULL_SHIFT
- Added Jon's Reviewed-by

v2:
- Added defines for some register fields
- Simplified bit looping logic in interrupt handler
- Changed write done polling to use readl_poll_timeout
- Removed unnecessary zero assignments
- Fixed two error cases in probe to do proper cleanup

 drivers/mailbox/tegra-hsp.c | 211 +++-
 1 file changed, 191 insertions(+), 20 deletions(-)

diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 5dc21a6d01bb..e0e238287502 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -21,6 +22,14 @@
 
 #include 
 
+#include "mailbox.h"
+
+#define HSP_INT0_IE0x100
+#define HSP_INT0_IE_FULL_SHIFT 8
+#define HSP_INT_IR 0x304
+#define HSP_INT_IR_FULL_SHIFT  8
+#define HSP_INT_IR_FULL_MASK   0xff
+
 #define HSP_INT_DIMENSIONING   0x380
 #define HSP_nSM_SHIFT  0
 #define HSP_nSS_SHIFT  4
@@ -34,6 +43,9 @@
 #define HSP_DB_RAW 0x8
 #define HSP_DB_PENDING 0xc
 
+#define HSP_SM_SHRD_MBOX   0x0
+#define HSP_SM_SHRD_MBOX_FULL  BIT(31)
+
 #define HSP_DB_CCPLEX  1
 #define HSP_DB_BPMP3
 #define HSP_DB_MAX 7
@@ -68,6 +80,18 @@ struct tegra_hsp_db_map {
unsigned int index;
 };
 
+struct tegra_hsp_mailbox {
+   struct tegra_hsp_channel channel;
+   unsigned int index;
+   bool sending;
+};
+
+static inline struct tegra_hsp_mailbox *
+channel_to_mailbox(struct tegra_hsp_channel *channel)
+{
+   return container_of(channel, struct tegra_hsp_mailbox, channel);
+}
+
 struct tegra_hsp_soc {
const struct tegra_hsp_db_map *map;
 };
@@ -77,6 +101,7 @@ struct tegra_hsp {
struct mbox_controller mbox;
void __iomem *regs;
unsigned int doorbell_irq;
+   unsigned int shared_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -85,6 +110,7 @@ struct tegra_hsp {
spinlock_t lock;
 
struct list_head doorbells;
+   struct tegra_hsp_mailbox *mailboxes;
 };
 
 static inline struct tegra_hsp *
@@ -189,6 +215,33 @@ static irqreturn_t tegra_hsp_doorbell_irq(int irq, void 
*data)
return IRQ_HANDLED;
 }
 
+static irqreturn_t tegra_hsp_shared_irq(int irq, void *data)
+{
+   struct tegra_hsp_mailbox *mb;
+   struct tegra_hsp *hsp = data;
+   unsigned long bit, mask;
+   u32 value;
+
+   mask = tegra_hsp_readl(hsp, HSP_INT_IR);
+   /* Only interested in FULL interrupts */
+   mask = (mask >> HSP_INT_IR_FULL_SHIFT) & HSP_INT_IR_FULL_MASK;
+
+   for_each_set_bit(bit, , 8) {
+   mb = >mailboxes[bit];
+
+   if (!mb->sending) {
+   value = tegra_hsp_channel_readl(>channel,
+   HSP_SM_SHRD_MBOX);
+   value &= ~HSP_SM_SHRD_MBOX_FULL;
+   mbox_chan_received_data(mb->channel.chan, );
+   tegra_hsp_channel_writel(>channel, value,
+HSP_SM_SHRD_MBOX);
+   }
+   }
+
+   return IRQ_HANDLED;
+}
+
 static struct tegra_hsp_channel *
 tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
  unsigned int master, unsigned int index)
@@ -277,14 +330,57 @@ static void tegra_hsp_doorbell_shutdown(struct 
tegra_hsp_doorbell *db)
spin_unlock_irqrestore(>lock, flags);
 }
 
+static int tegra_hsp_mailbox_startup(struct tegra_hsp_mailbox *mb)
+{
+   struct tegra_hsp *hsp = mb->channel.hsp;
+   u32 value;
+
+   mb->channel.chan->txdone_method = TXDONE_BY_BLOCK;
+
+   /* Route FULL interrupt to external IRQ 0 */
+   value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+   value |= BIT(HSP_INT0_IE_FULL_SHIFT + mb->index);
+   tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+   return 0;
+}
+
+static int tegra_hsp_mailbox_shutdown(struct tegra_hsp_mailbox *mb)
+{
+   struct tegra_hsp *hsp = mb->channel.hsp;
+   u32 value;
+
+   value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+   value &= ~BIT(mb->index + 8);
+   tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+  

[PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen
The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
v2:
- Removed (void) casts for unused variables.
- Changed the uart_set_options() call to be on one line, even if its
  over 80 characters.
- Added defines for magic numbers.
- Style fixes.
- Changed Kconfig entry to depend on the Tegra HSP driver instead of
  just the mailbox framework.

v3:
- Removed FLUSH bit, as it's unnecessary and slows down printing
- Removed call to uart_set_options
- Added mbox_free_channel calls to remove()

 drivers/tty/serial/Kconfig   |   9 ++
 drivers/tty/serial/Makefile  |   1 +
 drivers/tty/serial/tegra-tcu.c   | 291 +++
 include/uapi/linux/serial_core.h |   3 +
 4 files changed, 304 insertions(+)
 create mode 100644 drivers/tty/serial/tegra-tcu.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index df8bd0c7b97d..5fdd336e8937 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -322,6 +322,15 @@ config SERIAL_TEGRA
  are enabled). This driver uses the APB DMA to achieve higher baudrate
  and better performance.
 
+config SERIAL_TEGRA_TCU
+   tristate "NVIDIA Tegra Combined UART"
+   depends on ARCH_TEGRA && TEGRA_HSP_MBOX
+   select SERIAL_CORE
+   help
+ Support for the mailbox-based TCU (Tegra Combined UART) serial port.
+ TCU is a virtual serial port that allows multiplexing multiple data
+ streams into a single hardware serial port.
+
 config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index daac675612df..4ad82231ff8a 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_SERIAL_LANTIQ)   += lantiq.o
 obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
 obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
 obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
 obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
 obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
 obj-$(CONFIG_SERIAL_ARC)   += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
new file mode 100644
index ..de58815bb215
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TCU_MBOX_BYTE(i, x)((x) << (i*8))
+#define TCU_MBOX_BYTE_V(x, i)  (((x) >> (i*8)) & 0xff)
+#define TCU_MBOX_NUM_BYTES(x)  ((x) << 24)
+#define TCU_MBOX_NUM_BYTES_V(x)(((x) >> 24) & 0x3)
+
+static struct uart_driver tegra_tcu_uart_driver;
+static struct uart_port tegra_tcu_uart_port;
+
+struct tegra_tcu {
+   struct mbox_client tx_client, rx_client;
+   struct mbox_chan *tx, *rx;
+};
+
+static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port)
+{
+   return TIOCSER_TEMT;
+}
+
+static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int 
mctrl)
+{
+}
+
+static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port)
+{
+   return 0;
+}
+
+static void tegra_tcu_uart_stop_tx(struct uart_port *port)
+{
+}
+
+static void tegra_tcu_write(const char *s, unsigned int count)
+{
+   struct tegra_tcu *tcu = tegra_tcu_uart_port.private_data;
+   unsigned int written = 0, i = 0;
+   bool insert_nl = false;
+   uint32_t value = 0;
+
+   while (i < count) {
+   if (insert_nl) {
+   value |= TCU_MBOX_BYTE(written++, '\n');
+   insert_nl = false;
+   i++;
+   } else if (s[i] == '\n') {
+   value |= TCU_MBOX_BYTE(written++, '\r');
+   insert_nl = true;
+   } else {
+   value |= TCU_MBOX_BYTE(written++, s[i++]);
+   }
+
+   if (written == 3) {
+   value |= TCU_MBOX_NUM_BYTES(3);
+   mbox_send_message(tcu->tx, );
+   value = 0;
+   written = 0;
+   }
+   }
+
+   if (written) {
+   value |= TCU_MBOX_NUM_BYTES(written);
+   mbox_send_message(tcu->tx, );
+   }
+}
+

[PATCH v3 5/8] mailbox: tegra-hsp: Add support for shared mailboxes

2018-07-02 Thread Mikko Perttunen
The Tegra HSP block supports 'shared mailboxes' that are simple 32-bit
registers consisting of a FULL bit in MSB position and 31 bits of data.
The hardware can be configured to trigger interrupts when a mailbox
is empty or full. Add support for these shared mailboxes to the HSP
driver.

The initial use for the mailboxes is the Tegra Combined UART. For this
purpose, we use interrupts to receive data, and spinning to wait for
the transmit mailbox to be emptied to minimize unnecessary overhead.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Jon Hunter 
---

Notes:
v3:
- Added define HSP_INT0_IE_FULL_SHIFT
- Added Jon's Reviewed-by

v2:
- Added defines for some register fields
- Simplified bit looping logic in interrupt handler
- Changed write done polling to use readl_poll_timeout
- Removed unnecessary zero assignments
- Fixed two error cases in probe to do proper cleanup

 drivers/mailbox/tegra-hsp.c | 211 +++-
 1 file changed, 191 insertions(+), 20 deletions(-)

diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 5dc21a6d01bb..e0e238287502 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -21,6 +22,14 @@
 
 #include 
 
+#include "mailbox.h"
+
+#define HSP_INT0_IE0x100
+#define HSP_INT0_IE_FULL_SHIFT 8
+#define HSP_INT_IR 0x304
+#define HSP_INT_IR_FULL_SHIFT  8
+#define HSP_INT_IR_FULL_MASK   0xff
+
 #define HSP_INT_DIMENSIONING   0x380
 #define HSP_nSM_SHIFT  0
 #define HSP_nSS_SHIFT  4
@@ -34,6 +43,9 @@
 #define HSP_DB_RAW 0x8
 #define HSP_DB_PENDING 0xc
 
+#define HSP_SM_SHRD_MBOX   0x0
+#define HSP_SM_SHRD_MBOX_FULL  BIT(31)
+
 #define HSP_DB_CCPLEX  1
 #define HSP_DB_BPMP3
 #define HSP_DB_MAX 7
@@ -68,6 +80,18 @@ struct tegra_hsp_db_map {
unsigned int index;
 };
 
+struct tegra_hsp_mailbox {
+   struct tegra_hsp_channel channel;
+   unsigned int index;
+   bool sending;
+};
+
+static inline struct tegra_hsp_mailbox *
+channel_to_mailbox(struct tegra_hsp_channel *channel)
+{
+   return container_of(channel, struct tegra_hsp_mailbox, channel);
+}
+
 struct tegra_hsp_soc {
const struct tegra_hsp_db_map *map;
 };
@@ -77,6 +101,7 @@ struct tegra_hsp {
struct mbox_controller mbox;
void __iomem *regs;
unsigned int doorbell_irq;
+   unsigned int shared_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -85,6 +110,7 @@ struct tegra_hsp {
spinlock_t lock;
 
struct list_head doorbells;
+   struct tegra_hsp_mailbox *mailboxes;
 };
 
 static inline struct tegra_hsp *
@@ -189,6 +215,33 @@ static irqreturn_t tegra_hsp_doorbell_irq(int irq, void 
*data)
return IRQ_HANDLED;
 }
 
+static irqreturn_t tegra_hsp_shared_irq(int irq, void *data)
+{
+   struct tegra_hsp_mailbox *mb;
+   struct tegra_hsp *hsp = data;
+   unsigned long bit, mask;
+   u32 value;
+
+   mask = tegra_hsp_readl(hsp, HSP_INT_IR);
+   /* Only interested in FULL interrupts */
+   mask = (mask >> HSP_INT_IR_FULL_SHIFT) & HSP_INT_IR_FULL_MASK;
+
+   for_each_set_bit(bit, , 8) {
+   mb = >mailboxes[bit];
+
+   if (!mb->sending) {
+   value = tegra_hsp_channel_readl(>channel,
+   HSP_SM_SHRD_MBOX);
+   value &= ~HSP_SM_SHRD_MBOX_FULL;
+   mbox_chan_received_data(mb->channel.chan, );
+   tegra_hsp_channel_writel(>channel, value,
+HSP_SM_SHRD_MBOX);
+   }
+   }
+
+   return IRQ_HANDLED;
+}
+
 static struct tegra_hsp_channel *
 tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
  unsigned int master, unsigned int index)
@@ -277,14 +330,57 @@ static void tegra_hsp_doorbell_shutdown(struct 
tegra_hsp_doorbell *db)
spin_unlock_irqrestore(>lock, flags);
 }
 
+static int tegra_hsp_mailbox_startup(struct tegra_hsp_mailbox *mb)
+{
+   struct tegra_hsp *hsp = mb->channel.hsp;
+   u32 value;
+
+   mb->channel.chan->txdone_method = TXDONE_BY_BLOCK;
+
+   /* Route FULL interrupt to external IRQ 0 */
+   value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+   value |= BIT(HSP_INT0_IE_FULL_SHIFT + mb->index);
+   tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+   return 0;
+}
+
+static int tegra_hsp_mailbox_shutdown(struct tegra_hsp_mailbox *mb)
+{
+   struct tegra_hsp *hsp = mb->channel.hsp;
+   u32 value;
+
+   value = tegra_hsp_readl(hsp, HSP_INT0_IE);
+   value &= ~BIT(mb->index + 8);
+   tegra_hsp_writel(hsp, value, HSP_INT0_IE);
+
+  

[PATCH v3 6/8] serial: Add Tegra Combined UART driver

2018-07-02 Thread Mikko Perttunen
The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
multiplexing multiple "virtual UARTs" into a single hardware serial
port. The TCU is the primary serial port on Tegra194 devices.

Add a TCU driver utilizing the mailbox framework, as the used mailboxes
are part of Tegra HSP blocks that are already controlled by the Tegra
HSP mailbox driver.

Signed-off-by: Mikko Perttunen 
---

Notes:
v2:
- Removed (void) casts for unused variables.
- Changed the uart_set_options() call to be on one line, even if its
  over 80 characters.
- Added defines for magic numbers.
- Style fixes.
- Changed Kconfig entry to depend on the Tegra HSP driver instead of
  just the mailbox framework.

v3:
- Removed FLUSH bit, as it's unnecessary and slows down printing
- Removed call to uart_set_options
- Added mbox_free_channel calls to remove()

 drivers/tty/serial/Kconfig   |   9 ++
 drivers/tty/serial/Makefile  |   1 +
 drivers/tty/serial/tegra-tcu.c   | 291 +++
 include/uapi/linux/serial_core.h |   3 +
 4 files changed, 304 insertions(+)
 create mode 100644 drivers/tty/serial/tegra-tcu.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index df8bd0c7b97d..5fdd336e8937 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -322,6 +322,15 @@ config SERIAL_TEGRA
  are enabled). This driver uses the APB DMA to achieve higher baudrate
  and better performance.
 
+config SERIAL_TEGRA_TCU
+   tristate "NVIDIA Tegra Combined UART"
+   depends on ARCH_TEGRA && TEGRA_HSP_MBOX
+   select SERIAL_CORE
+   help
+ Support for the mailbox-based TCU (Tegra Combined UART) serial port.
+ TCU is a virtual serial port that allows multiplexing multiple data
+ streams into a single hardware serial port.
+
 config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index daac675612df..4ad82231ff8a 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_SERIAL_LANTIQ)   += lantiq.o
 obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
 obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
 obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
+obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
 obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
 obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
 obj-$(CONFIG_SERIAL_ARC)   += arc_uart.o
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
new file mode 100644
index ..de58815bb215
--- /dev/null
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TCU_MBOX_BYTE(i, x)((x) << (i*8))
+#define TCU_MBOX_BYTE_V(x, i)  (((x) >> (i*8)) & 0xff)
+#define TCU_MBOX_NUM_BYTES(x)  ((x) << 24)
+#define TCU_MBOX_NUM_BYTES_V(x)(((x) >> 24) & 0x3)
+
+static struct uart_driver tegra_tcu_uart_driver;
+static struct uart_port tegra_tcu_uart_port;
+
+struct tegra_tcu {
+   struct mbox_client tx_client, rx_client;
+   struct mbox_chan *tx, *rx;
+};
+
+static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port)
+{
+   return TIOCSER_TEMT;
+}
+
+static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int 
mctrl)
+{
+}
+
+static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port)
+{
+   return 0;
+}
+
+static void tegra_tcu_uart_stop_tx(struct uart_port *port)
+{
+}
+
+static void tegra_tcu_write(const char *s, unsigned int count)
+{
+   struct tegra_tcu *tcu = tegra_tcu_uart_port.private_data;
+   unsigned int written = 0, i = 0;
+   bool insert_nl = false;
+   uint32_t value = 0;
+
+   while (i < count) {
+   if (insert_nl) {
+   value |= TCU_MBOX_BYTE(written++, '\n');
+   insert_nl = false;
+   i++;
+   } else if (s[i] == '\n') {
+   value |= TCU_MBOX_BYTE(written++, '\r');
+   insert_nl = true;
+   } else {
+   value |= TCU_MBOX_BYTE(written++, s[i++]);
+   }
+
+   if (written == 3) {
+   value |= TCU_MBOX_NUM_BYTES(3);
+   mbox_send_message(tcu->tx, );
+   value = 0;
+   written = 0;
+   }
+   }
+
+   if (written) {
+   value |= TCU_MBOX_NUM_BYTES(written);
+   mbox_send_message(tcu->tx, );
+   }
+}
+

[PATCH v3 4/8] mailbox: tegra-hsp: Refactor in preparation of mailboxes

2018-07-02 Thread Mikko Perttunen
The HSP driver is currently in many places written with the assumption
of only supporting doorbells. Prepare for the addition of shared
mailbox support by removing these assumptions and cleaning up the code.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Jon Hunter 
---

Notes:
v2:
- Moved fixes for some style and other issues from the next patch
  here, where they belong.

v3:
- Added Jon's Reviewed-by.

 drivers/mailbox/tegra-hsp.c | 123 +---
 1 file changed, 81 insertions(+), 42 deletions(-)

diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 0cde356c11ab..5dc21a6d01bb 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -42,6 +42,7 @@ struct tegra_hsp_channel;
 struct tegra_hsp;
 
 struct tegra_hsp_channel {
+   unsigned int type;
struct tegra_hsp *hsp;
struct mbox_chan *chan;
void __iomem *regs;
@@ -55,6 +56,12 @@ struct tegra_hsp_doorbell {
unsigned int index;
 };
 
+static inline struct tegra_hsp_doorbell *
+channel_to_doorbell(struct tegra_hsp_channel *channel)
+{
+   return container_of(channel, struct tegra_hsp_doorbell, channel);
+}
+
 struct tegra_hsp_db_map {
const char *name;
unsigned int master;
@@ -69,7 +76,7 @@ struct tegra_hsp {
const struct tegra_hsp_soc *soc;
struct mbox_controller mbox;
void __iomem *regs;
-   unsigned int irq;
+   unsigned int doorbell_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -194,7 +201,7 @@ tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char 
*name,
if (!db)
return ERR_PTR(-ENOMEM);
 
-   offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
+   offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K;
offset += index * 0x100;
 
db->channel.regs = hsp->regs + offset;
@@ -218,18 +225,8 @@ static void __tegra_hsp_doorbell_destroy(struct 
tegra_hsp_doorbell *db)
kfree(db);
 }
 
-static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
-{
-   struct tegra_hsp_doorbell *db = chan->con_priv;
-
-   tegra_hsp_channel_writel(>channel, 1, HSP_DB_TRIGGER);
-
-   return 0;
-}
-
-static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
+static int tegra_hsp_doorbell_startup(struct tegra_hsp_doorbell *db)
 {
-   struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -260,9 +257,8 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan 
*chan)
return 0;
 }
 
-static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
+static void tegra_hsp_doorbell_shutdown(struct tegra_hsp_doorbell *db)
 {
-   struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -281,35 +277,60 @@ static void tegra_hsp_doorbell_shutdown(struct mbox_chan 
*chan)
spin_unlock_irqrestore(>lock, flags);
 }
 
-static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
-   .send_data = tegra_hsp_doorbell_send_data,
-   .startup = tegra_hsp_doorbell_startup,
-   .shutdown = tegra_hsp_doorbell_shutdown,
+static int tegra_hsp_send_data(struct mbox_chan *chan, void *data)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   tegra_hsp_channel_writel(channel, 1, HSP_DB_TRIGGER);
+   return 0;
+   }
+
+   return -EINVAL;
+}
+
+static int tegra_hsp_startup(struct mbox_chan *chan)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   return tegra_hsp_doorbell_startup(channel_to_doorbell(channel));
+   }
+
+   return -EINVAL;
+}
+
+static void tegra_hsp_shutdown(struct mbox_chan *chan)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   tegra_hsp_doorbell_shutdown(channel_to_doorbell(channel));
+   break;
+   }
+}
+
+static const struct mbox_chan_ops tegra_hsp_ops = {
+   .send_data = tegra_hsp_send_data,
+   .startup = tegra_hsp_startup,
+   .shutdown = tegra_hsp_shutdown,
 };
 
-static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
-

[PATCH v3 4/8] mailbox: tegra-hsp: Refactor in preparation of mailboxes

2018-07-02 Thread Mikko Perttunen
The HSP driver is currently in many places written with the assumption
of only supporting doorbells. Prepare for the addition of shared
mailbox support by removing these assumptions and cleaning up the code.

Signed-off-by: Mikko Perttunen 
Reviewed-by: Jon Hunter 
---

Notes:
v2:
- Moved fixes for some style and other issues from the next patch
  here, where they belong.

v3:
- Added Jon's Reviewed-by.

 drivers/mailbox/tegra-hsp.c | 123 +---
 1 file changed, 81 insertions(+), 42 deletions(-)

diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 0cde356c11ab..5dc21a6d01bb 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -42,6 +42,7 @@ struct tegra_hsp_channel;
 struct tegra_hsp;
 
 struct tegra_hsp_channel {
+   unsigned int type;
struct tegra_hsp *hsp;
struct mbox_chan *chan;
void __iomem *regs;
@@ -55,6 +56,12 @@ struct tegra_hsp_doorbell {
unsigned int index;
 };
 
+static inline struct tegra_hsp_doorbell *
+channel_to_doorbell(struct tegra_hsp_channel *channel)
+{
+   return container_of(channel, struct tegra_hsp_doorbell, channel);
+}
+
 struct tegra_hsp_db_map {
const char *name;
unsigned int master;
@@ -69,7 +76,7 @@ struct tegra_hsp {
const struct tegra_hsp_soc *soc;
struct mbox_controller mbox;
void __iomem *regs;
-   unsigned int irq;
+   unsigned int doorbell_irq;
unsigned int num_sm;
unsigned int num_as;
unsigned int num_ss;
@@ -194,7 +201,7 @@ tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char 
*name,
if (!db)
return ERR_PTR(-ENOMEM);
 
-   offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
+   offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) * SZ_64K;
offset += index * 0x100;
 
db->channel.regs = hsp->regs + offset;
@@ -218,18 +225,8 @@ static void __tegra_hsp_doorbell_destroy(struct 
tegra_hsp_doorbell *db)
kfree(db);
 }
 
-static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
-{
-   struct tegra_hsp_doorbell *db = chan->con_priv;
-
-   tegra_hsp_channel_writel(>channel, 1, HSP_DB_TRIGGER);
-
-   return 0;
-}
-
-static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
+static int tegra_hsp_doorbell_startup(struct tegra_hsp_doorbell *db)
 {
-   struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -260,9 +257,8 @@ static int tegra_hsp_doorbell_startup(struct mbox_chan 
*chan)
return 0;
 }
 
-static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
+static void tegra_hsp_doorbell_shutdown(struct tegra_hsp_doorbell *db)
 {
-   struct tegra_hsp_doorbell *db = chan->con_priv;
struct tegra_hsp *hsp = db->channel.hsp;
struct tegra_hsp_doorbell *ccplex;
unsigned long flags;
@@ -281,35 +277,60 @@ static void tegra_hsp_doorbell_shutdown(struct mbox_chan 
*chan)
spin_unlock_irqrestore(>lock, flags);
 }
 
-static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
-   .send_data = tegra_hsp_doorbell_send_data,
-   .startup = tegra_hsp_doorbell_startup,
-   .shutdown = tegra_hsp_doorbell_shutdown,
+static int tegra_hsp_send_data(struct mbox_chan *chan, void *data)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   tegra_hsp_channel_writel(channel, 1, HSP_DB_TRIGGER);
+   return 0;
+   }
+
+   return -EINVAL;
+}
+
+static int tegra_hsp_startup(struct mbox_chan *chan)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   return tegra_hsp_doorbell_startup(channel_to_doorbell(channel));
+   }
+
+   return -EINVAL;
+}
+
+static void tegra_hsp_shutdown(struct mbox_chan *chan)
+{
+   struct tegra_hsp_channel *channel = chan->con_priv;
+
+   switch (channel->type) {
+   case TEGRA_HSP_MBOX_TYPE_DB:
+   tegra_hsp_doorbell_shutdown(channel_to_doorbell(channel));
+   break;
+   }
+}
+
+static const struct mbox_chan_ops tegra_hsp_ops = {
+   .send_data = tegra_hsp_send_data,
+   .startup = tegra_hsp_startup,
+   .shutdown = tegra_hsp_shutdown,
 };
 
-static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
-

[PATCH v3 8/8] arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888

2018-07-02 Thread Mikko Perttunen
The Tegra Combined UART is the proper primary serial port on P2888,
so use it.

Signed-off-by: Mikko Perttunen 
Acked-by: Jon Hunter 
---

Notes:
v2:
- Added Jon's Acked-by.

 arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
index 859ab5af17c1..95e2433984f7 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -10,7 +10,7 @@
aliases {
sdhci0 = "/cbb/sdhci@346";
sdhci1 = "/cbb/sdhci@340";
-   serial0 = 
+   serial0 = 
i2c0 = "/bpmp/i2c";
i2c1 = "/cbb/i2c@316";
i2c2 = "/cbb/i2c@c24";
-- 
2.16.1



[PATCH v3 8/8] arm64: tegra: Mark tcu as primary serial port on Tegra194 P2888

2018-07-02 Thread Mikko Perttunen
The Tegra Combined UART is the proper primary serial port on P2888,
so use it.

Signed-off-by: Mikko Perttunen 
Acked-by: Jon Hunter 
---

Notes:
v2:
- Added Jon's Acked-by.

 arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
index 859ab5af17c1..95e2433984f7 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -10,7 +10,7 @@
aliases {
sdhci0 = "/cbb/sdhci@346";
sdhci1 = "/cbb/sdhci@340";
-   serial0 = 
+   serial0 = 
i2c0 = "/bpmp/i2c";
i2c1 = "/cbb/i2c@316";
i2c2 = "/cbb/i2c@c24";
-- 
2.16.1



  1   2   3   4   5   6   7   8   9   10   >