[PATCH] regulator: core: Fix device link error when registering regulator

2018-10-11 Thread Jeffy Chen
The sysfs device link can only be created after regulator device
registered.

Fixes: c438b9d017362 ("regulator: core: Move registration of regulator device")
Signed-off-by: Jeffy Chen 
---

 drivers/regulator/core.c | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2c66b528aedec..36e650b61f7a9 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1405,12 +1405,15 @@ static struct regulator *create_regulator(struct 
regulator_dev *rdev,
if (regulator->supply_name == NULL)
goto overflow_err;
 
-   err = sysfs_create_link_nowarn(>dev.kobj, >kobj,
-   buf);
-   if (err) {
-   rdev_dbg(rdev, "could not add device link %s err %d\n",
- dev->kobj.name, err);
-   /* non-fatal */
+   if (device_is_registered(dev)) {
+   err = sysfs_create_link_nowarn(>dev.kobj,
+  >kobj, buf);
+   if (err) {
+   rdev_dbg(rdev,
+"could not add device link %s err 
%d\n",
+dev->kobj.name, err);
+   /* non-fatal */
+   }
}
} else {
regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
@@ -4416,6 +4419,18 @@ regulator_register(const struct regulator_desc 
*regulator_desc,
goto unset_supplies;
}
 
+   /* Add a link to the device sysfs entry */
+   if (rdev->supply && rdev->supply->dev) {
+   ret = sysfs_create_link_nowarn(>supply->dev->kobj,
+  >dev.kobj,
+  rdev->supply->supply_name);
+   if (ret) {
+   rdev_dbg(rdev, "could not add device link %s err %d\n",
+rdev->dev.kobj.name, ret);
+   /* non-fatal */
+   }
+   }
+
rdev_init_debugfs(rdev);
 
/* try to resolve regulators supply since a new one was registered */
-- 
2.11.0




[PATCH] regulator: core: Fix device link error when registering regulator

2018-10-11 Thread Jeffy Chen
The sysfs device link can only be created after regulator device
registered.

Fixes: c438b9d017362 ("regulator: core: Move registration of regulator device")
Signed-off-by: Jeffy Chen 
---

 drivers/regulator/core.c | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2c66b528aedec..36e650b61f7a9 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1405,12 +1405,15 @@ static struct regulator *create_regulator(struct 
regulator_dev *rdev,
if (regulator->supply_name == NULL)
goto overflow_err;
 
-   err = sysfs_create_link_nowarn(>dev.kobj, >kobj,
-   buf);
-   if (err) {
-   rdev_dbg(rdev, "could not add device link %s err %d\n",
- dev->kobj.name, err);
-   /* non-fatal */
+   if (device_is_registered(dev)) {
+   err = sysfs_create_link_nowarn(>dev.kobj,
+  >kobj, buf);
+   if (err) {
+   rdev_dbg(rdev,
+"could not add device link %s err 
%d\n",
+dev->kobj.name, err);
+   /* non-fatal */
+   }
}
} else {
regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
@@ -4416,6 +4419,18 @@ regulator_register(const struct regulator_desc 
*regulator_desc,
goto unset_supplies;
}
 
+   /* Add a link to the device sysfs entry */
+   if (rdev->supply && rdev->supply->dev) {
+   ret = sysfs_create_link_nowarn(>supply->dev->kobj,
+  >dev.kobj,
+  rdev->supply->supply_name);
+   if (ret) {
+   rdev_dbg(rdev, "could not add device link %s err %d\n",
+rdev->dev.kobj.name, ret);
+   /* non-fatal */
+   }
+   }
+
rdev_init_debugfs(rdev);
 
/* try to resolve regulators supply since a new one was registered */
-- 
2.11.0




[RESEND PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability

2018-05-03 Thread Jeffy Chen
We saw spurious irq when changing irq's trigger type, for example
setting gpio-keys's wakeup irq trigger type.

And according to the TRM:
"Programming the GPIO registers for interrupt capability, edge-sensitive
or level-sensitive interrupts, and interrupt polarity should be
completed prior to enabling the interrupts on Port A in order to prevent
spurious glitches on the interrupt lines to the interrupt controller."

Reported-by: Brian Norris <briannor...@google.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/pinctrl/pinctrl-rockchip.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c 
b/drivers/pinctrl/pinctrl-rockchip.c
index 3924779f55785..7ff45ec8330d1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -2727,9 +2727,19 @@ static int rockchip_irq_set_type(struct irq_data *d, 
unsigned int type)
return -EINVAL;
}
 
+   /**
+* According to the TRM, we should keep irq disabled during programming
+* interrupt capability to prevent spurious glitches on the interrupt
+* lines to the interrupt controller.
+*/
+   data = readl(bank->reg_base + GPIO_INTEN);
+   writel_relaxed(data & ~mask, gc->reg_base + GPIO_INTEN);
+
writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
 
+   writel_relaxed(data, gc->reg_base + GPIO_INTEN);
+
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(>slock, flags);
clk_disable(bank->clk);
-- 
2.11.0




[RESEND PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability

2018-05-03 Thread Jeffy Chen
We saw spurious irq when changing irq's trigger type, for example
setting gpio-keys's wakeup irq trigger type.

And according to the TRM:
"Programming the GPIO registers for interrupt capability, edge-sensitive
or level-sensitive interrupts, and interrupt polarity should be
completed prior to enabling the interrupts on Port A in order to prevent
spurious glitches on the interrupt lines to the interrupt controller."

Reported-by: Brian Norris 
Signed-off-by: Jeffy Chen 
---

 drivers/pinctrl/pinctrl-rockchip.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c 
b/drivers/pinctrl/pinctrl-rockchip.c
index 3924779f55785..7ff45ec8330d1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -2727,9 +2727,19 @@ static int rockchip_irq_set_type(struct irq_data *d, 
unsigned int type)
return -EINVAL;
}
 
+   /**
+* According to the TRM, we should keep irq disabled during programming
+* interrupt capability to prevent spurious glitches on the interrupt
+* lines to the interrupt controller.
+*/
+   data = readl(bank->reg_base + GPIO_INTEN);
+   writel_relaxed(data & ~mask, gc->reg_base + GPIO_INTEN);
+
writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
 
+   writel_relaxed(data, gc->reg_base + GPIO_INTEN);
+
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(>slock, flags);
clk_disable(bank->clk);
-- 
2.11.0




[PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability

2018-05-03 Thread Jeffy Chen
We saw spurious irq when changing irq's trigger type, for example
setting gpio-keys's wakeup irq trigger type.

And according to the TRM:
"Programming the GPIO registers for interrupt capability, edge-sensitive
or level-sensitive interrupts, and interrupt polarity should be
completed prior to enabling the interrupts on Port A in order to prevent
spurious glitches on the interrupt lines to the interrupt controller."

Reported-by: Brian Norris <computersforpe...@gmail.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/pinctrl/pinctrl-rockchip.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c 
b/drivers/pinctrl/pinctrl-rockchip.c
index 3924779f55785..7ff45ec8330d1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -2727,9 +2727,19 @@ static int rockchip_irq_set_type(struct irq_data *d, 
unsigned int type)
return -EINVAL;
}
 
+   /**
+* According to the TRM, we should keep irq disabled during programming
+* interrupt capability to prevent spurious glitches on the interrupt
+* lines to the interrupt controller.
+*/
+   data = readl(bank->reg_base + GPIO_INTEN);
+   writel_relaxed(data & ~mask, gc->reg_base + GPIO_INTEN);
+
writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
 
+   writel_relaxed(data, gc->reg_base + GPIO_INTEN);
+
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(>slock, flags);
clk_disable(bank->clk);
-- 
2.11.0




[PATCH] pinctrl: rockchip: Disable interrupt when changing it's capability

2018-05-03 Thread Jeffy Chen
We saw spurious irq when changing irq's trigger type, for example
setting gpio-keys's wakeup irq trigger type.

And according to the TRM:
"Programming the GPIO registers for interrupt capability, edge-sensitive
or level-sensitive interrupts, and interrupt polarity should be
completed prior to enabling the interrupts on Port A in order to prevent
spurious glitches on the interrupt lines to the interrupt controller."

Reported-by: Brian Norris 
Signed-off-by: Jeffy Chen 
---

 drivers/pinctrl/pinctrl-rockchip.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c 
b/drivers/pinctrl/pinctrl-rockchip.c
index 3924779f55785..7ff45ec8330d1 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -2727,9 +2727,19 @@ static int rockchip_irq_set_type(struct irq_data *d, 
unsigned int type)
return -EINVAL;
}
 
+   /**
+* According to the TRM, we should keep irq disabled during programming
+* interrupt capability to prevent spurious glitches on the interrupt
+* lines to the interrupt controller.
+*/
+   data = readl(bank->reg_base + GPIO_INTEN);
+   writel_relaxed(data & ~mask, gc->reg_base + GPIO_INTEN);
+
writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
 
+   writel_relaxed(data, gc->reg_base + GPIO_INTEN);
+
irq_gc_unlock(gc);
raw_spin_unlock_irqrestore(>slock, flags);
clk_disable(bank->clk);
-- 
2.11.0




[PATCH v8 00/14] iommu/rockchip: Use OF_IOMMU

2018-03-23 Thread Jeffy Chen

This series fixes some issues in rockchip iommu driver, and add of_iommu
support in it.

Changes in v8:
Rebase on newest for-next.
Don't introduce the additional return.
Rename startup()/shutdown() to enable()/disable().
Do runtime PM suspend in .shutdown().
Modify pm_runtime_get_if_in_use()/pm_runtime_put() as Tomasz suggested.

Changes in v7:
Use iommu_group_ref_get to avoid ref leak

Changes in v6:
Add clk names, and modify all iommu nodes in all existing rockchip dts
Fix dt-binding as Robin suggested.
Use aclk and iface clk as Rob and Robin suggested, and split binding
patch.

Changes in v5:
Use out labels to save the duplication between the error and success paths.
Use RK_MMU_POLL_PERIOD_US instead of 100.
Remove clk names.
Use clk_bulk APIs.
Avoid race about pm_runtime_get_if_in_use() and pm_runtime_enabled().

Changes in v4:
Rewrite commit message.

Changes in v3:
Also remove remove() and module_exit() as Tomasz suggested.
Loop platform_get_irq() as Robin suggested.
Add struct rk_iommudata.
Squash iommu/rockchip: Use iommu_group_get_for_dev() for add_device
Only call startup() and shutdown() when iommu attached.
Remove pm_mutex.
Check runtime PM disabled.
Check pm_runtime in rk_iommu_irq().
Remove rk_iommudata->domain.

Changes in v2:
Move irq request to probe(in patch[0])
Move bus_set_iommu() to rk_iommu_probe().

Jeffy Chen (10):
  iommu/rockchip: Prohibit unbind and remove
  iommu/rockchip: Fix error handling in probe
  iommu/rockchip: Request irqs in rk_iommu_probe()
  ARM: dts: rockchip: add clocks in iommu nodes
  dt-bindings: iommu/rockchip: Add clock property
  iommu/rockchip: Use IOMMU device for dma mapping operations
  iommu/rockchip: Use OF_IOMMU to attach devices automatically
  iommu/rockchip: Fix error handling in init
  iommu/rockchip: Add runtime PM support
  iommu/rockchip: Support sharing IOMMU between masters

Tomasz Figa (4):
  iommu/rockchip: Fix error handling in attach
  iommu/rockchip: Use iopoll helpers to wait for hardware
  iommu/rockchip: Fix TLB flush of secondary IOMMUs
  iommu/rockchip: Control clocks needed to access the IOMMU

 .../devicetree/bindings/iommu/rockchip,iommu.txt   |   7 +
 arch/arm/boot/dts/rk3036.dtsi  |   2 +
 arch/arm/boot/dts/rk322x.dtsi  |   8 +
 arch/arm/boot/dts/rk3288.dtsi  |  12 +
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  10 +
 arch/arm64/boot/dts/rockchip/rk3368.dtsi   |  10 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  14 +-
 drivers/iommu/rockchip-iommu.c | 600 +++--
 8 files changed, 363 insertions(+), 300 deletions(-)

-- 
2.11.0




[PATCH v8 00/14] iommu/rockchip: Use OF_IOMMU

2018-03-23 Thread Jeffy Chen

This series fixes some issues in rockchip iommu driver, and add of_iommu
support in it.

Changes in v8:
Rebase on newest for-next.
Don't introduce the additional return.
Rename startup()/shutdown() to enable()/disable().
Do runtime PM suspend in .shutdown().
Modify pm_runtime_get_if_in_use()/pm_runtime_put() as Tomasz suggested.

Changes in v7:
Use iommu_group_ref_get to avoid ref leak

Changes in v6:
Add clk names, and modify all iommu nodes in all existing rockchip dts
Fix dt-binding as Robin suggested.
Use aclk and iface clk as Rob and Robin suggested, and split binding
patch.

Changes in v5:
Use out labels to save the duplication between the error and success paths.
Use RK_MMU_POLL_PERIOD_US instead of 100.
Remove clk names.
Use clk_bulk APIs.
Avoid race about pm_runtime_get_if_in_use() and pm_runtime_enabled().

Changes in v4:
Rewrite commit message.

Changes in v3:
Also remove remove() and module_exit() as Tomasz suggested.
Loop platform_get_irq() as Robin suggested.
Add struct rk_iommudata.
Squash iommu/rockchip: Use iommu_group_get_for_dev() for add_device
Only call startup() and shutdown() when iommu attached.
Remove pm_mutex.
Check runtime PM disabled.
Check pm_runtime in rk_iommu_irq().
Remove rk_iommudata->domain.

Changes in v2:
Move irq request to probe(in patch[0])
Move bus_set_iommu() to rk_iommu_probe().

Jeffy Chen (10):
  iommu/rockchip: Prohibit unbind and remove
  iommu/rockchip: Fix error handling in probe
  iommu/rockchip: Request irqs in rk_iommu_probe()
  ARM: dts: rockchip: add clocks in iommu nodes
  dt-bindings: iommu/rockchip: Add clock property
  iommu/rockchip: Use IOMMU device for dma mapping operations
  iommu/rockchip: Use OF_IOMMU to attach devices automatically
  iommu/rockchip: Fix error handling in init
  iommu/rockchip: Add runtime PM support
  iommu/rockchip: Support sharing IOMMU between masters

Tomasz Figa (4):
  iommu/rockchip: Fix error handling in attach
  iommu/rockchip: Use iopoll helpers to wait for hardware
  iommu/rockchip: Fix TLB flush of secondary IOMMUs
  iommu/rockchip: Control clocks needed to access the IOMMU

 .../devicetree/bindings/iommu/rockchip,iommu.txt   |   7 +
 arch/arm/boot/dts/rk3036.dtsi  |   2 +
 arch/arm/boot/dts/rk322x.dtsi  |   8 +
 arch/arm/boot/dts/rk3288.dtsi  |  12 +
 arch/arm64/boot/dts/rockchip/rk3328.dtsi   |  10 +
 arch/arm64/boot/dts/rockchip/rk3368.dtsi   |  10 +
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  14 +-
 drivers/iommu/rockchip-iommu.c | 600 +++--
 8 files changed, 363 insertions(+), 300 deletions(-)

-- 
2.11.0




[PATCH v8 03/14] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-03-23 Thread Jeffy Chen
Move request_irq to the end of rk_iommu_probe().

Suggested-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Acked-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Loop platform_get_irq() as Robin suggested.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 38 +-
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 73117dbe839e..ec3ff936aa60 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -90,8 +90,6 @@ struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
-   int *irq;
-   int num_irq;
bool reset_disabled;
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
@@ -830,13 +828,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   for (i = 0; i < iommu->num_irq; i++) {
-   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
-  IRQF_SHARED, dev_name(dev), iommu);
-   if (ret)
-   return ret;
-   }
-
for (i = 0; i < iommu->num_mmu; i++) {
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
   rk_domain->dt_dma);
@@ -885,9 +876,6 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   for (i = 0; i < iommu->num_irq; i++)
-   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
-
iommu->domain = NULL;
 
dev_dbg(dev, "Detached from iommu domain\n");
@@ -1138,7 +1126,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct rk_iommu *iommu;
struct resource *res;
int num_res = pdev->num_resources;
-   int err, i;
+   int err, i, irq;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -1165,23 +1153,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (iommu->num_mmu == 0)
return PTR_ERR(iommu->bases[0]);
 
-   iommu->num_irq = platform_irq_count(pdev);
-   if (iommu->num_irq < 0)
-   return iommu->num_irq;
-   if (iommu->num_irq == 0)
-   return -ENXIO;
+   i = 0;
+   while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
+   if (irq < 0)
+   return irq;
 
-   iommu->irq = devm_kcalloc(dev, iommu->num_irq, sizeof(*iommu->irq),
- GFP_KERNEL);
-   if (!iommu->irq)
-   return -ENOMEM;
-
-   for (i = 0; i < iommu->num_irq; i++) {
-   iommu->irq[i] = platform_get_irq(pdev, i);
-   if (iommu->irq[i] < 0) {
-   dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq[i]);
-   return -ENXIO;
-   }
+   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
+  IRQF_SHARED, dev_name(dev), iommu);
+   if (err)
+   return err;
}
 
iommu->reset_disabled = device_property_read_bool(dev,
-- 
2.11.0




[PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-03-23 Thread Jeffy Chen
Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure,
which allows attaching master devices to their IOMMUs automatically
according to DT properties.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Add struct rk_iommudata.
Squash iommu/rockchip: Use iommu_group_get_for_dev() for add_device

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 135 -
 1 file changed, 40 insertions(+), 95 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 7970d21b9858..bd8580b897e9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,10 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+struct rk_iommudata {
+   struct rk_iommu *iommu;
+};
+
 static struct device *dma_dev;
 
 static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
@@ -807,18 +812,9 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, 
unsigned long _iova,
 
 static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
 {
-   struct iommu_group *group;
-   struct device *iommu_dev;
-   struct rk_iommu *rk_iommu;
+   struct rk_iommudata *data = dev->archdata.iommu;
 
-   group = iommu_group_get(dev);
-   if (!group)
-   return NULL;
-   iommu_dev = iommu_group_get_iommudata(group);
-   rk_iommu = dev_get_drvdata(iommu_dev);
-   iommu_group_put(group);
-
-   return rk_iommu;
+   return data ? data->iommu : NULL;
 }
 
 static int rk_iommu_attach_device(struct iommu_domain *domain,
@@ -989,110 +985,53 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)
iommu_put_dma_cookie(_domain->domain);
 }
 
-static bool rk_iommu_is_dev_iommu_master(struct device *dev)
-{
-   struct device_node *np = dev->of_node;
-   int ret;
-
-   /*
-* An iommu master has an iommus property containing a list of phandles
-* to iommu nodes, each with an #iommu-cells property with value 0.
-*/
-   ret = of_count_phandle_with_args(np, "iommus", "#iommu-cells");
-   return (ret > 0);
-}
-
-static int rk_iommu_group_set_iommudata(struct iommu_group *group,
-   struct device *dev)
+static int rk_iommu_add_device(struct device *dev)
 {
-   struct device_node *np = dev->of_node;
-   struct platform_device *pd;
-   int ret;
-   struct of_phandle_args args;
+   struct iommu_group *group;
+   struct rk_iommu *iommu;
 
-   /*
-* An iommu master has an iommus property containing a list of phandles
-* to iommu nodes, each with an #iommu-cells property with value 0.
-*/
-   ret = of_parse_phandle_with_args(np, "iommus", "#iommu-cells", 0,
-);
-   if (ret) {
-   dev_err(dev, "of_parse_phandle_with_args(%pOF) => %d\n",
-   np, ret);
-   return ret;
-   }
-   if (args.args_count != 0) {
-   dev_err(dev, "incorrect number of iommu params found for %pOF 
(found %d, expected 0)\n",
-   args.np, args.args_count);
-   return -EINVAL;
-   }
+   iommu = rk_iommu_from_dev(dev);
+   if (!iommu)
+   return -ENODEV;
 
-   pd = of_find_device_by_node(args.np);
-   of_node_put(args.np);
-   if (!pd) {
-   dev_err(dev, "iommu %pOF not found\n", args.np);
-   return -EPROBE_DEFER;
-   }
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+   iommu_group_put(group);
 
-   /* TODO(djkurtz): handle multiple slave iommus for a single master */
-   iommu_group_set_iommudata(group, >dev, NULL);
+   iommu_device_link(>iommu, dev);
 
return 0;
 }
 
-static int rk_iommu_add_device(struct device *dev)
+static void rk_iommu_remove_device(struct device *dev)
 {
-   struct iommu_group *group;
struct rk_iommu *iommu;
-   int ret;
-
-   if (!rk_iommu_is_dev_iommu_master(dev))
-   return -ENODEV;
-
-   group = iommu_group_get(dev);
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, "Failed to allocate IOMMU group\n");
-   return PTR_ERR(group);
-   }
-   }
-
-   ret = iommu_group_add_device(group, dev);
-   if (ret)
-   goto err_put_g

[PATCH v8 03/14] iommu/rockchip: Request irqs in rk_iommu_probe()

2018-03-23 Thread Jeffy Chen
Move request_irq to the end of rk_iommu_probe().

Suggested-by: Robin Murphy 
Signed-off-by: Jeffy Chen 
Acked-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Loop platform_get_irq() as Robin suggested.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 38 +-
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 73117dbe839e..ec3ff936aa60 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -90,8 +90,6 @@ struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
-   int *irq;
-   int num_irq;
bool reset_disabled;
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
@@ -830,13 +828,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
iommu->domain = domain;
 
-   for (i = 0; i < iommu->num_irq; i++) {
-   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
-  IRQF_SHARED, dev_name(dev), iommu);
-   if (ret)
-   return ret;
-   }
-
for (i = 0; i < iommu->num_mmu; i++) {
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
   rk_domain->dt_dma);
@@ -885,9 +876,6 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
}
rk_iommu_disable_stall(iommu);
 
-   for (i = 0; i < iommu->num_irq; i++)
-   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
-
iommu->domain = NULL;
 
dev_dbg(dev, "Detached from iommu domain\n");
@@ -1138,7 +1126,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct rk_iommu *iommu;
struct resource *res;
int num_res = pdev->num_resources;
-   int err, i;
+   int err, i, irq;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -1165,23 +1153,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (iommu->num_mmu == 0)
return PTR_ERR(iommu->bases[0]);
 
-   iommu->num_irq = platform_irq_count(pdev);
-   if (iommu->num_irq < 0)
-   return iommu->num_irq;
-   if (iommu->num_irq == 0)
-   return -ENXIO;
+   i = 0;
+   while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
+   if (irq < 0)
+   return irq;
 
-   iommu->irq = devm_kcalloc(dev, iommu->num_irq, sizeof(*iommu->irq),
- GFP_KERNEL);
-   if (!iommu->irq)
-   return -ENOMEM;
-
-   for (i = 0; i < iommu->num_irq; i++) {
-   iommu->irq[i] = platform_get_irq(pdev, i);
-   if (iommu->irq[i] < 0) {
-   dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq[i]);
-   return -ENXIO;
-   }
+   err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
+  IRQF_SHARED, dev_name(dev), iommu);
+   if (err)
+   return err;
}
 
iommu->reset_disabled = device_property_read_bool(dev,
-- 
2.11.0




[PATCH v8 11/14] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-03-23 Thread Jeffy Chen
Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure,
which allows attaching master devices to their IOMMUs automatically
according to DT properties.

Signed-off-by: Jeffy Chen 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Add struct rk_iommudata.
Squash iommu/rockchip: Use iommu_group_get_for_dev() for add_device

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 135 -
 1 file changed, 40 insertions(+), 95 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 7970d21b9858..bd8580b897e9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,10 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+struct rk_iommudata {
+   struct rk_iommu *iommu;
+};
+
 static struct device *dma_dev;
 
 static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
@@ -807,18 +812,9 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, 
unsigned long _iova,
 
 static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
 {
-   struct iommu_group *group;
-   struct device *iommu_dev;
-   struct rk_iommu *rk_iommu;
+   struct rk_iommudata *data = dev->archdata.iommu;
 
-   group = iommu_group_get(dev);
-   if (!group)
-   return NULL;
-   iommu_dev = iommu_group_get_iommudata(group);
-   rk_iommu = dev_get_drvdata(iommu_dev);
-   iommu_group_put(group);
-
-   return rk_iommu;
+   return data ? data->iommu : NULL;
 }
 
 static int rk_iommu_attach_device(struct iommu_domain *domain,
@@ -989,110 +985,53 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)
iommu_put_dma_cookie(_domain->domain);
 }
 
-static bool rk_iommu_is_dev_iommu_master(struct device *dev)
-{
-   struct device_node *np = dev->of_node;
-   int ret;
-
-   /*
-* An iommu master has an iommus property containing a list of phandles
-* to iommu nodes, each with an #iommu-cells property with value 0.
-*/
-   ret = of_count_phandle_with_args(np, "iommus", "#iommu-cells");
-   return (ret > 0);
-}
-
-static int rk_iommu_group_set_iommudata(struct iommu_group *group,
-   struct device *dev)
+static int rk_iommu_add_device(struct device *dev)
 {
-   struct device_node *np = dev->of_node;
-   struct platform_device *pd;
-   int ret;
-   struct of_phandle_args args;
+   struct iommu_group *group;
+   struct rk_iommu *iommu;
 
-   /*
-* An iommu master has an iommus property containing a list of phandles
-* to iommu nodes, each with an #iommu-cells property with value 0.
-*/
-   ret = of_parse_phandle_with_args(np, "iommus", "#iommu-cells", 0,
-);
-   if (ret) {
-   dev_err(dev, "of_parse_phandle_with_args(%pOF) => %d\n",
-   np, ret);
-   return ret;
-   }
-   if (args.args_count != 0) {
-   dev_err(dev, "incorrect number of iommu params found for %pOF 
(found %d, expected 0)\n",
-   args.np, args.args_count);
-   return -EINVAL;
-   }
+   iommu = rk_iommu_from_dev(dev);
+   if (!iommu)
+   return -ENODEV;
 
-   pd = of_find_device_by_node(args.np);
-   of_node_put(args.np);
-   if (!pd) {
-   dev_err(dev, "iommu %pOF not found\n", args.np);
-   return -EPROBE_DEFER;
-   }
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+   iommu_group_put(group);
 
-   /* TODO(djkurtz): handle multiple slave iommus for a single master */
-   iommu_group_set_iommudata(group, >dev, NULL);
+   iommu_device_link(>iommu, dev);
 
return 0;
 }
 
-static int rk_iommu_add_device(struct device *dev)
+static void rk_iommu_remove_device(struct device *dev)
 {
-   struct iommu_group *group;
struct rk_iommu *iommu;
-   int ret;
-
-   if (!rk_iommu_is_dev_iommu_master(dev))
-   return -ENODEV;
-
-   group = iommu_group_get(dev);
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, "Failed to allocate IOMMU group\n");
-   return PTR_ERR(group);
-   }
-   }
-
-   ret = iommu_group_add_device(group, dev);
-   if (ret)
-   goto err_put_group;
-
-   ret = rk_iommu_group_set_iommudata(gr

[PATCH v8 13/14] iommu/rockchip: Add runtime PM support

2018-03-23 Thread Jeffy Chen
When the power domain is powered off, the IOMMU cannot be accessed and
register programming must be deferred until the power domain becomes
enabled.

Add runtime PM support, and use runtime PM device link from IOMMU to
master to enable and disable IOMMU.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v8:
Rename startup()/shutdown() to enable()/disable().
Do runtime PM suspend in .shutdown().
Modify pm_runtime_get_if_in_use()/pm_runtime_put() as Tomasz suggested.

Changes in v7: None
Changes in v6: None
Changes in v5:
Avoid race about pm_runtime_get_if_in_use() and pm_runtime_enabled().

Changes in v4: None
Changes in v3:
Only call startup() and shutdown() when iommu attached.
Remove pm_mutex.
Check runtime PM disabled.
Check pm_runtime in rk_iommu_irq().

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 181 +
 1 file changed, 129 insertions(+), 52 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0ce5e8a0658c..9f6f74689464 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -106,6 +107,7 @@ struct rk_iommu {
 };
 
 struct rk_iommudata {
+   struct device_link *link; /* runtime PM link from IOMMU to master */
struct rk_iommu *iommu;
 };
 
@@ -520,7 +522,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
int i;
 
-   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+   if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev)))
+   return 0;
+
+   if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
+   goto out;
 
for (i = 0; i < iommu->num_mmu; i++) {
int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS);
@@ -570,6 +576,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
 
clk_bulk_disable(iommu->num_clocks, iommu->clocks);
 
+out:
+   pm_runtime_put(iommu->dev);
return ret;
 }
 
@@ -611,10 +619,17 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain 
*rk_domain,
spin_lock_irqsave(_domain->iommus_lock, flags);
list_for_each(pos, _domain->iommus) {
struct rk_iommu *iommu;
+
iommu = list_entry(pos, struct rk_iommu, node);
-   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
-   rk_iommu_zap_lines(iommu, iova, size);
-   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
+   /* Only zap TLBs of IOMMUs that are powered on. */
+   if (pm_runtime_get_if_in_use(iommu->dev)) {
+   WARN_ON(clk_bulk_enable(iommu->num_clocks,
+   iommu->clocks));
+   rk_iommu_zap_lines(iommu, iova, size);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+   pm_runtime_put(iommu->dev);
+   }
}
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 }
@@ -817,22 +832,30 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
return data ? data->iommu : NULL;
 }
 
-static int rk_iommu_attach_device(struct iommu_domain *domain,
- struct device *dev)
+/* Must be called with iommu powered on and attached */
+static void rk_iommu_disable(struct rk_iommu *iommu)
 {
-   struct rk_iommu *iommu;
+   int i;
+
+   /* Ignore error while disabling, just keep going */
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+   rk_iommu_enable_stall(iommu);
+   rk_iommu_disable_paging(iommu);
+   for (i = 0; i < iommu->num_mmu; i++) {
+   rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
+   rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
+   }
+   rk_iommu_disable_stall(iommu);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+}
+
+/* Must be called with iommu powered on and attached */
+static int rk_iommu_enable(struct rk_iommu *iommu)
+{
+   struct iommu_domain *domain = iommu->domain;
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
-   unsigned long flags;
int ret, i;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
-   iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
-   return 0;
-
ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
if (ret)
return ret;
@@ -845,8 +868,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (ret)
goto out_disable_stall;
 
-   iommu->domain = dom

[PATCH v8 12/14] iommu/rockchip: Fix error handling in init

2018-03-23 Thread Jeffy Chen
It's hard to undo bus_set_iommu() in the error path, so move it to the
end of rk_iommu_probe().

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
Move bus_set_iommu() to rk_iommu_probe().

 drivers/iommu/rockchip-iommu.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index bd8580b897e9..0ce5e8a0658c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1133,6 +1133,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (!dma_dev)
dma_dev = >dev;
 
+   bus_set_iommu(_bus_type, _iommu_ops);
+
return 0;
 err_remove_sysfs:
iommu_device_sysfs_remove(>iommu);
@@ -1176,19 +1178,6 @@ static struct platform_driver rk_iommu_driver = {
 
 static int __init rk_iommu_init(void)
 {
-   struct device_node *np;
-   int ret;
-
-   np = of_find_matching_node(NULL, rk_iommu_dt_ids);
-   if (!np)
-   return 0;
-
-   of_node_put(np);
-
-   ret = bus_set_iommu(_bus_type, _iommu_ops);
-   if (ret)
-   return ret;
-
return platform_driver_register(_iommu_driver);
 }
 subsys_initcall(rk_iommu_init);
-- 
2.11.0




[PATCH v8 12/14] iommu/rockchip: Fix error handling in init

2018-03-23 Thread Jeffy Chen
It's hard to undo bus_set_iommu() in the error path, so move it to the
end of rk_iommu_probe().

Signed-off-by: Jeffy Chen 
Reviewed-by: Tomasz Figa 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
Move bus_set_iommu() to rk_iommu_probe().

 drivers/iommu/rockchip-iommu.c | 15 ++-
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index bd8580b897e9..0ce5e8a0658c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1133,6 +1133,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (!dma_dev)
dma_dev = >dev;
 
+   bus_set_iommu(_bus_type, _iommu_ops);
+
return 0;
 err_remove_sysfs:
iommu_device_sysfs_remove(>iommu);
@@ -1176,19 +1178,6 @@ static struct platform_driver rk_iommu_driver = {
 
 static int __init rk_iommu_init(void)
 {
-   struct device_node *np;
-   int ret;
-
-   np = of_find_matching_node(NULL, rk_iommu_dt_ids);
-   if (!np)
-   return 0;
-
-   of_node_put(np);
-
-   ret = bus_set_iommu(_bus_type, _iommu_ops);
-   if (ret)
-   return ret;
-
return platform_driver_register(_iommu_driver);
 }
 subsys_initcall(rk_iommu_init);
-- 
2.11.0




[PATCH v8 13/14] iommu/rockchip: Add runtime PM support

2018-03-23 Thread Jeffy Chen
When the power domain is powered off, the IOMMU cannot be accessed and
register programming must be deferred until the power domain becomes
enabled.

Add runtime PM support, and use runtime PM device link from IOMMU to
master to enable and disable IOMMU.

Signed-off-by: Jeffy Chen 
---

Changes in v8:
Rename startup()/shutdown() to enable()/disable().
Do runtime PM suspend in .shutdown().
Modify pm_runtime_get_if_in_use()/pm_runtime_put() as Tomasz suggested.

Changes in v7: None
Changes in v6: None
Changes in v5:
Avoid race about pm_runtime_get_if_in_use() and pm_runtime_enabled().

Changes in v4: None
Changes in v3:
Only call startup() and shutdown() when iommu attached.
Remove pm_mutex.
Check runtime PM disabled.
Check pm_runtime in rk_iommu_irq().

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 181 +
 1 file changed, 129 insertions(+), 52 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0ce5e8a0658c..9f6f74689464 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -106,6 +107,7 @@ struct rk_iommu {
 };
 
 struct rk_iommudata {
+   struct device_link *link; /* runtime PM link from IOMMU to master */
struct rk_iommu *iommu;
 };
 
@@ -520,7 +522,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
int i;
 
-   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+   if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev)))
+   return 0;
+
+   if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
+   goto out;
 
for (i = 0; i < iommu->num_mmu; i++) {
int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS);
@@ -570,6 +576,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
 
clk_bulk_disable(iommu->num_clocks, iommu->clocks);
 
+out:
+   pm_runtime_put(iommu->dev);
return ret;
 }
 
@@ -611,10 +619,17 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain 
*rk_domain,
spin_lock_irqsave(_domain->iommus_lock, flags);
list_for_each(pos, _domain->iommus) {
struct rk_iommu *iommu;
+
iommu = list_entry(pos, struct rk_iommu, node);
-   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
-   rk_iommu_zap_lines(iommu, iova, size);
-   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
+   /* Only zap TLBs of IOMMUs that are powered on. */
+   if (pm_runtime_get_if_in_use(iommu->dev)) {
+   WARN_ON(clk_bulk_enable(iommu->num_clocks,
+   iommu->clocks));
+   rk_iommu_zap_lines(iommu, iova, size);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+   pm_runtime_put(iommu->dev);
+   }
}
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 }
@@ -817,22 +832,30 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
return data ? data->iommu : NULL;
 }
 
-static int rk_iommu_attach_device(struct iommu_domain *domain,
- struct device *dev)
+/* Must be called with iommu powered on and attached */
+static void rk_iommu_disable(struct rk_iommu *iommu)
 {
-   struct rk_iommu *iommu;
+   int i;
+
+   /* Ignore error while disabling, just keep going */
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+   rk_iommu_enable_stall(iommu);
+   rk_iommu_disable_paging(iommu);
+   for (i = 0; i < iommu->num_mmu; i++) {
+   rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
+   rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
+   }
+   rk_iommu_disable_stall(iommu);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+}
+
+/* Must be called with iommu powered on and attached */
+static int rk_iommu_enable(struct rk_iommu *iommu)
+{
+   struct iommu_domain *domain = iommu->domain;
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
-   unsigned long flags;
int ret, i;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
-   iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
-   return 0;
-
ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
if (ret)
return ret;
@@ -845,8 +868,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (ret)
goto out_disable_stall;
 
-   iommu->domain = domain;
-

[PATCH v8 14/14] iommu/rockchip: Support sharing IOMMU between masters

2018-03-23 Thread Jeffy Chen
There would be some masters sharing the same IOMMU device. Put them in
the same iommu group and share the same iommu domain.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7:
Use iommu_group_ref_get to avoid ref leak

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Remove rk_iommudata->domain.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9f6f74689464..5fc8656c60f9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -104,6 +104,7 @@ struct rk_iommu {
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
struct iommu_domain *domain; /* domain to which iommu is attached */
+   struct iommu_group *group;
 };
 
 struct rk_iommudata {
@@ -1073,6 +1074,15 @@ static void rk_iommu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
 }
 
+static struct iommu_group *rk_iommu_device_group(struct device *dev)
+{
+   struct rk_iommu *iommu;
+
+   iommu = rk_iommu_from_dev(dev);
+
+   return iommu_group_ref_get(iommu->group);
+}
+
 static int rk_iommu_of_xlate(struct device *dev,
 struct of_phandle_args *args)
 {
@@ -1104,7 +1114,7 @@ static const struct iommu_ops rk_iommu_ops = {
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-   .device_group = generic_device_group,
+   .device_group = rk_iommu_device_group,
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
.of_xlate = rk_iommu_of_xlate,
 };
@@ -1173,9 +1183,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (err)
return err;
 
+   iommu->group = iommu_group_alloc();
+   if (IS_ERR(iommu->group)) {
+   err = PTR_ERR(iommu->group);
+   goto err_unprepare_clocks;
+   }
+
err = iommu_device_sysfs_add(>iommu, dev, NULL, dev_name(dev));
if (err)
-   goto err_unprepare_clocks;
+   goto err_put_group;
 
iommu_device_set_ops(>iommu, _iommu_ops);
iommu_device_set_fwnode(>iommu, >of_node->fwnode);
@@ -1199,6 +1215,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
return 0;
 err_remove_sysfs:
iommu_device_sysfs_remove(>iommu);
+err_put_group:
+   iommu_group_put(iommu->group);
 err_unprepare_clocks:
clk_bulk_unprepare(iommu->num_clocks, iommu->clocks);
return err;
-- 
2.11.0




[PATCH v8 10/14] iommu/rockchip: Use IOMMU device for dma mapping operations

2018-03-23 Thread Jeffy Chen
Use the first registered IOMMU device for dma mapping operations, and
drop the domain platform device.

This is similar to exynos iommu driver.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 85 --
 1 file changed, 24 insertions(+), 61 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 50ab9fd4eeb0..7970d21b9858 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -79,7 +79,6 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
-   struct platform_device *pdev;
u32 *dt; /* page directory table */
dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
@@ -105,12 +104,14 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+static struct device *dma_dev;
+
 static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
  unsigned int count)
 {
size_t size = count * sizeof(u32); /* count of u32 entry */
 
-   dma_sync_single_for_device(>pdev->dev, dma, size, DMA_TO_DEVICE);
+   dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -625,7 +626,6 @@ static void rk_iommu_zap_iova_first_last(struct 
rk_iommu_domain *rk_domain,
 static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
  dma_addr_t iova)
 {
-   struct device *dev = _domain->pdev->dev;
u32 *page_table, *dte_addr;
u32 dte_index, dte;
phys_addr_t pt_phys;
@@ -643,9 +643,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(dev, pt_dma)) {
-   dev_err(dev, "DMA mapping error while allocating page table\n");
+   pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(dma_dev, pt_dma)) {
+   dev_err(dma_dev, "DMA mapping error while allocating page 
table\n");
free_page((unsigned long)page_table);
return ERR_PTR(-ENOMEM);
}
@@ -911,29 +911,20 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
 static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
 {
struct rk_iommu_domain *rk_domain;
-   struct platform_device *pdev;
-   struct device *iommu_dev;
 
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
 
-   /* Register a pdev per domain, so DMA API can base on this *dev
-* even some virtual master doesn't have an iommu slave
-*/
-   pdev = platform_device_register_simple("rk_iommu_domain",
-  PLATFORM_DEVID_AUTO, NULL, 0);
-   if (IS_ERR(pdev))
+   if (!dma_dev)
return NULL;
 
-   rk_domain = devm_kzalloc(>dev, sizeof(*rk_domain), GFP_KERNEL);
+   rk_domain = devm_kzalloc(dma_dev, sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
-   goto err_unreg_pdev;
-
-   rk_domain->pdev = pdev;
+   return NULL;
 
if (type == IOMMU_DOMAIN_DMA &&
iommu_get_dma_cookie(_domain->domain))
-   goto err_unreg_pdev;
+   return NULL;
 
/*
 * rk32xx iommus use a 2 level pagetable.
@@ -944,11 +935,10 @@ static struct iommu_domain 
*rk_iommu_domain_alloc(unsigned type)
if (!rk_domain->dt)
goto err_put_cookie;
 
-   iommu_dev = >dev;
-   rk_domain->dt_dma = dma_map_single(iommu_dev, rk_domain->dt,
+   rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
   SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(iommu_dev, rk_domain->dt_dma)) {
-   dev_err(iommu_dev, "DMA map error for DT\n");
+   if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
+   dev_err(dma_dev, "DMA map error for DT\n");
goto err_free_dt;
}
 
@@ -969,8 +959,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
 err_put_cookie:
if (type == IOMMU_DOMAIN_DMA)
iommu_put_dma_cookie(_domain->domain);
-err_unreg_pdev:
-   platform_device_unregister(pdev);
 
return NULL

[PATCH v8 14/14] iommu/rockchip: Support sharing IOMMU between masters

2018-03-23 Thread Jeffy Chen
There would be some masters sharing the same IOMMU device. Put them in
the same iommu group and share the same iommu domain.

Signed-off-by: Jeffy Chen 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7:
Use iommu_group_ref_get to avoid ref leak

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
Remove rk_iommudata->domain.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9f6f74689464..5fc8656c60f9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -104,6 +104,7 @@ struct rk_iommu {
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
struct iommu_domain *domain; /* domain to which iommu is attached */
+   struct iommu_group *group;
 };
 
 struct rk_iommudata {
@@ -1073,6 +1074,15 @@ static void rk_iommu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
 }
 
+static struct iommu_group *rk_iommu_device_group(struct device *dev)
+{
+   struct rk_iommu *iommu;
+
+   iommu = rk_iommu_from_dev(dev);
+
+   return iommu_group_ref_get(iommu->group);
+}
+
 static int rk_iommu_of_xlate(struct device *dev,
 struct of_phandle_args *args)
 {
@@ -1104,7 +1114,7 @@ static const struct iommu_ops rk_iommu_ops = {
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-   .device_group = generic_device_group,
+   .device_group = rk_iommu_device_group,
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
.of_xlate = rk_iommu_of_xlate,
 };
@@ -1173,9 +1183,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (err)
return err;
 
+   iommu->group = iommu_group_alloc();
+   if (IS_ERR(iommu->group)) {
+   err = PTR_ERR(iommu->group);
+   goto err_unprepare_clocks;
+   }
+
err = iommu_device_sysfs_add(>iommu, dev, NULL, dev_name(dev));
if (err)
-   goto err_unprepare_clocks;
+   goto err_put_group;
 
iommu_device_set_ops(>iommu, _iommu_ops);
iommu_device_set_fwnode(>iommu, >of_node->fwnode);
@@ -1199,6 +1215,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
return 0;
 err_remove_sysfs:
iommu_device_sysfs_remove(>iommu);
+err_put_group:
+   iommu_group_put(iommu->group);
 err_unprepare_clocks:
clk_bulk_unprepare(iommu->num_clocks, iommu->clocks);
return err;
-- 
2.11.0




[PATCH v8 10/14] iommu/rockchip: Use IOMMU device for dma mapping operations

2018-03-23 Thread Jeffy Chen
Use the first registered IOMMU device for dma mapping operations, and
drop the domain platform device.

This is similar to exynos iommu driver.

Signed-off-by: Jeffy Chen 
Reviewed-by: Tomasz Figa 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 85 --
 1 file changed, 24 insertions(+), 61 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 50ab9fd4eeb0..7970d21b9858 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -79,7 +79,6 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
-   struct platform_device *pdev;
u32 *dt; /* page directory table */
dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
@@ -105,12 +104,14 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+static struct device *dma_dev;
+
 static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
  unsigned int count)
 {
size_t size = count * sizeof(u32); /* count of u32 entry */
 
-   dma_sync_single_for_device(>pdev->dev, dma, size, DMA_TO_DEVICE);
+   dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -625,7 +626,6 @@ static void rk_iommu_zap_iova_first_last(struct 
rk_iommu_domain *rk_domain,
 static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
  dma_addr_t iova)
 {
-   struct device *dev = _domain->pdev->dev;
u32 *page_table, *dte_addr;
u32 dte_index, dte;
phys_addr_t pt_phys;
@@ -643,9 +643,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(dev, pt_dma)) {
-   dev_err(dev, "DMA mapping error while allocating page table\n");
+   pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(dma_dev, pt_dma)) {
+   dev_err(dma_dev, "DMA mapping error while allocating page 
table\n");
free_page((unsigned long)page_table);
return ERR_PTR(-ENOMEM);
}
@@ -911,29 +911,20 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
 static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
 {
struct rk_iommu_domain *rk_domain;
-   struct platform_device *pdev;
-   struct device *iommu_dev;
 
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
 
-   /* Register a pdev per domain, so DMA API can base on this *dev
-* even some virtual master doesn't have an iommu slave
-*/
-   pdev = platform_device_register_simple("rk_iommu_domain",
-  PLATFORM_DEVID_AUTO, NULL, 0);
-   if (IS_ERR(pdev))
+   if (!dma_dev)
return NULL;
 
-   rk_domain = devm_kzalloc(>dev, sizeof(*rk_domain), GFP_KERNEL);
+   rk_domain = devm_kzalloc(dma_dev, sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
-   goto err_unreg_pdev;
-
-   rk_domain->pdev = pdev;
+   return NULL;
 
if (type == IOMMU_DOMAIN_DMA &&
iommu_get_dma_cookie(_domain->domain))
-   goto err_unreg_pdev;
+   return NULL;
 
/*
 * rk32xx iommus use a 2 level pagetable.
@@ -944,11 +935,10 @@ static struct iommu_domain 
*rk_iommu_domain_alloc(unsigned type)
if (!rk_domain->dt)
goto err_put_cookie;
 
-   iommu_dev = >dev;
-   rk_domain->dt_dma = dma_map_single(iommu_dev, rk_domain->dt,
+   rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
   SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(iommu_dev, rk_domain->dt_dma)) {
-   dev_err(iommu_dev, "DMA map error for DT\n");
+   if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
+   dev_err(dma_dev, "DMA map error for DT\n");
goto err_free_dt;
}
 
@@ -969,8 +959,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
 err_put_cookie:
if (type == IOMMU_DOMAIN_DMA)
iommu_put_dma_cookie(_domain->domain);
-err_unreg_pdev:
-   platform_device_unregister(pdev);
 
return NULL;
 }
@@ -987,20 +975,18 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)

[PATCH v8 09/14] dt-bindings: iommu/rockchip: Add clock property

2018-03-23 Thread Jeffy Chen
Add clock property, since we are going to control clocks in rockchip
iommu driver.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt 
b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
index 2098f7732264..6ecefea1c6f9 100644
--- a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
@@ -14,6 +14,11 @@ Required properties:
 "single-master" device, and needs no additional information
 to associate with its master device.  See:
 Documentation/devicetree/bindings/iommu/iommu.txt
+- clocks  : A list of clocks required for the IOMMU to be accessible by
+the host CPU.
+- clock-names : Should contain the following:
+   "iface" - Main peripheral bus clock (PCLK/HCL) (required)
+   "aclk"  - AXI bus clock (required)
 
 Optional properties:
 - rockchip,disable-mmu-reset : Don't use the mmu reset operation.
@@ -27,5 +32,7 @@ Example:
reg = <0xff940300 0x100>;
interrupts = ;
interrupt-names = "vopl_mmu";
+   clocks = < ACLK_VOP1>, < HCLK_VOP1>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
};
-- 
2.11.0




[PATCH v8 09/14] dt-bindings: iommu/rockchip: Add clock property

2018-03-23 Thread Jeffy Chen
Add clock property, since we are going to control clocks in rockchip
iommu driver.

Signed-off-by: Jeffy Chen 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt 
b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
index 2098f7732264..6ecefea1c6f9 100644
--- a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt
@@ -14,6 +14,11 @@ Required properties:
 "single-master" device, and needs no additional information
 to associate with its master device.  See:
 Documentation/devicetree/bindings/iommu/iommu.txt
+- clocks  : A list of clocks required for the IOMMU to be accessible by
+the host CPU.
+- clock-names : Should contain the following:
+   "iface" - Main peripheral bus clock (PCLK/HCL) (required)
+   "aclk"  - AXI bus clock (required)
 
 Optional properties:
 - rockchip,disable-mmu-reset : Don't use the mmu reset operation.
@@ -27,5 +32,7 @@ Example:
reg = <0xff940300 0x100>;
interrupts = ;
interrupt-names = "vopl_mmu";
+   clocks = < ACLK_VOP1>, < HCLK_VOP1>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
};
-- 
2.11.0




[PATCH v8 06/14] iommu/rockchip: Fix TLB flush of secondary IOMMUs

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

Due to the bug in current code, only first IOMMU has the TLB lines
flushed in rk_iommu_zap_lines. This patch fixes the inner loop to
execute for all IOMMUs and properly flush the TLB.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 7130d92ff79c..c3df53e480ea 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -274,19 +274,21 @@ static void rk_iommu_base_command(void __iomem *base, u32 
command)
 {
writel(command, base + RK_MMU_COMMAND);
 }
-static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova,
+static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova_start,
   size_t size)
 {
int i;
-
-   dma_addr_t iova_end = iova + size;
+   dma_addr_t iova_end = iova_start + size;
/*
 * TODO(djkurtz): Figure out when it is more efficient to shootdown the
 * entire iotlb rather than iterate over individual iovas.
 */
-   for (i = 0; i < iommu->num_mmu; i++)
-   for (; iova < iova_end; iova += SPAGE_SIZE)
+   for (i = 0; i < iommu->num_mmu; i++) {
+   dma_addr_t iova;
+
+   for (iova = iova_start; iova < iova_end; iova += SPAGE_SIZE)
rk_iommu_write(iommu->bases[i], RK_MMU_ZAP_ONE_LINE, 
iova);
+   }
 }
 
 static bool rk_iommu_is_stall_active(struct rk_iommu *iommu)
-- 
2.11.0




[PATCH v8 07/14] ARM: dts: rockchip: add clocks in iommu nodes

2018-03-23 Thread Jeffy Chen
Add clocks in iommu nodes, since we are going to control clocks in
rockchip iommu driver.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6:
Add clk names, and modify all iommu nodes in all existing rockchip dts

Changes in v5:
Remove clk names.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/boot/dts/rk3036.dtsi|  2 ++
 arch/arm/boot/dts/rk322x.dtsi|  8 
 arch/arm/boot/dts/rk3288.dtsi| 12 
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 10 ++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 10 ++
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 14 --
 6 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index a97458112ff6..567a6a725f9c 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -197,6 +197,8 @@
reg = <0x10118300 0x100>;
interrupts = ;
interrupt-names = "vop_mmu";
+   clocks = < ACLK_LCDC>, < HCLK_LCDC>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index df1e47858675..be80e9a2c9af 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -584,6 +584,8 @@
reg = <0x20020800 0x100>;
interrupts = ;
interrupt-names = "vpu_mmu";
+   clocks = < ACLK_VPU>, < HCLK_VPU>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -593,6 +595,8 @@
reg = <0x20030480 0x40>, <0x200304c0 0x40>;
interrupts = ;
interrupt-names = "vdec_mmu";
+   clocks = < ACLK_RKVDEC>, < HCLK_RKVDEC>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -602,6 +606,8 @@
reg = <0x20053f00 0x100>;
interrupts = ;
interrupt-names = "vop_mmu";
+   clocks = < ACLK_VOP>, < HCLK_VOP>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -611,6 +617,8 @@
reg = <0x20070800 0x100>;
interrupts = ;
interrupt-names = "iep_mmu";
+   clocks = < ACLK_IEP>, < HCLK_IEP>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index be9acb6d28a1..d7e49d29ace5 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -959,6 +959,8 @@
reg = <0x0 0xff900800 0x0 0x40>;
interrupts = ;
interrupt-names = "iep_mmu";
+   clocks = < ACLK_IEP>, < HCLK_IEP>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -968,6 +970,8 @@
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
interrupts = ;
interrupt-names = "isp_mmu";
+   clocks = < ACLK_ISP>, < HCLK_ISP>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
@@ -1027,6 +1031,8 @@
reg = <0x0 0xff930300 0x0 0x100>;
interrupts = ;
interrupt-names = "vopb_mmu";
+   clocks = < ACLK_VOP0>, < HCLK_VOP0>;
+   clock-names = "aclk", "iface";
power-domains = < RK3288_PD_VIO>;
#iommu-cells = <0>;
status = "disabled";
@@ -1075,6 +1081,8 @@
reg = <0x0 0xff940300 0x0 0x100>;
interrupts = ;
interrupt-names = "vopl_mmu";
+   clocks = < ACLK_VOP1>, < HCLK_VOP1>;
+   clock-names = "aclk", "iface";
power-domains = < RK3288_PD_VIO>;
#iommu-cells = <0>;
status = &

[PATCH v8 06/14] iommu/rockchip: Fix TLB flush of secondary IOMMUs

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa 

Due to the bug in current code, only first IOMMU has the TLB lines
flushed in rk_iommu_zap_lines. This patch fixes the inner loop to
execute for all IOMMUs and properly flush the TLB.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 7130d92ff79c..c3df53e480ea 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -274,19 +274,21 @@ static void rk_iommu_base_command(void __iomem *base, u32 
command)
 {
writel(command, base + RK_MMU_COMMAND);
 }
-static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova,
+static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova_start,
   size_t size)
 {
int i;
-
-   dma_addr_t iova_end = iova + size;
+   dma_addr_t iova_end = iova_start + size;
/*
 * TODO(djkurtz): Figure out when it is more efficient to shootdown the
 * entire iotlb rather than iterate over individual iovas.
 */
-   for (i = 0; i < iommu->num_mmu; i++)
-   for (; iova < iova_end; iova += SPAGE_SIZE)
+   for (i = 0; i < iommu->num_mmu; i++) {
+   dma_addr_t iova;
+
+   for (iova = iova_start; iova < iova_end; iova += SPAGE_SIZE)
rk_iommu_write(iommu->bases[i], RK_MMU_ZAP_ONE_LINE, 
iova);
+   }
 }
 
 static bool rk_iommu_is_stall_active(struct rk_iommu *iommu)
-- 
2.11.0




[PATCH v8 07/14] ARM: dts: rockchip: add clocks in iommu nodes

2018-03-23 Thread Jeffy Chen
Add clocks in iommu nodes, since we are going to control clocks in
rockchip iommu driver.

Signed-off-by: Jeffy Chen 
---

Changes in v8: None
Changes in v7: None
Changes in v6:
Add clk names, and modify all iommu nodes in all existing rockchip dts

Changes in v5:
Remove clk names.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/boot/dts/rk3036.dtsi|  2 ++
 arch/arm/boot/dts/rk322x.dtsi|  8 
 arch/arm/boot/dts/rk3288.dtsi| 12 
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 10 ++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 10 ++
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 14 --
 6 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index a97458112ff6..567a6a725f9c 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -197,6 +197,8 @@
reg = <0x10118300 0x100>;
interrupts = ;
interrupt-names = "vop_mmu";
+   clocks = < ACLK_LCDC>, < HCLK_LCDC>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index df1e47858675..be80e9a2c9af 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -584,6 +584,8 @@
reg = <0x20020800 0x100>;
interrupts = ;
interrupt-names = "vpu_mmu";
+   clocks = < ACLK_VPU>, < HCLK_VPU>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -593,6 +595,8 @@
reg = <0x20030480 0x40>, <0x200304c0 0x40>;
interrupts = ;
interrupt-names = "vdec_mmu";
+   clocks = < ACLK_RKVDEC>, < HCLK_RKVDEC>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -602,6 +606,8 @@
reg = <0x20053f00 0x100>;
interrupts = ;
interrupt-names = "vop_mmu";
+   clocks = < ACLK_VOP>, < HCLK_VOP>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -611,6 +617,8 @@
reg = <0x20070800 0x100>;
interrupts = ;
interrupt-names = "iep_mmu";
+   clocks = < ACLK_IEP>, < HCLK_IEP>;
+   clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index be9acb6d28a1..d7e49d29ace5 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -959,6 +959,8 @@
reg = <0x0 0xff900800 0x0 0x40>;
interrupts = ;
interrupt-names = "iep_mmu";
+   clocks = < ACLK_IEP>, < HCLK_IEP>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -968,6 +970,8 @@
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
interrupts = ;
interrupt-names = "isp_mmu";
+   clocks = < ACLK_ISP>, < HCLK_ISP>;
+   clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
@@ -1027,6 +1031,8 @@
reg = <0x0 0xff930300 0x0 0x100>;
interrupts = ;
interrupt-names = "vopb_mmu";
+   clocks = < ACLK_VOP0>, < HCLK_VOP0>;
+   clock-names = "aclk", "iface";
power-domains = < RK3288_PD_VIO>;
#iommu-cells = <0>;
status = "disabled";
@@ -1075,6 +1081,8 @@
reg = <0x0 0xff940300 0x0 0x100>;
interrupts = ;
interrupt-names = "vopl_mmu";
+   clocks = < ACLK_VOP1>, < HCLK_VOP1>;
+   clock-names = "aclk", "iface";
power-domains = < RK3288_PD_VIO>;
#iommu-cells = <0>;
status = "disabled";
@@ -1206

[PATCH v8 08/14] iommu/rockchip: Control clocks needed to access the IOMMU

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

Current code relies on master driver enabling necessary clocks before
IOMMU is accessed, however there are cases when the IOMMU should be
accessed while the master is not running yet, for example allocating
V4L2 videobuf2 buffers, which is done by the VB2 framework using DMA
mapping API and doesn't engage the master driver at all.

This patch fixes the problem by letting clocks needed for IOMMU
operation to be listed in Device Tree and making the driver enable them
for the time of accessing the hardware.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Acked-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6:
Fix dt-binding as Robin suggested.
Use aclk and iface clk as Rob and Robin suggested, and split binding
patch.

Changes in v5:
Use clk_bulk APIs.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 50 +++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c3df53e480ea..50ab9fd4eeb0 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,6 +4,7 @@
  * published by the Free Software Foundation.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -87,10 +88,17 @@ struct rk_iommu_domain {
struct iommu_domain domain;
 };
 
+/* list of clocks required by IOMMU */
+static const char * const rk_iommu_clocks[] = {
+   "aclk", "iface",
+};
+
 struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
+   struct clk_bulk_data *clocks;
+   int num_clocks;
bool reset_disabled;
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
@@ -506,6 +514,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
int i;
 
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+
for (i = 0; i < iommu->num_mmu; i++) {
int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS);
if (int_status == 0)
@@ -552,6 +562,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
rk_iommu_write(iommu->bases[i], RK_MMU_INT_CLEAR, int_status);
}
 
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
return ret;
 }
 
@@ -594,7 +606,9 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain 
*rk_domain,
list_for_each(pos, _domain->iommus) {
struct rk_iommu *iommu;
iommu = list_entry(pos, struct rk_iommu, node);
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
rk_iommu_zap_lines(iommu, iova, size);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
}
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 }
@@ -823,10 +837,14 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (!iommu)
return 0;
 
-   ret = rk_iommu_enable_stall(iommu);
+   ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
if (ret)
return ret;
 
+   ret = rk_iommu_enable_stall(iommu);
+   if (ret)
+   goto out_disable_clocks;
+
ret = rk_iommu_force_reset(iommu);
if (ret)
goto out_disable_stall;
@@ -852,6 +870,8 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
 out_disable_stall:
rk_iommu_disable_stall(iommu);
+out_disable_clocks:
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
return ret;
 }
 
@@ -873,6 +893,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 
/* Ignore error while disabling, just keep going */
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
rk_iommu_enable_stall(iommu);
rk_iommu_disable_paging(iommu);
for (i = 0; i < iommu->num_mmu; i++) {
@@ -880,6 +901,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
}
rk_iommu_disable_stall(iommu);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
 
iommu->domain = NULL;
 
@@ -1172,15 +1194,37 @@ static int rk_iommu_probe(struct platform_device *pdev)
iommu->reset_disabled = device_property_read_bool(dev,
"rockchip,disable-mmu-reset");
 
-   err = iommu_device_sysfs_add(>iommu, dev, NULL, dev_name(dev));
+   iommu->num_clocks = ARRAY_SIZE(rk_iommu_clocks);
+   iommu->clocks

[PATCH v8 05/14] iommu/rockchip: Use iopoll helpers to wait for hardware

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

This patch converts the rockchip-iommu driver to use the in-kernel
iopoll helpers to wait for certain status bits to change in registers
instead of an open-coded custom macro.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5:
Use RK_MMU_POLL_PERIOD_US instead of 100.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 75 ++
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5cbd5ceeb039..7130d92ff79c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +36,10 @@
 #define RK_MMU_AUTO_GATING 0x24
 
 #define DTE_ADDR_DUMMY 0xCAFEBABE
-#define FORCE_RESET_TIMEOUT100 /* ms */
+
+#define RK_MMU_POLL_PERIOD_US  100
+#define RK_MMU_FORCE_RESET_TIMEOUT_US  10
+#define RK_MMU_POLL_TIMEOUT_US 1000
 
 /* RK_MMU_STATUS fields */
 #define RK_MMU_STATUS_PAGING_ENABLED   BIT(0)
@@ -73,8 +76,6 @@
   */
 #define RK_IOMMU_PGSIZE_BITMAP 0x007ff000
 
-#define IOMMU_REG_POLL_COUNT_FAST 1000
-
 struct rk_iommu_domain {
struct list_head iommus;
struct platform_device *pdev;
@@ -109,27 +110,6 @@ static struct rk_iommu_domain *to_rk_domain(struct 
iommu_domain *dom)
return container_of(dom, struct rk_iommu_domain, domain);
 }
 
-/**
- * Inspired by _wait_for in intel_drv.h
- * This is NOT safe for use in interrupt context.
- *
- * Note that it's important that we check the condition again after having
- * timed out, since the timeout could be due to preemption or similar and
- * we've never had a chance to check the condition before the timeout.
- */
-#define rk_wait_for(COND, MS) ({ \
-   unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;   \
-   int ret__ = 0;  \
-   while (!(COND)) {   \
-   if (time_after(jiffies, timeout__)) {   \
-   ret__ = (COND) ? 0 : -ETIMEDOUT;\
-   break;  \
-   }   \
-   usleep_range(50, 100);  \
-   }   \
-   ret__;  \
-})
-
 /*
  * The Rockchip rk3288 iommu uses a 2-level page table.
  * The first level is the "Directory Table" (DT).
@@ -333,9 +313,21 @@ static bool rk_iommu_is_paging_enabled(struct rk_iommu 
*iommu)
return enable;
 }
 
+static bool rk_iommu_is_reset_done(struct rk_iommu *iommu)
+{
+   bool done = true;
+   int i;
+
+   for (i = 0; i < iommu->num_mmu; i++)
+   done &= rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0;
+
+   return done;
+}
+
 static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (rk_iommu_is_stall_active(iommu))
return 0;
@@ -346,7 +338,9 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
 
-   ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+val, RK_MMU_POLL_PERIOD_US,
+RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
@@ -358,13 +352,16 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (!rk_iommu_is_stall_active(iommu))
return 0;
 
rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_STALL);
 
-   ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+!val, RK_MMU_POLL_PERIOD_US,
+RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Disable stall request timed out, 
status: %#08x\n",
@@ -376,13 +373,16 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 static int r

[PATCH v8 08/14] iommu/rockchip: Control clocks needed to access the IOMMU

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa 

Current code relies on master driver enabling necessary clocks before
IOMMU is accessed, however there are cases when the IOMMU should be
accessed while the master is not running yet, for example allocating
V4L2 videobuf2 buffers, which is done by the VB2 framework using DMA
mapping API and doesn't engage the master driver at all.

This patch fixes the problem by letting clocks needed for IOMMU
operation to be listed in Device Tree and making the driver enable them
for the time of accessing the hardware.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
Acked-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6:
Fix dt-binding as Robin suggested.
Use aclk and iface clk as Rob and Robin suggested, and split binding
patch.

Changes in v5:
Use clk_bulk APIs.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 50 +++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index c3df53e480ea..50ab9fd4eeb0 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,6 +4,7 @@
  * published by the Free Software Foundation.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -87,10 +88,17 @@ struct rk_iommu_domain {
struct iommu_domain domain;
 };
 
+/* list of clocks required by IOMMU */
+static const char * const rk_iommu_clocks[] = {
+   "aclk", "iface",
+};
+
 struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
+   struct clk_bulk_data *clocks;
+   int num_clocks;
bool reset_disabled;
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
@@ -506,6 +514,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
int i;
 
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+
for (i = 0; i < iommu->num_mmu; i++) {
int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS);
if (int_status == 0)
@@ -552,6 +562,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
rk_iommu_write(iommu->bases[i], RK_MMU_INT_CLEAR, int_status);
}
 
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
return ret;
 }
 
@@ -594,7 +606,9 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain 
*rk_domain,
list_for_each(pos, _domain->iommus) {
struct rk_iommu *iommu;
iommu = list_entry(pos, struct rk_iommu, node);
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
rk_iommu_zap_lines(iommu, iova, size);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
}
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 }
@@ -823,10 +837,14 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (!iommu)
return 0;
 
-   ret = rk_iommu_enable_stall(iommu);
+   ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
if (ret)
return ret;
 
+   ret = rk_iommu_enable_stall(iommu);
+   if (ret)
+   goto out_disable_clocks;
+
ret = rk_iommu_force_reset(iommu);
if (ret)
goto out_disable_stall;
@@ -852,6 +870,8 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
 out_disable_stall:
rk_iommu_disable_stall(iommu);
+out_disable_clocks:
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
return ret;
 }
 
@@ -873,6 +893,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
spin_unlock_irqrestore(_domain->iommus_lock, flags);
 
/* Ignore error while disabling, just keep going */
+   WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
rk_iommu_enable_stall(iommu);
rk_iommu_disable_paging(iommu);
for (i = 0; i < iommu->num_mmu; i++) {
@@ -880,6 +901,7 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
}
rk_iommu_disable_stall(iommu);
+   clk_bulk_disable(iommu->num_clocks, iommu->clocks);
 
iommu->domain = NULL;
 
@@ -1172,15 +1194,37 @@ static int rk_iommu_probe(struct platform_device *pdev)
iommu->reset_disabled = device_property_read_bool(dev,
"rockchip,disable-mmu-reset");
 
-   err = iommu_device_sysfs_add(>iommu, dev, NULL, dev_name(dev));
+   iommu->num_clocks = ARRAY_SIZE(rk_iommu_clocks);
+   iommu->clocks = devm_kcalloc(iommu->dev, iommu->num_clocks,
+sizeof(*iommu-&g

[PATCH v8 05/14] iommu/rockchip: Use iopoll helpers to wait for hardware

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa 

This patch converts the rockchip-iommu driver to use the in-kernel
iopoll helpers to wait for certain status bits to change in registers
instead of an open-coded custom macro.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5:
Use RK_MMU_POLL_PERIOD_US instead of 100.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 75 ++
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5cbd5ceeb039..7130d92ff79c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +36,10 @@
 #define RK_MMU_AUTO_GATING 0x24
 
 #define DTE_ADDR_DUMMY 0xCAFEBABE
-#define FORCE_RESET_TIMEOUT100 /* ms */
+
+#define RK_MMU_POLL_PERIOD_US  100
+#define RK_MMU_FORCE_RESET_TIMEOUT_US  10
+#define RK_MMU_POLL_TIMEOUT_US 1000
 
 /* RK_MMU_STATUS fields */
 #define RK_MMU_STATUS_PAGING_ENABLED   BIT(0)
@@ -73,8 +76,6 @@
   */
 #define RK_IOMMU_PGSIZE_BITMAP 0x007ff000
 
-#define IOMMU_REG_POLL_COUNT_FAST 1000
-
 struct rk_iommu_domain {
struct list_head iommus;
struct platform_device *pdev;
@@ -109,27 +110,6 @@ static struct rk_iommu_domain *to_rk_domain(struct 
iommu_domain *dom)
return container_of(dom, struct rk_iommu_domain, domain);
 }
 
-/**
- * Inspired by _wait_for in intel_drv.h
- * This is NOT safe for use in interrupt context.
- *
- * Note that it's important that we check the condition again after having
- * timed out, since the timeout could be due to preemption or similar and
- * we've never had a chance to check the condition before the timeout.
- */
-#define rk_wait_for(COND, MS) ({ \
-   unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;   \
-   int ret__ = 0;  \
-   while (!(COND)) {   \
-   if (time_after(jiffies, timeout__)) {   \
-   ret__ = (COND) ? 0 : -ETIMEDOUT;\
-   break;  \
-   }   \
-   usleep_range(50, 100);  \
-   }   \
-   ret__;  \
-})
-
 /*
  * The Rockchip rk3288 iommu uses a 2-level page table.
  * The first level is the "Directory Table" (DT).
@@ -333,9 +313,21 @@ static bool rk_iommu_is_paging_enabled(struct rk_iommu 
*iommu)
return enable;
 }
 
+static bool rk_iommu_is_reset_done(struct rk_iommu *iommu)
+{
+   bool done = true;
+   int i;
+
+   for (i = 0; i < iommu->num_mmu; i++)
+   done &= rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0;
+
+   return done;
+}
+
 static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (rk_iommu_is_stall_active(iommu))
return 0;
@@ -346,7 +338,9 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
 
-   ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+val, RK_MMU_POLL_PERIOD_US,
+RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
@@ -358,13 +352,16 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (!rk_iommu_is_stall_active(iommu))
return 0;
 
rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_STALL);
 
-   ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+!val, RK_MMU_POLL_PERIOD_US,
+RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Disable stall request timed out, 
status: %#08x\n",
@@ -376,13 +373,16 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 static int rk_iommu_enable_paging(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (rk_iommu_is_paging_enabled(iommu

[PATCH v8 02/14] iommu/rockchip: Fix error handling in probe

2018-03-23 Thread Jeffy Chen
Add missing iommu_device_sysfs_remove in error path.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Acked-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8:
Don't introduce the additional return.

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index e7fb824d123e..73117dbe839e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1193,6 +1193,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
iommu_device_set_ops(>iommu, _iommu_ops);
err = iommu_device_register(>iommu);
+   if (err)
+   iommu_device_sysfs_remove(>iommu);
 
return err;
 }
-- 
2.11.0




[PATCH v8 01/14] iommu/rockchip: Prohibit unbind and remove

2018-03-23 Thread Jeffy Chen
Removal of IOMMUs cannot be done reliably.

This is similar to exynos iommu driver.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Acked-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8:
Rebase on newest for-next.

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
Rewrite commit message.

Changes in v3:
Also remove remove() and module_exit() as Tomasz suggested.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 21 +
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 6a3719e118da..e7fb824d123e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1197,18 +1197,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
return err;
 }
 
-static int rk_iommu_remove(struct platform_device *pdev)
-{
-   struct rk_iommu *iommu = platform_get_drvdata(pdev);
-
-   if (iommu) {
-   iommu_device_sysfs_remove(>iommu);
-   iommu_device_unregister(>iommu);
-   }
-
-   return 0;
-}
-
 static void rk_iommu_shutdown(struct platform_device *pdev)
 {
struct rk_iommu *iommu = platform_get_drvdata(pdev);
@@ -1234,11 +1222,11 @@ MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids);
 
 static struct platform_driver rk_iommu_driver = {
.probe = rk_iommu_probe,
-   .remove = rk_iommu_remove,
.shutdown = rk_iommu_shutdown,
.driver = {
   .name = "rk_iommu",
   .of_match_table = rk_iommu_dt_ids,
+  .suppress_bind_attrs = true,
},
 };
 
@@ -1266,14 +1254,7 @@ static int __init rk_iommu_init(void)
platform_driver_unregister(_iommu_domain_driver);
return ret;
 }
-static void __exit rk_iommu_exit(void)
-{
-   platform_driver_unregister(_iommu_driver);
-   platform_driver_unregister(_iommu_domain_driver);
-}
-
 subsys_initcall(rk_iommu_init);
-module_exit(rk_iommu_exit);
 
 MODULE_DESCRIPTION("IOMMU API for Rockchip");
 MODULE_AUTHOR("Simon Xue <x...@rock-chips.com> and Daniel Kurtz 
<djku...@chromium.org>");
-- 
2.11.0




[PATCH v8 02/14] iommu/rockchip: Fix error handling in probe

2018-03-23 Thread Jeffy Chen
Add missing iommu_device_sysfs_remove in error path.

Signed-off-by: Jeffy Chen 
Reviewed-by: Tomasz Figa 
Acked-by: Robin Murphy 
---

Changes in v8:
Don't introduce the additional return.

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index e7fb824d123e..73117dbe839e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1193,6 +1193,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
iommu_device_set_ops(>iommu, _iommu_ops);
err = iommu_device_register(>iommu);
+   if (err)
+   iommu_device_sysfs_remove(>iommu);
 
return err;
 }
-- 
2.11.0




[PATCH v8 01/14] iommu/rockchip: Prohibit unbind and remove

2018-03-23 Thread Jeffy Chen
Removal of IOMMUs cannot be done reliably.

This is similar to exynos iommu driver.

Signed-off-by: Jeffy Chen 
Reviewed-by: Tomasz Figa 
Acked-by: Robin Murphy 
---

Changes in v8:
Rebase on newest for-next.

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
Rewrite commit message.

Changes in v3:
Also remove remove() and module_exit() as Tomasz suggested.

Changes in v2: None

 drivers/iommu/rockchip-iommu.c | 21 +
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 6a3719e118da..e7fb824d123e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1197,18 +1197,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
return err;
 }
 
-static int rk_iommu_remove(struct platform_device *pdev)
-{
-   struct rk_iommu *iommu = platform_get_drvdata(pdev);
-
-   if (iommu) {
-   iommu_device_sysfs_remove(>iommu);
-   iommu_device_unregister(>iommu);
-   }
-
-   return 0;
-}
-
 static void rk_iommu_shutdown(struct platform_device *pdev)
 {
struct rk_iommu *iommu = platform_get_drvdata(pdev);
@@ -1234,11 +1222,11 @@ MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids);
 
 static struct platform_driver rk_iommu_driver = {
.probe = rk_iommu_probe,
-   .remove = rk_iommu_remove,
.shutdown = rk_iommu_shutdown,
.driver = {
   .name = "rk_iommu",
   .of_match_table = rk_iommu_dt_ids,
+  .suppress_bind_attrs = true,
},
 };
 
@@ -1266,14 +1254,7 @@ static int __init rk_iommu_init(void)
platform_driver_unregister(_iommu_domain_driver);
return ret;
 }
-static void __exit rk_iommu_exit(void)
-{
-   platform_driver_unregister(_iommu_driver);
-   platform_driver_unregister(_iommu_domain_driver);
-}
-
 subsys_initcall(rk_iommu_init);
-module_exit(rk_iommu_exit);
 
 MODULE_DESCRIPTION("IOMMU API for Rockchip");
 MODULE_AUTHOR("Simon Xue  and Daniel Kurtz 
");
-- 
2.11.0




[PATCH v8 04/14] iommu/rockchip: Fix error handling in attach

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa <tf...@chromium.org>

Currently if the driver encounters an error while attaching device, it
will leave the IOMMU in an inconsistent state. Even though it shouldn't
really happen in reality, let's just add proper error path to keep
things consistent.

Signed-off-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Reviewed-by: Robin Murphy <robin.mur...@arm.com>
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5:
Use out labels to save the duplication between the error and success paths.

Changes in v4: None
Changes in v3: None
Changes in v2:
Move irq request to probe(in patch[0])

 drivers/iommu/rockchip-iommu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec3ff936aa60..5cbd5ceeb039 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -824,7 +824,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
ret = rk_iommu_force_reset(iommu);
if (ret)
-   return ret;
+   goto out_disable_stall;
 
iommu->domain = domain;
 
@@ -837,7 +837,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
ret = rk_iommu_enable_paging(iommu);
if (ret)
-   return ret;
+   goto out_disable_stall;
 
spin_lock_irqsave(_domain->iommus_lock, flags);
list_add_tail(>node, _domain->iommus);
@@ -845,9 +845,9 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
dev_dbg(dev, "Attached to iommu domain\n");
 
+out_disable_stall:
rk_iommu_disable_stall(iommu);
-
-   return 0;
+   return ret;
 }
 
 static void rk_iommu_detach_device(struct iommu_domain *domain,
-- 
2.11.0




[PATCH v8 04/14] iommu/rockchip: Fix error handling in attach

2018-03-23 Thread Jeffy Chen
From: Tomasz Figa 

Currently if the driver encounters an error while attaching device, it
will leave the IOMMU in an inconsistent state. Even though it shouldn't
really happen in reality, let's just add proper error path to keep
things consistent.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
Reviewed-by: Robin Murphy 
---

Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5:
Use out labels to save the duplication between the error and success paths.

Changes in v4: None
Changes in v3: None
Changes in v2:
Move irq request to probe(in patch[0])

 drivers/iommu/rockchip-iommu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec3ff936aa60..5cbd5ceeb039 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -824,7 +824,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
ret = rk_iommu_force_reset(iommu);
if (ret)
-   return ret;
+   goto out_disable_stall;
 
iommu->domain = domain;
 
@@ -837,7 +837,7 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
ret = rk_iommu_enable_paging(iommu);
if (ret)
-   return ret;
+   goto out_disable_stall;
 
spin_lock_irqsave(_domain->iommus_lock, flags);
list_add_tail(>node, _domain->iommus);
@@ -845,9 +845,9 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
dev_dbg(dev, "Attached to iommu domain\n");
 
+out_disable_stall:
rk_iommu_disable_stall(iommu);
-
-   return 0;
+   return ret;
 }
 
 static void rk_iommu_detach_device(struct iommu_domain *domain,
-- 
2.11.0




[PATCH v6] clk: lpc32xx: Set name of regmap_config

2018-03-18 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Acked-by: Vladimir Zapolskiy <v...@mleia.com>
---

Changes in v6:
Modify name as Vladimir suggested.

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..5eeecee17b69 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v6] clk: lpc32xx: Set name of regmap_config

2018-03-18 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
Acked-by: Vladimir Zapolskiy 
---

Changes in v6:
Modify name as Vladimir suggested.

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..5eeecee17b69 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 4/4] ARM: rockchip: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 4/4] ARM: rockchip: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 1/4] mfd: syscon: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5:
CC lee.jo...@linaro.org

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v5 0/4] Set name of regmap_config

2018-03-12 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v5:
CC lee.jo...@linaro.org

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[PATCH v5 1/4] mfd: syscon: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v5:
CC lee.jo...@linaro.org

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v5 0/4] Set name of regmap_config

2018-03-12 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v5:
CC lee.jo...@linaro.org

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[PATCH v5 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-12 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v5: None
Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 1/4] mfd: syscon: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[RESEND PATCH v4 4/4] ARM: rockchip: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 4/4] ARM: rockchip: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[RESEND PATCH v4 1/4] mfd: syscon: Set name of regmap_config

2018-03-09 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[RESEND PATCH v4 0/4] Set name of regmap_config

2018-03-09 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[RESEND PATCH v4 0/4] Set name of regmap_config

2018-03-09 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[PATCH v4 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 4/4] ARM: rockchip: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 0/4] Set name of regmap_config

2018-03-08 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[PATCH v4 4/4] ARM: rockchip: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 2/4] rtc: at91sam9: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
 };
 
 static const struct regmap_config gpbr_regmap_config = {
+   .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v4 0/4] Set name of regmap_config

2018-03-08 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v4:
Not to use rtc dev to init regmap, the gpbr is not directly related to
the rtc.

Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Set name of regmap_config
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 1 +
 4 files changed, 4 insertions(+)

-- 
2.11.0




[PATCH v4 1/4] mfd: syscon: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v4 1/4] mfd: syscon: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v3 1/4] mfd: syscon: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v3 4/4] ARM: rockchip: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v3 1/4] mfd: syscon: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v3:
Modify commit message.

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index fc9ba0ea4e44..b6d05cd934e6 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -110,6 +110,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v3 4/4] ARM: rockchip: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v3: None

 arch/arm/mach-rockchip/platsmp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index ecec340ca345..51984a40b097 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -208,6 +208,7 @@ static int __init rockchip_smp_prepare_sram(struct 
device_node *node)
 }
 
 static const struct regmap_config rockchip_pmu_regmap_config = {
+   .name = "rockchip-pmu",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v3 2/4] rtc: at91sam9: Pass pdev->dev to regmap_init_mmio()

2018-03-08 Thread Jeffy Chen
Otherwise it would use "dummy*" to create regmap debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..0d6a17a77841 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -402,7 +402,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (IS_ERR(gpbr))
return PTR_ERR(gpbr);
 
-   rtc->gpbr = regmap_init_mmio(NULL, gpbr,
+   rtc->gpbr = regmap_init_mmio(>dev, gpbr,
 _regmap_config);
} else {
struct of_phandle_args args;
-- 
2.11.0




[PATCH v3 2/4] rtc: at91sam9: Pass pdev->dev to regmap_init_mmio()

2018-03-08 Thread Jeffy Chen
Otherwise it would use "dummy*" to create regmap debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v3: None

 drivers/rtc/rtc-at91sam9.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..0d6a17a77841 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -402,7 +402,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (IS_ERR(gpbr))
return PTR_ERR(gpbr);
 
-   rtc->gpbr = regmap_init_mmio(NULL, gpbr,
+   rtc->gpbr = regmap_init_mmio(>dev, gpbr,
 _regmap_config);
} else {
struct of_phandle_args args;
-- 
2.11.0




[PATCH v3 0/4] Set name of regmap_config

2018-03-08 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Pass pdev->dev to regmap_init_mmio()
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 2 +-
 4 files changed, 4 insertions(+), 1 deletion(-)

-- 
2.11.0




[PATCH v3 0/4] Set name of regmap_config

2018-03-08 Thread Jeffy Chen

After 9b947a13e7f6 ("regmap: use debugfs even when no device"), we are
allowing regmap to create debugfs without a valid device. Some of them
would end up using "dummy*" as debugfs name.

This series try to set names in some regmap_config to avoid that.


Changes in v3:
Modify commit message.

Jeffy Chen (4):
  mfd: syscon: Set name of regmap_config
  rtc: at91sam9: Pass pdev->dev to regmap_init_mmio()
  clk: lpc32xx: Set name of regmap_config
  ARM: rockchip: Set name of regmap_config

 arch/arm/mach-rockchip/platsmp.c | 1 +
 drivers/clk/nxp/clk-lpc32xx.c| 1 +
 drivers/mfd/syscon.c | 1 +
 drivers/rtc/rtc-at91sam9.c   | 2 +-
 4 files changed, 4 insertions(+), 1 deletion(-)

-- 
2.11.0




[PATCH v3 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v3 3/4] clk: lpc32xx: Set name of regmap_config

2018-03-08 Thread Jeffy Chen
We are now allowing to register debugfs without a valid device, and not
having a valid name will end up using "dummy*" to create debugfs dir.

Signed-off-by: Jeffy Chen 
---

Changes in v3: None

 drivers/clk/nxp/clk-lpc32xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
index f5d815f577e0..a2a0a7f3bc57 100644
--- a/drivers/clk/nxp/clk-lpc32xx.c
+++ b/drivers/clk/nxp/clk-lpc32xx.c
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+   .name = "lpc32xx-scb",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
-- 
2.11.0




[PATCH v5 3/3] arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

2018-03-07 Thread Jeffy Chen
Add wakeup event action for Pen Insert gpio key, to avoid wakeup when
inserting the pen.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Tested-by: Enric Balletbo i Serra <enric.balle...@collabora.com>
---

Changes in v5: None
Changes in v4:
Include dt-binding gpio-keys.h

Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts 
b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 191a6bcb1704..89126dbe5d91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -44,6 +44,7 @@
 
 /dts-v1/;
 #include "rk3399-gru.dtsi"
+#include 
 #include 
 
 /*
@@ -134,6 +135,8 @@
gpios = < 13 GPIO_ACTIVE_LOW>;
linux,code = ;
linux,input-type = ;
+   /* Wakeup only when ejecting */
+   wakeup-event-action = ;
wakeup-source;
};
 };
-- 
2.11.0




[PATCH v5 3/3] arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

2018-03-07 Thread Jeffy Chen
Add wakeup event action for Pen Insert gpio key, to avoid wakeup when
inserting the pen.

Signed-off-by: Jeffy Chen 
Tested-by: Enric Balletbo i Serra 
---

Changes in v5: None
Changes in v4:
Include dt-binding gpio-keys.h

Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts 
b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 191a6bcb1704..89126dbe5d91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -44,6 +44,7 @@
 
 /dts-v1/;
 #include "rk3399-gru.dtsi"
+#include 
 #include 
 
 /*
@@ -134,6 +135,8 @@
gpios = < 13 GPIO_ACTIVE_LOW>;
linux,code = ;
linux,input-type = ;
+   /* Wakeup only when ejecting */
+   wakeup-event-action = ;
wakeup-source;
};
 };
-- 
2.11.0




[PATCH v5 1/3] Input: gpio-keys - add support for wakeup event action

2018-03-07 Thread Jeffy Chen
Add support for specifying event actions to trigger wakeup when using
the gpio-keys input device as a wakeup source.

This would allow the device to configure when to wakeup the system. For
example a gpio-keys input device for pen insert, may only want to wakeup
the system when ejecting the pen.

Suggested-by: Brian Norris <briannor...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5:
Remove unneeded irq_wake flag as Andy suggested.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 drivers/input/keyboard/gpio_keys.c| 63 +--
 include/dt-bindings/input/gpio-keys.h | 13 
 include/linux/gpio_keys.h |  2 ++
 3 files changed, 75 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 87e613dc33b8..f6d5cfd44833 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -45,6 +46,7 @@ struct gpio_button_data {
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
+   unsigned int wakeup_trigger_type;
spinlock_t lock;
bool disabled;
bool key_pressed;
@@ -540,6 +542,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
if (bdata->gpiod) {
+   int active_low = gpiod_is_active_low(bdata->gpiod);
+
if (button->debounce_interval) {
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
@@ -568,6 +572,24 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
 
+   switch (button->wakeup_event_action) {
+   case EV_ACT_ASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+   break;
+   case EV_ACT_DEASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
+   break;
+   case EV_ACT_ANY:
+   /* fall through */
+   default:
+   /*
+* For other cases, we are OK letting suspend/resume
+* not reconfigure the trigger type.
+*/
+   break;
+   }
} else {
if (!button->irq) {
dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +608,11 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
 
isr = gpio_keys_irq_isr;
irqflags = 0;
+
+   /*
+* For IRQ buttons, there is no interrupt for release.
+* So we don't need to reconfigure the trigger type for wakeup.
+*/
}
 
bdata->code = >keymap[idx];
@@ -718,6 +745,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
 
+   fwnode_property_read_u32(child, "wakeup-event-action",
+>wakeup_event_action);
+
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
 
@@ -845,6 +875,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
return 0;
 }
 
+static int gpio_keys_enable_wakeup(struct gpio_button_data *bdata)
+{
+   int ret;
+
+   ret = enable_irq_wake(bdata->irq);
+   if (ret)
+   return ret;
+
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, bdata->wakeup_trigger_type);
+
+   return 0;
+}
+
+static void gpio_keys_disable_wakeup(struct gpio_button_data *bdata)
+{
+   /**
+* The trigger type is always both edges for gpio-based keys and we do
+* not support changing wakeup trigger for interrupt-based keys.
+*/
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
+   disable_irq_wake(bdata->irq);
+}
+
 static int __maybe_unused gp

[PATCH v5 1/3] Input: gpio-keys - add support for wakeup event action

2018-03-07 Thread Jeffy Chen
Add support for specifying event actions to trigger wakeup when using
the gpio-keys input device as a wakeup source.

This would allow the device to configure when to wakeup the system. For
example a gpio-keys input device for pen insert, may only want to wakeup
the system when ejecting the pen.

Suggested-by: Brian Norris 
Signed-off-by: Jeffy Chen 
---

Changes in v5:
Remove unneeded irq_wake flag as Andy suggested.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 drivers/input/keyboard/gpio_keys.c| 63 +--
 include/dt-bindings/input/gpio-keys.h | 13 
 include/linux/gpio_keys.h |  2 ++
 3 files changed, 75 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 87e613dc33b8..f6d5cfd44833 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -45,6 +46,7 @@ struct gpio_button_data {
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
+   unsigned int wakeup_trigger_type;
spinlock_t lock;
bool disabled;
bool key_pressed;
@@ -540,6 +542,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
if (bdata->gpiod) {
+   int active_low = gpiod_is_active_low(bdata->gpiod);
+
if (button->debounce_interval) {
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
@@ -568,6 +572,24 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
 
+   switch (button->wakeup_event_action) {
+   case EV_ACT_ASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+   break;
+   case EV_ACT_DEASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
+   break;
+   case EV_ACT_ANY:
+   /* fall through */
+   default:
+   /*
+* For other cases, we are OK letting suspend/resume
+* not reconfigure the trigger type.
+*/
+   break;
+   }
} else {
if (!button->irq) {
dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +608,11 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
 
isr = gpio_keys_irq_isr;
irqflags = 0;
+
+   /*
+* For IRQ buttons, there is no interrupt for release.
+* So we don't need to reconfigure the trigger type for wakeup.
+*/
}
 
bdata->code = >keymap[idx];
@@ -718,6 +745,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
 
+   fwnode_property_read_u32(child, "wakeup-event-action",
+>wakeup_event_action);
+
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
 
@@ -845,6 +875,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
return 0;
 }
 
+static int gpio_keys_enable_wakeup(struct gpio_button_data *bdata)
+{
+   int ret;
+
+   ret = enable_irq_wake(bdata->irq);
+   if (ret)
+   return ret;
+
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, bdata->wakeup_trigger_type);
+
+   return 0;
+}
+
+static void gpio_keys_disable_wakeup(struct gpio_button_data *bdata)
+{
+   /**
+* The trigger type is always both edges for gpio-based keys and we do
+* not support changing wakeup trigger for interrupt-based keys.
+*/
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
+   disable_irq_wake(bdata->irq);
+}
+
 static int __maybe_unused gpio_keys_suspend(struct device *dev)
 {
struct gpio_keys_dr

[PATCH v5 0/3] gpio-keys: Add support for specifying wakeup event action

2018-03-07 Thread Jeffy Chen

On chromebook kevin, we are using gpio-keys for pen insert event. But
we only want it to wakeup the system when ejecting the pen.

So we may need to change the interrupt trigger type during suspending.

Changes in v5:
Remove unneeded irq_wake flag as Andy suggested.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.
Include dt-binding gpio-keys.h

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.

Jeffy Chen (3):
  Input: gpio-keys - add support for wakeup event action
  Input: gpio-keys - allow setting wakeup event action in DT
  arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

 .../devicetree/bindings/input/gpio-keys.txt|  8 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  |  3 ++
 drivers/input/keyboard/gpio_keys.c | 63 --
 include/dt-bindings/input/gpio-keys.h  | 13 +
 include/linux/gpio_keys.h  |  2 +
 5 files changed, 86 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

-- 
2.11.0




[PATCH v5 2/3] Input: gpio-keys - allow setting wakeup event action in DT

2018-03-07 Thread Jeffy Chen
Allow specifying event actions to trigger wakeup when using the
gpio-keys input device as a wakeup source.

Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 Documentation/devicetree/bindings/input/gpio-keys.txt | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt 
b/Documentation/devicetree/bindings/input/gpio-keys.txt
index a94940481e55..996ce84352cb 100644
--- a/Documentation/devicetree/bindings/input/gpio-keys.txt
+++ b/Documentation/devicetree/bindings/input/gpio-keys.txt
@@ -26,6 +26,14 @@ Optional subnode-properties:
  If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
 (Legacy property supported: "gpio-key,wakeup")
+   - wakeup-event-action: Specifies whether the key should wake the
+ system when asserted, when deasserted, or both. This property is
+ only valid for keys that wake up the system (e.g., when the
+ "wakeup-source" property is also provided).
+ Supported values are defined in linux-event-codes.h:
+   EV_ACT_ASSERTED - asserted
+   EV_ACT_DEASSERTED   - deasserted
+   EV_ACT_ANY  - both asserted and deasserted
- linux,can-disable: Boolean, indicates that button is connected
  to dedicated (not shared) interrupt which can be disabled to
  suppress events from the button.
-- 
2.11.0




[PATCH v5 0/3] gpio-keys: Add support for specifying wakeup event action

2018-03-07 Thread Jeffy Chen

On chromebook kevin, we are using gpio-keys for pen insert event. But
we only want it to wakeup the system when ejecting the pen.

So we may need to change the interrupt trigger type during suspending.

Changes in v5:
Remove unneeded irq_wake flag as Andy suggested.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.
Include dt-binding gpio-keys.h

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.

Jeffy Chen (3):
  Input: gpio-keys - add support for wakeup event action
  Input: gpio-keys - allow setting wakeup event action in DT
  arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

 .../devicetree/bindings/input/gpio-keys.txt|  8 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  |  3 ++
 drivers/input/keyboard/gpio_keys.c | 63 --
 include/dt-bindings/input/gpio-keys.h  | 13 +
 include/linux/gpio_keys.h  |  2 +
 5 files changed, 86 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

-- 
2.11.0




[PATCH v5 2/3] Input: gpio-keys - allow setting wakeup event action in DT

2018-03-07 Thread Jeffy Chen
Allow specifying event actions to trigger wakeup when using the
gpio-keys input device as a wakeup source.

Reviewed-by: Rob Herring 
Signed-off-by: Jeffy Chen 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 Documentation/devicetree/bindings/input/gpio-keys.txt | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt 
b/Documentation/devicetree/bindings/input/gpio-keys.txt
index a94940481e55..996ce84352cb 100644
--- a/Documentation/devicetree/bindings/input/gpio-keys.txt
+++ b/Documentation/devicetree/bindings/input/gpio-keys.txt
@@ -26,6 +26,14 @@ Optional subnode-properties:
  If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
 (Legacy property supported: "gpio-key,wakeup")
+   - wakeup-event-action: Specifies whether the key should wake the
+ system when asserted, when deasserted, or both. This property is
+ only valid for keys that wake up the system (e.g., when the
+ "wakeup-source" property is also provided).
+ Supported values are defined in linux-event-codes.h:
+   EV_ACT_ASSERTED - asserted
+   EV_ACT_DEASSERTED   - deasserted
+   EV_ACT_ANY  - both asserted and deasserted
- linux,can-disable: Boolean, indicates that button is connected
  to dedicated (not shared) interrupt which can be disabled to
  suppress events from the button.
-- 
2.11.0




[PATCH v2 3/3] regmap: debugfs: Free map->debugfs_name when debugfs_create_dir() failed

2018-03-06 Thread Jeffy Chen
Free map->debugfs_name when debugfs_create_dir() failed to avoid memory
leak.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/base/regmap/regmap-debugfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/base/regmap/regmap-debugfs.c 
b/drivers/base/regmap/regmap-debugfs.c
index 5479a183248f..55e862a81e82 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -582,6 +582,9 @@ void regmap_debugfs_init(struct regmap *map, const char 
*name)
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
dev_warn(map->dev, "Failed to create debugfs directory\n");
+
+   kfree(map->debugfs_name);
+   map->debugfs_name = NULL;
return;
}
 
-- 
2.11.0




[PATCH v2 2/3] regmap: debugfs: Fix kmemleak in regmap_debugfs_init

2018-03-06 Thread Jeffy Chen
Use map->debugfs_name to store allocated debugfs name, so it would be
freed in regmap_debugfs_exit().

Kmemleak reported:
unreferenced object 0xffc0cf78cf00 (size 128):
  comm "swapper/0", pid 1, jiffies 4294669168 (age 89.152s)
  hex dump (first 32 bytes):
64 75 6d 6d 79 32 33 00 00 00 00 00 00 00 00 00  dummy23.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
  backtrace:
[<27429160>] kmemleak_alloc+0x58/0x8c
[<81861ddf>] __kmalloc_track_caller+0x1dc/0x2bc
[<258a341f>] kvasprintf+0xd0/0x168
[<f3243f27>] kasprintf+0xac/0xd8
[<5f585642>] regmap_debugfs_init+0x1a0/0x3b0
[<2c08b110>] __regmap_init+0x12b8/0x135c
[<f64bcddb>] __regmap_init_mmio_clk+0x70/0x84
[<9c8f06b5>] of_syscon_register+0x278/0x378
[<87e6c121>] syscon_node_to_regmap+0x80/0xb0

Fixes: a430ab205d29 ("regmap: debugfs: Disambiguate dummy debugfs file name")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/base/regmap/regmap-debugfs.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/base/regmap/regmap-debugfs.c 
b/drivers/base/regmap/regmap-debugfs.c
index e3e7b91cc421..5479a183248f 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -570,15 +570,15 @@ void regmap_debugfs_init(struct regmap *map, const char 
*name)
map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
  devname, name);
name = map->debugfs_name;
+   } else if (!map->dev) {
+   map->debugfs_name = kasprintf(GFP_KERNEL, "%s%d",
+ devname, dummy_index);
+   name = map->debugfs_name;
+   dummy_index++;
} else {
name = devname;
}
 
-   if (!strcmp(name, "dummy")) {
-   name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index);
-   dummy_index++;
-   }
-
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
dev_warn(map->dev, "Failed to create debugfs directory\n");
-- 
2.11.0




[PATCH v2 3/3] regmap: debugfs: Free map->debugfs_name when debugfs_create_dir() failed

2018-03-06 Thread Jeffy Chen
Free map->debugfs_name when debugfs_create_dir() failed to avoid memory
leak.

Signed-off-by: Jeffy Chen 
---

 drivers/base/regmap/regmap-debugfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/base/regmap/regmap-debugfs.c 
b/drivers/base/regmap/regmap-debugfs.c
index 5479a183248f..55e862a81e82 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -582,6 +582,9 @@ void regmap_debugfs_init(struct regmap *map, const char 
*name)
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
dev_warn(map->dev, "Failed to create debugfs directory\n");
+
+   kfree(map->debugfs_name);
+   map->debugfs_name = NULL;
return;
}
 
-- 
2.11.0




[PATCH v2 2/3] regmap: debugfs: Fix kmemleak in regmap_debugfs_init

2018-03-06 Thread Jeffy Chen
Use map->debugfs_name to store allocated debugfs name, so it would be
freed in regmap_debugfs_exit().

Kmemleak reported:
unreferenced object 0xffc0cf78cf00 (size 128):
  comm "swapper/0", pid 1, jiffies 4294669168 (age 89.152s)
  hex dump (first 32 bytes):
64 75 6d 6d 79 32 33 00 00 00 00 00 00 00 00 00  dummy23.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
  backtrace:
[<27429160>] kmemleak_alloc+0x58/0x8c
[<81861ddf>] __kmalloc_track_caller+0x1dc/0x2bc
[<258a341f>] kvasprintf+0xd0/0x168
[<f3243f27>] kasprintf+0xac/0xd8
[<5f585642>] regmap_debugfs_init+0x1a0/0x3b0
[<2c08b110>] __regmap_init+0x12b8/0x135c
[<f64bcddb>] __regmap_init_mmio_clk+0x70/0x84
[<9c8f06b5>] of_syscon_register+0x278/0x378
[<87e6c121>] syscon_node_to_regmap+0x80/0xb0

Fixes: a430ab205d29 ("regmap: debugfs: Disambiguate dummy debugfs file name")
Signed-off-by: Jeffy Chen 
---

 drivers/base/regmap/regmap-debugfs.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/base/regmap/regmap-debugfs.c 
b/drivers/base/regmap/regmap-debugfs.c
index e3e7b91cc421..5479a183248f 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -570,15 +570,15 @@ void regmap_debugfs_init(struct regmap *map, const char 
*name)
map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
  devname, name);
name = map->debugfs_name;
+   } else if (!map->dev) {
+   map->debugfs_name = kasprintf(GFP_KERNEL, "%s%d",
+ devname, dummy_index);
+   name = map->debugfs_name;
+   dummy_index++;
} else {
name = devname;
}
 
-   if (!strcmp(name, "dummy")) {
-   name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index);
-   dummy_index++;
-   }
-
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
dev_warn(map->dev, "Failed to create debugfs directory\n");
-- 
2.11.0




[PATCH v2 1/3] mfd: syscon: Set name of regmap_config

2018-03-06 Thread Jeffy Chen
We are now allowing to register debugfs for syscon regmap, and not
having a valid name will end up using "dummy" to create debugfs dir.

Fixes: 9b947a13e7f6 ("regmap: use debugfs even when no device")
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 7eaa40bc703f..250d22f40c84 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -109,6 +109,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v2 1/3] mfd: syscon: Set name of regmap_config

2018-03-06 Thread Jeffy Chen
We are now allowing to register debugfs for syscon regmap, and not
having a valid name will end up using "dummy" to create debugfs dir.

Fixes: 9b947a13e7f6 ("regmap: use debugfs even when no device")
Signed-off-by: Jeffy Chen 
---

 drivers/mfd/syscon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 7eaa40bc703f..250d22f40c84 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -109,6 +109,7 @@ static struct syscon *of_syscon_register(struct device_node 
*np)
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size() - reg_io_width;
+   syscon_config.name = of_node_full_name(np);
 
regmap = regmap_init_mmio(NULL, base, _config);
if (IS_ERR(regmap)) {
-- 
2.11.0




[PATCH v4 3/3] arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

2018-03-05 Thread Jeffy Chen
Add wakeup event action for Pen Insert gpio key, to avoid wakeup when
inserting the pen.

Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
Tested-by: Enric Balletbo i Serra <enric.balle...@collabora.com>
---

Changes in v4:
Include dt-binding gpio-keys.h

Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts 
b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 191a6bcb1704..89126dbe5d91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -44,6 +44,7 @@
 
 /dts-v1/;
 #include "rk3399-gru.dtsi"
+#include 
 #include 
 
 /*
@@ -134,6 +135,8 @@
gpios = < 13 GPIO_ACTIVE_LOW>;
linux,code = ;
linux,input-type = ;
+   /* Wakeup only when ejecting */
+   wakeup-event-action = ;
wakeup-source;
};
 };
-- 
2.11.0




[PATCH v4 2/3] Input: gpio-keys - allow setting wakeup event action in DT

2018-03-05 Thread Jeffy Chen
Allow specifying event actions to trigger wakeup when using the
gpio-keys input device as a wakeup source.

Reviewed-by: Rob Herring <r...@kernel.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4: None
Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 Documentation/devicetree/bindings/input/gpio-keys.txt | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt 
b/Documentation/devicetree/bindings/input/gpio-keys.txt
index a94940481e55..996ce84352cb 100644
--- a/Documentation/devicetree/bindings/input/gpio-keys.txt
+++ b/Documentation/devicetree/bindings/input/gpio-keys.txt
@@ -26,6 +26,14 @@ Optional subnode-properties:
  If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
 (Legacy property supported: "gpio-key,wakeup")
+   - wakeup-event-action: Specifies whether the key should wake the
+ system when asserted, when deasserted, or both. This property is
+ only valid for keys that wake up the system (e.g., when the
+ "wakeup-source" property is also provided).
+ Supported values are defined in linux-event-codes.h:
+   EV_ACT_ASSERTED - asserted
+   EV_ACT_DEASSERTED   - deasserted
+   EV_ACT_ANY  - both asserted and deasserted
- linux,can-disable: Boolean, indicates that button is connected
  to dedicated (not shared) interrupt which can be disabled to
  suppress events from the button.
-- 
2.11.0




[PATCH v4 2/3] Input: gpio-keys - allow setting wakeup event action in DT

2018-03-05 Thread Jeffy Chen
Allow specifying event actions to trigger wakeup when using the
gpio-keys input device as a wakeup source.

Reviewed-by: Rob Herring 
Signed-off-by: Jeffy Chen 
---

Changes in v4: None
Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 Documentation/devicetree/bindings/input/gpio-keys.txt | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt 
b/Documentation/devicetree/bindings/input/gpio-keys.txt
index a94940481e55..996ce84352cb 100644
--- a/Documentation/devicetree/bindings/input/gpio-keys.txt
+++ b/Documentation/devicetree/bindings/input/gpio-keys.txt
@@ -26,6 +26,14 @@ Optional subnode-properties:
  If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
 (Legacy property supported: "gpio-key,wakeup")
+   - wakeup-event-action: Specifies whether the key should wake the
+ system when asserted, when deasserted, or both. This property is
+ only valid for keys that wake up the system (e.g., when the
+ "wakeup-source" property is also provided).
+ Supported values are defined in linux-event-codes.h:
+   EV_ACT_ASSERTED - asserted
+   EV_ACT_DEASSERTED   - deasserted
+   EV_ACT_ANY  - both asserted and deasserted
- linux,can-disable: Boolean, indicates that button is connected
  to dedicated (not shared) interrupt which can be disabled to
  suppress events from the button.
-- 
2.11.0




[PATCH v4 3/3] arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

2018-03-05 Thread Jeffy Chen
Add wakeup event action for Pen Insert gpio key, to avoid wakeup when
inserting the pen.

Signed-off-by: Jeffy Chen 
Tested-by: Enric Balletbo i Serra 
---

Changes in v4:
Include dt-binding gpio-keys.h

Changes in v3: None
Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts 
b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 191a6bcb1704..89126dbe5d91 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -44,6 +44,7 @@
 
 /dts-v1/;
 #include "rk3399-gru.dtsi"
+#include 
 #include 
 
 /*
@@ -134,6 +135,8 @@
gpios = < 13 GPIO_ACTIVE_LOW>;
linux,code = ;
linux,input-type = ;
+   /* Wakeup only when ejecting */
+   wakeup-event-action = ;
wakeup-source;
};
 };
-- 
2.11.0




[PATCH v4 1/3] Input: gpio-keys - add support for wakeup event action

2018-03-05 Thread Jeffy Chen
Add support for specifying event actions to trigger wakeup when using
the gpio-keys input device as a wakeup source.

This would allow the device to configure when to wakeup the system. For
example a gpio-keys input device for pen insert, may only want to wakeup
the system when ejecting the pen.

Suggested-by: Brian Norris <briannor...@chromium.org>
Signed-off-by: Jeffy Chen <jeffy.c...@rock-chips.com>
---

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 drivers/input/keyboard/gpio_keys.c| 67 +--
 include/dt-bindings/input/gpio-keys.h | 13 +++
 include/linux/gpio_keys.h |  2 ++
 3 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 87e613dc33b8..4bc23648b6a7 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -45,10 +46,12 @@ struct gpio_button_data {
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
+   unsigned int wakeup_trigger_type;
spinlock_t lock;
bool disabled;
bool key_pressed;
bool suspended;
+   bool wakeup_enabled;
 };
 
 struct gpio_keys_drvdata {
@@ -540,6 +543,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
if (bdata->gpiod) {
+   int active_low = gpiod_is_active_low(bdata->gpiod);
+
if (button->debounce_interval) {
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
@@ -568,6 +573,24 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
 
+   switch (button->wakeup_event_action) {
+   case EV_ACT_ASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+   break;
+   case EV_ACT_DEASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
+   break;
+   case EV_ACT_ANY:
+   /* fall through */
+   default:
+   /*
+* For other cases, we are OK letting suspend/resume
+* not reconfigure the trigger type.
+*/
+   break;
+   }
} else {
if (!button->irq) {
dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +609,11 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
 
isr = gpio_keys_irq_isr;
irqflags = 0;
+
+   /*
+* For IRQ buttons, there is no interrupt for release.
+* So we don't need to reconfigure the trigger type for wakeup.
+*/
}
 
bdata->code = >keymap[idx];
@@ -718,6 +746,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
 
+   fwnode_property_read_u32(child, "wakeup-event-action",
+>wakeup_event_action);
+
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
 
@@ -845,6 +876,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
return 0;
 }
 
+static int gpio_keys_enable_wakeup(struct gpio_button_data *bdata)
+{
+   int ret;
+
+   ret = enable_irq_wake(bdata->irq);
+   if (ret)
+   return ret;
+
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, bdata->wakeup_trigger_type);
+
+   return 0;
+}
+
+static void gpio_keys_disable_wakeup(struct gpio_button_data *bdata)
+{
+   /**
+* The trigger type is always both edges for gpio-based keys and we do
+* not support changing wakeup trigger for interrupt-based keys.
+*/
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
+   disable_irq_wake(bdata->irq);

[PATCH v4 1/3] Input: gpio-keys - add support for wakeup event action

2018-03-05 Thread Jeffy Chen
Add support for specifying event actions to trigger wakeup when using
the gpio-keys input device as a wakeup source.

This would allow the device to configure when to wakeup the system. For
example a gpio-keys input device for pen insert, may only want to wakeup
the system when ejecting the pen.

Suggested-by: Brian Norris 
Signed-off-by: Jeffy Chen 
---

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.

 drivers/input/keyboard/gpio_keys.c| 67 +--
 include/dt-bindings/input/gpio-keys.h | 13 +++
 include/linux/gpio_keys.h |  2 ++
 3 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index 87e613dc33b8..4bc23648b6a7 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -45,10 +46,12 @@ struct gpio_button_data {
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
 
unsigned int irq;
+   unsigned int wakeup_trigger_type;
spinlock_t lock;
bool disabled;
bool key_pressed;
bool suspended;
+   bool wakeup_enabled;
 };
 
 struct gpio_keys_drvdata {
@@ -540,6 +543,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
 
if (bdata->gpiod) {
+   int active_low = gpiod_is_active_low(bdata->gpiod);
+
if (button->debounce_interval) {
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
@@ -568,6 +573,24 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
 
+   switch (button->wakeup_event_action) {
+   case EV_ACT_ASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+   break;
+   case EV_ACT_DEASSERTED:
+   bdata->wakeup_trigger_type = active_low ?
+   IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
+   break;
+   case EV_ACT_ANY:
+   /* fall through */
+   default:
+   /*
+* For other cases, we are OK letting suspend/resume
+* not reconfigure the trigger type.
+*/
+   break;
+   }
} else {
if (!button->irq) {
dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +609,11 @@ static int gpio_keys_setup_key(struct platform_device 
*pdev,
 
isr = gpio_keys_irq_isr;
irqflags = 0;
+
+   /*
+* For IRQ buttons, there is no interrupt for release.
+* So we don't need to reconfigure the trigger type for wakeup.
+*/
}
 
bdata->code = >keymap[idx];
@@ -718,6 +746,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
 
+   fwnode_property_read_u32(child, "wakeup-event-action",
+>wakeup_event_action);
+
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
 
@@ -845,6 +876,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
return 0;
 }
 
+static int gpio_keys_enable_wakeup(struct gpio_button_data *bdata)
+{
+   int ret;
+
+   ret = enable_irq_wake(bdata->irq);
+   if (ret)
+   return ret;
+
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, bdata->wakeup_trigger_type);
+
+   return 0;
+}
+
+static void gpio_keys_disable_wakeup(struct gpio_button_data *bdata)
+{
+   /**
+* The trigger type is always both edges for gpio-based keys and we do
+* not support changing wakeup trigger for interrupt-based keys.
+*/
+   if (bdata->wakeup_trigger_type)
+   irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
+   disable_irq_wake(bdata->irq);
+}
+
 static int __maybe_unused gpio_keys_suspend(struct device *dev

[PATCH v4 0/3] gpio-keys: Add support for specifying wakeup event action

2018-03-05 Thread Jeffy Chen

On chromebook kevin, we are using gpio-keys for pen insert event. But
we only want it to wakeup the system when ejecting the pen.

So we may need to change the interrupt trigger type during suspending.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.
Include dt-binding gpio-keys.h

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.

Jeffy Chen (3):
  Input: gpio-keys - add support for wakeup event action
  Input: gpio-keys - allow setting wakeup event action in DT
  arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

 .../devicetree/bindings/input/gpio-keys.txt|  8 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  |  3 +
 drivers/input/keyboard/gpio_keys.c | 67 +-
 include/dt-bindings/input/gpio-keys.h  | 13 +
 include/linux/gpio_keys.h  |  2 +
 5 files changed, 90 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

-- 
2.11.0




[PATCH v4 0/3] gpio-keys: Add support for specifying wakeup event action

2018-03-05 Thread Jeffy Chen

On chromebook kevin, we are using gpio-keys for pen insert event. But
we only want it to wakeup the system when ejecting the pen.

So we may need to change the interrupt trigger type during suspending.

Changes in v4:
Add dt-binding gpio-keys.h, stop saving irq trigger type, add enable/disable 
wakeup helpers as Dmitry suggested.
Include dt-binding gpio-keys.h

Changes in v3:
Adding more comments as Brian suggested.

Changes in v2:
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.
Specify wakeup event action instead of irq trigger type as Brian
suggested.

Jeffy Chen (3):
  Input: gpio-keys - add support for wakeup event action
  Input: gpio-keys - allow setting wakeup event action in DT
  arm64: dts: rockchip: kevin: Avoid wakeup when inserting the pen

 .../devicetree/bindings/input/gpio-keys.txt|  8 +++
 arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts  |  3 +
 drivers/input/keyboard/gpio_keys.c | 67 +-
 include/dt-bindings/input/gpio-keys.h  | 13 +
 include/linux/gpio_keys.h  |  2 +
 5 files changed, 90 insertions(+), 3 deletions(-)
 create mode 100644 include/dt-bindings/input/gpio-keys.h

-- 
2.11.0




  1   2   3   4   5   6   7   8   9   10   >