* [PATCH v6 12/16] drivers: iommu: arm-smmu: split probe functions into DT/generic portions
From: Lorenzo Pieralisi @ 2016-10-18 16:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
Current ARM SMMU probe functions intermingle HW and DT probing
in the initialization functions to detect and programme the ARM SMMU
driver features. In order to allow probing the ARM SMMU with other
firmwares than DT, this patch splits the ARM SMMU init functions into
DT and HW specific portions so that other FW interfaces (ie ACPI) can
reuse the HW probing functions and skip the DT portion accordingly.
This patch implements no functional change, only code reshuffling.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 62 +++++++++++++++++++++++++++++-------------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9b0b501..813dbf2 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1656,7 +1656,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
unsigned long size;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
u32 id;
- bool cttw_dt, cttw_reg;
+ bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
int i;
dev_notice(smmu->dev, "probing hardware configuration...\n");
@@ -1701,20 +1701,17 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
/*
* In order for DMA API calls to work properly, we must defer to what
- * the DT says about coherency, regardless of what the hardware claims.
+ * the FW says about coherency, regardless of what the hardware claims.
* Fortunately, this also opens up a workaround for systems where the
* ID register value has ended up configured incorrectly.
*/
- cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
cttw_reg = !!(id & ID0_CTTW);
- if (cttw_dt)
- smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
- if (cttw_dt || cttw_reg)
+ if (cttw_fw || cttw_reg)
dev_notice(smmu->dev, "\t%scoherent table walk\n",
- cttw_dt ? "" : "non-");
- if (cttw_dt != cttw_reg)
+ cttw_fw ? "" : "non-");
+ if (cttw_fw != cttw_reg)
dev_notice(smmu->dev,
- "\t(IDR0.CTTW overridden by dma-coherent property)\n");
+ "\t(IDR0.CTTW overridden by FW configuration)\n");
/* Max. number of entries we have for stream matching/indexing */
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
@@ -1895,15 +1892,25 @@ static const struct of_device_id arm_smmu_of_match[] = {
};
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+ struct arm_smmu_device *smmu)
{
const struct arm_smmu_match_data *data;
- struct resource *res;
- struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
- int num_irqs, i, err;
bool legacy_binding;
+ if (of_property_read_u32(dev->of_node, "#global-interrupts",
+ &smmu->num_global_irqs)) {
+ dev_err(dev, "missing #global-interrupts property\n");
+ return -ENODEV;
+ }
+
+ data = of_device_get_match_data(dev);
+ smmu->version = data->version;
+ smmu->model = data->model;
+
+ parse_driver_options(smmu);
+
legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
if (legacy_binding && !using_generic_binding) {
if (!using_legacy_binding)
@@ -1916,6 +1923,19 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
return -ENODEV;
}
+ if (of_dma_is_coherent(smmu->dev->of_node))
+ smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+
+ return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct arm_smmu_device *smmu;
+ struct device *dev = &pdev->dev;
+ int num_irqs, i, err;
+
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
dev_err(dev, "failed to allocate arm_smmu_device\n");
@@ -1923,9 +1943,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
}
smmu->dev = dev;
- data = of_device_get_match_data(dev);
- smmu->version = data->version;
- smmu->model = data->model;
+ err = arm_smmu_device_dt_probe(pdev, smmu);
+ if (err)
+ return err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
smmu->base = devm_ioremap_resource(dev, res);
@@ -1933,12 +1953,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
return PTR_ERR(smmu->base);
smmu->size = resource_size(res);
- if (of_property_read_u32(dev->of_node, "#global-interrupts",
- &smmu->num_global_irqs)) {
- dev_err(dev, "missing #global-interrupts property\n");
- return -ENODEV;
- }
-
num_irqs = 0;
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
num_irqs++;
@@ -1973,8 +1987,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
if (err)
return err;
- parse_driver_options(smmu);
-
if (smmu->version == ARM_SMMU_V2 &&
smmu->num_context_banks != smmu->num_context_irqs) {
dev_err(dev,
@@ -2036,7 +2048,7 @@ static struct platform_driver arm_smmu_driver = {
.name = "arm-smmu",
.of_match_table = of_match_ptr(arm_smmu_of_match),
},
- .probe = arm_smmu_device_dt_probe,
+ .probe = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
};
--
2.10.0
^ permalink raw reply related
* [PATCH v6 13/16] drivers: iommu: arm-smmu: add IORT configuration
From: Lorenzo Pieralisi @ 2016-10-18 16:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU components.
Add static configuration functions to the IORT kernel layer for
the ARM SMMU components, so that the ARM SMMU driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
drivers/acpi/arm64/iort.c | 81 +++++++++++++++++++++++++++++++++++++++++++++
drivers/iommu/arm-smmu.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/acpi_iort.h | 3 ++
3 files changed, 167 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index ea90bc8..04cc5f7 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -548,6 +548,78 @@ static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
}
+static int __init arm_smmu_count_resources(struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu *smmu;
+ int num_irqs;
+ u64 *glb_irq;
+
+ /* Retrieve SMMU specific data */
+ smmu = (struct acpi_iort_smmu *)node->node_data;
+
+ glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
+ if (!IORT_IRQ_MASK(glb_irq[1])) /* 0 means not implemented */
+ num_irqs = 1;
+ else
+ num_irqs = 2;
+
+ num_irqs += smmu->context_interrupt_count;
+
+ return num_irqs + 1;
+}
+
+static void __init arm_smmu_init_resources(struct resource *res,
+ struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu *smmu;
+ int i, hw_irq, trigger, num_res = 0;
+ u64 *ctx_irq, *glb_irq;
+
+ /* Retrieve SMMU specific data */
+ smmu = (struct acpi_iort_smmu *)node->node_data;
+
+ res[num_res].start = smmu->base_address;
+ res[num_res].end = smmu->base_address + smmu->span - 1;
+ res[num_res].flags = IORESOURCE_MEM;
+ num_res++;
+
+ glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
+ /* Global IRQs */
+ hw_irq = IORT_IRQ_MASK(glb_irq[0]);
+ trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[0]);
+
+ acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
+ &res[num_res++]);
+
+ /* Global IRQs */
+ hw_irq = IORT_IRQ_MASK(glb_irq[1]);
+ if (hw_irq) {
+ trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[1]);
+ acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
+ &res[num_res++]);
+ }
+
+ /* Context IRQs */
+ ctx_irq = ACPI_ADD_PTR(u64, node, smmu->context_interrupt_offset);
+ for (i = 0; i < smmu->context_interrupt_count; i++) {
+ hw_irq = IORT_IRQ_MASK(ctx_irq[i]);
+ trigger = IORT_IRQ_TRIGGER_MASK(ctx_irq[i]);
+
+ acpi_iort_register_irq(hw_irq, "arm-smmu-context", trigger,
+ &res[num_res++]);
+ }
+}
+
+static bool __init arm_smmu_is_coherent(struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu *smmu;
+
+ /* Retrieve SMMU specific data */
+ smmu = (struct acpi_iort_smmu *)node->node_data;
+
+ return smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK;
+}
+
struct iort_iommu_config {
const char *name;
int (*iommu_init)(struct acpi_iort_node *node);
@@ -564,12 +636,21 @@ static const struct iort_iommu_config iort_arm_smmu_v3_cfg __initconst = {
.iommu_init_resources = arm_smmu_v3_init_resources
};
+static const struct iort_iommu_config iort_arm_smmu_cfg __initconst = {
+ .name = "arm-smmu",
+ .iommu_is_coherent = arm_smmu_is_coherent,
+ .iommu_count_resources = arm_smmu_count_resources,
+ .iommu_init_resources = arm_smmu_init_resources
+};
+
static __init
const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
{
switch (node->type) {
case ACPI_IORT_NODE_SMMU_V3:
return &iort_arm_smmu_v3_cfg;
+ case ACPI_IORT_NODE_SMMU:
+ return &iort_arm_smmu_cfg;
default:
return NULL;
}
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 813dbf2..aa2d944 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -28,6 +28,8 @@
#define pr_fmt(fmt) "arm-smmu: " fmt
+#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
@@ -1892,6 +1894,71 @@ static const struct of_device_id arm_smmu_of_match[] = {
};
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
+#ifdef CONFIG_ACPI
+static int acpi_smmu_get_data(u32 model, u32 *version, u32 *impl)
+{
+ int ret = 0;
+
+ switch (model) {
+ case ACPI_IORT_SMMU_V1:
+ case ACPI_IORT_SMMU_CORELINK_MMU400:
+ *version = ARM_SMMU_V1;
+ *impl = GENERIC_SMMU;
+ break;
+ case ACPI_IORT_SMMU_V2:
+ *version = ARM_SMMU_V2;
+ *impl = GENERIC_SMMU;
+ break;
+ case ACPI_IORT_SMMU_CORELINK_MMU500:
+ *version = ARM_SMMU_V2;
+ *impl = ARM_MMU500;
+ break;
+ default:
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+ struct arm_smmu_device *smmu)
+{
+ struct device *dev = smmu->dev;
+ struct acpi_iort_node *node =
+ *(struct acpi_iort_node **)dev_get_platdata(dev);
+ struct acpi_iort_smmu *iort_smmu;
+ u64 *glb_irq;
+ int ret;
+
+ /* Retrieve SMMU1/2 specific data */
+ iort_smmu = (struct acpi_iort_smmu *)node->node_data;
+
+ ret = acpi_smmu_get_data(iort_smmu->model, &smmu->version,
+ &smmu->model);
+ if (ret < 0)
+ return ret;
+
+ glb_irq = ACPI_ADD_PTR(u64, iort_smmu,
+ iort_smmu->global_interrupt_offset);
+
+ if (!IORT_IRQ_MASK(glb_irq[1])) /* 0 means not implemented */
+ smmu->num_global_irqs = 1;
+ else
+ smmu->num_global_irqs = 2;
+
+ if (iort_smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK)
+ smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+
+ return 0;
+}
+#else
+static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+ struct arm_smmu_device *smmu)
+{
+ return -ENODEV;
+}
+#endif
+
static int arm_smmu_device_dt_probe(struct platform_device *pdev,
struct arm_smmu_device *smmu)
{
@@ -1943,7 +2010,11 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
}
smmu->dev = dev;
- err = arm_smmu_device_dt_probe(pdev, smmu);
+ if (dev->of_node)
+ err = arm_smmu_device_dt_probe(pdev, smmu);
+ else
+ err = arm_smmu_device_acpi_probe(pdev, smmu);
+
if (err)
return err;
@@ -2091,6 +2162,17 @@ IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", arm_smmu_of_init);
IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", arm_smmu_of_init);
IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", arm_smmu_of_init);
+#ifdef CONFIG_ACPI
+static int __init arm_smmu_acpi_init(struct acpi_table_header *table)
+{
+ if (iort_node_match(ACPI_IORT_NODE_SMMU))
+ return arm_smmu_init();
+
+ return 0;
+}
+IORT_ACPI_DECLARE(arm_smmu, ACPI_SIG_IORT, arm_smmu_acpi_init);
+#endif
+
MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 17bb078..79ba1bb 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -23,6 +23,9 @@
#include <linux/fwnode.h>
#include <linux/irqdomain.h>
+#define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL)
+#define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL)
+
int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
void iort_deregister_domain_token(int trans_id);
struct fwnode_handle *iort_find_domain_token(int trans_id);
--
2.10.0
^ permalink raw reply related
* [PATCH v6 14/16] drivers: acpi: iort: replace rid map type with type mask
From: Lorenzo Pieralisi @ 2016-10-18 16:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
IORT tables provide data that allow the kernel to carry out
device ID mappings between endpoints and system components
(eg interrupt controllers, IOMMUs). When the mapping for a
given device ID is carried out, the translation mechanism
is done on a per-subsystem basis rather than a component
subtype (ie the IOMMU kernel layer will look for mappings
from a device to all IORT node types corresponding to IOMMU
components), therefore the corresponding mapping API should
work on a range (ie mask) of IORT node types corresponding
to a common set of components (eg IOMMUs) rather than a
specific node type.
Upgrade the IORT iort_node_map_rid() API to work with a
type mask instead of a single node type so that it can
be used for mappings that span multiple components types
(ie IOMMUs).
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 04cc5f7..f205d41 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -26,6 +26,9 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#define IORT_TYPE_MASK(type) (1 << (type))
+#define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP)
+
struct iort_its_msi_chip {
struct list_head list;
struct fwnode_handle *fw_node;
@@ -317,7 +320,7 @@ static int iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in,
static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
u32 rid_in, u32 *rid_out,
- u8 type)
+ u8 type_mask)
{
u32 rid = rid_in;
@@ -326,7 +329,7 @@ static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
struct acpi_iort_id_mapping *map;
int i;
- if (node->type == type) {
+ if (IORT_TYPE_MASK(node->type) & type_mask) {
if (rid_out)
*rid_out = rid;
return node;
@@ -399,7 +402,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
if (!node)
return req_id;
- iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+ iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
return dev_id;
}
@@ -421,7 +424,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 req_id,
if (!node)
return -ENXIO;
- node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP);
+ node = iort_node_map_rid(node, req_id, NULL, IORT_MSI_TYPE);
if (!node)
return -ENXIO;
--
2.10.0
^ permalink raw reply related
* [PATCH v6 15/16] drivers: acpi: iort: add single mapping function
From: Lorenzo Pieralisi @ 2016-10-18 16:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
The current IORT id mapping API requires components to provide
an input requester ID (a Bus-Device-Function (BDF) identifier for
PCI devices) to translate an input identifier to an output
identifier through an IORT range mapping.
Named components do not have an identifiable source ID therefore
their respective input/output mapping can only be defined in
IORT tables through single mappings, that provide a translation
that does not require any input identifier.
Current IORT interface for requester id mappings (iort_node_map_rid())
is not suitable for components that do not provide a requester id,
so it cannot be used for IORT named components.
Add an interface to the IORT API to enable retrieval of id
by allowing an indexed walk of the single mappings array for
a given component, therefore completing the IORT mapping API.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index f205d41..db7b153 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -318,6 +318,45 @@ static int iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in,
return 0;
}
+static
+struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
+ u32 *id_out, u8 type_mask,
+ int index)
+{
+ struct acpi_iort_node *parent;
+ struct acpi_iort_id_mapping *map;
+
+ if (!node->mapping_offset || !node->mapping_count ||
+ index >= node->mapping_count)
+ return NULL;
+
+ map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+ node->mapping_offset);
+
+ /* Firmware bug! */
+ if (!map->output_reference) {
+ pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
+ node, node->type);
+ return NULL;
+ }
+
+ parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+ map->output_reference);
+
+ if (!(IORT_TYPE_MASK(parent->type) & type_mask))
+ return NULL;
+
+ if (map[index].flags & ACPI_IORT_ID_SINGLE_MAPPING) {
+ if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+ node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
+ *id_out = map[index].output_base;
+ return parent;
+ }
+ }
+
+ return NULL;
+}
+
static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
u32 rid_in, u32 *rid_out,
u8 type_mask)
--
2.10.0
^ permalink raw reply related
* [PATCH v6 16/16] drivers: acpi: iort: introduce iort_iommu_configure
From: Lorenzo Pieralisi @ 2016-10-18 16:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
DT based systems have a generic kernel API to configure IOMMUs
for devices (ie of_iommu_configure()).
On ARM based ACPI systems, the of_iommu_configure() equivalent can
be implemented atop ACPI IORT kernel API, with the corresponding
functions to map device identifiers to IOMMUs and retrieve the
corresponding IOMMU operations necessary for DMA operations set-up.
By relying on the iommu_fwspec generic kernel infrastructure,
implement the IORT based IOMMU configuration for ARM ACPI systems
and hook it up in the ACPI kernel layer that implements DMA
configuration for a device.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 7 +++-
include/linux/acpi_iort.h | 6 +++
3 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index db7b153..5741bfd 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -28,6 +28,8 @@
#define IORT_TYPE_MASK(type) (1 << (type))
#define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP)
+#define IORT_IOMMU_TYPE ((1 << ACPI_IORT_NODE_SMMU) | \
+ (1 << ACPI_IORT_NODE_SMMU_V3))
struct iort_its_msi_chip {
struct list_head list;
@@ -501,6 +503,103 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
}
+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
+{
+ u32 *rid = data;
+
+ *rid = alias;
+ return 0;
+}
+
+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
+ struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+ int ret = iommu_fwspec_init(dev, fwnode, ops);
+
+ if (!ret)
+ ret = iommu_fwspec_add_ids(dev, &streamid, 1);
+
+ return ret;
+}
+
+static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
+ struct acpi_iort_node *node,
+ u32 streamid)
+{
+ struct fwnode_handle *iort_fwnode = NULL;
+ const struct iommu_ops *ops = NULL;
+ int ret = -ENODEV;
+
+ if (node) {
+ iort_fwnode = iort_get_fwnode(node);
+ if (!iort_fwnode)
+ return NULL;
+
+ ops = fwnode_iommu_get_ops(iort_fwnode);
+ if (!ops)
+ return NULL;
+
+ ret = arm_smmu_iort_xlate(dev, streamid,
+ iort_fwnode, ops);
+ }
+
+ return ret ? NULL : ops;
+}
+
+/**
+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ *
+ * @dev: device to configure
+ *
+ * Returns: iommu_ops pointer on configuration success
+ * NULL on configuration failure
+ */
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{
+ struct acpi_iort_node *node, *parent;
+ const struct iommu_ops *ops = NULL;
+ u32 streamid = 0;
+
+ if (dev_is_pci(dev)) {
+ struct pci_bus *bus = to_pci_dev(dev)->bus;
+ u32 rid;
+
+ pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
+ &rid);
+
+ node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+ iort_match_node_callback, &bus->dev);
+ if (!node)
+ return NULL;
+
+ parent = iort_node_map_rid(node, rid, &streamid,
+ IORT_IOMMU_TYPE);
+
+ ops = iort_iommu_xlate(dev, parent, streamid);
+
+ } else {
+ int i = 0;
+
+ node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+ iort_match_node_callback, dev);
+ if (!node)
+ return NULL;
+
+ parent = iort_node_get_id(node, &streamid,
+ IORT_IOMMU_TYPE, i++);
+
+ while (parent) {
+ ops = iort_iommu_xlate(dev, parent, streamid);
+
+ parent = iort_node_get_id(node, &streamid,
+ IORT_IOMMU_TYPE, i++);
+ }
+ }
+
+ return ops;
+}
+
static void __init acpi_iort_register_irq(int hwirq, const char *name,
int trigger,
struct resource *res)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 694e0b6..e5f7004 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
#include <linux/signal.h>
#include <linux/kthread.h>
#include <linux/dmi.h>
@@ -1377,6 +1378,8 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
*/
void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
{
+ const struct iommu_ops *iommu;
+
/*
* Set default coherent_dma_mask to 32 bit. Drivers are expected to
* setup the correct supported mask.
@@ -1391,11 +1394,13 @@ void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
if (!dev->dma_mask)
dev->dma_mask = &dev->coherent_dma_mask;
+ iommu = iort_iommu_configure(dev);
+
/*
* Assume dma valid range starts at 0 and covers the whole
* coherent_dma_mask.
*/
- arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+ arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
attr == DEV_DMA_COHERENT);
}
EXPORT_SYMBOL_GPL(acpi_dma_configure);
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 79ba1bb..dcb2b60 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -34,6 +34,8 @@ void acpi_iort_init(void);
bool iort_node_match(u8 type);
u32 iort_msi_map_rid(struct device *dev, u32 req_id);
struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+/* IOMMU interface */
+const struct iommu_ops *iort_iommu_configure(struct device *dev);
#else
static inline void acpi_iort_init(void) { }
static inline bool iort_node_match(u8 type) { return false; }
@@ -42,6 +44,10 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
static inline struct irq_domain *iort_get_device_domain(struct device *dev,
u32 req_id)
{ return NULL; }
+/* IOMMU interface */
+static inline
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{ return NULL; }
#endif
#define IORT_ACPI_DECLARE(name, table_id, fn) \
--
2.10.0
^ permalink raw reply related
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Peter Griffin @ 2016-10-18 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c8a1898e-e60f-b25a-f4d2-7384f04b6f3f@siemens.com>
Hi Jan,
On Tue, 18 Oct 2016, Jan Kiszka wrote:
> On 2016-10-18 17:07, Peter Griffin wrote:
> > lx-fdtdump dumps the flatenned device tree passed to the kernel
> > from the bootloader to a file called fdtdump.dtb to allow further
> > post processing on the machine running GDB. The fdt header is also
> > also printed in the GDB console. For example:
> >
> > (gdb) lx-fdtdump
> > fdt_magic: 0xD00DFEED
> > fdt_totalsize: 0xC108
> > off_dt_struct: 0x38
> > off_dt_strings: 0x3804
> > off_mem_rsvmap: 0x28
> > version: 17
> > last_comp_version: 16
> > Dumped fdt to fdtdump.dtb
> >
> >> fdtdump fdtdump.dtb | less
> >
> > This command is useful as the bootloader can often re-write parts
> > of the device tree, and this can sometimes cause the kernel to not
> > boot.
> >
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> > scripts/gdb/linux/constants.py.in | 8 +++++
> > scripts/gdb/linux/proc.py | 70 ++++++++++++++++++++++++++++++++++++++-
> > 2 files changed, 77 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
> > index 7986f4e..43c6241 100644
> > --- a/scripts/gdb/linux/constants.py.in
> > +++ b/scripts/gdb/linux/constants.py.in
> > @@ -14,6 +14,7 @@
> >
> > #include <linux/fs.h>
> > #include <linux/mount.h>
> > +#include <linux/of_fdt.h>
> >
> > /* We need to stringify expanded macros so that they can be parsed */
> >
> > @@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
> > LX_VALUE(MNT_NOATIME)
> > LX_VALUE(MNT_NODIRATIME)
> > LX_VALUE(MNT_RELATIME)
> > +
> > +/* linux/of_fdt.h> */
> > +LX_VALUE(OF_DT_HEADER)
> > +
> > +/* Kernel Configs */
> > +LX_CONFIG(CONFIG_OF)
> > +
> > diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
> > index 38b1f09..f20fcfa 100644
> > --- a/scripts/gdb/linux/proc.py
> > +++ b/scripts/gdb/linux/proc.py
> > @@ -16,7 +16,7 @@ from linux import constants
> > from linux import utils
> > from linux import tasks
> > from linux import lists
> > -
> > +from struct import *
> >
> > class LxCmdLine(gdb.Command):
> > """ Report the Linux Commandline used in the current kernel.
> > @@ -195,3 +195,71 @@ values of that process namespace"""
> > info_opts(MNT_INFO, m_flags)))
> >
> > LxMounts()
> > +
> > +class LxFdtDump(gdb.Command):
> > + """Output Flattened Device Tree header and dump FDT blob to a file
> > + Equivalent to 'cat /proc/fdt > fdtdump.dtb' on a running target"""
> > +
> > + def __init__(self):
> > + super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA)
> > +
> > + def fdthdr_to_cpu(self, fdt_header):
> > +
> > + fdt_header_be = ">IIIIIII"
> > + fdt_header_le = "<IIIIIII"
> > +
> > + if utils.get_target_endianness() == 1:
> > + output_fmt = fdt_header_le
> > + else:
> > + output_fmt = fdt_header_be
> > +
> > + return unpack(output_fmt, pack(fdt_header_be,
> > + fdt_header['magic'],
> > + fdt_header['totalsize'],
> > + fdt_header['off_dt_struct'],
> > + fdt_header['off_dt_strings'],
> > + fdt_header['off_mem_rsvmap'],
> > + fdt_header['version'],
> > + fdt_header['last_comp_version']))
> > +
> > + def invoke(self, arg, from_tty):
> > +
> > + if constants.LX_CONFIG_OF:
> > +
> > + filename = "fdtdump.dtb"
>
> Why not specifying the file name as argument? Safer than silently
> overwriting potentially pre-existing files or failing without
> alternatives if the current directory is not writable.
Good idea, I will update to have the filename as the command argument in v2.
regards,
Peter
^ permalink raw reply
* [PATCH] crypto: sun4i-ss: support the Security System PRNG
From: PrasannaKumar Muralidharan @ 2016-10-18 16:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476794067-28563-1-git-send-email-clabbe.montjoie@gmail.com>
Hi Corentin,
I have a few minor comments.
On 18 October 2016 at 18:04, Corentin Labbe <clabbe.montjoie@gmail.com> wrote:
> From: LABBE Corentin <clabbe.montjoie@gmail.com>
>
> The Security System have a PRNG.
> This patch add support for it as an hwrng.
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> ---
> drivers/crypto/Kconfig | 8 ++++
> drivers/crypto/sunxi-ss/Makefile | 1 +
> drivers/crypto/sunxi-ss/sun4i-ss-core.c | 14 +++++++
> drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c | 70 ++++++++++++++++++++++++++++++++
> drivers/crypto/sunxi-ss/sun4i-ss.h | 8 ++++
> 5 files changed, 101 insertions(+)
> create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c
>
> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
> index 4d2b81f..38f7aca 100644
> --- a/drivers/crypto/Kconfig
> +++ b/drivers/crypto/Kconfig
> @@ -538,6 +538,14 @@ config CRYPTO_DEV_SUN4I_SS
> To compile this driver as a module, choose M here: the module
> will be called sun4i-ss.
>
> +config CRYPTO_DEV_SUN4I_SS_PRNG
> + bool "Support for Allwinner Security System PRNG"
> + depends on CRYPTO_DEV_SUN4I_SS
> + select HW_RANDOM
> + help
> + This driver provides kernel-side support for the Pseudo-Random
> + Number Generator found in the Security System.
> +
> config CRYPTO_DEV_ROCKCHIP
> tristate "Rockchip's Cryptographic Engine driver"
> depends on OF && ARCH_ROCKCHIP
> diff --git a/drivers/crypto/sunxi-ss/Makefile b/drivers/crypto/sunxi-ss/Makefile
> index 8f4c7a2..ca049ee 100644
> --- a/drivers/crypto/sunxi-ss/Makefile
> +++ b/drivers/crypto/sunxi-ss/Makefile
> @@ -1,2 +1,3 @@
> obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o
> sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o
> +sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-hwrng.o
> diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
> index 3ac6c6c..fa739de 100644
> --- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
> +++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
> @@ -359,6 +359,16 @@ static int sun4i_ss_probe(struct platform_device *pdev)
> }
> }
> platform_set_drvdata(pdev, ss);
> +
> +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
> + /* Voluntarily made the PRNG optional */
> + err = sun4i_ss_hwrng_register(&ss->hwrng);
> + if (!err)
> + dev_info(ss->dev, "sun4i-ss PRNG loaded");
> + else
> + dev_err(ss->dev, "sun4i-ss PRNG failed");
> +#endif
> +
> return 0;
> error_alg:
> i--;
> @@ -386,6 +396,10 @@ static int sun4i_ss_remove(struct platform_device *pdev)
> int i;
> struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
>
> +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
> + sun4i_ss_hwrng_remove(&ss->hwrng);
> +#endif
> +
> for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
> switch (ss_algs[i].type) {
> case CRYPTO_ALG_TYPE_ABLKCIPHER:
> diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c
> new file mode 100644
> index 0000000..95fadb7
> --- /dev/null
> +++ b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c
> @@ -0,0 +1,70 @@
> +#include "sun4i-ss.h"
> +
> +static int sun4i_ss_hwrng_init(struct hwrng *hwrng)
> +{
> + struct sun4i_ss_ctx *ss;
> +
> + ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng);
> + get_random_bytes(ss->seed, SS_SEED_LEN);
> +
> + return 0;
> +}
> +
> +static int sun4i_ss_hwrng_read(struct hwrng *hwrng, void *buf,
> + size_t max, bool wait)
> +{
> + int i;
> + u32 v;
> + u32 *data = buf;
> + const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED;
> + size_t len;
> + struct sun4i_ss_ctx *ss;
> +
> + ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng);
> + len = min_t(size_t, SS_DATA_LEN, max);
> +
> + spin_lock_bh(&ss->slock);
Is spin_lock_bh really required here? I could see it is being used in
sun4i-ss-hash.c but could not find any comment/info about the need.
> + writel(mode, ss->base + SS_CTL);
> +
> + /* write the seed */
> + for (i = 0; i < SS_SEED_LEN / 4; i++)
> + writel(ss->seed[i], ss->base + SS_KEY0 + i * 4);
> + writel(mode | SS_PRNG_START, ss->base + SS_CTL);
> +
> + /* Read the random data */
> + readsl(ss->base + SS_TXFIFO, data, len / 4);
> +
> + if (len % 4 > 0) {
> + v = readl(ss->base + SS_TXFIFO);
> + memcpy(data + len / 4, &v, len % 4);
> + }
hwrng core asks for "rng_buffer_size()" of data which is a multiple of
4. So len % 4 will be 0. I think the above check is not required. Feel
free to correct if I am wrong.
> + /* Update the seed */
> + for (i = 0; i < SS_SEED_LEN / 4; i++) {
> + v = readl(ss->base + SS_KEY0 + i * 4);
> + ss->seed[i] = v;
> + }
> +
> + writel(0, ss->base + SS_CTL);
> + spin_unlock_bh(&ss->slock);
> + return len;
> +}
> +
> +int sun4i_ss_hwrng_register(struct hwrng *hwrng)
> +{
> + hwrng->name = "sun4i Security System PRNG";
> + hwrng->init = sun4i_ss_hwrng_init;
> + hwrng->read = sun4i_ss_hwrng_read;
> + hwrng->quality = 1000;
> +
> + /* Cannot use devm_hwrng_register() since we need to hwrng_unregister
> + * before stopping clocks/regulator
> + */
> + return hwrng_register(hwrng);
> +}
> +
> +void sun4i_ss_hwrng_remove(struct hwrng *hwrng)
> +{
> + hwrng_unregister(hwrng);
> +}
> diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h
> index f04c0f8..1297510 100644
> --- a/drivers/crypto/sunxi-ss/sun4i-ss.h
> +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h
> @@ -23,6 +23,7 @@
> #include <linux/scatterlist.h>
> #include <linux/interrupt.h>
> #include <linux/delay.h>
> +#include <linux/hw_random.h>
> #include <crypto/md5.h>
> #include <crypto/sha.h>
> #include <crypto/hash.h>
> @@ -125,6 +126,9 @@
> #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2)
> #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0)
>
> +#define SS_SEED_LEN (192 / 8)
> +#define SS_DATA_LEN (160 / 8)
> +
> struct sun4i_ss_ctx {
> void __iomem *base;
> int irq;
> @@ -134,6 +138,8 @@ struct sun4i_ss_ctx {
> struct device *dev;
> struct resource *res;
> spinlock_t slock; /* control the use of the device */
> + struct hwrng hwrng;
> + u32 seed[SS_SEED_LEN / 4];
> };
>
> struct sun4i_ss_alg_template {
> @@ -199,3 +205,5 @@ int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
> unsigned int keylen);
> int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
> unsigned int keylen);
> +int sun4i_ss_hwrng_register(struct hwrng *hwrng);
> +void sun4i_ss_hwrng_remove(struct hwrng *hwrng);
> --
> 2.7.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Jan Kiszka @ 2016-10-18 16:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160638.GA24851@griffinp-ThinkPad-X1-Carbon-2nd>
On 2016-10-18 18:06, Peter Griffin wrote:
> Hi Jan,
>
> On Tue, 18 Oct 2016, Jan Kiszka wrote:
>
>> On 2016-10-18 17:07, Peter Griffin wrote:
>>> lx-fdtdump dumps the flatenned device tree passed to the kernel
>>> from the bootloader to a file called fdtdump.dtb to allow further
>>> post processing on the machine running GDB. The fdt header is also
>>> also printed in the GDB console. For example:
>>>
>>> (gdb) lx-fdtdump
>>> fdt_magic: 0xD00DFEED
>>> fdt_totalsize: 0xC108
>>> off_dt_struct: 0x38
>>> off_dt_strings: 0x3804
>>> off_mem_rsvmap: 0x28
>>> version: 17
>>> last_comp_version: 16
>>> Dumped fdt to fdtdump.dtb
>>>
>>>> fdtdump fdtdump.dtb | less
>>>
>>> This command is useful as the bootloader can often re-write parts
>>> of the device tree, and this can sometimes cause the kernel to not
>>> boot.
>>>
>>> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
>>> ---
>>> scripts/gdb/linux/constants.py.in | 8 +++++
>>> scripts/gdb/linux/proc.py | 70 ++++++++++++++++++++++++++++++++++++++-
>>> 2 files changed, 77 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
>>> index 7986f4e..43c6241 100644
>>> --- a/scripts/gdb/linux/constants.py.in
>>> +++ b/scripts/gdb/linux/constants.py.in
>>> @@ -14,6 +14,7 @@
>>>
>>> #include <linux/fs.h>
>>> #include <linux/mount.h>
>>> +#include <linux/of_fdt.h>
>>>
>>> /* We need to stringify expanded macros so that they can be parsed */
>>>
>>> @@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
>>> LX_VALUE(MNT_NOATIME)
>>> LX_VALUE(MNT_NODIRATIME)
>>> LX_VALUE(MNT_RELATIME)
>>> +
>>> +/* linux/of_fdt.h> */
>>> +LX_VALUE(OF_DT_HEADER)
>>> +
>>> +/* Kernel Configs */
>>> +LX_CONFIG(CONFIG_OF)
>>> +
>>> diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
>>> index 38b1f09..f20fcfa 100644
>>> --- a/scripts/gdb/linux/proc.py
>>> +++ b/scripts/gdb/linux/proc.py
>>> @@ -16,7 +16,7 @@ from linux import constants
>>> from linux import utils
>>> from linux import tasks
>>> from linux import lists
>>> -
>>> +from struct import *
>>>
>>> class LxCmdLine(gdb.Command):
>>> """ Report the Linux Commandline used in the current kernel.
>>> @@ -195,3 +195,71 @@ values of that process namespace"""
>>> info_opts(MNT_INFO, m_flags)))
>>>
>>> LxMounts()
>>> +
>>> +class LxFdtDump(gdb.Command):
>>> + """Output Flattened Device Tree header and dump FDT blob to a file
>>> + Equivalent to 'cat /proc/fdt > fdtdump.dtb' on a running target"""
>>> +
>>> + def __init__(self):
>>> + super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA)
>>> +
>>> + def fdthdr_to_cpu(self, fdt_header):
>>> +
>>> + fdt_header_be = ">IIIIIII"
>>> + fdt_header_le = "<IIIIIII"
>>> +
>>> + if utils.get_target_endianness() == 1:
>>> + output_fmt = fdt_header_le
>>> + else:
>>> + output_fmt = fdt_header_be
>>> +
>>> + return unpack(output_fmt, pack(fdt_header_be,
>>> + fdt_header['magic'],
>>> + fdt_header['totalsize'],
>>> + fdt_header['off_dt_struct'],
>>> + fdt_header['off_dt_strings'],
>>> + fdt_header['off_mem_rsvmap'],
>>> + fdt_header['version'],
>>> + fdt_header['last_comp_version']))
>>> +
>>> + def invoke(self, arg, from_tty):
>>> +
>>> + if constants.LX_CONFIG_OF:
>>> +
>>> + filename = "fdtdump.dtb"
>>
>> Why not specifying the file name as argument? Safer than silently
>> overwriting potentially pre-existing files or failing without
>> alternatives if the current directory is not writable.
>
> Good idea, I will update to have the filename as the command argument in v2.
>
Also check gdb.COMPLETE_FILENAME [1] at that chance. :)
Jan
[1]
https://sourceware.org/gdb/onlinedocs/gdb/Commands-In-Python.html#Commands-In-Python
--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
^ permalink raw reply
* [PATCH V2 3/4] ACPI,PCI,IRQ: separate ISA penalty calculation
From: Sinan Kaya @ 2016-10-18 16:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018104649.GA13940@localhost>
On 10/18/2016 3:46 AM, Bjorn Helgaas wrote:
> Hi Sinan,
>
> On Wed, Jun 29, 2016 at 04:27:37AM -0400, Sinan Kaya wrote:
>> Since commit 103544d86976 ("ACPI,PCI,IRQ: reduce resource requirements")
>> the penalty values are calculated on the fly rather than boot time.
>>
>> This works fine for PCI interrupts but not so well for the ISA interrupts.
>> Whether an ISA interrupt is in use or not information is not available
>> inside the pci_link.c file. This information gets sent externally via
>> acpi_penalize_isa_irq function. If active is true, then the IRQ is in use
>> by ISA. Otherwise, IRQ is in use by PCI.
>>
>> Since the current code relies on PCI Link object for determination of
>> penalties, we are factoring in the PCI penalty twice after
>> acpi_penalize_isa_irq function is called.
>
> I know this patch has already been merged, but I'm confused.
>
> Can you be a little more specific about how we factor in the PCI
> penalty twice? I think that when we enumerate an enabled link device,
> we call acpi_penalize_isa_irq(x) in this path:
>
> pnpacpi_allocated_resource
> pnpacpi_add_irqresource
> pcibios_penalize_isa_irq
> acpi_penalize_isa_irq
> acpi_isa_irq_penalty[x] = PIRQ_PENALTY_ISA_USED
>
This is not really a problem but more information about how things work.
I was trying to point out the fact that acpi_penalize_isa_irq is changing
the penalties externally while ISA IRQs get initialized based on the active
parameter.
The penalty determination of ISA IRQ goes through 2 paths.
1. assign PCI_USING during power up via acpi_irq_penalty_init
2. update the penalty with acpi_irq_pci_sharing_penalty function based on active
parameter.
> And I see that acpi_irq_penalty_init() also adds in some penalty
> (either "PIRQ_PENALTY_PCI_POSSIBLE / possible_count" or
> PIRQ_PENALTY_PCI_POSSIBLE). And when we call acpi_irq_get_penalty(x),
> we add in PIRQ_PENALTY_PCI_USING.
>
> It doesn't seem right to me that we're adding both
> PIRQ_PENALTY_ISA_USED and PIRQ_PENALTY_PCI_USING. Is that the problem
> you're referring to?
Correct, this is the one. What happened in this case is that
acpi_irq_penalty_init added a PCI_USING penalty during boot. Then, when we
wanted to get the penalty for an ISA IRQ. This added another PCI_USING penalty
in acpi_irq_pci_sharing_penalty function in addition to originally added penalty.
Now, we have 2 * PCI_USING assigned to an ISA IRQ.
>
>> This change is limiting the newly added functionality to just PCI
>> interrupts so that old behavior is still maintained.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> ---
>> drivers/acpi/pci_link.c | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
>> index 714ba4d..8c08971 100644
>> --- a/drivers/acpi/pci_link.c
>> +++ b/drivers/acpi/pci_link.c
>> @@ -496,9 +496,6 @@ static int acpi_irq_get_penalty(int irq)
>> {
>> int penalty = 0;
>>
>> - if (irq < ACPI_MAX_ISA_IRQS)
>> - penalty += acpi_isa_irq_penalty[irq];
>> -
>> /*
>> * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
>> * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
>> @@ -513,6 +510,9 @@ static int acpi_irq_get_penalty(int irq)
>> penalty += PIRQ_PENALTY_PCI_USING;
>> }
>>
>> + if (irq < ACPI_MAX_ISA_IRQS)
>> + return penalty + acpi_isa_irq_penalty[irq];
>> +
>> penalty += acpi_irq_pci_sharing_penalty(irq);
>> return penalty;
>
> I don't understand what's going on here.
>
> acpi_irq_pci_sharing_penalty(X) basically tells us how many link
> devices are already using IRQ X. This change makes it so we don't
> consider that information if X < ACPI_MAX_ISA_IRQS.
>
The ISA IRQ doesn't need the penalties coming from
acpi_irq_pci_sharing_penalty function since acpi_irq_pci_sharing_penalty
is intended do the same thing as acpi_irq_penalty_init. It is just smarter
to cover more IRQ range.
Since acpi_irq_penalty_init is called during boot for the ISA IRQS, calling
acpi_irq_pci_sharing_penalty again is incorrect.
> Let's say we have several link devices that are initially disabled,
> e.g.,
>
> LNKA (IRQs 9 10 11)
> LNKB (IRQs 9 10 11)
> LNKC (IRQs 9 10 11)
>
> When we enable these, I think we'll choose the same IRQ for all of
> them because we no longer look at the other links to see how they're
> configured.
You are right. This is the reason why I have this patch.
[PATCH V3 1/3] ACPI, PCI IRQ: add PCI_USING penalty for ISA interrupts
The penalties get assigned by the acpi_irq_penalty_init and acpi_penalize_isa_irq
functions before the PCI Link object is created until this moment.
By the time link object is getting initialized, the code chooses the correct penalty here:
/
* Select the best IRQ. This is done in reverse to promote
* the use of IRQs 9, 10, 11, and >15.
*/
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
if (acpi_irq_get_penalty(irq) >
acpi_irq_get_penalty(link->irq.possible[i]))
irq = link->irq.possible[i];
}
and the code needs to increment the penalty on this IRQ so that the next PCI Link object
would find another IRQ. This is missing right now.
>
>> }
>> --
>> 1.8.2.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [BUG] LPC32xx gpio driver broken by commit 762c2e46 in 4.9-rc1
From: Sylvain Lemieux @ 2016-10-18 16:23 UTC (permalink / raw)
To: linux-arm-kernel
Vladimir, Linus, Alexandre,
the current LPC32xx GPIO driver is broken by commit 762c2e46
(gpio: of: remove of_gpiochip_and_xlate() and struct gg_data).
A call to "of_get_named_gpio" to retrieve the GPIO will
always return -EINVAL, except for the first GPIO bank.
Prior to this commit, the driver was working properly
because of the side-effect of the match function called by
"gpiochip_find" inside "of_get_named_gpiod_flags" function.
I think, the proper long-term solution is to replace the
LPC32xx GPIO driver; an initial version was previously
submitted, by Vladimir Zapolskiy, to the mailing list:
http://www.spinics.net/lists/linux-gpio/msg09746.html
Is there any short-term solution that can be done with
the existing driver to keep the LPC32xx platform working
properly in the 4.9 mainline kernel?
Regards,
Sylvain Lemieux
^ permalink raw reply
* [PATCH v20 03/10] add bindings document for altera freeze bridge
From: Rob Herring @ 2016-10-18 16:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017160941.4205-4-atull@opensource.altera.com>
On Mon, Oct 17, 2016 at 11:09:34AM -0500, Alan Tull wrote:
> Add bindings document for the Altera Freeze Bridge. A Freeze
> Bridge is used to gate traffic to/from a region of a FPGA
> such that that region can be reprogrammed. The Freeze Bridge
> exist in FPGA fabric that is not currently being reconfigured.
>
> Signed-off-by: Alan Tull <atull@opensource.altera.com>
> Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
> ---
> v19: Added in v19 of patchset, uses fpga image info struct
> v20: fix one underscore to hyphen
> ---
> .../bindings/fpga/altera-freeze-bridge.txt | 23 ++++++++++++++++++++++
> 1 file changed, 23 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH V7 2/3] stm class: ftrace: Add ftrace-export-over-stm driver
From: Steven Rostedt @ 2016-10-18 16:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476778140-10319-3-git-send-email-zhang.chunyan@linaro.org>
On Tue, 18 Oct 2016 16:08:59 +0800
Chunyan Zhang <zhang.chunyan@linaro.org> wrote:
> This patch adds a driver that models itself as an stm_source called
> stm_ftrace. Once the stm device and stm_ftrace have been linked via
> sysfs, the driver registers itself as a trace_export and everything
> passed to the interface from Ftrace subsystem will end up in the STM
> trace engine.
>
> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>
> ---
> drivers/hwtracing/stm/Kconfig | 11 ++++++
> drivers/hwtracing/stm/Makefile | 2 +
> drivers/hwtracing/stm/ftrace.c | 88 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 101 insertions(+)
> create mode 100644 drivers/hwtracing/stm/ftrace.c
>
> diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
> index 847a39b..b34ea96 100644
> --- a/drivers/hwtracing/stm/Kconfig
> +++ b/drivers/hwtracing/stm/Kconfig
> @@ -39,4 +39,15 @@ config STM_SOURCE_HEARTBEAT
> If you want to send heartbeat messages over STM devices,
> say Y.
>
> +config STM_SOURCE_FTRACE
> + tristate "Copy the output from kernel Ftrace to STM engine"
> + depends on TRACING
I think it should depend on FUNCTION_TRACER
> + help
> + This option can be used to copy the output from kernel Ftrace
> + to STM engine. Enabling this option will introduce a slight
> + timing effect.
> +
> + If you want to send kernel Ftrace messages over STM devices,
> + say Y.
> +
> endif
> diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
> index a9ce3d4..3abd84c 100644
> --- a/drivers/hwtracing/stm/Makefile
> +++ b/drivers/hwtracing/stm/Makefile
> @@ -6,6 +6,8 @@ obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
>
> obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o
> obj-$(CONFIG_STM_SOURCE_HEARTBEAT) += stm_heartbeat.o
> +obj-$(CONFIG_STM_SOURCE_FTRACE) += stm_ftrace.o
>
> stm_console-y := console.o
> stm_heartbeat-y := heartbeat.o
> +stm_ftrace-y := ftrace.o
> diff --git a/drivers/hwtracing/stm/ftrace.c b/drivers/hwtracing/stm/ftrace.c
> new file mode 100644
> index 0000000..1a114c8f
> --- /dev/null
> +++ b/drivers/hwtracing/stm/ftrace.c
> @@ -0,0 +1,88 @@
> +/*
> + * Simple kernel driver to link kernel Ftrace and an STM device
> + * Copyright (c) 2016, Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * STM Ftrace will be registered as a trace_export.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/stm.h>
> +#include <linux/trace.h>
> +
> +#define STM_FTRACE_NR_CHANNELS 1
> +#define STM_FTRACE_CHAN 0
> +
> +static int stm_ftrace_link(struct stm_source_data *data);
> +static void stm_ftrace_unlink(struct stm_source_data *data);
> +
> +static struct stm_ftrace {
> + struct stm_source_data data;
> + struct trace_export ftrace;
> +} stm_ftrace = {
> + .data = {
> + .name = "ftrace",
> + .nr_chans = STM_FTRACE_NR_CHANNELS,
> + .link = stm_ftrace_link,
> + .unlink = stm_ftrace_unlink,
> + },
> +};
> +
> +/**
> + * stm_ftrace_write() - write data to STM via 'stm_ftrace' source
> + * @buf: buffer containing the data packet
> + * @len: length of the data packet
> + */
> +static void notrace
> +stm_ftrace_write(const char *buf, unsigned int len)
> +{
> + stm_source_write(&stm_ftrace.data, STM_FTRACE_CHAN, buf, len);
> +}
> +
> +static int stm_ftrace_link(struct stm_source_data *data)
> +{
> + struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
> +
> + sf->ftrace.write = stm_ftrace_write;
> + sf->ftrace.next = NULL;
Why setting this to NULL? register_ftrace_export() should not require
nor depend on that.
-- Steve
> +
> + return register_ftrace_export(&sf->ftrace);
> +}
> +
> +static void stm_ftrace_unlink(struct stm_source_data *data)
> +{
> + struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
> +
> + unregister_ftrace_export(&sf->ftrace);
> +}
> +
> +static int __init stm_ftrace_init(void)
> +{
> + int ret;
> +
> + ret = stm_source_register_device(NULL, &stm_ftrace.data);
> + if (ret)
> + pr_err("Failed to register stm_source - ftrace.\n");
> +
> + return ret;
> +}
> +
> +static void __exit stm_ftrace_exit(void)
> +{
> + stm_source_unregister_device(&stm_ftrace.data);
> +}
> +
> +module_init(stm_ftrace_init);
> +module_exit(stm_ftrace_exit);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("stm_ftrace driver");
> +MODULE_AUTHOR("Chunyan Zhang <zhang.chunyan@linaro.org>");
^ permalink raw reply
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Peter Griffin @ 2016-10-18 16:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0143426e-7e92-aaff-7641-519e1f63e075@siemens.com>
Hi Jan,
On Tue, 18 Oct 2016, Jan Kiszka wrote:
> On 2016-10-18 18:06, Peter Griffin wrote:
> > Hi Jan,
> >
> > On Tue, 18 Oct 2016, Jan Kiszka wrote:
> >
> >> On 2016-10-18 17:07, Peter Griffin wrote:
> >>> lx-fdtdump dumps the flatenned device tree passed to the kernel
> >>> from the bootloader to a file called fdtdump.dtb to allow further
> >>> post processing on the machine running GDB. The fdt header is also
> >>> also printed in the GDB console. For example:
> >>>
> >>> (gdb) lx-fdtdump
> >>> fdt_magic: 0xD00DFEED
> >>> fdt_totalsize: 0xC108
> >>> off_dt_struct: 0x38
> >>> off_dt_strings: 0x3804
> >>> off_mem_rsvmap: 0x28
> >>> version: 17
> >>> last_comp_version: 16
> >>> Dumped fdt to fdtdump.dtb
> >>>
> >>>> fdtdump fdtdump.dtb | less
> >>>
> >>> This command is useful as the bootloader can often re-write parts
> >>> of the device tree, and this can sometimes cause the kernel to not
> >>> boot.
> >>>
> >>> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> >>> ---
> >>> scripts/gdb/linux/constants.py.in | 8 +++++
> >>> scripts/gdb/linux/proc.py | 70 ++++++++++++++++++++++++++++++++++++++-
> >>> 2 files changed, 77 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
> >>> index 7986f4e..43c6241 100644
> >>> --- a/scripts/gdb/linux/constants.py.in
> >>> +++ b/scripts/gdb/linux/constants.py.in
> >>> @@ -14,6 +14,7 @@
> >>>
> >>> #include <linux/fs.h>
> >>> #include <linux/mount.h>
> >>> +#include <linux/of_fdt.h>
> >>>
> >>> /* We need to stringify expanded macros so that they can be parsed */
> >>>
> >>> @@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
> >>> LX_VALUE(MNT_NOATIME)
> >>> LX_VALUE(MNT_NODIRATIME)
> >>> LX_VALUE(MNT_RELATIME)
> >>> +
> >>> +/* linux/of_fdt.h> */
> >>> +LX_VALUE(OF_DT_HEADER)
> >>> +
> >>> +/* Kernel Configs */
> >>> +LX_CONFIG(CONFIG_OF)
> >>> +
> >>> diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
> >>> index 38b1f09..f20fcfa 100644
> >>> --- a/scripts/gdb/linux/proc.py
> >>> +++ b/scripts/gdb/linux/proc.py
> >>> @@ -16,7 +16,7 @@ from linux import constants
> >>> from linux import utils
> >>> from linux import tasks
> >>> from linux import lists
> >>> -
> >>> +from struct import *
> >>>
> >>> class LxCmdLine(gdb.Command):
> >>> """ Report the Linux Commandline used in the current kernel.
> >>> @@ -195,3 +195,71 @@ values of that process namespace"""
> >>> info_opts(MNT_INFO, m_flags)))
> >>>
> >>> LxMounts()
> >>> +
> >>> +class LxFdtDump(gdb.Command):
> >>> + """Output Flattened Device Tree header and dump FDT blob to a file
> >>> + Equivalent to 'cat /proc/fdt > fdtdump.dtb' on a running target"""
> >>> +
> >>> + def __init__(self):
> >>> + super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA)
> >>> +
> >>> + def fdthdr_to_cpu(self, fdt_header):
> >>> +
> >>> + fdt_header_be = ">IIIIIII"
> >>> + fdt_header_le = "<IIIIIII"
> >>> +
> >>> + if utils.get_target_endianness() == 1:
> >>> + output_fmt = fdt_header_le
> >>> + else:
> >>> + output_fmt = fdt_header_be
> >>> +
> >>> + return unpack(output_fmt, pack(fdt_header_be,
> >>> + fdt_header['magic'],
> >>> + fdt_header['totalsize'],
> >>> + fdt_header['off_dt_struct'],
> >>> + fdt_header['off_dt_strings'],
> >>> + fdt_header['off_mem_rsvmap'],
> >>> + fdt_header['version'],
> >>> + fdt_header['last_comp_version']))
> >>> +
> >>> + def invoke(self, arg, from_tty):
> >>> +
> >>> + if constants.LX_CONFIG_OF:
> >>> +
> >>> + filename = "fdtdump.dtb"
> >>
> >> Why not specifying the file name as argument? Safer than silently
> >> overwriting potentially pre-existing files or failing without
> >> alternatives if the current directory is not writable.
> >
> > Good idea, I will update to have the filename as the command argument in v2.
> >
>
> Also check gdb.COMPLETE_FILENAME [1] at that chance. :)
>
> Jan
>
> [1]
> https://sourceware.org/gdb/onlinedocs/gdb/Commands-In-Python.html#Commands-In-Python
>
Thanks for the tip, that is very cool!
Will add gdb.COMPLETE_FILENAME in V2.
regads,
Peter.
^ permalink raw reply
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Peter Griffin @ 2016-10-18 16:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a440581a-e28c-2f9f-8110-26203e0b3809@bingham.xyz>
Hi Kieran,
Thanks for reviewing.
On Tue, 18 Oct 2016, Kieran Bingham wrote:
> Hi Pete,
>
> Thanks for your patch.
>
> On 18/10/16 16:07, Peter Griffin wrote:
> > lx-fdtdump dumps the flatenned device tree passed to the kernel
>
> s/flatenned/flattened/
>
> > from the bootloader to a file called fdtdump.dtb to allow further
> > post processing on the machine running GDB. The fdt header is also
> > also printed in the GDB console. For example:
> >
>
> Excellent - I've been looking forward to this
>
> General comment: It would be good to see the output filename
> configurable as a parameter, defaulting to fdtdump.dtb if none provided.
>
> Is this something you have time to add?
Have added this in v2 :)
>
> > (gdb) lx-fdtdump
> > fdt_magic: 0xD00DFEED
> > fdt_totalsize: 0xC108
> > off_dt_struct: 0x38
> > off_dt_strings: 0x3804
> > off_mem_rsvmap: 0x28
> > version: 17
> > last_comp_version: 16
> > Dumped fdt to fdtdump.dtb
> >
> >> fdtdump fdtdump.dtb | less
> >
> > This command is useful as the bootloader can often re-write parts
> > of the device tree, and this can sometimes cause the kernel to not
> > boot.
> >
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> > scripts/gdb/linux/constants.py.in | 8 +++++
> > scripts/gdb/linux/proc.py | 70 ++++++++++++++++++++++++++++++++++++++-
> > 2 files changed, 77 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
> > index 7986f4e..43c6241 100644
> > --- a/scripts/gdb/linux/constants.py.in
> > +++ b/scripts/gdb/linux/constants.py.in
> > @@ -14,6 +14,7 @@
> >
> > #include <linux/fs.h>
> > #include <linux/mount.h>
> > +#include <linux/of_fdt.h>
> >
> > /* We need to stringify expanded macros so that they can be parsed */
> >
> > @@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
> > LX_VALUE(MNT_NOATIME)
> > LX_VALUE(MNT_NODIRATIME)
> > LX_VALUE(MNT_RELATIME)
> > +
> > +/* linux/of_fdt.h> */
> > +LX_VALUE(OF_DT_HEADER)
> > +
> > +/* Kernel Configs */
> > +LX_CONFIG(CONFIG_OF)
> > +
> > diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
> > index 38b1f09..f20fcfa 100644
> > --- a/scripts/gdb/linux/proc.py
> > +++ b/scripts/gdb/linux/proc.py
> > @@ -16,7 +16,7 @@ from linux import constants
> > from linux import utils
> > from linux import tasks
> > from linux import lists
> > -
> > +from struct import *
> >
> > class LxCmdLine(gdb.Command):
> > """ Report the Linux Commandline used in the current kernel.
> > @@ -195,3 +195,71 @@ values of that process namespace"""
> > info_opts(MNT_INFO, m_flags)))
> >
> > LxMounts()
> > +
> > +class LxFdtDump(gdb.Command):
> > + """Output Flattened Device Tree header and dump FDT blob to a file
> > + Equivalent to 'cat /proc/fdt > fdtdump.dtb' on a running target"""
> > +
> > + def __init__(self):
> > + super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA)
> > +
> > + def fdthdr_to_cpu(self, fdt_header):
> > +
> > + fdt_header_be = ">IIIIIII"
> > + fdt_header_le = "<IIIIIII"
> > +
> > + if utils.get_target_endianness() == 1:
> > + output_fmt = fdt_header_le
> > + else:
> > + output_fmt = fdt_header_be
> > +
> > + return unpack(output_fmt, pack(fdt_header_be,
> > + fdt_header['magic'],
> > + fdt_header['totalsize'],
> > + fdt_header['off_dt_struct'],
> > + fdt_header['off_dt_strings'],
> > + fdt_header['off_mem_rsvmap'],
> > + fdt_header['version'],
> > + fdt_header['last_comp_version']))
> > +
> > + def invoke(self, arg, from_tty):
> > +
> > + if constants.LX_CONFIG_OF:
> > +
> > + filename = "fdtdump.dtb"
> > +
>
> You could parse the arguments here to allow users to write to their own
> file / path ... arg is just a string, so you can either parse it as such
> or convert to argv with
> argv = gdb.string_to_argv(arg)
>
>
> Aha - I see Jan beat me to it :)
>
>
> > + py_fdt_header_ptr = gdb.parse_and_eval(
> > + "(const struct fdt_header *) initial_boot_params")
> > + py_fdt_header = py_fdt_header_ptr.dereference()
> > +
> > + fdt_header = self.fdthdr_to_cpu(py_fdt_header)
> > +
> > + if fdt_header[0] != constants.LX_OF_DT_HEADER:
> > + raise gdb.GdbError("No flattened device tree magic found\n")
> > +
> > + gdb.write("fdt_magic: 0x{:02X}\n".format(fdt_header[0]))
> > + gdb.write("fdt_totalsize: 0x{:02X}\n".format(fdt_header[1]))
> > + gdb.write("off_dt_struct: 0x{:02X}\n".format(fdt_header[2]))
> > + gdb.write("off_dt_strings: 0x{:02X}\n".format(fdt_header[3]))
> > + gdb.write("off_mem_rsvmap: 0x{:02X}\n".format(fdt_header[4]))
> > + gdb.write("version: {}\n".format(fdt_header[5]))
> > + gdb.write("last_comp_version: {}\n".format(fdt_header[6]))
> > +
> > + inf = gdb.inferiors()[0]
> > + fdt_buf = utils.read_memoryview(inf, py_fdt_header_ptr,
> > + fdt_header[1]).tobytes()
> > +
> > + try:
> > + f = open(filename, 'wb')
> > + except:
> > + raise gdb.GdbError("Could not open file to dump fdt")
> > +
> > + f.write(fdt_buf)
> > + f.close()
> > +
> > + gdb.write("Dumped fdt to " + filename + "\n")
> > +
> > + else:
> > + gdb.write("Kernel not compiled with CONFIG_OF\n")
>
> Would it be cleaner to write
> if not constants.LX_CONFIG_OF:
> raise gdb.GdbError("Kernel not compiled with CONFIG_OF\n")
>
> at the beginning, and reduce the indentation level required ?
Good idea, have updated like you suggest in V2 and reduced the
indentation.
regards,
Peter
^ permalink raw reply
* [PATCH v2] scripts/gdb: add lx-fdtdump command
From: Peter Griffin @ 2016-10-18 16:33 UTC (permalink / raw)
To: linux-arm-kernel
lx-fdtdump dumps the flattened device tree passed to the kernel
from the bootloader to the filename specified as the command
argument. If no argument is provided it defaults to fdtdump.dtb.
This then allows further post processing on the machine running GDB.
The fdt header is also also printed in the GDB console. For example:
(gdb) lx-fdtdump
fdt_magic: 0xD00DFEED
fdt_totalsize: 0xC108
off_dt_struct: 0x38
off_dt_strings: 0x3804
off_mem_rsvmap: 0x28
version: 17
last_comp_version: 16
Dumped fdt to fdtdump.dtb
>fdtdump fdtdump.dtb | less
This command is useful as the bootloader can often re-write parts
of the device tree, and this can sometimes cause the kernel to not
boot.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
Changes since v1
- s/flatenned/flattened/ (Kieran)
- Add filename as argument to command (Jan / Kieran)
- Check LX_CONFIG_OF early to reduce indendation (Kieran)
- Add gdb.COMPLETE_FILENAME to get auto completion (Jan)
- Squash pep8 fixup patch (Kieran)
---
scripts/gdb/linux/constants.py.in | 8 +++++
scripts/gdb/linux/proc.py | 73 +++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 7986f4e..43c6241 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -14,6 +14,7 @@
#include <linux/fs.h>
#include <linux/mount.h>
+#include <linux/of_fdt.h>
/* We need to stringify expanded macros so that they can be parsed */
@@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
LX_VALUE(MNT_NOATIME)
LX_VALUE(MNT_NODIRATIME)
LX_VALUE(MNT_RELATIME)
+
+/* linux/of_fdt.h> */
+LX_VALUE(OF_DT_HEADER)
+
+/* Kernel Configs */
+LX_CONFIG(CONFIG_OF)
+
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 38b1f09..086d272 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -16,6 +16,7 @@ from linux import constants
from linux import utils
from linux import tasks
from linux import lists
+from struct import *
class LxCmdLine(gdb.Command):
@@ -195,3 +196,75 @@ values of that process namespace"""
info_opts(MNT_INFO, m_flags)))
LxMounts()
+
+
+class LxFdtDump(gdb.Command):
+ """Output Flattened Device Tree header and dump FDT blob to the filename
+ specified as the command argument. Equivalent to
+ 'cat /proc/fdt > fdtdump.dtb' on a running target"""
+
+ def __init__(self):
+ super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA,
+ gdb.COMPLETE_FILENAME)
+
+ def fdthdr_to_cpu(self, fdt_header):
+
+ fdt_header_be = ">IIIIIII"
+ fdt_header_le = "<IIIIIII"
+
+ if utils.get_target_endianness() == 1:
+ output_fmt = fdt_header_le
+ else:
+ output_fmt = fdt_header_be
+
+ return unpack(output_fmt, pack(fdt_header_be,
+ fdt_header['magic'],
+ fdt_header['totalsize'],
+ fdt_header['off_dt_struct'],
+ fdt_header['off_dt_strings'],
+ fdt_header['off_mem_rsvmap'],
+ fdt_header['version'],
+ fdt_header['last_comp_version']))
+
+ def invoke(self, arg, from_tty):
+
+ if not constants.LX_CONFIG_OF:
+ raise gdb.GdbError("Kernel not compiled with CONFIG_OF\n")
+
+ if len(arg) == 0:
+ filename = "fdtdump.dtb"
+ else:
+ filename = arg
+
+ py_fdt_header_ptr = gdb.parse_and_eval(
+ "(const struct fdt_header *) initial_boot_params")
+ py_fdt_header = py_fdt_header_ptr.dereference()
+
+ fdt_header = self.fdthdr_to_cpu(py_fdt_header)
+
+ if fdt_header[0] != constants.LX_OF_DT_HEADER:
+ raise gdb.GdbError("No flattened device tree magic found\n")
+
+ gdb.write("fdt_magic: 0x{:02X}\n".format(fdt_header[0]))
+ gdb.write("fdt_totalsize: 0x{:02X}\n".format(fdt_header[1]))
+ gdb.write("off_dt_struct: 0x{:02X}\n".format(fdt_header[2]))
+ gdb.write("off_dt_strings: 0x{:02X}\n".format(fdt_header[3]))
+ gdb.write("off_mem_rsvmap: 0x{:02X}\n".format(fdt_header[4]))
+ gdb.write("version: {}\n".format(fdt_header[5]))
+ gdb.write("last_comp_version: {}\n".format(fdt_header[6]))
+
+ inf = gdb.inferiors()[0]
+ fdt_buf = utils.read_memoryview(inf, py_fdt_header_ptr,
+ fdt_header[1]).tobytes()
+
+ try:
+ f = open(filename, 'wb')
+ except:
+ raise gdb.GdbError("Could not open file to dump fdt")
+
+ f.write(fdt_buf)
+ f.close()
+
+ gdb.write("Dumped fdt blob to " + filename + "\n")
+
+LxFdtDump()
--
1.9.1
^ permalink raw reply related
* [PATCH v2] ARM: bcm2835: Add names for the Raspberry Pi GPIO lines
From: Eric Anholt @ 2016-10-18 16:38 UTC (permalink / raw)
To: linux-arm-kernel
From: Linus Walleij <linus.walleij@linaro.org>
The idea is to give useful names to GPIO lines that an implementer
will be using from userspace, e.g. for maker type projects. These are
user-visible using tools/gpio/lsgpio.c
v2: Major rewrite by anholt: Flatten each GPIO line to a line in the
file for better diffing, prefix all expansion header pins with
"P<number>" or "P5HEADER_P<number>" and drop the mostly-unused
GPIO_GEN<smallnumber> names in favor of GPIO<socgpionumber>, fix
extra '[]' on a couple of lines, fix locations of SD_CARD_DETECT,
CAM_GPIO and STATUS_LED, fix HDMI_HPD polarities, rewrite A+ using
unreleased schematics.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
---
Note: I haven't actually booted these and checked that the names line
up, just tried to visually review them. Hopefully with more
GPIO<number> values, it's easier to spot errors.
The only other thing here I think I would do is drop the [] around
names for behavior when pinmuxed. I find it more confusing than
helpful.
Linus, are these names considered ABI? Will we be locked into
whatever set of names we merge and release? My assumption would be
"yes".
arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 66 +++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2835-rpi-a.dts | 68 ++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 67 +++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts | 67 +++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2835-rpi-b.dts | 68 ++++++++++++++++++++++++++++++++
5 files changed, 336 insertions(+)
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
index 21507c922783..cec4c6e49e7b 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
@@ -22,6 +22,72 @@
};
&gpio {
+ /*
+ * This is based on the unreleased schematic for the Model A+.
+ *
+ * Legend:
+ * "NC" = not connected (no rail from the SoC)
+ * "[FOO]" = pin is muxed for peripheral FOO (not GPIO)
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "[SDA0]",
+ "[SCL0]",
+ "[P3_SDA1]",
+ "[P5_SCL1]",
+ "[P7_GPIO_GCLK]",
+ "P29_GPIO5",
+ "P31_GPIO6",
+ "[P26_SPI_CE1_N]",
+ "[P24_SPI_CE0_N]",
+ "[P21_SPI_MISO]",
+ "[P19_SPI_MOSI]",
+ "[P23_SPI_SCLK]",
+ "P32_GPIO12",
+ "P33_GPIO13",
+ /* Serial port */
+ "[P8_TXD0]",
+ "[P10_RXD0]",
+ "P36_GPIO16",
+ "P11_GPIO17",
+ "P12_GPIO18",
+ "P35_GPIO19",
+ "P38_GPIO20",
+ "P40_GPIO21",
+ "P15_GPIO22",
+ "P16_GPIO23",
+ "P18_GPIO24",
+ "P22_GPIO25",
+ "P37_GPIO26",
+ "P13_GPIO27",
+ "[SDA0]",
+ "[SCL0]",
+ "NC", /* GPIO30 */
+ "NC", /* GPIO31 */
+ "NC", /* GPIO32 */
+ "NC", /* GPIO33 */
+ "NC", /* GPIO34 */
+ "PWR_LOW_N", /* GPIO35 */
+ "NC", /* GPIO36 */
+ "NC", /* GPIO37 */
+ "NC", /* GPIO38 */
+ "NC", /* GPIO39 */
+ "[PWM0_OUT]", /* GPIO40 */
+ "CAM_GPIO0", /* GPIO41 */
+ "NC", /* GPIO42 */
+ "NC", /* GPIO43 */
+ "NC", /* GPIO44 */
+ "[PWM1_OUT]", /* GPIO45 */
+ "HDMI_HPD_N",
+ "STATUS_LED",
+ /* Used by SD Card */
+ "[SD_CLK_R]",
+ "[SD_CMD_R]",
+ "[SD_DATA0_R]",
+ "[SD_DATA1_R]",
+ "[SD_DATA2_R]",
+ "[SD_DATA3_R]";
+
pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
/* I2S interface */
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts
index 5afba0900449..0ff96ed4d15b 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
@@ -15,6 +15,74 @@
};
&gpio {
+ /*
+ * Taken from Raspberry-Pi-Rev-1.0-Model-AB-Schematics.pdf
+ * RPI00021 sheet 02
+ *
+ * Legend:
+ * "NC" = not connected (no rail from the SoC)
+ * "[FOO]" = pin is muxed for peripheral FOO (not GPIO)
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "[P3_SDA0]",
+ "[P5_SCL0]",
+ "[SDA1]",
+ "[SCL1]",
+ "[P7_GPIO_GCLK]",
+ "[CAM_CLK]",
+ "LAN_RUN",
+ "[P26_SPI_CE1_N]",
+ "[P24_SPI_CE0_N]",
+ "[P21_SPI_MISO]",
+ "[P19_SPI_MOSI]",
+ "[P23_SPI_SCLK]",
+ "NC", /* GPIO12 */
+ "NC", /* GPIO13 */
+ /* Serial port */
+ "[P8_TXD0]",
+ "[P10_RXD0]",
+ "STATUS_LED_N",
+ "P11_GPIO17",
+ "P12_GPIO18",
+ "NC", /* GPIO19 */
+ "NC", /* GPIO20 */
+ "P13_GPIO21",
+ "P15_GPIO22",
+ "P16_GPIO23",
+ "P18_GPIO24",
+ "P22_GPIO25",
+ "NC", /* GPIO26 */
+ "CAM_GPIO",
+ /* Binary number representing build/revision */
+ "CONFIG0",
+ "CONFIG1",
+ "CONFIG2",
+ "CONFIG3",
+ "NC", /* GPIO32 */
+ "NC", /* GPIO33 */
+ "NC", /* GPIO34 */
+ "NC", /* GPIO35 */
+ "NC", /* GPIO36 */
+ "NC", /* GPIO37 */
+ "NC", /* GPIO38 */
+ "NC", /* GPIO39 */
+ "[PWM0_OUT]",
+ "NC", /* GPIO41 */
+ "NC", /* GPIO42 */
+ "NC", /* GPIO43 */
+ "NC", /* GPIO44 */
+ "[PWM1_OUT]",
+ "HDMI_HPD_P",
+ "SD_CARD_DET",
+ /* Used by SD Card */
+ "[SD_CLK_R]",
+ "[SD_CMD_R]",
+ "[SD_DATA0_R]",
+ "[SD_DATA1_R]",
+ "[SD_DATA2_R]",
+ "[SD_DATA3_R]";
+
pinctrl-0 = <&gpioout &alt0 &i2s_alt2>;
/* I2S interface */
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
index 38f66aa244fe..0e04fc2eb65e 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
@@ -23,6 +23,73 @@
};
&gpio {
+ /*
+ * Taken from Raspberry-Pi-B-Plus-V1.2-Schematics.pdf
+ * RPI-BPLUS sheet 1
+ *
+ * Legend:
+ * "NC" = not connected (no rail from the SoC)
+ * "[FOO]" = pin is muxed for peripheral FOO (not GPIO)
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "[ID_SD]",
+ "[ID_SC]",
+ "[P3_SDA1]",
+ "[P5_SCL1]",
+ "[P7_GPIO_GCLK]",
+ "P29_GPIO5",
+ "P31_GPIO6",
+ "[P26_SPI_CE1_N]",
+ "[P24_SPI_CE0_N]",
+ "[P21_SPI_MISO]",
+ "[P19_SPI_MOSI]",
+ "[P23_SPI_SCLK]",
+ "P23_GPIO12",
+ "P33_GPIO13",
+ /* Serial port */
+ "[P8_TXD0]",
+ "[P10_RXD0]",
+ "P36_GPIO16",
+ "P11_GPIO17",
+ "P12_GPIO18",
+ "P35_GPIO19",
+ "P38_GPIO20",
+ "P40_GPIO21",
+ "P15_GPIO22",
+ "P16_GPIO23",
+ "P18_GPIO24",
+ "P22_GPIO25",
+ "P37_GPIO26",
+ "P13_GPIO27",
+ "[SDA0]",
+ "[SCL0]",
+ "NC", /* GPIO30 */
+ "LAN_RUN", /* GPIO31 */
+ "CAM_GPIO1", /* GPIO32 */
+ "NC", /* GPIO33 */
+ "NC", /* GPIO34 */
+ "PWR_LOW_N", /* GPIO35 */
+ "NC", /* GPIO36 */
+ "NC", /* GPIO37 */
+ "NC", /* GPIO38 */
+ "NC", /* GPIO39 */
+ "[PWM0_OUT]", /* GPIO40 */
+ "CAM_GPIO0", /* GPIO41 */
+ "NC", /* GPIO42 */
+ "NC", /* GPIO43 */
+ "ETHCLK", /* GPIO44 */
+ "[PWM1_OUT]", /* GPIO45 */
+ "HDMI_HPD_N",
+ "STATUS_LED",
+ /* Used by SD Card */
+ "[SD_CLK_R]",
+ "[SD_CMD_R]",
+ "[SD_DATA0_R]",
+ "[SD_DATA1_R]",
+ "[SD_DATA2_R]",
+ "[SD_DATA3_R]";
+
pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
/* I2S interface */
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
index 75e045aba7ce..6c91c9f0536c 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
@@ -16,6 +16,73 @@
};
&gpio {
+ /*
+ * Taken from Raspberry-Pi-Rev-2.0-Model-AB-Schematics.pdf
+ * RPI00022 sheet 02
+ *
+ * Legend:
+ * "NC" = not connected (no rail from the SoC)
+ * "[FOO]" = pin is muxed for peripheral FOO (not GPIO)
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "[SDA0]",
+ "[SCL0]",
+ "[P3_SDA1]",
+ "[P5_SCL1]",
+ "[P7_GPIO_GCLK]",
+ "[CAM_CLK]",
+ "LAN_RUN",
+ "[P26_SPI_CE1_N]",
+ "[P24_SPI_CE0_N]",
+ "[P21_SPI_MISO]",
+ "[P19_SPI_MOSI]",
+ "[P23_SPI_SCLK]",
+ "NC", /* GPIO12 */
+ "NC", /* GPIO13 */
+ /* Serial port */
+ "[P8_TXD0]",
+ "[P10_RXD0]",
+ "STATUS_LED_N",
+ "P11_GPIO17",
+ "P12_GPIO18",
+ "NC", /* GPIO19 */
+ "NC", /* GPIO20 */
+ "CAM_GPIO",
+ "P15_GPIO22",
+ "P16_GPIO23",
+ "P18_GPIO24",
+ "P22_GPIO25",
+ "NC", /* GPIO 26 */
+ "P13_GPIO27",
+ "P5HEADER_P3_GPIO28",
+ "P5HEADER_P4_GPIO29",
+ "P5HEADER_P5_GPIO30",
+ "P5HEADER_P6_GPIO31",
+ "NC", /* GPIO32 */
+ "NC", /* GPIO33 */
+ "NC", /* GPIO34 */
+ "NC", /* GPIO35 */
+ "NC", /* GPIO36 */
+ "NC", /* GPIO37 */
+ "NC", /* GPIO38 */
+ "NC", /* GPIO39 */
+ "[PWM0_OUT]",
+ "NC", /* GPIO41 */
+ "NC", /* GPIO42 */
+ "NC", /* GPIO43 */
+ "NC", /* GPIO44 */
+ "[PWM1_OUT]",
+ "HDMI_HPD_P",
+ "SD_CARD_DET",
+ /* Used by SD Card */
+ "[SD_CLK_R]",
+ "[SD_CMD_R]",
+ "[SD_DATA0_R]",
+ "[SD_DATA1_R]",
+ "[SD_DATA2_R]",
+ "[SD_DATA3_R]";
+
pinctrl-0 = <&gpioout &alt0 &i2s_alt2>;
/* I2S interface */
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 76a254b3219a..023239946826 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -16,6 +16,74 @@
};
&gpio {
+ /*
+ * Taken from Raspberry-Pi-Rev-1.0-Model-AB-Schematics.pdf
+ * RPI00021 sheet 02
+ *
+ * Legend:
+ * "NC" = not connected (no rail from the SoC)
+ * "[FOO]" = pin is muxed for peripheral FOO (not GPIO)
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "[P3_SDA0]",
+ "[P5_SCL0]",
+ "[SDA1]",
+ "[SCL1]",
+ "[P7_GPIO_GCLK]",
+ "[CAM_CLK]",
+ "LAN_RUN",
+ "[P26_SPI_CE1_N]",
+ "[P24_SPI_CE0_N]",
+ "[P21_SPI_MISO]",
+ "[P19_SPI_MOSI]",
+ "[P23_SPI_SCLK]",
+ "NC", /* GPIO12 */
+ "NC", /* GPIO13 */
+ /* Serial port */
+ "[P8_TXD0]",
+ "[P10_RXD0]",
+ "STATUS_LED_N",
+ "P11_GPIO17",
+ "P12_GPIO18",
+ "NC", /* GPIO19 */
+ "NC", /* GPIO20 */
+ "P13_GPIO21",
+ "P15_GPIO22",
+ "P16_GPIO23",
+ "P18_GPIO24",
+ "P22_GPIO25",
+ "NC", /* GPIO26 */
+ "CAM_GPIO",
+ /* Binary number representing build/revision */
+ "CONFIG0",
+ "CONFIG1",
+ "CONFIG2",
+ "CONFIG3",
+ "NC", /* GPIO32 */
+ "NC", /* GPIO33 */
+ "NC", /* GPIO34 */
+ "NC", /* GPIO35 */
+ "NC", /* GPIO36 */
+ "NC", /* GPIO37 */
+ "NC", /* GPIO38 */
+ "NC", /* GPIO39 */
+ "[PWM0_OUT]",
+ "NC", /* GPIO41 */
+ "NC", /* GPIO42 */
+ "NC", /* GPIO43 */
+ "NC", /* GPIO44 */
+ "[PWM1_OUT]",
+ "HDMI_HPD_P",
+ "SD_CARD_DET",
+ /* Used by SD Card */
+ "[SD_CLK_R]",
+ "[SD_CMD_R]",
+ "[SD_DATA0_R]",
+ "[SD_DATA1_R]",
+ "[SD_DATA2_R]",
+ "[SD_DATA3_R]";
+
pinctrl-0 = <&gpioout &alt0>;
};
--
2.9.3
^ permalink raw reply related
* [PATCH v3 4/4] net: smsc91x: add u16 workaround for pxa platforms
From: Rob Herring @ 2016-10-18 16:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476733532-29716-5-git-send-email-robert.jarzmik@free.fr>
On Mon, Oct 17, 2016 at 09:45:32PM +0200, Robert Jarzmik wrote:
> Add a workaround for mainstone, idp and stargate2 boards, for u16 writes
> which must be aligned on 32 bits addresses.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> Cc: Jeremy Linton <jeremy.linton@arm.com>
> ---
> Since v1: rename dt property to pxa-u16-align4
> change the binding documentation file
> ---
> Documentation/devicetree/bindings/net/smsc-lan91c111.txt | 2 ++
> 1 file changed, 2 insertions(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH v5 03/23] usb: ulpi: Support device discovery via DT
From: Rob Herring @ 2016-10-18 16:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018015636.11701-4-stephen.boyd@linaro.org>
On Mon, Oct 17, 2016 at 06:56:16PM -0700, Stephen Boyd wrote:
> The qcom HSIC ULPI phy doesn't have any bits set in the vendor or
> product ID registers. This makes it impossible to make a ULPI
> driver match against the ID registers. Add support to discover
> the ULPI phys via DT help alleviate this problem. In the DT case,
> we'll look for a ULPI bus node underneath the device registering
> the ULPI viewport (or the parent of that device to support
> chipidea's device layout) and then match up the phy node
> underneath that with the ULPI device that's created.
>
> The side benefit of this is that we can use standard properties
> in the phy node like clks, regulators, gpios, etc. because we
> don't have firmware like ACPI to turn these things on for us. And
> we can use the DT phy binding to point our phy consumer to the
> phy provider.
>
> The ULPI bus code supports native enumeration by reading the
> vendor ID and product ID registers at device creation time, but
> we can't be certain that those register reads will succeed if the
> phy is not powered up. To avoid any problems with reading the ID
> registers before the phy is powered we fallback to DT matching
> when the ID reads fail.
>
> If the ULPI spec had some generic power sequencing for these
> registers we could put that into the ULPI bus layer and power up
> the device before reading the ID registers. Unfortunately this
> doesn't exist and the power sequence is usually device specific.
> By having the device matched up with DT we can avoid this
> problem.
>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: <devicetree@vger.kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> Documentation/devicetree/bindings/usb/ulpi.txt | 20 +++++++
> drivers/usb/common/ulpi.c | 79 ++++++++++++++++++++++++--
> 2 files changed, 93 insertions(+), 6 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/usb/ulpi.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH v5 23/23] phy: Add support for Qualcomm's USB HS phy
From: Rob Herring @ 2016-10-18 16:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018015636.11701-24-stephen.boyd@linaro.org>
On Mon, Oct 17, 2016 at 06:56:36PM -0700, Stephen Boyd wrote:
> The high-speed phy on qcom SoCs is controlled via the ULPI
> viewport.
>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: <devicetree@vger.kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> .../devicetree/bindings/phy/qcom,usb-hs-phy.txt | 86 +++++++
Acked-by: Rob Herring <robh@kernel.org>
> drivers/phy/Kconfig | 8 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-qcom-usb-hs.c | 286 +++++++++++++++++++++
> 4 files changed, 381 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
> create mode 100644 drivers/phy/phy-qcom-usb-hs.c
^ permalink raw reply
* [PATCH v5 23/23] phy: Add support for Qualcomm's USB HS phy
From: Rob Herring @ 2016-10-18 16:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018015636.11701-24-stephen.boyd@linaro.org>
On Mon, Oct 17, 2016 at 06:56:36PM -0700, Stephen Boyd wrote:
> The high-speed phy on qcom SoCs is controlled via the ULPI
> viewport.
>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: <devicetree@vger.kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> .../devicetree/bindings/phy/qcom,usb-hs-phy.txt | 86 +++++++
Acked-by: Rob Herring <robh@kernel.org>
> drivers/phy/Kconfig | 8 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-qcom-usb-hs.c | 286 +++++++++++++++++++++
> 4 files changed, 381 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
> create mode 100644 drivers/phy/phy-qcom-usb-hs.c
^ permalink raw reply
* [PATCH] [ARM] Fix stack alignment when processing backtraces
From: Jason Gunthorpe @ 2016-10-18 17:05 UTC (permalink / raw)
To: linux-arm-kernel
The dumpstm helper within c_backtrace pushed 5 dwords onto the stack
causing the stack to become unaligned and then calls printk. This
causes memory corruption in the kernel which assumes AAPCS calling
convention.
Since this bit of asm doesn't use the standard prologue just add
another register to restore alignment.
Fixes: 7ab3f8d595a1b ("[ARM] Add ability to dump exception stacks to kernel backtraces")
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
arch/arm/lib/backtrace.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
In my case the kernel was hitting a WARN_ON during boot and then
reliably failed to start the compiled-in initramfs.
I'm inferring that the stack misalignment caused some kind of memory
corruption which wiped out the unpacked initramfs.
Saw with gcc 5.4.0 on a kirkwood armv5te
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index fab5a50503ae..25e1cce19991 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -116,7 +116,8 @@ ENDPROC(c_backtrace)
#define reg r5
#define stack r6
-.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
+ /* Must maintain 8 byte stack alignment */
+.Ldumpstm: stmfd sp!, {r3, instr, reg, stack, r7, lr}
mov stack, r0
mov instr, r1
mov reg, #10
@@ -140,7 +141,7 @@ ENDPROC(c_backtrace)
teq r7, #0
adrne r0, .Lcr
blne printk
- ldmfd sp!, {instr, reg, stack, r7, pc}
+ ldmfd sp!, {r3, instr, reg, stack, r7, pc}
.Lfp: .asciz " r%d:%08x%s"
.Lcr: .asciz "\n"
--
2.1.4
^ permalink raw reply related
* [PATCH v9 0/2] Add a new board TOPEET iTOP for Exynos 4412
From: Randy Li @ 2016-10-18 17:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <devicetree@vger.kernel.org>
Changelog:
- v9:
- fix some warnings.
- use the new pin defined for pinctrl.
- v8:
- add the missing LDOs for PMIC, the pins for LDOs are not avaiabled in core
board.
- re-order the header files in core board.
- skip the vendor prefix file
- v7:
- add a missing header file
- add a rootdelay to bootargs or it can't mount root filesystem
- fix the memory node
- v6:
- move pwms pinctrl to pwms node
- fix the order of the dtb file in Makefile
- v5:
- correct the mail format
- v4:
- re-order some nodes in alphabetical order
- fix some minor bugs
- add a entry in vendor list
- v3:
- fixing the rtc clock, using clock source from PMIC
- enable the tmu
- enable the fimc for elite board
- suuport the audio codec at elite board, but the audio sound a little
distortion
- fixing minor bugs in the last commit
- v2:
- removing rtc node
the clock source driver is not done yet.
- adding exynos-bus
- fixing the MFC
Randy Li (2):
ARM: dts: Add TOPEET itop core board SCP package version
ARM: dts: add TOPEET itop elite based board
.../bindings/arm/samsung/samsung-boards.txt | 3 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/exynos4412-itop-elite.dts | 240 ++++++++++
arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi | 501 +++++++++++++++++++++
4 files changed, 745 insertions(+)
create mode 100644 arch/arm/boot/dts/exynos4412-itop-elite.dts
create mode 100644 arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
--
2.7.4
^ permalink raw reply
* [PATCH v9 1/2] ARM: dts: Add TOPEET itop core board SCP package version
From: Randy Li @ 2016-10-18 17:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476811129-4450-1-git-send-email-ayaka@soulik.info>
The TOPEET itop is a samsung exnynos 4412 core board, which have
two package versions. This patch add the support for SCP version.
Currently supported are USB3503A HSIC, USB OTG, eMMC, rtc and
PMIC. The future features are in the based board. Also MFC and
watchdog have been enabled.
Signed-off-by: Randy Li <ayaka@soulik.info>
---
arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi | 501 ++++++++++++++++++++++++
1 file changed, 501 insertions(+)
create mode 100644 arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
diff --git a/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
new file mode 100644
index 0000000..881dc76
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
@@ -0,0 +1,501 @@
+/*
+ * TOPEET's Exynos4412 based itop board device tree source
+ *
+ * Copyright (c) 2016 SUMOMO Computer Association
+ * https://www.sumomo.mobi
+ * Randy Li <ayaka@soulik.info>
+ *
+ * Device tree source file for TOPEET iTop Exynos 4412 SCP package core
+ * board which is based on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/samsung,s2mps11.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "exynos4412.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
+
+/ {
+ memory at 40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x40000000>;
+ };
+
+ firmware at 0203F000 {
+ compatible = "samsung,secure-firmware";
+ reg = <0x0203F000 0x1000>;
+ };
+
+ fixed-rate-clocks {
+ xxti {
+ compatible = "samsung,clock-xxti";
+ clock-frequency = <0>;
+ };
+
+ xusbxti {
+ compatible = "samsung,clock-xusbxti";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ cooling-maps {
+ map0 {
+ /* Corresponds to 800MHz at freq_table */
+ cooling-device = <&cpu0 7 7>;
+ };
+ map1 {
+ /* Corresponds to 200MHz at freq_table */
+ cooling-device = <&cpu0 13 13>;
+ };
+ };
+ };
+ };
+
+ usb-hub {
+ compatible = "smsc,usb3503a";
+ reset-gpios = <&gpm2 4 GPIO_ACTIVE_LOW>;
+ connect-gpios = <&gpm3 3 GPIO_ACTIVE_HIGH>;
+ intn-gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hsic_reset>;
+ };
+};
+
+&bus_dmc {
+ devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+ vdd-supply = <&buck1_reg>;
+ status = "okay";
+};
+
+&bus_acp {
+ devfreq = <&bus_dmc>;
+ status = "okay";
+};
+
+&bus_c2c {
+ devfreq = <&bus_dmc>;
+ status = "okay";
+};
+
+&bus_leftbus {
+ devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+ vdd-supply = <&buck3_reg>;
+ status = "okay";
+};
+
+&bus_rightbus {
+ devfreq = <&bus_leftbus>;
+ status = "okay";
+};
+
+&bus_fsys {
+ devfreq = <&bus_leftbus>;
+ status = "okay";
+};
+
+&bus_peri {
+ devfreq = <&bus_leftbus>;
+ status = "okay";
+};
+
+&bus_mfc {
+ devfreq = <&bus_leftbus>;
+ status = "okay";
+};
+
+&cpu0 {
+ cpu0-supply = <&buck2_reg>;
+};
+
+&hsotg {
+ vusb_d-supply = <&ldo15_reg>;
+ vusb_a-supply = <&ldo12_reg>;
+};
+
+&i2c_1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <400000>;
+ pinctrl-0 = <&i2c1_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ s5m8767: s5m8767-pmic at 66 {
+ compatible = "samsung,s5m8767-pmic";
+ reg = <0x66>;
+
+ s5m8767,pmic-buck-default-dvs-idx = <3>;
+
+ s5m8767,pmic-buck-dvs-gpios = <&gpb 5 GPIO_ACTIVE_HIGH>,
+ <&gpb 6 GPIO_ACTIVE_HIGH>,
+ <&gpb 7 GPIO_ACTIVE_HIGH>;
+
+ s5m8767,pmic-buck-ds-gpios = <&gpm3 5 GPIO_ACTIVE_HIGH>,
+ <&gpm3 6 GPIO_ACTIVE_HIGH>,
+ <&gpm3 7 GPIO_ACTIVE_HIGH>;
+
+ /* VDD_ARM */
+ s5m8767,pmic-buck2-dvs-voltage = <1356250>, <1300000>,
+ <1243750>, <1118750>,
+ <1068750>, <1012500>,
+ <956250>, <900000>;
+ /* VDD_INT */
+ s5m8767,pmic-buck3-dvs-voltage = <1000000>, <1000000>,
+ <925000>, <925000>,
+ <887500>, <887500>,
+ <850000>, <850000>;
+ /* VDD_G3D */
+ s5m8767,pmic-buck4-dvs-voltage = <1081250>, <1081250>,
+ <1025000>, <950000>,
+ <918750>, <900000>,
+ <875000>, <831250>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ALIVE";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ /* SCP uses 1.5v, POP uses 1.2v */
+ ldo2_reg: LDO2 {
+ regulator-name = "VDDQ_M12";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VDDIOAP_18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VDDQ_PRE";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "VDD_LDO5";
+ op_mode = <0>; /* Always off Mode */
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VDD10_MPLL";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VDD10_XPLL";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "VDD10_MIPI";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "VDD33_LCD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "VDD18_MIPI";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "VDD18_ABB1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "VDD33_UOTG";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "VDDIOPERI_18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "VDD18_ABB02";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "VDD10_USH";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "VDD18_HSIC";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "VDDIOAP_MMC012_28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ /* Used by HSIC */
+ ldo18_reg: LDO18 {
+ regulator-name = "VDDIOPERI_28";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo19_reg: LDO19 {
+ regulator-name = "VDD_LDO19";
+ op_mode = <0>; /* Always off Mode */
+ };
+
+ ldo20_reg: LDO20 {
+ regulator-name = "VDD28_CAM";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo21_reg: LDO21 {
+ regulator-name = "VDD28_AF";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo22_reg: LDO22 {
+ regulator-name = "VDDA28_2M";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo23_reg: LDO23 {
+ regulator-name = "VDD28_TF";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo24_reg: LDO24 {
+ regulator-name = "VDD33_A31";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo25_reg: LDO25 {
+ regulator-name = "VDD18_CAM";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo26_reg: LDO26 {
+ regulator-name = "VDD18_A31";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo27_reg: LDO27 {
+ regulator-name = "GPS_1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo28_reg: LDO28 {
+ regulator-name = "DVDD12";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "vdd_mif";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1456250>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "vdd_int";
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "vdd_g3d";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-name = "vdd_m12";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck6_reg: BUCK6 {
+ regulator-name = "vdd12_5m";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-name = "pvdd_buck7";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck8_reg: BUCK8 {
+ regulator-name = "pvdd_buck8";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck9_reg: BUCK9 {
+ regulator-name = "vddf28_emmc";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <3000000>;
+ op_mode = <1>; /* Normal Mode */
+ };
+ };
+
+ s5m8767_osc: clocks {
+ #clock-cells = <1>;
+ clock-output-names = "s5m8767_ap",
+ "s5m8767_cp", "s5m8767_bt";
+ };
+
+ };
+};
+
+&mfc {
+ status = "okay";
+};
+
+&mshc_0 {
+ pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+ pinctrl-names = "default";
+ status = "okay";
+ vmmc-supply = <&buck9_reg>;
+ num-slots = <1>;
+ broken-cd;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+};
+
+&pinctrl_1 {
+ hsic_reset: hsic-reset {
+ samsung,pins = "gpm2-4";
+ samsung,pin-function = <EXYNOS_PIN_PDN_OUT1>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
+ };
+};
+
+&rtc {
+ status = "okay";
+ clocks = <&clock CLK_RTC>, <&s5m8767_osc S2MPS11_CLK_AP>;
+ clock-names = "rtc", "rtc_src";
+};
+
+&tmu {
+ vtmu-supply = <&ldo16_reg>;
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v9 2/2] ARM: dts: add TOPEET itop elite based board
From: Randy Li @ 2016-10-18 17:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476811129-4450-1-git-send-email-ayaka@soulik.info>
The TOPEET itop exynos 4412 have three versions base board. The
Elite version is the cheap one without too much peripheral devices
on it.
Currently supported are serial console, wired networking(USB),
USB OTG in peripheral mode, USB host, SD storage, GPIO buttons,
PWM beeper, ADC and LEDs. The WM8960 analog audio codec is also
enabled.
The FIMC is not used for camera currently, I enabled it just for a
colorspace converter.
Signed-off-by: Randy Li <ayaka@soulik.info>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
.../bindings/arm/samsung/samsung-boards.txt | 3 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/exynos4412-itop-elite.dts | 240 +++++++++++++++++++++
3 files changed, 244 insertions(+)
create mode 100644 arch/arm/boot/dts/exynos4412-itop-elite.dts
diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index 0ea7f14..5160fa5 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -22,6 +22,9 @@ Required root node properties:
* FriendlyARM
- "friendlyarm,tiny4412" - for Exynos4412-based FriendlyARM
TINY4412 board.
+ * TOPEET
+ - "topeet,itop4412-elite" - for Exynos4412-based TOPEET
+ Elite base board.
* Google
- "google,pi" - for Exynos5800-based Google Peach Pi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index befcd26..d709f74 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -136,6 +136,7 @@ dtb-$(CONFIG_ARCH_EXYNOS4) += \
exynos4210-smdkv310.dtb \
exynos4210-trats.dtb \
exynos4210-universal_c210.dtb \
+ exynos4412-itop-elite.dtb \
exynos4412-odroidu3.dtb \
exynos4412-odroidx.dtb \
exynos4412-odroidx2.dtb \
diff --git a/arch/arm/boot/dts/exynos4412-itop-elite.dts b/arch/arm/boot/dts/exynos4412-itop-elite.dts
new file mode 100644
index 0000000..7440e54
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-itop-elite.dts
@@ -0,0 +1,240 @@
+/*
+ * TOPEET's Exynos4412 based itop board device tree source
+ *
+ * Copyright (c) 2016 SUMOMO Computer Association
+ * https://www.sumomo.mobi
+ * Randy Li <ayaka@soulik.info>
+ *
+ * Device tree source file for TOPEET iTop Exynos 4412 core board
+ * which is based on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/sound/samsung-i2s.h>
+#include "exynos4412-itop-scp-core.dtsi"
+
+/ {
+ model = "TOPEET iTop 4412 Elite board based on Exynos4412";
+ compatible = "topeet,itop4412-elite", "samsung,exynos4412", "samsung,exynos4";
+
+ chosen {
+ bootargs = "root=/dev/mmcblk0p2 rw rootfstype=ext4 rootdelay=1 rootwait";
+ stdout-path = "serial2:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led2 {
+ label = "red:system";
+ gpios = <&gpx1 0 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led3 {
+ label = "red:user";
+ gpios = <&gpk1 1 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ home {
+ label = "GPIO Key Home";
+ linux,code = <KEY_HOME>;
+ gpios = <&gpx1 1 GPIO_ACTIVE_LOW>;
+ };
+
+ back {
+ label = "GPIO Key Back";
+ linux,code = <KEY_BACK>;
+ gpios = <&gpx1 2 GPIO_ACTIVE_LOW>;
+ };
+
+ sleep {
+ label = "GPIO Key Sleep";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
+ };
+
+ vol-up {
+ label = "GPIO Key Vol+";
+ linux,code = <KEY_UP>;
+ gpios = <&gpx2 1 GPIO_ACTIVE_LOW>;
+ };
+
+ vol-down {
+ label = "GPIO Key Vol-";
+ linux,code = <KEY_DOWN>;
+ gpios = <&gpx2 0 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "wm-sound";
+
+ assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
+ <&clock_audss EXYNOS_MOUT_I2S>,
+ <&clock_audss EXYNOS_DOUT_SRP>,
+ <&clock_audss EXYNOS_DOUT_AUD_BUS>;
+ assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
+ <&clock_audss EXYNOS_MOUT_AUDSS>;
+ assigned-clock-rates = <0>,
+ <0>,
+ <112896000>,
+ <11289600>;
+
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&link0_codec>;
+ simple-audio-card,frame-master = <&link0_codec>;
+
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Speaker", "SPK_LP",
+ "Speaker", "SPK_LN",
+ "Speaker", "SPK_RP",
+ "Speaker", "SPK_RN",
+ "LINPUT1", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Mic Jack",
+ "RINPUT2", "Mic Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0 0>;
+ };
+
+ link0_codec: simple-audio-card,codec {
+ sound-dai = <&codec>;
+ clocks = <&i2s0 CLK_I2S_CDCLK>;
+ system-clock-frequency = <11289600>;
+ };
+ };
+
+ beep {
+ compatible = "pwm-beeper";
+ pwms = <&pwm 0 4000000 PWM_POLARITY_INVERTED>;
+ };
+
+ camera: camera {
+ pinctrl-0 = <&cam_port_a_clk_active>;
+ pinctrl-names = "default";
+ status = "okay";
+ assigned-clocks = <&clock CLK_MOUT_CAM0>;
+ assigned-clock-parents = <&clock CLK_XUSBXTI>;
+ };
+};
+
+&adc {
+ vdd-supply = <&ldo3_reg>;
+ status = "okay";
+};
+
+&ehci {
+ status = "okay";
+ /* In order to reset USB ethernet */
+ samsung,vbus-gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>;
+
+ port at 0 {
+ status = "okay";
+ };
+
+ port at 2 {
+ status = "okay";
+ };
+};
+
+&exynos_usbphy {
+ status = "okay";
+};
+
+&fimc_0 {
+ status = "okay";
+ assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+ <&clock CLK_SCLK_FIMC0>;
+ assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+ assigned-clock-rates = <0>, <176000000>;
+};
+
+&hsotg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&i2c_4 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-slave-addr = <0x10>;
+ samsung,i2c-max-bus-freq = <100000>;
+ pinctrl-0 = <&i2c4_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ codec: wm8960 at 1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ clocks = <&pmu_system_controller 0>;
+ clock-names = "MCLK1";
+ wlf,shared-lrclk;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&i2s0 {
+ pinctrl-0 = <&i2s0_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+ clocks = <&clock_audss EXYNOS_I2S_BUS>,
+ <&clock_audss EXYNOS_DOUT_AUD_BUS>,
+ <&clock_audss EXYNOS_SCLK_I2S>;
+ clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
+};
+
+&pinctrl_1 {
+ ether-reset {
+ samsung,pins = "gpc0-1";
+ samsung,pin-function = <EXYNOS_PIN_PDN_OUT1>;
+ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+ };
+};
+
+&pwm {
+ status = "okay";
+ pinctrl-0 = <&pwm0_out>;
+ pinctrl-names = "default";
+ samsung,pwm-outputs = <0>;
+};
+
+&sdhci_2 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+ pinctrl-names = "default";
+ cd-gpio = <&gpx0 7 GPIO_ACTIVE_LOW>;
+ cap-sd-highspeed;
+ vmmc-supply = <&ldo23_reg>;
+ vqmmc-supply = <&ldo17_reg>;
+ status = "okay";
+};
+
+&serial_1 {
+ status = "okay";
+};
+
+&serial_2 {
+ status = "okay";
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v9 1/2] ARM: dts: Add TOPEET itop core board SCP package version
From: Krzysztof Kozlowski @ 2016-10-18 17:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476811129-4450-2-git-send-email-ayaka@soulik.info>
On Wed, Oct 19, 2016 at 01:18:48AM +0800, Randy Li wrote:
> The TOPEET itop is a samsung exnynos 4412 core board, which have
> two package versions. This patch add the support for SCP version.
>
> Currently supported are USB3503A HSIC, USB OTG, eMMC, rtc and
> PMIC. The future features are in the based board. Also MFC and
> watchdog have been enabled.
>
> Signed-off-by: Randy Li <ayaka@soulik.info>
> ---
> arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi | 501 ++++++++++++++++++++++++
> 1 file changed, 501 insertions(+)
> create mode 100644 arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
Thanks, applied, with minor changes in commit msg and fix in pin
function (you used macro for pull up/down instead of function).
Best regards,
Krzysztof
^ 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