* [PATCH 02/16] iommu/arm-smmu: Add split pagetable support for arm-smmu-v2
From: Jordan Crouse @ 2018-05-18 21:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518213500.31595-1-jcrouse@codeaurora.org>
Add support for a split pagetable (TTBR0/TTBR1) scheme for
arm-smmu-v2. If split pagetables are enabled, create a
pagetable for TTBR1 and set up the sign extension bit so
that all IOVAs with that bit set are mapped and translated
from the TTBR1 pagetable.
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---
drivers/iommu/arm-smmu-regs.h | 18 ++++
drivers/iommu/arm-smmu.c | 148 +++++++++++++++++++++++++++++----
drivers/iommu/io-pgtable-arm.c | 3 +-
3 files changed, 153 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
index a1226e4ab5f8..56f97093f46a 100644
--- a/drivers/iommu/arm-smmu-regs.h
+++ b/drivers/iommu/arm-smmu-regs.h
@@ -193,7 +193,25 @@ enum arm_smmu_s2cr_privcfg {
#define RESUME_RETRY (0 << 0)
#define RESUME_TERMINATE (1 << 0)
+#define TTBCR_EPD1 (1 << 23)
+#define TTBCR_T1SZ_SHIFT 16
+#define TTBCR_IRGN1_SHIFT 24
+#define TTBCR_ORGN1_SHIFT 26
+#define TTBCR_RGN_WBWA 1
+#define TTBCR_SH1_SHIFT 28
+#define TTBCR_SH_IS 3
+
+#define TTBCR_TG1_16K (1 << 30)
+#define TTBCR_TG1_4K (2 << 30)
+#define TTBCR_TG1_64K (3 << 30)
+
#define TTBCR2_SEP_SHIFT 15
+#define TTBCR2_SEP_31 (0x0 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_SEP_35 (0x1 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_SEP_39 (0x2 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_SEP_41 (0x3 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_SEP_43 (0x4 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_SEP_47 (0x5 << TTBCR2_SEP_SHIFT)
#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
#define TTBCR2_AS (1 << 4)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 69e7c60792a8..3568e8b073ec 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -143,6 +143,7 @@ struct arm_smmu_cb {
u32 tcr[2];
u32 mair[2];
struct arm_smmu_cfg *cfg;
+ u64 split_table_mask;
};
struct arm_smmu_master_cfg {
@@ -200,6 +201,7 @@ struct arm_smmu_device {
unsigned long va_size;
unsigned long ipa_size;
unsigned long pa_size;
+ unsigned long ubs_size;
unsigned long pgsize_bitmap;
u32 num_global_irqs;
@@ -242,12 +244,13 @@ enum arm_smmu_domain_stage {
struct arm_smmu_domain {
struct arm_smmu_device *smmu;
- struct io_pgtable_ops *pgtbl_ops;
+ struct io_pgtable_ops *pgtbl_ops[2];
const struct iommu_gather_ops *tlb_ops;
struct arm_smmu_cfg cfg;
enum arm_smmu_domain_stage stage;
struct mutex init_mutex; /* Protects smmu pointer */
spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */
+ u32 attributes;
struct iommu_domain domain;
};
@@ -582,6 +585,69 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
return IRQ_HANDLED;
}
+static void arm_smmu_init_ttbr1(struct arm_smmu_domain *smmu_domain,
+ struct io_pgtable_cfg *pgtbl_cfg)
+{
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_cb *cb = &smmu_domain->smmu->cbs[cfg->cbndx];
+ int pgsize = 1 << __ffs(pgtbl_cfg->pgsize_bitmap);
+
+ /* Enable speculative walks through the TTBR1 */
+ cb->tcr[0] &= ~TTBCR_EPD1;
+
+ cb->tcr[0] |= TTBCR_SH_IS << TTBCR_SH1_SHIFT;
+ cb->tcr[0] |= TTBCR_RGN_WBWA << TTBCR_IRGN1_SHIFT;
+ cb->tcr[0] |= TTBCR_RGN_WBWA << TTBCR_ORGN1_SHIFT;
+
+ switch (pgsize) {
+ case SZ_4K:
+ cb->tcr[0] |= TTBCR_TG1_4K;
+ break;
+ case SZ_16K:
+ cb->tcr[0] |= TTBCR_TG1_16K;
+ break;
+ case SZ_64K:
+ cb->tcr[0] |= TTBCR_TG1_64K;
+ break;
+ }
+
+ cb->tcr[0] |= (64ULL - smmu->va_size) << TTBCR_T1SZ_SHIFT;
+
+ /* Clear the existing SEP configuration */
+ cb->tcr[1] &= ~TTBCR2_SEP_UPSTREAM;
+
+ /* Set up the sign extend bit */
+ switch (smmu->va_size) {
+ case 32:
+ cb->tcr[1] |= TTBCR2_SEP_31;
+ cb->split_table_mask = (1ULL << 31);
+ break;
+ case 36:
+ cb->tcr[1] |= TTBCR2_SEP_35;
+ cb->split_table_mask = (1ULL << 35);
+ break;
+ case 40:
+ cb->tcr[1] |= TTBCR2_SEP_39;
+ cb->split_table_mask = (1ULL << 39);
+ break;
+ case 42:
+ cb->tcr[1] |= TTBCR2_SEP_41;
+ cb->split_table_mask = (1ULL << 41);
+ break;
+ case 44:
+ cb->tcr[1] |= TTBCR2_SEP_43;
+ cb->split_table_mask = (1ULL << 43);
+ break;
+ case 48:
+ cb->tcr[1] |= TTBCR2_SEP_UPSTREAM;
+ cb->split_table_mask = (1ULL << 48);
+ }
+
+ cb->ttbr[1] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
+ cb->ttbr[1] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+}
+
static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
struct io_pgtable_cfg *pgtbl_cfg)
{
@@ -614,8 +680,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
cb->ttbr[0] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
- cb->ttbr[1] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
- cb->ttbr[1] |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+
+ /*
+ * Set TTBR1 to empty by default - it will get
+ * programmed later if it is enabled
+ */
+ cb->ttbr[1] = (u64)cfg->asid << TTBRn_ASID_SHIFT;
}
} else {
cb->ttbr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
@@ -724,11 +794,13 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
{
int irq, start, ret = 0;
unsigned long ias, oas;
- struct io_pgtable_ops *pgtbl_ops;
+ struct io_pgtable_ops *pgtbl_ops[2];
struct io_pgtable_cfg pgtbl_cfg;
enum io_pgtable_fmt fmt;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ bool split_tables =
+ (smmu_domain->attributes & (1 << DOMAIN_ATTR_SPLIT_TABLES));
mutex_lock(&smmu_domain->init_mutex);
if (smmu_domain->smmu)
@@ -758,8 +830,11 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
*
* Note that you can't actually request stage-2 mappings.
*/
- if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
+ if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1)) {
smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
+ /* FIXME: fail instead? */
+ split_tables = false;
+ }
if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2))
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
@@ -776,8 +851,11 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
if (IS_ENABLED(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) &&
!IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_ARM_LPAE) &&
(smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S) &&
- (smmu_domain->stage == ARM_SMMU_DOMAIN_S1))
+ (smmu_domain->stage == ARM_SMMU_DOMAIN_S1)) {
+ /* FIXME: fail instead? */
+ split_tables = false;
cfg->fmt = ARM_SMMU_CTX_FMT_AARCH32_S;
+ }
if ((IS_ENABLED(CONFIG_64BIT) || cfg->fmt == ARM_SMMU_CTX_FMT_NONE) &&
(smmu->features & (ARM_SMMU_FEAT_FMT_AARCH64_64K |
ARM_SMMU_FEAT_FMT_AARCH64_16K |
@@ -864,8 +942,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
pgtbl_cfg.quirks = IO_PGTABLE_QUIRK_NO_DMA;
smmu_domain->smmu = smmu;
- pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
- if (!pgtbl_ops) {
+ pgtbl_ops[0] = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
+ if (!pgtbl_ops[0]) {
ret = -ENOMEM;
goto out_clear_smmu;
}
@@ -877,6 +955,22 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
/* Initialise the context bank with our page table cfg */
arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg);
+
+ pgtbl_ops[1] = NULL;
+
+ if (split_tables) {
+ /* FIXME: I think it is safe to reuse pgtbl_cfg here */
+ pgtbl_ops[1] = alloc_io_pgtable_ops(fmt, &pgtbl_cfg,
+ smmu_domain);
+ if (!pgtbl_ops[1]) {
+ free_io_pgtable_ops(pgtbl_ops[0]);
+ ret = -ENOMEM;
+ goto out_clear_smmu;
+ }
+
+ arm_smmu_init_ttbr1(smmu_domain, &pgtbl_cfg);
+ }
+
arm_smmu_write_context_bank(smmu, cfg->cbndx);
/*
@@ -895,7 +989,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
mutex_unlock(&smmu_domain->init_mutex);
/* Publish page table ops for map/unmap */
- smmu_domain->pgtbl_ops = pgtbl_ops;
+ smmu_domain->pgtbl_ops[0] = pgtbl_ops[0];
+ smmu_domain->pgtbl_ops[1] = pgtbl_ops[1];
+
return 0;
out_clear_smmu:
@@ -927,7 +1023,9 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
devm_free_irq(smmu->dev, irq, domain);
}
- free_io_pgtable_ops(smmu_domain->pgtbl_ops);
+ free_io_pgtable_ops(smmu_domain->pgtbl_ops[0]);
+ free_io_pgtable_ops(smmu_domain->pgtbl_ops[1]);
+
__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
}
@@ -1230,10 +1328,23 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
return arm_smmu_domain_add_master(smmu_domain, fwspec);
}
+static struct io_pgtable_ops *
+arm_smmu_get_pgtbl_ops(struct iommu_domain *domain, unsigned long iova)
+{
+ struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_cb *cb = &smmu_domain->smmu->cbs[cfg->cbndx];
+
+ if (iova & cb->split_table_mask)
+ return smmu_domain->pgtbl_ops[1];
+
+ return smmu_domain->pgtbl_ops[0];
+}
+
static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
- struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
+ struct io_pgtable_ops *ops = arm_smmu_get_pgtbl_ops(domain, iova);
if (!ops)
return -ENODEV;
@@ -1244,7 +1355,7 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
size_t size)
{
- struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
+ struct io_pgtable_ops *ops = arm_smmu_get_pgtbl_ops(domain, iova);
if (!ops)
return 0;
@@ -1266,7 +1377,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
- struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
+ struct io_pgtable_ops *ops = arm_smmu_get_pgtbl_ops(domain, iova);
struct device *dev = smmu->dev;
void __iomem *cb_base;
u32 tmp;
@@ -1307,7 +1418,7 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
+ struct io_pgtable_ops *ops = arm_smmu_get_pgtbl_ops(domain, iova);
if (domain->type == IOMMU_DOMAIN_IDENTITY)
return iova;
@@ -1477,6 +1588,10 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
case DOMAIN_ATTR_NESTING:
*(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
return 0;
+ case DOMAIN_ATTR_SPLIT_TABLES:
+ *((int *)data) = !!(smmu_domain->attributes
+ & (1 << DOMAIN_ATTR_SPLIT_TABLES));
+ return 0;
default:
return -ENODEV;
}
@@ -1506,6 +1621,11 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
break;
+ case DOMAIN_ATTR_SPLIT_TABLES:
+ if (*((int *)data))
+ smmu_domain->attributes |=
+ 1 << DOMAIN_ATTR_SPLIT_TABLES;
+ break;
default:
ret = -ENODEV;
}
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index fe851eae9057..920d9faa2a76 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -422,8 +422,7 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;
- if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) ||
- paddr >= (1ULL << data->iop.cfg.oas)))
+ if (WARN_ON(paddr >= (1ULL << data->iop.cfg.oas)))
return -ERANGE;
prot = arm_lpae_prot_to_pte(data, iommu_prot);
--
2.17.0
^ permalink raw reply related
* [PATCH 01/16] iommu: Add DOMAIN_ATTR_SPLIT_TABLES
From: Jordan Crouse @ 2018-05-18 21:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518213500.31595-1-jcrouse@codeaurora.org>
Add a new domain attribute to enable split pagetable support for devices
devices that support it.
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---
include/linux/iommu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d7e2f54086e4..366254e4b07f 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -153,6 +153,7 @@ enum iommu_attr {
DOMAIN_ATTR_FSL_PAMU_ENABLE,
DOMAIN_ATTR_FSL_PAMUV1,
DOMAIN_ATTR_NESTING, /* two stages of translation */
+ DOMAIN_ATTR_SPLIT_TABLES,
DOMAIN_ATTR_MAX,
};
--
2.17.0
^ permalink raw reply related
* [RFC v2 00/16] Private PASID and per-instance pagetables
From: Jordan Crouse @ 2018-05-18 21:34 UTC (permalink / raw)
To: linux-arm-kernel
This is v2 of a patchset of changes to implmeent private PASID support
for arm-smmu-v2 targets and implement per-instance pagetables for
MSM GPUs.
Per-instance pagetables allow the target GPU driver to create and manage
an individual pagetable for each file descriptor instance and switch
between them asynchronously using the GPU to reprogram the pagetable
registers on the fly.
This is done by expanding the shared PASID support from Jean Phillipe [1]
to create a "private" version of a PASID that enables a IOMMU driver
(arm-smmu-v2) to allocate a new pagetable and associate it with a PASID
identifier. That identifier could then be passed to a set of iommu
map/unmap functions to map entries into the new pagetable. Using a
set of sideband functions the GPU driver can get the TTBR0 and
other information for each PASID and use that information to
reporgram the pagetables.
The first three patches implement split pagetables for arm-smmu-v2
targets. This allows the GPU to take advantage of split pagetables
to map global buffers that won't be affected by the pagetable switch.
The next 3 patches implement private PASID support by adding a few
new API hooks and piggybacking on existing functions from the shared
PASID effort.
The next 8 patches hook up the MSM-GPU driver to implement and use
per-instance pagetables if available.
And finally the last 2 patches are a re-post of changes I provided
a few weeks ago to get the GPU driver to "opt out" of the DMA domain
and thus keeps the context bank free for the GPU domain (which is
important because the per-instance mechanism only knows how to work
on context bank 0).
All of this is based on top of Jean Phillipe's latest tree available
from.
git://linux-arm.org/linux-jpb.git sva/v2
[changes from v1]:
* Switch the domain attribute to SPLIT_TABLES (Robin Murphy)
* Reuse existing mm hooks as much as possible (Jean Phillipe Brucker)
* Consolidate iommu map/unmap code (Jean Phillipe Brucker)
[1] https://patchwork.kernel.org/patch/10394883/
Jordan Crouse (16):
iommu: Add DOMAIN_ATTR_SPLIT_TABLES
iommu/arm-smmu: Add split pagetable support for arm-smmu-v2
iommu/io-pgtable-arm: Remove ttbr[1] from io_pgtbl_cfg
iommu: sva: Add support for private PASIDs
iommu: arm-smmu: Add support for private PASIDs
iommu: arm-smmu: Add side-band function for specific PASID callbacks
drm/msm: Enable 64 bit mode by default
drm/msm: Pass the MMU domain index in struct msm_file_private
drm/msm/gpu: Support using split page tables for kernel buffer objects
drm/msm: Add msm_mmu features
drm/msm: Add support for iommu-sva PASIDs
drm/msm: Add support for per-instance address spaces
drm/msm/a5xx: Support per-instance pagetables
drm/msm: Support per-instance address spaces
iommu: Gracefully allow drivers to not attach to a default domain
iommu/arm-smmu: Add list of devices to opt out of DMA domains
drivers/gpu/drm/msm/Kconfig | 1 +
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 69 ++++
drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 17 +
drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 74 ++++-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 11 +
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 5 +
drivers/gpu/drm/msm/msm_drv.c | 45 ++-
drivers/gpu/drm/msm/msm_drv.h | 4 +
drivers/gpu/drm/msm/msm_gem.h | 1 +
drivers/gpu/drm/msm/msm_gem_submit.c | 11 +-
drivers/gpu/drm/msm/msm_gem_vma.c | 37 ++-
drivers/gpu/drm/msm/msm_gpu.c | 24 +-
drivers/gpu/drm/msm/msm_gpu.h | 4 +-
drivers/gpu/drm/msm/msm_iommu.c | 192 ++++++++++-
drivers/gpu/drm/msm/msm_mmu.h | 19 ++
drivers/gpu/drm/msm/msm_ringbuffer.h | 1 +
drivers/iommu/arm-smmu-regs.h | 18 ++
drivers/iommu/arm-smmu-v3-context.c | 2 +-
drivers/iommu/arm-smmu.c | 370 ++++++++++++++++++++--
drivers/iommu/io-pgtable-arm-v7s.c | 3 +-
drivers/iommu/io-pgtable-arm.c | 8 +-
drivers/iommu/io-pgtable.h | 14 +-
drivers/iommu/iommu-sva.c | 139 +++++++-
drivers/iommu/iommu.c | 83 +++--
drivers/iommu/ipmmu-vmsa.c | 2 +-
drivers/iommu/msm_iommu.c | 4 +-
drivers/iommu/mtk_iommu.c | 4 +-
drivers/iommu/qcom_iommu.c | 3 +-
include/linux/arm-smmu.h | 18 ++
include/linux/iommu.h | 75 ++++-
30 files changed, 1137 insertions(+), 121 deletions(-)
create mode 100644 include/linux/arm-smmu.h
--
2.17.0
^ permalink raw reply
* dma_sync_*_for_cpu and direction=TO_DEVICE (was Re: [PATCH 02/20] dma-mapping: provide a generic dma-noncoherent implementation)
From: Russell King - ARM Linux @ 2018-05-18 21:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <182840dedb4890a88c672b1c5d556920bf89a8fb.camel@synopsys.com>
On Fri, May 18, 2018 at 07:57:34PM +0000, Alexey Brodkin wrote:
> Hi Russel,
That's Russell.
> On Fri, 2018-05-18 at 18:50 +0100, Russell King - ARM Linux wrote:
> > It's necessary. Take a moment to think carefully about this:
> >
> > dma_map_single(, dir)
> >
> > dma_sync_single_for_cpu(, dir)
> >
> > dma_sync_single_for_device(, dir)
> >
> > dma_unmap_single(, dir)
> >
> > In the case of a DMA-incoherent architecture, the operations done at each
> > stage depend on the direction argument:
> >
> > map for_cpu for_device unmap
> > TO_DEV writeback none writeback none
> > TO_CPU invalidate invalidate* invalidate invalidate*
> > BIDIR writeback invalidate writeback invalidate
> >
> > * - only necessary if the CPU speculatively prefetches.
>
> I think invalidation of DMA buffer is required on for_cpu(TO_CPU) even
> if CPU doesn't preferch - what if we reuse the same buffer for multiple
> reads from DMA device?
That's fine - for non-coherent DMA, the CPU caches will only end up
containing data for that memory if:
- the CPU speculatively fetches data from that memory, or
- the CPU explicitly touches that memory
> > The multiple invalidations for the TO_CPU case handles different
> > conditions that can result in data corruption, and for some CPUs, all
> > four are necessary.
>
> I would agree that map()/unmap() a quite a special cases and so depending
> on direction we need to execute in them either for_cpu() or for_device()
> call-backs depending on direction.
>
> As for invalidation in case of for_device(TO_CPU) I still don't see
> a rationale behind it. Would be interesting to see a real example where
> we benefit from this.
Yes, you could avoid that, but depending how you structure the
architecture implementation, it can turn out to be a corner case.
The above table is precisely how 32-bit ARM is implemented, because
the way we implement them is based on who owns the memory - the "map"
and "for_device" operations translate internally to a cpu-to-device
ownership transition of the buffer. Similar for "unmap" and "to_cpu".
It basically avoids having to add additional functions at the lower
implementation levels.
> > Things get more interesting if the implementation behind the DMA API has
> > to copy data between the buffer supplied to the mapping and some DMA
> > accessible buffer:
> >
> > map for_cpu for_device unmap
> > TO_DEV copy to dma none copy to dma none
> > TO_CPU none copy to cpu none copy to cpu
> > BIDIR copy to dma copy to cpu copy to dma copy to cpu
> >
> > So, in both cases, the value of the direction argument defines what you
> > need to do in each call.
>
> Interesting enough in your seond table (which describes more complicated
> case indeed) you set "none" for for_device(TO_CPU) which looks logical
> to me.
>
> So IMHO that's what make sense:
> ---------------------------->8-----------------------------
> map for_cpu for_device unmap
> TO_DEV writeback none writeback none
> TO_CPU none invalidate none invalidate*
> BIDIR writeback invalidate writeback invalidate*
> ---------------------------->8-----------------------------
That doesn't make sense for the TO_CPU case. If the caches contain
dirty cache lines, and you're DMAing from the device to the system
RAM, other system activity can cause the dirty cache lines to be
evicted (written back) to memory which the DMA has already overwritten.
The result is data corruption. So, you really can't have "none" in
the "map" case there.
Given that, the "for_cpu" case becomes dependent on whether the CPU
speculatively prefetches.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH 05/15] mtd: nand: pxa3xx: remove the dmaengine compat need
From: Daniel Mack @ 2018-05-18 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180402142656.26815-6-robert.jarzmik@free.fr>
Hi Robert,
Thanks for this series.
On Monday, April 02, 2018 04:26 PM, Robert Jarzmik wrote:
> From: Robert Jarzmik <robert.jarzmik@renault.com>
>
> As the pxa architecture switched towards the dmaengine slave map, the
> old compatibility mechanism to acquire the dma requestor line number and
> priority are not needed anymore.
>
> This patch simplifies the dma resource acquisition, using the more
> generic function dma_request_slave_channel().
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
> drivers/mtd/nand/pxa3xx_nand.c | 10 +---------
This driver was replaced by drivers/mtd/nand/raw/marvell_nand.c
recently, so this patch can be dropped. I attached a version for the new
driver which you can pick instead.
Thanks,
Daniel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-mtd-rawnand-marvell-remove-dmaengine-compat-code.patch
Type: text/x-patch
Size: 1633 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180518/23dc3757/attachment.bin>
^ permalink raw reply
* [PATCH v3 1/2] dt-bindings: add MediaTek XS-PHY binding
From: Rob Herring @ 2018-05-18 21:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1525932629-10603-2-git-send-email-chunfeng.yun@mediatek.com>
On Thu, May 10, 2018 at 02:10:28PM +0800, Chunfeng Yun wrote:
> Add a DT binding documentation of XS-PHY for MediaTek SoCs
> with USB3.1 GEN2 controller
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> .../devicetree/bindings/phy/phy-mtk-xsphy.txt | 110 ++++++++++++++++++++
> 1 file changed, 110 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/phy-mtk-xsphy.txt
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Andy Shevchenko @ 2018-05-18 21:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-5-jmkrzyszt@gmail.com>
On Sat, May 19, 2018 at 12:09 AM, Janusz Krzysztofik
<jmkrzyszt@gmail.com> wrote:
> + gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
> + if (!IS_ERR_OR_NULL(gpiod_rdy)) {
So, is it optional or not at the end?
If it is, why do we check for NULL?
> this->dev_ready = ams_delta_nand_ready;
> } else {
> this->dev_ready = NULL;
> pr_notice("Couldn't request gpio for Delta NAND ready.\n");
dev_notice() ?
> }
> +err_gpiod:
> + if (err == -ENODEV || err == -ENOENT)
> + err = -EPROBE_DEFER;
Hmm...
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH 1/2] dt-bindings: power: Add ZynqMP power domain bindings
From: Jolly Shah @ 2018-05-18 21:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <be5cecb2-3d0d-22f8-48a2-f94ed9546e04@samsung.com>
Hi Marek,
> -----Original Message-----
> From: Marek Szyprowski [mailto:m.szyprowski at samsung.com]
> Sent: Thursday, May 17, 2018 11:31 PM
> To: Jolly Shah <JOLLYS@xilinx.com>; Geert Uytterhoeven <geert@linux-
> m68k.org>; Rob Herring <robh@kernel.org>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>; Andy Gross
> <andy.gross@linaro.org>; Shawn Guo <shawnguo@kernel.org>; Geert
> Uytterhoeven <geert+renesas@glider.be>; Bj?rn Andersson
> <bjorn.andersson@linaro.org>; sean.wang at mediatek.com; Michal Simek
> <michal.simek@xilinx.com>; Mark Rutland <mark.rutland@arm.com>; Rajan
> Vaja <RAJANV@xilinx.com>; open list:OPEN FIRMWARE AND FLATTENED
> DEVICE TREE BINDINGS <devicetree@vger.kernel.org>; Linux ARM <linux-arm-
> kernel at lists.infradead.org>; Linux Kernel Mailing List <linux-
> kernel at vger.kernel.org>
> Subject: Re: [PATCH 1/2] dt-bindings: power: Add ZynqMP power domain
> bindings
>
> Hi Jolly,
>
> On 2018-05-17 23:10, Jolly Shah wrote:
>
> >>>>>> +Example:
> >>>>>> + zynqmp-genpd {
> >>>>>> + compatible = "xlnx,zynqmp-genpd";
> >>>>> What's the control interface for controlling the domains?
> >>>>>> +
> >>>>>> + pd_usb0: pd-usb0 {
> >>>>>> + pd-id = <22>;
> >>>>>> + #power-domain-cells = <0>;
> >>>>> There's no need for all these sub nodes. Make #power-domain-cells
> >>>>> 1 and put the id in the cell value.
> >>>> That was my first reaction, too...
> >>>>>> + };
> >>>>>> +
> >>>>>> + pd_sata: pd-sata {
> >>>>>> + pd-id = <28>;
> >>>>>> + #power-domain-cells = <0>;
> >>>>>> + };
> >>>>>> +
> >>>>>> + pd_gpu: pd-gpu {
> >>>>>> + pd-id = <58 20 21>;
> >>>> ... until I saw the above.
> >>>> Controlling the GPU power area requires controlling 3 physical areas?
> >>>>
> >>>> However, doing it this way may bite you in the future, if a need
> >>>> arises to control a subset. And what about power up/down order?
> >>> What about defining 3 separate domains and arranging them in
> >>> parent-child relationship? generic power domains already supports
> >>> that and this allows to nicely define the power on/off order.
> >>>
> >>>>>> + #power-domain-cells = <0x0>;
> >>>>>> + };
> >>>>>> + };
> >> I agree it should be arranged in as parent child order to control
> >> subset or control order. Will incorporate those changes in next version.
> >
> > As suggested, I tried out parent, child approach. However what I found is
> Genpd core takes care of parent child dependencies for power on off routines
> only. In our case, We need them in attach-detach routines too. In that case, we
> need to handle dependencies manually for those routines. Please suggest better
> approach, if any.
>
> What do you mean to handle attach-detach?
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
For our power domain driver, we request usage of these nodes in attach routines and power them on in power on routine. So for below specific case, when attach_dev is called, all 3 nodes need to be requested.
> >>>>>> + pd_gpu: pd-gpu {
> >>>>>> + pd-id = <58 20 21>;
Thanks,
Jolly Shah
^ permalink raw reply
* [PATCH 6/6] ARM: OMAP1: ams-delta: make board header file local to mach-omap1
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-1-jmkrzyszt@gmail.com>
Now as the AMS Delta board header file is no longer included by
drivers, move it to the root directory of mach-omap1.
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
arch/arm/mach-omap1/ams-delta-fiq-handler.S | 2 +-
arch/arm/mach-omap1/ams-delta-fiq.c | 3 +--
arch/arm/mach-omap1/board-ams-delta.c | 2 +-
arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h | 0
4 files changed, 3 insertions(+), 4 deletions(-)
rename arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h (100%)
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index bf608441b357..9005c00db948 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -16,9 +16,9 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-#include <mach/board-ams-delta.h>
#include <mach/ams-delta-fiq.h>
+#include "board-ams-delta.h"
#include "iomap.h"
#include "soc.h"
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index d7ca9e2b40d2..30aedcc3f2b3 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -19,11 +19,10 @@
#include <linux/module.h>
#include <linux/io.h>
-#include <mach/board-ams-delta.h>
-
#include <asm/fiq.h>
#include <mach/ams-delta-fiq.h>
+#include "board-ams-delta.h"
static struct fiq_handler fh = {
.name = "ams-delta-fiq"
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 80f54cb54276..17d69eb64df3 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -36,7 +36,6 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <mach/board-ams-delta.h>
#include <linux/platform_data/keypad-omap.h>
#include <mach/mux.h>
@@ -45,6 +44,7 @@
#include "camera.h"
#include <mach/usb.h>
+#include "board-ams-delta.h"
#include "iomap.h"
#include "common.h"
diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h b/arch/arm/mach-omap1/board-ams-delta.h
similarity index 100%
rename from arch/arm/mach-omap1/include/mach/board-ams-delta.h
rename to arch/arm/mach-omap1/board-ams-delta.h
--
2.16.1
^ permalink raw reply related
* [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-1-jmkrzyszt@gmail.com>
Now as the Amstrad Delta board provides GPIO lookup tables, switch from
GPIO numbers to GPIO descriptors and use the table to locate required
GPIO pins.
Declare static variables for storing GPIO descriptors and replace
gpio_ functions with their gpiod_ equivalents. Return -EPROBE_DEFER
if the GPIO pins are not yet available so device initialization is
postponed instead of aborted.
Pin naming used by the driver should be followed while respective GPIO
lookup table is initialized by a board init code.
Created and tested against linux-4.17-rc3, on top of patch 1/6 "ARM:
OMAP1: ams-delta: add GPIO lookup tables"
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
drivers/mtd/nand/raw/ams-delta.c | 110 +++++++++++++++++++++------------------
1 file changed, 58 insertions(+), 52 deletions(-)
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 37a3cc21c7bc..c44be2f5a65c 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -20,23 +20,28 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
-#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
#include <asm/io.h>
#include <asm/sizes.h>
-#include <mach/board-ams-delta.h>
-
#include <mach/hardware.h>
/*
* MTD structure for E3 (Delta)
*/
static struct mtd_info *ams_delta_mtd = NULL;
+static struct gpio_desc *gpiod_rdy;
+static struct gpio_desc *gpiod_nce;
+static struct gpio_desc *gpiod_nre;
+static struct gpio_desc *gpiod_nwp;
+static struct gpio_desc *gpiod_nwe;
+static struct gpio_desc *gpiod_ale;
+static struct gpio_desc *gpiod_cle;
/*
* Define partitions for flash devices
@@ -70,9 +75,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
+ gpiod_set_value(gpiod_nwe, 0);
ndelay(40);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
+ gpiod_set_value(gpiod_nwe, 1);
}
static u_char ams_delta_read_byte(struct mtd_info *mtd)
@@ -81,11 +86,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
+ gpiod_set_value(gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
+ gpiod_set_value(gpiod_nre, 1);
return res;
}
@@ -120,12 +125,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
{
if (ctrl & NAND_CTRL_CHANGE) {
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
- (ctrl & NAND_NCE) == 0);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
- (ctrl & NAND_CLE) != 0);
- gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
- (ctrl & NAND_ALE) != 0);
+ gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
+ gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
+ gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
}
if (cmd != NAND_CMD_NONE)
@@ -134,41 +136,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
static int ams_delta_nand_ready(struct mtd_info *mtd)
{
- return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
+ return gpiod_get_value(gpiod_rdy);
}
-static const struct gpio _mandatory_gpio[] = {
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE,
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "nand_nce",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE,
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "nand_nre",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP,
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "nand_nwp",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE,
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "nand_nwe",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "nand_ale",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "nand_cle",
- },
-};
/*
* Main initialization routine
@@ -216,12 +186,15 @@ static int ams_delta_init(struct platform_device *pdev)
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf;
this->cmd_ctrl = ams_delta_hwcontrol;
- if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
+
+ gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
+ if (!IS_ERR_OR_NULL(gpiod_rdy)) {
this->dev_ready = ams_delta_nand_ready;
} else {
this->dev_ready = NULL;
pr_notice("Couldn't request gpio for Delta NAND ready.\n");
}
+
/* 25 us command delay time */
this->chip_delay = 30;
this->ecc.mode = NAND_ECC_SOFT;
@@ -230,7 +203,44 @@ static int ams_delta_init(struct platform_device *pdev)
platform_set_drvdata(pdev, io_base);
/* Set chip enabled, but */
- err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
+ gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_nwp)) {
+ err = PTR_ERR(gpiod_nwp);
+ dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err);
+ goto err_gpiod;
+ }
+ gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_nce)) {
+ err = PTR_ERR(gpiod_nce);
+ dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err);
+ goto err_gpiod;
+ }
+ gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_nre)) {
+ err = PTR_ERR(gpiod_nre);
+ dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err);
+ goto err_gpiod;
+ }
+ gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_nwe)) {
+ err = PTR_ERR(gpiod_nwe);
+ dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err);
+ goto err_gpiod;
+ }
+ gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_ale)) {
+ err = PTR_ERR(gpiod_ale);
+ dev_err(&pdev->dev, "ALE GPIO request failed (%d)\n", err);
+ goto err_gpiod;
+ }
+ gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_cle)) {
+ err = PTR_ERR(gpiod_cle);
+ dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
+ }
+err_gpiod:
+ if (err == -ENODEV || err == -ENOENT)
+ err = -EPROBE_DEFER;
if (err)
goto out_gpio;
@@ -246,9 +256,7 @@ static int ams_delta_init(struct platform_device *pdev)
goto out;
out_mtd:
- gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
out_gpio:
- gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
out_free:
kfree(this);
@@ -266,8 +274,6 @@ static int ams_delta_cleanup(struct platform_device *pdev)
/* Release resources, unregister device */
nand_release(ams_delta_mtd);
- gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
- gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
/* Free the MTD device structure */
--
2.16.1
^ permalink raw reply related
* [PATCH 4/6] fbdev: omapfb: lcd_ams_delta: use GPIO lookup table
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-1-jmkrzyszt@gmail.com>
Now as the Amstrad Delta board provides GPIO lookup tables, switch from
GPIO numbers to GPIO descriptors and use the table to locate required
GPIO pins.
Declare static variables for storing GPIO descriptors and replace
gpio_ functions with their gpiod_ equivalents. Move GPIO lookup
to the driver probe function so device initialization can be postponed
instead of aborted if the GPIO pin is not yet available.
Pin naming used by the driver should be followed while respective GPIO
lookup table is initialized by a board init code.
Created and tested against linux-4.17-rc3, on top of patch 1/6 "ARM:
OMAP1: ams-delta: add GPIO lookup tables"
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
drivers/video/fbdev/omap/lcd_ams_delta.c | 59 ++++++++++++++------------------
1 file changed, 26 insertions(+), 33 deletions(-)
diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c
index a4ee947006c7..19b6425b54be 100644
--- a/drivers/video/fbdev/omap/lcd_ams_delta.c
+++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
@@ -24,11 +24,10 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/lcd.h>
-#include <linux/gpio.h>
#include <mach/hardware.h>
-#include <mach/board-ams-delta.h>
#include "omapfb.h"
@@ -41,6 +40,8 @@
/* LCD class device section */
static int ams_delta_lcd;
+static struct gpio_desc *gpiod_vblen;
+static struct gpio_desc *gpiod_ndisp;
static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
{
@@ -99,41 +100,17 @@ static struct lcd_ops ams_delta_lcd_ops = {
/* omapfb panel section */
-static const struct gpio _gpios[] = {
- {
- .gpio = AMS_DELTA_GPIO_PIN_LCD_VBLEN,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "lcd_vblen",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_LCD_NDISP,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "lcd_ndisp",
- },
-};
-
-static int ams_delta_panel_init(struct lcd_panel *panel,
- struct omapfb_device *fbdev)
-{
- return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
-static void ams_delta_panel_cleanup(struct lcd_panel *panel)
-{
- gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
static int ams_delta_panel_enable(struct lcd_panel *panel)
{
- gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
- gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
+ gpiod_set_value(gpiod_ndisp, 1);
+ gpiod_set_value(gpiod_vblen, 1);
return 0;
}
static void ams_delta_panel_disable(struct lcd_panel *panel)
{
- gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
- gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
+ gpiod_set_value(gpiod_vblen, 0);
+ gpiod_set_value(gpiod_ndisp, 0);
}
static struct lcd_panel ams_delta_panel = {
@@ -154,8 +131,6 @@ static struct lcd_panel ams_delta_panel = {
.pcd = 0,
.acb = 37,
- .init = ams_delta_panel_init,
- .cleanup = ams_delta_panel_cleanup,
.enable = ams_delta_panel_enable,
.disable = ams_delta_panel_disable,
};
@@ -166,9 +141,27 @@ static struct lcd_panel ams_delta_panel = {
static int ams_delta_panel_probe(struct platform_device *pdev)
{
struct lcd_device *lcd_device = NULL;
-#ifdef CONFIG_LCD_CLASS_DEVICE
int ret;
+ gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_vblen)) {
+ ret = PTR_ERR(gpiod_vblen);
+ dev_err(&pdev->dev, "VBLEN GPIO request failed (%d)\n", ret);
+ if (ret == -ENODEV || ret == -ENOENT)
+ ret = -EPROBE_DEFER;
+ return ret;
+ }
+
+ gpiod_ndisp = devm_gpiod_get(&pdev->dev, "ndisp", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_ndisp)) {
+ ret = PTR_ERR(gpiod_ndisp);
+ dev_err(&pdev->dev, "NDISP GPIO request failed (%d)\n", ret);
+ if (ret == -ENODEV || ret == -ENOENT)
+ ret = -EPROBE_DEFER;
+ return ret;
+ }
+
+#ifdef CONFIG_LCD_CLASS_DEVICE
lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
&ams_delta_lcd_ops);
--
2.16.1
^ permalink raw reply related
* [PATCH 3/6] ASoC: ams_delta: use GPIO lookup table
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-1-jmkrzyszt@gmail.com>
Now as the Amstrad Delta board provides GPIO lookup tables, switch from
GPIO numbers to GPIO descriptors and use the table to locate required
GPIO pins.
The card uses two pins, one for jack and the other for voice modem
codec DAI control.
For jack pin, remove hardcoded GPIO number and use GPIO descriptor
based variant of jack GPIO initialization.
For modem_codec pin, declare static variable for storing its GPIO
descriptor, obtain it on card initialization and replace obsolete
ams_delta_latch2_write() with gpiod_set_value(). For that to work,
don't request the modem_codec pin from the board init code anymore.
If the modem_codec GPIO lookup fails, skip initialization of
functionality of the card which depends on its availability.
Pin naming used by the driver should be followed while respective GPIO
lookup table is initialized by a board init code.
Created and tested against linux-4.17-rc3, on top of patch 1/6 "ARM:
OMAP1: ams-delta: add GPIO lookup tables"
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
arch/arm/mach-omap1/board-ams-delta.c | 5 -----
sound/soc/omap/ams-delta.c | 38 +++++++++++++++++++----------------
2 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 4b78e73f8bf7..80f54cb54276 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -259,11 +259,6 @@ static const struct gpio latch_gpios[] __initconst = {
.flags = GPIOF_OUT_INIT_LOW,
.label = "scard_cmdvcc",
},
- {
- .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "modem_codec",
- },
{
.gpio = AMS_DELTA_LATCH2_GPIO_BASE + 14,
.flags = GPIOF_OUT_INIT_LOW,
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 77a30f0f0c96..4dce494dfbd3 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -22,7 +22,7 @@
*
*/
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spinlock.h>
#include <linux/tty.h>
#include <linux/module.h>
@@ -32,7 +32,6 @@
#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
@@ -213,7 +212,6 @@ static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
static struct snd_soc_jack ams_delta_hook_switch;
static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
{
- .gpio = 4,
.name = "hook_switch",
.report = SND_JACK_HEADSET,
.invert = 1,
@@ -259,6 +257,7 @@ static struct timer_list cx81801_timer;
static bool cx81801_cmd_pending;
static bool ams_delta_muted;
static DEFINE_SPINLOCK(ams_delta_lock);
+static struct gpio_desc *gpiod_modem_codec;
static void cx81801_timeout(struct timer_list *unused)
{
@@ -272,7 +271,7 @@ static void cx81801_timeout(struct timer_list *unused)
/* Reconnect the codec DAI back from the modem to the CPU DAI
* only if digital mute still off */
if (!muted)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+ gpiod_set_value(gpiod_modem_codec, 0);
}
/* Line discipline .open() */
@@ -381,8 +380,7 @@ static void cx81801_receive(struct tty_struct *tty,
/* Apply config pulse by connecting the codec to the modem
* if not already done */
if (apply)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
- AMS_DELTA_LATCH2_MODEM_CODEC);
+ gpiod_set_value(gpiod_modem_codec, 1);
break;
}
}
@@ -432,8 +430,7 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
spin_unlock_bh(&ams_delta_lock);
if (apply)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
- mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
+ gpiod_set_value(gpiod_modem_codec, !!mute);
return 0;
}
@@ -469,14 +466,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Store a pointer to the codec structure for tty ldisc use */
cx20442_codec = rtd->codec_dai->component;
- /* Set up digital mute if not provided by the codec */
- if (!codec_dai->driver->ops) {
- codec_dai->driver->ops = &ams_delta_dai_ops;
- } else {
- ams_delta_ops.startup = ams_delta_startup;
- ams_delta_ops.shutdown = ams_delta_shutdown;
- }
-
/* Add hook switch - can be used to control the codec from userspace
* even if line discipline fails */
ret = snd_soc_card_jack_new(card, "hook_switch", SND_JACK_HEADSET,
@@ -486,7 +475,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
"Failed to allocate resources for hook switch, "
"will continue without one.\n");
else {
- ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
+ ret = snd_soc_jack_add_gpiods(card->dev, &ams_delta_hook_switch,
ARRAY_SIZE(ams_delta_hook_switch_gpios),
ams_delta_hook_switch_gpios);
if (ret)
@@ -495,6 +484,21 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
"will continue with hook switch inactive.\n");
}
+ gpiod_modem_codec = devm_gpiod_get(card->dev, "modem_codec",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_modem_codec)) {
+ dev_warn(card->dev, "Failed to obtain modem_codec GPIO\n");
+ return 0;
+ }
+
+ /* Set up digital mute if not provided by the codec */
+ if (!codec_dai->driver->ops) {
+ codec_dai->driver->ops = &ams_delta_dai_ops;
+ } else {
+ ams_delta_ops.startup = ams_delta_startup;
+ ams_delta_ops.shutdown = ams_delta_shutdown;
+ }
+
/* Register optional line discipline for over the modem control */
ret = tty_register_ldisc(N_V253, &cx81801_ops);
if (ret) {
--
2.16.1
^ permalink raw reply related
* [PATCH 2/6] Input: ams_delta_serio: use GPIO lookup table
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-1-jmkrzyszt@gmail.com>
Now as the Amstrad Delta board provides GPIO lookup tables, switch from
GPIO numbers to GPIO descriptors and use the table to locate required
GPIO pins.
Declare static variables for storing GPIO descriptors and replace
gpio_ functions with their gpiod_ equivalents.
Pin naming used by the driver should be followed while respective GPIO
lookup table is initialized by a board init code.
Created and tested against linux-4.17-rc3, on top of patch 1/6 "ARM:
OMAP1: ams-delta: add GPIO lookup tables"
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
drivers/input/serio/ams_delta_serio.c | 98 +++++++++++++++++++----------------
1 file changed, 53 insertions(+), 45 deletions(-)
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 3df501c3421b..dd1f8f118c08 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -20,14 +20,13 @@
* However, when used with the E3 mailboard that producecs non-standard
* scancodes, a custom key table must be prepared and loaded from userspace.
*/
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/irq.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
#include <mach/ams-delta-fiq.h>
@@ -36,6 +35,10 @@ MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
MODULE_LICENSE("GPL");
static struct serio *ams_delta_serio;
+static struct gpio_desc *gpiod_data;
+static struct gpio_desc *gpiod_clock;
+static struct gpio_desc *gpiod_power;
+static struct gpio_desc *gpiod_dataout;
static int check_data(int data)
{
@@ -92,7 +95,7 @@ static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
static int ams_delta_serio_open(struct serio *serio)
{
/* enable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1);
+ gpiod_set_value(gpiod_power, 1);
return 0;
}
@@ -100,32 +103,9 @@ static int ams_delta_serio_open(struct serio *serio)
static void ams_delta_serio_close(struct serio *serio)
{
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ gpiod_set_value(gpiod_power, 0);
}
-static const struct gpio ams_delta_gpios[] __initconst_or_module = {
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
- .flags = GPIOF_DIR_IN,
- .label = "serio-data",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
- .flags = GPIOF_DIR_IN,
- .label = "serio-clock",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-dataout",
- },
-};
-
static int __init ams_delta_serio_init(void)
{
int err;
@@ -145,36 +125,62 @@ static int __init ams_delta_serio_init(void)
strlcpy(ams_delta_serio->phys, "GPIO/serio0",
sizeof(ams_delta_serio->phys));
- err = gpio_request_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
- if (err) {
- pr_err("ams_delta_serio: Couldn't request gpio pins\n");
+ gpiod_data = gpiod_get(NULL, "data", GPIOD_IN);
+ if (IS_ERR(gpiod_data)) {
+ err = PTR_ERR(gpiod_data);
+ pr_err("%s: 'data' GPIO request failed (%d)\n", __func__,
+ err);
goto serio;
}
+ gpiod_clock = gpiod_get(NULL, "clock", GPIOD_IN);
+ if (IS_ERR(gpiod_clock)) {
+ err = PTR_ERR(gpiod_clock);
+ pr_err("%s: 'clock' GPIO request failed (%d)\n", __func__,
+ err);
+ goto gpio_data;
+ }
+ gpiod_power = gpiod_get(NULL, "power", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_power)) {
+ err = PTR_ERR(gpiod_power);
+ pr_err("%s: 'power' GPIO request failed (%d)\n", __func__,
+ err);
+ goto gpio_clock;
+ }
+ gpiod_dataout = gpiod_get(NULL, "dataout", GPIOD_OUT_LOW);
+ if (IS_ERR(gpiod_dataout)) {
+ err = PTR_ERR(gpiod_dataout);
+ pr_err("%s: 'dataout' GPIO request failed (%d)\n",
+ __func__, err);
+ goto gpio_power;
+ }
- err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
- "ams-delta-serio", 0);
+ err = request_irq(gpiod_to_irq(gpiod_clock),
+ ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
+ "ams-delta-serio", 0);
if (err < 0) {
- pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
- gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
- goto gpio;
+ pr_err("%s: 'clock' GPIO interrupt request failed (%d)\n",
+ __func__, err);
+ goto gpio_dataout;
}
/*
* Since GPIO register handling for keyboard clock pin is performed
*@FIQ level, switch back from edge to simple interrupt handler
* to avoid bad interaction.
*/
- irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- handle_simple_irq);
+ irq_set_handler(gpiod_to_irq(gpiod_clock), handle_simple_irq);
serio_register_port(ams_delta_serio);
dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
return 0;
-gpio:
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
+gpio_dataout:
+ gpiod_put(gpiod_dataout);
+gpio_power:
+ gpiod_put(gpiod_power);
+gpio_clock:
+ gpiod_put(gpiod_clock);
+gpio_data:
+ gpiod_put(gpiod_data);
serio:
kfree(ams_delta_serio);
return err;
@@ -184,8 +190,10 @@ module_init(ams_delta_serio_init);
static void __exit ams_delta_serio_exit(void)
{
serio_unregister_port(ams_delta_serio);
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
+ free_irq(gpiod_to_irq(gpiod_clock), 0);
+ gpiod_put(gpiod_dataout);
+ gpiod_put(gpiod_power);
+ gpiod_put(gpiod_clock);
+ gpiod_put(gpiod_data);
}
module_exit(ams_delta_serio_exit);
--
2.16.1
^ permalink raw reply related
* [PATCH 1/6] ARM: OMAP1: ams-delta: add GPIO lookup tables
From: Janusz Krzysztofik @ 2018-05-18 21:09 UTC (permalink / raw)
To: linux-arm-kernel
Scope of the change is limited to GPIO pins used by board specific
device drivers which will be updated by follow-up patches of the
series. Those are some OMAP GPIO (gpio-0-15) and most of Amstrad Delta
latch2 GPIO bank pins. Remaining pins of those banks, as well as
Amstrad Delta latch1 pins, will be addressed later.
Assign a label ("latch2") to the bank, enumerate its pins and put that
information, together with OMAP GPIO bank pins, in GPIO lookup tables.
Assign lookup tables to devices as soon as those devices are registered
and their names can be obtained.
A step froward in:
- removal of hard-coded GPIO numbers from drivers,
- removal of board mach includes from drivers,
- switching to dynamically assigned GPIO numbers.
Created and compile tested agains linux-4.17-rc3
Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
---
arch/arm/mach-omap1/board-ams-delta.c | 102 ++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 52e8e53ca154..4b78e73f8bf7 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -12,6 +12,7 @@
* published by the Free Software Foundation.
*/
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -202,7 +203,10 @@ static struct resource latch2_resources[] = {
},
};
+#define LATCH2_LABEL "latch2"
+
static struct bgpio_pdata latch2_pdata = {
+ .label = LATCH2_LABEL,
.base = AMS_DELTA_LATCH2_GPIO_BASE,
.ngpio = AMS_DELTA_LATCH2_NGPIO,
};
@@ -217,6 +221,23 @@ static struct platform_device latch2_gpio_device = {
},
};
+#define LATCH2_PIN_LCD_VBLEN 0
+#define LATCH2_PIN_LCD_NDISP 1
+#define LATCH2_PIN_NAND_NCE 2
+#define LATCH2_PIN_NAND_NRE 3
+#define LATCH2_PIN_NAND_NWP 4
+#define LATCH2_PIN_NAND_NWE 5
+#define LATCH2_PIN_NAND_ALE 6
+#define LATCH2_PIN_NAND_CLE 7
+#define LATCH2_PIN_KEYBRD_PWR 8
+#define LATCH2_PIN_KEYBRD_DATAOUT 9
+#define LATCH2_PIN_SCARD_RSTIN 10
+#define LATCH2_PIN_SCARD_CMDVCC 11
+#define LATCH2_PIN_MODEM_NRESET 12
+#define LATCH2_PIN_MODEM_CODEC 13
+#define LATCH2_PIN_HOOKFLASH1 14
+#define LATCH2_PIN_HOOKFLASH2 15
+
static const struct gpio latch_gpios[] __initconst = {
{
.gpio = LATCH1_GPIO_BASE + 6,
@@ -323,6 +344,22 @@ static struct platform_device ams_delta_nand_device = {
.resource = ams_delta_nand_resources,
};
+#define OMAP_GPIO_LABEL "gpio-0-15"
+
+static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy",
+ 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+ { },
+ },
+};
+
static struct resource ams_delta_kp_resources[] = {
[0] = {
.start = INT_KEYBOARD,
@@ -358,6 +395,14 @@ static struct platform_device ams_delta_lcd_device = {
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_lcd_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_VBLEN, "vblen", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_NDISP, "ndisp", 0),
+ { },
+ },
+};
+
static const struct gpio_led gpio_leds[] __initconst = {
{
.name = "camera",
@@ -449,11 +494,35 @@ static struct platform_device ams_delta_audio_device = {
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_audio_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_HOOK_SWITCH,
+ "hook_switch", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
+ "modem_codec", 0),
+ { },
+ },
+};
+
static struct platform_device cx20442_codec_device = {
.name = "cx20442-codec",
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_serio_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
+ "data", 0),
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
+ "clock", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR,
+ "power", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT,
+ "dataout", 0),
+ { },
+ },
+};
+
static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
@@ -468,6 +537,16 @@ static struct platform_device *late_devices[] __initdata = {
&cx20442_codec_device,
};
+static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
+ &ams_delta_audio_gpio_table,
+ &ams_delta_serio_gpio_table,
+};
+
+static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
+ &ams_delta_lcd_gpio_table,
+ &ams_delta_nand_gpio_table,
+};
+
static void __init ams_delta_init(void)
{
/* mux pins for uarts */
@@ -500,6 +579,20 @@ static void __init ams_delta_init(void)
gpio_led_register_device(-1, &leds_pdata);
platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
+ /*
+ * As soon as devices have been registered, assign their dev_names
+ * to respective GPIO lookup tables before they are added.
+ */
+ ams_delta_audio_gpio_table.dev_id =
+ dev_name(&ams_delta_audio_device.dev);
+ /*
+ * No device name is assigned to GPIO lookup table for serio device
+ * as long as serio driver is not converted to platform device driver.
+ */
+
+ gpiod_add_lookup_tables(ams_delta_gpio_tables,
+ ARRAY_SIZE(ams_delta_gpio_tables));
+
ams_delta_init_fiq();
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
@@ -570,6 +663,15 @@ static int __init late_init(void)
platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
+ /*
+ * As soon as devices have been registered, assign their dev_names
+ * to respective GPIO lookup tables before they are added.
+ */
+ ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
+ ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
+
+ gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables));
+
err = platform_device_register(&modem_nreset_device);
if (err) {
pr_err("Couldn't register the modem regulator device\n");
--
2.16.1
^ permalink raw reply related
* [PATCH v7 2/2] drivers: soc: Add LLCC driver
From: Andy Shevchenko @ 2018-05-18 21:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526492623-20527-3-git-send-email-rishabhb@codeaurora.org>
On Wed, May 16, 2018 at 8:43 PM, Rishabh Bhatnagar
<rishabhb@codeaurora.org> wrote:
> LLCC (Last Level Cache Controller) provides additional cache memory
> in the system. LLCC is partitioned into multiple slices and each
> slice gets its own priority, size, ID and other config parameters.
> LLCC driver programs these parameters for each slice. Clients that
> are assigned to use LLCC need to get information such size & ID of the
> slice they get and activate or deactivate the slice as needed. LLCC driver
> provides API for the clients to perform these operations.
> +static const struct of_device_id sdm845_qcom_llcc_of_match[] = {
> + { .compatible = "qcom,sdm845-llcc", },
> + { },
Slightly better w/o comma
> +};
> +static struct platform_driver sdm845_qcom_llcc_driver = {
> + .driver = {
> + .name = "sdm845-llcc",
> + .owner = THIS_MODULE,
No need. See below.
> + .of_match_table = sdm845_qcom_llcc_of_match,
> + },
> + .probe = sdm845_qcom_llcc_probe,
> +};
> +
> +static int __init sdm845_init_qcom_llcc_init(void)
> +{
> + return platform_driver_register(&sdm845_qcom_llcc_driver);
> +}
> +module_init(sdm845_init_qcom_llcc_init);
> +
> +static void __exit sdm845_exit_qcom_llcc_exit(void)
> +{
> + platform_driver_unregister(&sdm845_qcom_llcc_driver);
> +}
> +module_exit(sdm845_exit_qcom_llcc_exit);
Why not to use module_platform_driver() macro?
> +#define ACTIVATE 0x1
> +#define DEACTIVATE 0x2
> +#define ACT_CTRL_OPCODE_ACTIVATE 0x1
> +#define ACT_CTRL_OPCODE_DEACTIVATE 0x2
> +#define ACT_CTRL_ACT_TRIG 0x1
Are these bits? Perhaps BIT() ?
> +#define ACT_CTRL_OPCODE_SHIFT 0x1
> +#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x2
> +#define ATTR1_FIXED_SIZE_SHIFT 0x3
> +#define ATTR1_PRIORITY_SHIFT 0x4
> +#define ATTR1_MAX_CAP_SHIFT 0x10
Better to use fixed size pattern, i.e. 0x01, 0x02, 0x03, 0x04, 0x10.
> +#define ATTR0_RES_WAYS_MASK 0x00000fff
> +#define ATTR0_BONUS_WAYS_MASK 0x0fff0000
GENMASK()
> +#define LLCC_LB_CNT_MASK 0xf0000000
Ditto.
> +#define MAX_CAP_TO_BYTES(n) (n * 1024)
(n * SZ_1K) ?
> +#define LLCC_TRP_ACT_CTRLn(n) (n * 0x1000)
SZ_4K ?
> +#define LLCC_TRP_STATUSn(n) (4 + n * 0x1000)
Ditto.
> +struct llcc_slice_desc *llcc_slice_getd(u32 uid)
> +{
> + const struct llcc_slice_config *cfg;
> + struct llcc_slice_desc *desc;
> + u32 sz, count = 0;
> +
> + cfg = drv_data->cfg;
> + sz = drv_data->cfg_size;
> +
> + while (cfg && count < sz) {
> + if (cfg->usecase_id == uid)
> + break;
> + cfg++;
> + count++;
> + }
> + if (cfg == NULL || count == sz)
> + return ERR_PTR(-ENODEV);
if (!cfg)
return ERR_PTR(-ENODEV);
while (cfg->... != uid) {
cfg++;
count++;
}
if (count == sz)
return ...
Though I would rather put it to for () loop.
> +static int llcc_update_act_ctrl(u32 sid,
> + u32 act_ctrl_reg_val, u32 status)
> +{
> + u32 act_ctrl_reg;
> + u32 status_reg;
> + u32 slice_status;
> + int ret = 0;
Useless assignment. Check entire patch series for a such.
> + ret = regmap_read_poll_timeout(drv_data->regmap, status_reg,
> + slice_status, !(slice_status & status), 0, LLCC_STATUS_READ_DELAY);
Wrong indentation.
> + return ret;
> +}
> + ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
> + DEACTIVATE);
Perhaps one line (~83 characters here is OK) ?
> + ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
> + ACTIVATE);
Ditto.
> + attr1_cfg = bcast_off +
> + LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
> + attr0_cfg = bcast_off +
> + LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
Ditto.
> + attr1_val |= llcc_table[i].probe_target_ways <<
> + ATTR1_PROBE_TARGET_WAYS_SHIFT;
> + attr1_val |= llcc_table[i].fixed_size <<
> + ATTR1_FIXED_SIZE_SHIFT;
> + attr1_val |= llcc_table[i].priority << ATTR1_PRIORITY_SHIFT;
foo |=
bar << SHIFT;
would look slightly better.
> +int qcom_llcc_probe(struct platform_device *pdev,
> + const struct llcc_slice_config *llcc_cfg, u32 sz)
> +{
> + drv_data->offsets = devm_kzalloc(dev, num_banks * sizeof(u32),
> + GFP_KERNEL);
> + if (!drv_data->offsets)
> + return -ENOMEM;
devm_kcalloc() ?
> +
> + for (i = 0; i < num_banks; i++)
> + drv_data->offsets[i] = (i * BANK_OFFSET_STRIDE);
Pointless parens.
> + drv_data->bitmap = devm_kcalloc(dev,
> + BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
> + GFP_KERNEL);
> + if (!drv_data->bitmap)
> + return -ENOMEM;
Perhaps at some point someone will add
bitmap_alloc()
devm_bitmap_alloc()
> + bitmap_zero(drv_data->bitmap, drv_data->max_slices);
Pointless
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* AArch64 memory
From: Robin Murphy @ 2018-05-18 20:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAJ+vNU3BM0BnB=owYz6iTLeqexL3=uu3+PeoN4zGOcqg3=HLaA@mail.gmail.com>
On Fri, 18 May 2018 11:49:05 -0700
Tim Harvey <tharvey@gateworks.com> wrote:
> On Fri, May 18, 2018 at 11:15 AM, Robin Murphy <robin.murphy@arm.com>
> wrote:
> > On 18/05/18 17:43, Tim Harvey wrote:
> > [...]
> >
> >>>> My second question has to do with CMA and coherent_pool. I have
> >>>> understood CMA as being a chunk of physical memory carved out by
> >>>> the kernel for allocations from dma_alloc_coherent by drivers
> >>>> that need chunks of contiguous memory for DMA buffers. I believe
> >>>> that before CMA was introduced we had to do this by defining
> >>>> memory holes. I'm not understanding the difference between CMA
> >>>> and the coherent pool. I've noticed that if CONFIG_DMA_CMA=y
> >>>> then the coherent pool allocates from CMA. Is there some
> >>>> disadvantage of CONFIG_DMA_CMA=y other than if defined you need
> >>>> to make sure your CMA is larger than coherent_pool? What
> >>>> drivers/calls use coherent_pool vs cma?
> >>>
> >>>
> >>>
> >>> coherent_pool is a special thing which exists for the sake of
> >>> non-hardware-coherent devices - normally for those we satisfy
> >>> DMA-coherent
> >>> allocations by setting up a non-cacheable remap of the allocated
> >>> buffer - see dma_common_contiguous_remap(). However, drivers may
> >>> call dma_alloc_coherent(..., GFP_ATOMIC) from interrupt handlers,
> >>> at which point
> >>> we can't call get_vm_area() to remap on demand, since that might
> >>> sleep, so
> >>> we reserve a pool pre-mapped as non-cacheable to satisfy such
> >>> atomic allocations from. I'm not sure why its user-visible name
> >>> is "coherent pool"
> >>> rather than the more descriptive "atomic pool" which it's named
> >>> internally,
> >>> but there's probably some history there. If you're lucky enough
> >>> not to have
> >>> any non-coherent DMA masters then you can safely ignore the whole
> >>> thing; otherwise it's still generally rare that it should need
> >>> adjusting.
> >>
> >>
> >> is there an easy way to tell if I have non-coherent DMA masters?
> >> The Cavium SDK uses a kernel cmdline param of coherent_pool=16M so
> >> I'm guessing something in the CN80XX/CN81XX (BGX NIC's or CPT
> >> perhaps) need atomic pool mem.
> >
> >
> > AFAIK the big-boy CN88xx is fully coherent everywhere, but whether
> > the peripherals and interconnect in the littler Octeon TX variants
> > are different I have no idea. If the contents of your dts-newport
> > repo on GitHub are the right thing to be looking at, then you do
> > have the "dma-coherent" property on the PCI nodes, which should
> > cover everything beneath (I'd expect that in reality the SMMU may
> > actually be coherent as well, but fortunately that's irrelevant
> > here). Thus everything which matters *should* be being picked up as
> > coherent already, and if not it would be a Linux problem. I can't
> > imagine what the SDK is up to there, but 16MB of coherent pool does
> > sound like something being done wrong, like incorrectly
> > compensating for bad firmware failing to describe the hardware
> > properly in the first place.
>
> Yes https://github.com/Gateworks/dts-newport/ is the board that I'm
> working with :)
>
> Ok, I think I understand now that the dma-coherent property on the PCI
> host controller is saying that all allocations by PCI device drivers
> will come from the atomic pool defined by coherent_pool=.
No no, quite the opposite! With that property present, all the devices
should be treated as hardware-coherent, meaning that CPU accesses to
DMA buffers can be via the regular (cacheable) kernel address, and the
non-cacheable remaps aren't necessary. Thus *nothing* will be touching
the atomic pool at all.
> Why does coherent_pool=16M seem wrong to you?
Because it's two-hundred and fifty six times the default value, and
atomic allocations should be very rare to begin with. IOW it stinks
of badly-written drivers.
> >
> >>> CMA is, as you surmise, a much more general thing for providing
> >>> large physically-contiguous areas, which the arch code
> >>> correspondingly uses to get
> >>> DMA-contiguous buffers. Unless all your DMA masters are behind
> >>> IOMMUs (such
> >>> that we can make any motley collection of pages look
> >>> DMA-contiguous), you probably don't want to turn it off. None of
> >>> these details should be relevant
> >>> as far as drivers are concerned, since from their viewpoint it's
> >>> all abstracted behind dma_alloc_coherent().
> >>>
> >>
> >> I don't want to turn off CONFIG_CMA but I'm still not clear if I
> >> should turn off CONFIG_DMA_CMA. I noticed the Cavium SDK 4.9 kernel
> >> has CONFIG_CMA=y but does not enable CONFIG_DMA_CMA which I believe
> >> means that the atomic pool does not pull its chunks from the CMA
> >> pool.
> >
> >
> > I wouldn't think there's much good reason to turn DMA_CMA off
> > either, even if nothing actually needs huge DMA buffers. Where the
> > atomic pool comes from shouldn't really matter, as it's a very
> > early one-off allocation. To speculate wildly I suppose there
> > *might* possibly be some performance difference between cma_alloc()
> > and falling back to the regular page allocator - if that were the
> > case it ought to be measurable by profiling something which calls
> > dma_alloc_coherent() in process context a lot, under both
> > configurations. Even then I'd imagine it's something that would
> > matter most on the 2-socket 96-core systems, and not so much on the
> > diddy ones.
>
> If you enable DMA_CMA then you have to make sure to size CMA large
> enough to handle coherent_pool (and any additional CMA you will need).
> I made the mistake of setting CONFIG_CMA_SIZE_MBYTES=16 then passing
> in a coherent_pool=64M which causes the coherent pool DMA allocation
> to fail and I'm not clear if that even has an impact on the system. It
> seems to me that the kernel should perhaps catch the case where CMA <
> dma_coherent when CONFIG_CMA_DMA=y and either warn about that
> condition or set cma to coherent_pool to resolve it.
Unfortunately that's not really practical - the default DMA_CMA region
is pulled out of memblock way early by generic code, while the atomic
pool is an Arm-specific thing which only comes into the picture much
later. Users already get a warning when creating the atomic pool
failed, so if they really want to go to crazy town with command-line
values they can always just reboot with "cma=<bigger>" as well (and
without CMA you're way beyond MAX_ORDER with those kind of sizes
anyway).
Robin.
^ permalink raw reply
* [GIT PULL 2/5] memory: tegra: Changes for v4.18-rc1
From: Thierry Reding @ 2018-05-18 20:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518142245.20242-2-thierry.reding@gmail.com>
On Fri, May 18, 2018 at 04:22:42PM +0200, Thierry Reding wrote:
> Hi ARM SoC maintainers,
>
> The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
>
> Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
>
> are available in the Git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.18-memory
>
> for you to fetch changes up to bef89a8d81ca97aca864778746b110cf52847868:
>
> memory: tegra: Remove Tegra114 SATA and AFI reset definitions (2018-05-18 12:33:02 +0200)
>
> Thanks,
> Thierry
>
> ----------------------------------------------------------------
> memory: tegra: Changes for v4.18-rc1
>
> This contains some cleanup of the memory controller driver as well as
> unification work to share more code between Tegra20 and later SoC
> generations. Also included are an implementation for the hot resets
> functionality by the memory controller which is required to properly
> reset busy hardware.
>
> ----------------------------------------------------------------
> Dmitry Osipenko (14):
> dt-bindings: memory: tegra: Add hot resets definitions
> memory: tegra: Do not handle spurious interrupts
> memory: tegra: Setup interrupts mask before requesting IRQ
> memory: tegra: Apply interrupts mask per SoC
> memory: tegra: Remove unused headers inclusions
> memory: tegra: Squash tegra20-mc into common tegra-mc driver
> memory: tegra: Introduce memory client hot reset
> memory: tegra: Add Tegra20 memory controller hot resets
> memory: tegra: Add Tegra30 memory controller hot resets
> memory: tegra: Add Tegra114 memory controller hot resets
> memory: tegra: Add Tegra124 memory controller hot resets
> memory: tegra: Register SMMU after MC driver became ready
> dt-bindings: memory: tegra: Remove Tegra114 SATA and AFI reset definitions
> memory: tegra: Remove Tegra114 SATA and AFI reset definitions
Please don't pull this just yet. Dmitry just pointed out to me that the
final two patches here break bisectibility. I'll reorder them and will
send out a new pull request.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180518/a3395a04/attachment-0001.sig>
^ permalink raw reply
* [PATCH] ARM: dts: da850-evm: Enable SATA port
From: Adam Ford @ 2018-05-18 20:43 UTC (permalink / raw)
To: linux-arm-kernel
The DA850-EVM from Logic PD has a SATA port and the module that went
with the kit support it as well. This patch will enable the SATA
controller.
Signed-off-by: Adam Ford <aford173@gmail.com>
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index a76c2ddfd23e..afccbe7681e7 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -160,6 +160,10 @@
};
};
+&sata {
+ status = "okay";
+};
+
&serial0 {
status = "okay";
};
--
2.17.0
^ permalink raw reply related
* dma_sync_*_for_cpu and direction=TO_DEVICE (was Re: [PATCH 02/20] dma-mapping: provide a generic dma-noncoherent implementation)
From: Vineet Gupta @ 2018-05-18 20:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518175004.GF17671@n2100.armlinux.org.uk>
On 05/18/2018 10:50 AM, Russell King - ARM Linux wrote:
> On Fri, May 18, 2018 at 10:20:02AM -0700, Vineet Gupta wrote:
>> I never understood the need for this direction. And if memory serves me
>> right, at that time I was seeing twice the amount of cache flushing !
> It's necessary. Take a moment to think carefully about this:
>
> dma_map_single(, dir)
>
> dma_sync_single_for_cpu(, dir)
>
> dma_sync_single_for_device(, dir)
>
> dma_unmap_single(, dir)
As an aside, do these imply a state machine of sorts - does a driver needs to
always call map_single first ?
My original point of contention/confusion is the specific combinations of API and
direction, specifically for_cpu(TO_DEV) and for_device(TO_CPU)
Semantically what does dma_sync_single_for_cpu(TO_DEV) even imply for a non dma
coherent arch.
Your tables below have "none" for both, implying it is unlikely to be a real
combination (for ARM and ARC atleast).
The other case, actually @dir TO_CPU, independent of for_{cpu, device}? implies
driver intends to touch it after the call, so it would invalidate any stray lines,
unconditionally (and not just for speculative prefetch case).
> In the case of a DMA-incoherent architecture, the operations done at each
> stage depend on the direction argument:
>
> map for_cpu for_device unmap
> TO_DEV writeback none writeback none
> TO_CPU invalidate invalidate* invalidate invalidate*
> BIDIR writeback invalidate writeback invalidate
>
> * - only necessary if the CPU speculatively prefetches.
>
> The multiple invalidations for the TO_CPU case handles different
> conditions that can result in data corruption, and for some CPUs, all
> four are necessary.
Can you please explain in some more detail, TO_CPU row, why invalidate is
conditional sometimes.
^ permalink raw reply
* [PATCH V7] ARM: dts: da850-evm: Enable LCD and Backlight
From: Adam Ford @ 2018-05-18 20:33 UTC (permalink / raw)
To: linux-arm-kernel
When using the board files the LCD works, but not with the DT.
This adds enables the original da850-evm to work with the same
LCD in device tree mode.
The EVM has a gpio for the regulator and a PWM for dimming the
backlight. The LCD and the vpif display pins are mutually
exclusive, so if using the LCD, do not load the vpif driver.
Signed-off-by: Adam Ford <aford173@gmail.com>
---
V7: Missed one reference to backlight_reg->backlight_lcd
V6: Fix some whitespace and comment formatting. Rename backlight_reg to
backlight_lcd
V5: Resync against v4.18/dt
V4: Move the backlight to PWM, so the driver can control the regulator allowing the
regulator to power down and enabling the ability to change the brightness of the
backlight
V3: Fix errant GPIO, label GPIO pins, and rename the regulator to be more explict to
backlight which better matches the schematic. Updated the description to explain
that it cannot be used at the same time as the vpif driver.
V2: Add regulator and GPIO enable pins. Remove PWM backlight and replace with GPIO
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 0e82bb988fde..a76c2ddfd23e 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -27,6 +27,60 @@
spi0 = &spi1;
};
+ backlight: backlight-pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ecap2_pins>;
+ power-supply = <&backlight_lcd>;
+ compatible = "pwm-backlight";
+ pwms = <&ecap2 0 50000 0>;
+ brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
+ default-brightness-level = <7>;
+ };
+
+ panel {
+ compatible = "ti,tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+ /*
+ * The vpif and the LCD are mutually exclusive.
+ * To enable VPIF, change the status below to 'disabled' then
+ * then change the status of the vpif below to 'okay'
+ */
+ status = "okay";
+ enable-gpios = <&gpio 40 GPIO_ACTIVE_HIGH>; /* lcd_panel_pwr */
+
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+ dma-burst-sz = <16>;
+ bpp = <16>;
+ fdd = <0x80>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
+ };
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 480x272 {
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <3>;
+ hback-porch = <2>;
+ hsync-len = <42>;
+ vback-porch = <3>;
+ vfront-porch = <4>;
+ vsync-len = <11>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
@@ -35,6 +89,15 @@
regulator-boot-on;
};
+ backlight_lcd: backlight-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "lcd_backlight_pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio 47 GPIO_ACTIVE_HIGH>; /* lcd_backlight_pwr */
+ enable-active-high;
+ };
+
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "DA850/OMAP-L138 EVM";
@@ -63,6 +126,10 @@
};
};
+&ecap2 {
+ status = "okay";
+};
+
&pmx_core {
status = "okay";
@@ -109,6 +176,10 @@
status = "okay";
};
+&lcdc {
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
clock-frequency = <100000>;
@@ -336,5 +407,10 @@
&vpif {
pinctrl-names = "default";
pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
- status = "okay";
+ /*
+ * The vpif and the LCD are mutually exclusive.
+ * To enable VPIF, disable the ti,tilcdc,panel then
+ * changed the status below to 'okay'
+ */
+ status = "disabled";
};
--
2.17.0
^ permalink raw reply related
* [PATCH 02/20] dma-mapping: provide a generic dma-noncoherent implementation
From: Helge Deller @ 2018-05-18 20:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bad125dff49f6e49c895e818c9d1abb346a46e8e.camel@synopsys.com>
On 18.05.2018 15:03, Alexey Brodkin wrote:
> But the real fix of my problem is:
> ---------------------------------------->8------------------------------------
> --- a/lib/dma-noncoherent.c
> +++ b/lib/dma-noncoherent.c
> @@ -35,7 +35,7 @@ static dma_addr_t dma_noncoherent_map_page(struct device *dev, struct page *page
>
> addr = dma_direct_map_page(dev, page, offset, size, dir, attrs);
> if (!dma_mapping_error(dev, addr) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
> - arch_sync_dma_for_device(dev, page_to_phys(page), size, dir);
> + arch_sync_dma_for_device(dev, page_to_phys(page) + offset, size, dir);
> return addr;
> }
> ---------------------------------------->8------------------------------------
>
> You seem to lost an offset in the page so if we happen to have a buffer not aligned to
> a page boundary then we were obviously corrupting data outside our data :)
Good.
This patch seems to fix the dma issues I faced on my 32bit B160L parisc box.
So it leaves only one open issue on parisc:
Now every 32 bit parisc system is unnecessarily non-coherent.
Helge
^ permalink raw reply
* dma_sync_*_for_cpu and direction=TO_DEVICE (was Re: [PATCH 02/20] dma-mapping: provide a generic dma-noncoherent implementation)
From: Alexey Brodkin @ 2018-05-18 19:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518175004.GF17671@n2100.armlinux.org.uk>
Hi Russel,
On Fri, 2018-05-18 at 18:50 +0100, Russell King - ARM Linux wrote:
> It's necessary. Take a moment to think carefully about this:
>
> dma_map_single(, dir)
>
> dma_sync_single_for_cpu(, dir)
>
> dma_sync_single_for_device(, dir)
>
> dma_unmap_single(, dir)
>
> In the case of a DMA-incoherent architecture, the operations done at each
> stage depend on the direction argument:
>
> map for_cpu for_device unmap
> TO_DEV writeback none writeback none
> TO_CPU invalidate invalidate* invalidate invalidate*
> BIDIR writeback invalidate writeback invalidate
>
> * - only necessary if the CPU speculatively prefetches.
I think invalidation of DMA buffer is required on for_cpu(TO_CPU) even
if CPU doesn't preferch - what if we reuse the same buffer for multiple
reads from DMA device?
> The multiple invalidations for the TO_CPU case handles different
> conditions that can result in data corruption, and for some CPUs, all
> four are necessary.
I would agree that map()/unmap() a quite a special cases and so depending
on direction we need to execute in them either for_cpu() or for_device()
call-backs depending on direction.
As for invalidation in case of for_device(TO_CPU) I still don't see
a rationale behind it. Would be interesting to see a real example where
we benefit from this.
> This is what is implemented for 32-bit ARM, depending on the CPU
> capabilities, as we have DMA incoherent devices and we have CPUs that
> speculatively prefetch data, and so may load data into the caches while
> DMA is in operation.
>
>
> Things get more interesting if the implementation behind the DMA API has
> to copy data between the buffer supplied to the mapping and some DMA
> accessible buffer:
>
> map for_cpu for_device unmap
> TO_DEV copy to dma none copy to dma none
> TO_CPU none copy to cpu none copy to cpu
> BIDIR copy to dma copy to cpu copy to dma copy to cpu
>
> So, in both cases, the value of the direction argument defines what you
> need to do in each call.
Interesting enough in your seond table (which describes more complicated
case indeed) you set "none" for for_device(TO_CPU) which looks logical
to me.
So IMHO that's what make sense:
---------------------------->8-----------------------------
map for_cpu for_device unmap
TO_DEV writeback none writeback none
TO_CPU none invalidate none invalidate*
BIDIR writeback invalidate writeback invalidate*
---------------------------->8-----------------------------
* is the case for prefetching CPU.
-Alexey
^ permalink raw reply
* [PATCH v7 2/2] PCI: mediatek: Using chained IRQ to setup IRQ handle
From: Bjorn Helgaas @ 2018-05-18 19:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1525412853-24367-3-git-send-email-honghui.zhang@mediatek.com>
On Fri, May 04, 2018 at 01:47:33PM +0800, honghui.zhang at mediatek.com wrote:
> From: Honghui Zhang <honghui.zhang@mediatek.com>
>
> Using irq_chip solution to setup IRQs in order to consist
> with IRQ framework.
>
> Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
> Acked-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
> drivers/pci/host/pcie-mediatek.c | 206 ++++++++++++++++++++++-----------------
> 1 file changed, 115 insertions(+), 91 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> index c3dc549..dabf1086 100644
> --- a/drivers/pci/host/pcie-mediatek.c
> +++ b/drivers/pci/host/pcie-mediatek.c
> ...
> -static int mtk_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
> - irq_hw_number_t hwirq)
> +static struct msi_domain_info mtk_msi_domain_info = {
I think this patch should be amended to include this:
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 0d0177ce436c..368b70d9371b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -193,7 +193,7 @@ config PCIE_MEDIATEK
bool "MediaTek PCIe controller"
depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
depends on OF
- depends on PCI
+ depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
help
Say Y here if you want to enable PCIe controller support on
Lorenzo, if you want to fold that in and update your branch, I can pull it.
If not, I can add a patch on top, which should only break compile-testing
bisection.
^ permalink raw reply related
* [PATCH 2/2] arm64: dts: renesas: v3hsk: add GEther support
From: Sergei Shtylyov @ 2018-05-18 19:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a4230699-e46f-0782-e3b1-22d58b9033c8@cogentembedded.com>
Define the V3H Starter Kit board dependent part of the GEther device node.
Based on the original (and large) patch by Vladimir Barinov.
Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
Index: renesas/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
===================================================================
--- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
+++ renesas/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
@@ -15,6 +15,7 @@
aliases {
serial0 = &scif0;
+ ethernet0 = &gether;
};
chosen {
@@ -36,7 +37,27 @@
clock-frequency = <32768>;
};
+&gether {
+ pinctrl-0 = <&gether_pins>;
+ pinctrl-names = "default";
+
+ phy-mode = "rgmii";
+ phy-handle = <&phy0>;
+ renesas,no-ether-link;
+ status = "okay";
+
+ phy0: ethernet-phy at 0 {
+ reg = <0>;
+ };
+};
+
&pfc {
+ gether_pins: gether {
+ groups = "gether_mdio_a", "gether_rgmii",
+ "gether_txcrefclk", "gether_txcrefclk_mega";
+ function = "gether";
+ };
+
scif0_pins: scif0 {
groups = "scif0_data";
function = "scif0";
^ permalink raw reply
* [PATCH 1/2] arm64: dts: renesas: r8a77980: add GEther support
From: Sergei Shtylyov @ 2018-05-18 19:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a4230699-e46f-0782-e3b1-22d58b9033c8@cogentembedded.com>
Define the generic R8A77980 part of the GEther device node.
Based on the original (and large) patch by Vladimir Barinov.
Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
---
arch/arm64/boot/dts/renesas/r8a77980.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
Index: renesas/arch/arm64/boot/dts/renesas/r8a77980.dtsi
===================================================================
--- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ renesas/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -417,6 +417,17 @@
dma-channels = <16>;
};
+ gether: ethernet at e7400000 {
+ compatible = "renesas,gether-r8a77980";
+ reg = <0 0xe7400000 0 0x1000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 813>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
mmc0: mmc at ee140000 {
compatible = "renesas,sdhi-r8a77980",
"renesas,rcar-gen3-sdhi";
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox