* [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 11/16] drivers: iommu: arm-smmu-v3: 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 v3 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 v3 components.
Add static configuration functions to the IORT kernel layer for
the ARM SMMU v3 components, so that the ARM SMMU v3 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 | 103 +++++++++++++++++++++++++++++++++++++++++++-
drivers/iommu/arm-smmu-v3.c | 49 ++++++++++++++++++++-
2 files changed, 150 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 2eda2f5..ea90bc8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -459,6 +459,95 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
}
+static void __init acpi_iort_register_irq(int hwirq, const char *name,
+ int trigger,
+ struct resource *res)
+{
+ int irq = acpi_register_gsi(NULL, hwirq, trigger,
+ ACPI_ACTIVE_HIGH);
+
+ if (irq <= 0) {
+ pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+ name);
+ return;
+ }
+
+ res->start = irq;
+ res->end = irq;
+ res->flags = IORESOURCE_IRQ;
+ res->name = name;
+}
+
+static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu_v3 *smmu;
+ /* Always present mem resource */
+ int num_res = 1;
+
+ /* Retrieve SMMUv3 specific data */
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ if (smmu->event_gsiv)
+ num_res++;
+
+ if (smmu->pri_gsiv)
+ num_res++;
+
+ if (smmu->gerr_gsiv)
+ num_res++;
+
+ if (smmu->sync_gsiv)
+ num_res++;
+
+ return num_res;
+}
+
+static void __init arm_smmu_v3_init_resources(struct resource *res,
+ struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu_v3 *smmu;
+ int num_res = 0;
+
+ /* Retrieve SMMUv3 specific data */
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ res[num_res].start = smmu->base_address;
+ res[num_res].end = smmu->base_address + SZ_128K - 1;
+ res[num_res].flags = IORESOURCE_MEM;
+
+ num_res++;
+
+ if (smmu->event_gsiv)
+ acpi_iort_register_irq(smmu->event_gsiv, "eventq",
+ ACPI_EDGE_SENSITIVE,
+ &res[num_res++]);
+
+ if (smmu->pri_gsiv)
+ acpi_iort_register_irq(smmu->pri_gsiv, "priq",
+ ACPI_EDGE_SENSITIVE,
+ &res[num_res++]);
+
+ if (smmu->gerr_gsiv)
+ acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
+ ACPI_EDGE_SENSITIVE,
+ &res[num_res++]);
+
+ if (smmu->sync_gsiv)
+ acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
+ ACPI_EDGE_SENSITIVE,
+ &res[num_res++]);
+}
+
+static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu_v3 *smmu;
+
+ /* Retrieve SMMUv3 specific data */
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
struct iort_iommu_config {
const char *name;
int (*iommu_init)(struct acpi_iort_node *node);
@@ -468,10 +557,22 @@ struct iort_iommu_config {
struct acpi_iort_node *node);
};
+static const struct iort_iommu_config iort_arm_smmu_v3_cfg __initconst = {
+ .name = "arm-smmu-v3",
+ .iommu_is_coherent = arm_smmu_v3_is_coherent,
+ .iommu_count_resources = arm_smmu_v3_count_resources,
+ .iommu_init_resources = arm_smmu_v3_init_resources
+};
+
static __init
const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
{
- return NULL;
+ switch (node->type) {
+ case ACPI_IORT_NODE_SMMU_V3:
+ return &iort_arm_smmu_v3_cfg;
+ default:
+ return NULL;
+ }
}
/**
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 3faf348..4abcdc3 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -20,6 +20,8 @@
* This driver is powered by bad coffee and bombay mix.
*/
+#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
#include <linux/err.h>
@@ -2559,6 +2561,36 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
return 0;
}
+#ifdef CONFIG_ACPI
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+ struct arm_smmu_device *smmu,
+ bool *bypass)
+{
+ struct acpi_iort_smmu_v3 *iort_smmu;
+ struct device *dev = smmu->dev;
+ struct acpi_iort_node *node;
+
+ node = *(struct acpi_iort_node **)dev_get_platdata(dev);
+
+ /* Retrieve SMMUv3 specific data */
+ iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+ if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
+ smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+ *bypass = false;
+
+ return 0;
+}
+#else
+static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+ struct arm_smmu_device *smmu,
+ bool *bypass)
+{
+ return -ENODEV;
+}
+#endif
+
static int arm_smmu_device_dt_probe(struct platform_device *pdev,
struct arm_smmu_device *smmu,
bool *bypass)
@@ -2626,7 +2658,11 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
if (irq > 0)
smmu->gerr_irq = irq;
- ret = arm_smmu_device_dt_probe(pdev, smmu, &bypass);
+ if (dev->of_node)
+ ret = arm_smmu_device_dt_probe(pdev, smmu, &bypass);
+ else
+ ret = arm_smmu_device_acpi_probe(pdev, smmu, &bypass);
+
if (ret)
return ret;
@@ -2722,6 +2758,17 @@ static int __init arm_smmu_of_init(struct device_node *np)
}
IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
+#ifdef CONFIG_ACPI
+static int __init acpi_smmu_v3_init(struct acpi_table_header *table)
+{
+ if (iort_node_match(ACPI_IORT_NODE_SMMU_V3))
+ return arm_smmu_init();
+
+ return 0;
+}
+IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
+#endif
+
MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
MODULE_LICENSE("GPL v2");
--
2.10.0
^ permalink raw reply related
* [PATCH v6 10/16] drivers: iommu: arm-smmu-v3: 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 SMMUv3 probe functions intermingle HW and DT probing in the
initialization functions to detect and programme the ARM SMMU v3 driver
features. In order to allow probing the ARM SMMUv3 with other firmwares
than DT, this patch splits the ARM SMMUv3 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>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
drivers/iommu/arm-smmu-v3.c | 46 +++++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index bbc2818..3faf348 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2381,10 +2381,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
return 0;
}
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
{
u32 reg;
- bool coherent;
+ bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
/* IDR0 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2436,13 +2436,9 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
smmu->features |= ARM_SMMU_FEAT_HYP;
/*
- * The dma-coherent property is used in preference to the ID
+ * The coherency feature as set by FW is used in preference to the ID
* register, but warn on mismatch.
*/
- coherent = of_dma_is_coherent(smmu->dev->of_node);
- if (coherent)
- smmu->features |= ARM_SMMU_FEAT_COHERENCY;
-
if (!!(reg & IDR0_COHACC) != coherent)
dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
coherent ? "true" : "false");
@@ -2563,21 +2559,37 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
return 0;
}
-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,
+ bool *bypass)
{
- int irq, ret;
- struct resource *res;
- struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
- bool bypass = true;
u32 cells;
+ *bypass = true;
+
if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
dev_err(dev, "missing #iommu-cells property\n");
else if (cells != 1)
dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
else
- bypass = false;
+ *bypass = false;
+
+ parse_driver_options(smmu);
+
+ if (of_dma_is_coherent(smmu->dev->of_node))
+ smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+ return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
+{
+ int irq, ret;
+ struct resource *res;
+ struct arm_smmu_device *smmu;
+ struct device *dev = &pdev->dev;
+ bool bypass;
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
@@ -2614,10 +2626,12 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
if (irq > 0)
smmu->gerr_irq = irq;
- parse_driver_options(smmu);
+ ret = arm_smmu_device_dt_probe(pdev, smmu, &bypass);
+ if (ret)
+ return ret;
/* Probe the h/w */
- ret = arm_smmu_device_probe(smmu);
+ ret = arm_smmu_device_hw_probe(smmu);
if (ret)
return ret;
@@ -2670,7 +2684,7 @@ static struct platform_driver arm_smmu_driver = {
.name = "arm-smmu-v3",
.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 09/16] drivers: acpi: iort: add support for ARM SMMU platform devices creation
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 ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.
This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.
ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.
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 | 151 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 151 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 1433de3..2eda2f5 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -19,9 +19,11 @@
#define pr_fmt(fmt) "ACPI: IORT: " fmt
#include <linux/acpi_iort.h>
+#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
struct iort_its_msi_chip {
@@ -457,6 +459,153 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
}
+struct iort_iommu_config {
+ const char *name;
+ int (*iommu_init)(struct acpi_iort_node *node);
+ bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+ int (*iommu_count_resources)(struct acpi_iort_node *node);
+ void (*iommu_init_resources)(struct resource *res,
+ struct acpi_iort_node *node);
+};
+
+static __init
+const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
+{
+ return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+static int __init iort_add_smmu_platform_device(struct acpi_iort_node *node)
+{
+ struct fwnode_handle *fwnode;
+ struct platform_device *pdev;
+ struct resource *r;
+ enum dev_dma_attr attr;
+ int ret, count;
+ const struct iort_iommu_config *ops = iort_get_iommu_cfg(node);
+
+ if (!ops)
+ return -ENODEV;
+
+ pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+ if (!pdev)
+ return PTR_ERR(pdev);
+
+ count = ops->iommu_count_resources(node);
+
+ r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+ if (!r) {
+ ret = -ENOMEM;
+ goto dev_put;
+ }
+
+ ops->iommu_init_resources(r, node);
+
+ ret = platform_device_add_resources(pdev, r, count);
+ /*
+ * Resources are duplicated in platform_device_add_resources,
+ * free their allocated memory
+ */
+ kfree(r);
+
+ if (ret)
+ goto dev_put;
+
+ /*
+ * Add a copy of IORT node pointer to platform_data to
+ * be used to retrieve IORT data information.
+ */
+ ret = platform_device_add_data(pdev, &node, sizeof(node));
+ if (ret)
+ goto dev_put;
+
+ /*
+ * We expect the dma masks to be equivalent for
+ * all SMMUs set-ups
+ */
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ fwnode = iort_get_fwnode(node);
+
+ if (!fwnode) {
+ ret = -ENODEV;
+ goto dev_put;
+ }
+
+ pdev->dev.fwnode = fwnode;
+
+ attr = ops->iommu_is_coherent(node) ?
+ DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+ /* Configure DMA for the page table walker */
+ acpi_dma_configure(&pdev->dev, attr);
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto dma_deconfigure;
+
+ return 0;
+
+dma_deconfigure:
+ acpi_dma_deconfigure(&pdev->dev);
+dev_put:
+ platform_device_put(pdev);
+
+ return ret;
+}
+
+static void __init iort_init_platform_devices(void)
+{
+ struct acpi_iort_node *iort_node, *iort_end;
+ struct acpi_table_iort *iort;
+ struct fwnode_handle *fwnode;
+ int i, ret;
+
+ /*
+ * iort_table and iort both point to the start of IORT table, but
+ * have different struct types
+ */
+ iort = (struct acpi_table_iort *)iort_table;
+
+ /* Get the first IORT node */
+ iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+ iort->node_offset);
+ iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+ iort_table->length);
+
+ for (i = 0; i < iort->node_count; i++) {
+ if (iort_node >= iort_end) {
+ pr_err("iort node pointer overflows, bad table\n");
+ return;
+ }
+
+ if ((iort_node->type == ACPI_IORT_NODE_SMMU) ||
+ (iort_node->type == ACPI_IORT_NODE_SMMU_V3)) {
+
+ fwnode = acpi_alloc_fwnode_static();
+ if (!fwnode)
+ return;
+
+ iort_set_fwnode(iort_node, fwnode);
+
+ ret = iort_add_smmu_platform_device(iort_node);
+ if (ret) {
+ iort_delete_fwnode(iort_node);
+ acpi_free_fwnode_static(fwnode);
+ return;
+ }
+ }
+
+ iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+ iort_node->length);
+ }
+}
+
void __init acpi_iort_init(void)
{
acpi_status status;
@@ -468,5 +617,7 @@ void __init acpi_iort_init(void)
return;
}
+ iort_init_platform_devices();
+
acpi_probe_device_table(iort);
}
--
2.10.0
^ permalink raw reply related
* [PATCH v6 08/16] drivers: acpi: iort: add node match 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>
Device drivers (eg ARM SMMU) need to know if a specific component
is part of the IORT table, so that kernel data structures are not
initialized at initcalls time if the respective component is not
part of the IORT table.
To this end, this patch adds a trivial function that allows detecting
if a given IORT node type is present or not in the ACPI table, providing
an ACPI IORT equivalent for of_find_matching_node().
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 | 15 +++++++++++++++
include/linux/acpi_iort.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 75ff7fa..1433de3 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -227,6 +227,21 @@ static struct acpi_iort_node *iort_scan_node(enum acpi_iort_node_type type,
return NULL;
}
+static acpi_status
+iort_match_type_callback(struct acpi_iort_node *node, void *context)
+{
+ return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+ struct acpi_iort_node *node;
+
+ node = iort_scan_node(type, iort_match_type_callback, NULL);
+
+ return node != NULL;
+}
+
static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
void *context)
{
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index d16fdda..17bb078 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -28,10 +28,12 @@ void iort_deregister_domain_token(int trans_id);
struct fwnode_handle *iort_find_domain_token(int trans_id);
#ifdef CONFIG_ACPI_IORT
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);
#else
static inline void acpi_iort_init(void) { }
+static inline bool iort_node_match(u8 type) { return false; }
static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
{ return req_id; }
static inline struct irq_domain *iort_get_device_domain(struct device *dev,
--
2.10.0
^ permalink raw reply related
* [PATCH v6 07/16] drivers: acpi: implement acpi_dma_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>
On DT based systems, the of_dma_configure() API implements DMA
configuration for a given device. On ACPI systems an API equivalent to
of_dma_configure() is missing which implies that it is currently not
possible to set-up DMA operations for devices through the ACPI generic
kernel layer.
This patch fills the gap by introducing acpi_dma_configure/deconfigure()
calls that for now are just wrappers around arch_setup_dma_ops() and
arch_teardown_dma_ops() and also updates ACPI and PCI core code to use
the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions.
Since acpi_dma_configure() is used to configure DMA operations, the
function initializes the dma/coherent_dma masks to sane default values
if the current masks are uninitialized (also to keep the default values
consistent with DT systems) to make sure the device has a complete
default DMA set-up.
The DMA range size passed to arch_setup_dma_ops() is sized according
to the device coherent_dma_mask (starting at address 0x0), mirroring the
DT probing path behaviour when a dma-ranges property is not provided
for the device being probed; this changes the current arch_setup_dma_ops()
call parameters in the ACPI probing case, but since arch_setup_dma_ops()
is a NOP on all architectures but ARM/ARM64 this patch does not change
the current kernel behaviour on them.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> [pci]
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/glue.c | 4 ++--
drivers/acpi/scan.c | 40 ++++++++++++++++++++++++++++++++++++++++
drivers/pci/probe.c | 3 +--
include/acpi/acpi_bus.h | 2 ++
include/linux/acpi.h | 5 +++++
5 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc2..f8d6564 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
attr = acpi_get_dma_attr(acpi_dev);
if (attr != DEV_DMA_NOT_SUPPORTED)
- arch_setup_dma_ops(dev, 0, 0, NULL,
- attr == DEV_DMA_COHERENT);
+ acpi_dma_configure(dev, attr);
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
return 0;
err:
+ acpi_dma_deconfigure(dev);
ACPI_COMPANION_SET(dev, NULL);
put_device(dev);
put_device(&acpi_dev->dev);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 035ac64..694e0b6 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1370,6 +1370,46 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
return DEV_DMA_NON_COHERENT;
}
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+ /*
+ * Set default coherent_dma_mask to 32 bit. Drivers are expected to
+ * setup the correct supported mask.
+ */
+ if (!dev->coherent_dma_mask)
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ /*
+ * Set it to coherent_dma_mask by default if the architecture
+ * code has not set it.
+ */
+ if (!dev->dma_mask)
+ dev->dma_mask = &dev->coherent_dma_mask;
+
+ /*
+ * 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,
+ attr == DEV_DMA_COHERENT);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_configure);
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+ arch_teardown_dma_ops(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_deconfigure);
+
static void acpi_init_coherency(struct acpi_device *adev)
{
unsigned long long cca = 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ab00267..c29e07a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1738,8 +1738,7 @@ static void pci_dma_configure(struct pci_dev *dev)
if (attr == DEV_DMA_NOT_SUPPORTED)
dev_warn(&dev->dev, "DMA not supported.\n");
else
- arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
- attr == DEV_DMA_COHERENT);
+ acpi_dma_configure(&dev->dev, attr);
}
pci_put_host_bridge_device(bridge);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index c1a524d..4242c31 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -573,6 +573,8 @@ struct acpi_pci_root {
bool acpi_dma_supported(struct acpi_device *adev);
enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+void acpi_dma_deconfigure(struct device *dev);
struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
u64 address, bool check_children);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index a284273..3abbf2b 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -763,6 +763,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
return DEV_DMA_NOT_SUPPORTED;
}
+static inline void acpi_dma_configure(struct device *dev,
+ enum dev_dma_attr attr) { }
+
+static inline void acpi_dma_deconfigure(struct device *dev) { }
+
#define ACPI_PTR(_ptr) (NULL)
static inline void acpi_device_set_enumerated(struct acpi_device *adev)
--
2.10.0
^ permalink raw reply related
* [PATCH v6 06/16] drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode usage
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 v3 driver rely on the struct device.of_node pointer for
device look-up and iommu_ops retrieval.
In preparation for ACPI probing enablement, convert the driver to use
the struct device.fwnode member for device and iommu_ops look-up so that
the driver infrastructure can be used also on systems that do not
associate an of_node pointer to a struct device (eg ACPI), making the
device look-up and iommu_ops retrieval firmware agnostic.
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-v3.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 15c01c3..bbc2818 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1723,13 +1723,14 @@ static struct platform_driver arm_smmu_driver;
static int arm_smmu_match_node(struct device *dev, void *data)
{
- return dev->of_node == data;
+ return dev->fwnode == data;
}
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static
+struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
{
struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
- np, arm_smmu_match_node);
+ fwnode, arm_smmu_match_node);
put_device(dev);
return dev ? dev_get_drvdata(dev) : NULL;
}
@@ -1765,7 +1766,7 @@ static int arm_smmu_add_device(struct device *dev)
master = fwspec->iommu_priv;
smmu = master->smmu;
} else {
- smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
+ smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
if (!smmu)
return -ENODEV;
master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -2634,7 +2635,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
return ret;
/* And we're up. Go go go! */
- of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
+ fwnode_iommu_set_ops(dev->fwnode, &arm_smmu_ops);
+
#ifdef CONFIG_PCI
pci_request_acs();
ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
--
2.10.0
^ permalink raw reply related
* [PATCH v6 05/16] drivers: iommu: arm-smmu: convert struct device of_node to fwnode usage
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 driver rely on the struct device.of_node pointer for
device look-up and iommu_ops retrieval.
In preparation for ACPI probing enablement, convert the driver to use
the struct device.fwnode member for device and iommu_ops look-up so that
the driver infrastructure can be used also on systems that do not
associate an of_node pointer to a struct device (eg ACPI), making the
device look-up and iommu_ops retrieval firmware agnostic.
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 | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index c841eb7..9b0b501 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1367,13 +1367,14 @@ static bool arm_smmu_capable(enum iommu_cap cap)
static int arm_smmu_match_node(struct device *dev, void *data)
{
- return dev->of_node == data;
+ return dev->fwnode == data;
}
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static
+struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
{
struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
- np, arm_smmu_match_node);
+ fwnode, arm_smmu_match_node);
put_device(dev);
return dev ? dev_get_drvdata(dev) : NULL;
}
@@ -1391,7 +1392,7 @@ static int arm_smmu_add_device(struct device *dev)
if (ret)
goto out_free;
} else if (fwspec) {
- smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
+ smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
} else {
return -ENODEV;
}
@@ -1995,7 +1996,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
}
}
- of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
+ fwnode_iommu_set_ops(dev->fwnode, &arm_smmu_ops);
platform_set_drvdata(pdev, smmu);
arm_smmu_device_reset(smmu);
--
2.10.0
^ permalink raw reply related
* [PATCH v6 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
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 of_iommu_{set/get}_ops() API is used to associate a device
tree node with a specific set of IOMMU operations. The same
kernel interface is required on systems booting with ACPI, where
devices are not associated with a device tree node, therefore
the interface requires generalization.
The struct device fwnode member represents the fwnode token
associated with the device and the struct it points at is firmware
specific; regardless, it is initialized on both ACPI and DT systems
and makes an ideal candidate to use it to associate a set of IOMMU
operations to a given device, through its struct device.fwnode member
pointer.
Convert the DT specific of_iommu_{set/get}_ops() interface to
use struct device.fwnode as a look-up token, making the interface
usable on ACPI systems.
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>
Cc: Joerg Roedel <joro@8bytes.org>
---
drivers/iommu/iommu.c | 43 +++++++++++++++++++++++++++++++++++++++++++
drivers/iommu/of_iommu.c | 39 ---------------------------------------
include/linux/iommu.h | 14 ++++++++++++++
include/linux/of_iommu.h | 12 ++++++++++--
4 files changed, 67 insertions(+), 41 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9a2f196..320eb8c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1615,6 +1615,49 @@ int iommu_request_dm_for_dev(struct device *dev)
return ret;
}
+struct fwnode_iommu_node {
+ struct list_head list;
+ struct fwnode_handle *fwnode;
+ const struct iommu_ops *ops;
+};
+static LIST_HEAD(fwnode_iommu_list);
+static DEFINE_SPINLOCK(fwnode_iommu_lock);
+
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+ struct fwnode_iommu_node *iommu =
+ kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+ if (WARN_ON(!iommu))
+ return;
+
+ if (is_of_node(fwnode))
+ of_node_get(to_of_node(fwnode));
+
+ INIT_LIST_HEAD(&iommu->list);
+ iommu->fwnode = fwnode;
+ iommu->ops = ops;
+ spin_lock(&fwnode_iommu_lock);
+ list_add_tail(&iommu->list, &fwnode_iommu_list);
+ spin_unlock(&fwnode_iommu_lock);
+}
+
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ struct fwnode_iommu_node *node;
+ const struct iommu_ops *ops = NULL;
+
+ spin_lock(&fwnode_iommu_lock);
+ list_for_each_entry(node, &fwnode_iommu_list, list)
+ if (node->fwnode == fwnode) {
+ ops = node->ops;
+ break;
+ }
+ spin_unlock(&fwnode_iommu_lock);
+ return ops;
+}
+
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops)
{
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 5b82862..0f57ddc 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,45 +96,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
}
EXPORT_SYMBOL_GPL(of_get_dma_window);
-struct of_iommu_node {
- struct list_head list;
- struct device_node *np;
- const struct iommu_ops *ops;
-};
-static LIST_HEAD(of_iommu_list);
-static DEFINE_SPINLOCK(of_iommu_lock);
-
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops)
-{
- struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
- if (WARN_ON(!iommu))
- return;
-
- of_node_get(np);
- INIT_LIST_HEAD(&iommu->list);
- iommu->np = np;
- iommu->ops = ops;
- spin_lock(&of_iommu_lock);
- list_add_tail(&iommu->list, &of_iommu_list);
- spin_unlock(&of_iommu_lock);
-}
-
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
- struct of_iommu_node *node;
- const struct iommu_ops *ops = NULL;
-
- spin_lock(&of_iommu_lock);
- list_for_each_entry(node, &of_iommu_list, list)
- if (node->np == np) {
- ops = node->ops;
- break;
- }
- spin_unlock(&of_iommu_lock);
- return ops;
-}
-
static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
{
struct of_phandle_args *iommu_spec = data;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 436dc21..15d5478 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops);
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops);
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode);
#else /* CONFIG_IOMMU_API */
@@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
return -ENODEV;
}
+static inline void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+}
+
+static inline
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index e80b9c7..7681007 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,8 +31,16 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
#endif /* CONFIG_OF_IOMMU */
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+static inline void of_iommu_set_ops(struct device_node *np,
+ const struct iommu_ops *ops)
+{
+ fwnode_iommu_set_ops(&np->fwnode, ops);
+}
+
+static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
+{
+ return fwnode_iommu_get_ops(&np->fwnode);
+}
extern struct of_device_id __iommu_of_table;
--
2.10.0
^ permalink raw reply related
* [PATCH v6 03/16] drivers: acpi: iort: add support for IOMMU fwnode registration
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 ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.
This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
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 | 86 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 6b51ca7..75ff7fa 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -20,7 +20,9 @@
#include <linux/acpi_iort.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/slab.h>
struct iort_its_msi_chip {
struct list_head list;
@@ -28,6 +30,90 @@ struct iort_its_msi_chip {
u32 translation_id;
};
+struct iort_fwnode {
+ struct list_head list;
+ struct acpi_iort_node *iort_node;
+ struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ * iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ * <0 on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+ struct fwnode_handle *fwnode)
+{
+ struct iort_fwnode *np;
+
+ np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+ if (WARN_ON(!np))
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&np->list);
+ np->iort_node = iort_node;
+ np->fwnode = fwnode;
+
+ spin_lock(&iort_fwnode_lock);
+ list_add_tail(&np->list, &iort_fwnode_list);
+ spin_unlock(&iort_fwnode_lock);
+
+ return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+ */
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr;
+ struct fwnode_handle *fwnode = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ fwnode = curr->fwnode;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return fwnode;
+}
+
+/**
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
+ *
+ * @node: IORT table node associated with fwnode to delete
+ */
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr, *tmp;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ list_del(&curr->list);
+ kfree(curr);
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+}
+
typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
--
2.10.0
^ permalink raw reply related
* [PATCH v6 02/16] drivers: acpi: iort: introduce linker section for IORT entries probing
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>
Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).
Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.
To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.
Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/acpi/arm64/iort.c | 3 +++
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi_iort.h | 3 +++
3 files changed, 7 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 6b81746..6b51ca7 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -364,5 +364,8 @@ void __init acpi_iort_init(void)
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
const char *msg = acpi_format_exception(status);
pr_err("Failed to get table, %s\n", msg);
+ return;
}
+
+ acpi_probe_device_table(iort);
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 3074796..f9c9f3c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -563,6 +563,7 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(clksrc) \
+ ACPI_PROBE_TABLE(iort) \
EARLYCON_TABLE()
#define INIT_TEXT \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 0e32dac..d16fdda 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -39,4 +39,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
{ return NULL; }
#endif
+#define IORT_ACPI_DECLARE(name, table_id, fn) \
+ ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
#endif /* __ACPI_IORT_H__ */
--
2.10.0
^ permalink raw reply related
* [PATCH v6 01/16] drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
From: Lorenzo Pieralisi @ 2016-10-18 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018160414.1228-1-lorenzo.pieralisi@arm.com>
On systems booting with a device tree, every struct device is associated
with a struct device_node, that provides its DT firmware representation.
The device node can be used in generic kernel contexts (eg IRQ
translation, IOMMU streamid mapping), to retrieve the properties
associated with the device and carry out kernel operations accordingly.
Owing to the 1:1 relationship between the device and its device_node,
the device_node can also be used as a look-up token for the device (eg
looking up a device through its device_node), to retrieve the device in
kernel paths where the device_node is available.
On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.
The struct acpi_device, that represents firmware objects in the
ACPI namespace already includes a struct fwnode_handle of
type FWNODE_ACPI as their member; the same abstraction is missing
though for devices that are instantiated out of static ACPI tables
entries (eg ARM SMMU devices).
Add a new fwnode_handle type to associate devices created out
of static ACPI table entries to the respective firmware components
and create a simple ACPI core layer interface to dynamically allocate
and free the corresponding firmware nodes so that kernel subsystems
can use it to instantiate the nodes and associate them with the
respective devices.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
include/linux/acpi.h | 21 +++++++++++++++++++++
include/linux/fwnode.h | 3 ++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index ddbeda6..a284273 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,27 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
+static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+ if (!fwnode)
+ return NULL;
+
+ fwnode->type = FWNODE_ACPI_STATIC;
+
+ return fwnode;
+}
+
+static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
+{
+ if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
+ return;
+
+ kfree(fwnode);
+}
+
/**
* ACPI_DEVICE_CLASS - macro used to describe an ACPI device with
* the PCI-defined class-code information
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..8bd28ce 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,8 +17,9 @@ enum fwnode_type {
FWNODE_OF,
FWNODE_ACPI,
FWNODE_ACPI_DATA,
+ FWNODE_ACPI_STATIC,
FWNODE_PDATA,
- FWNODE_IRQCHIP,
+ FWNODE_IRQCHIP
};
struct fwnode_handle {
--
2.10.0
^ permalink raw reply related
* [PATCH v6 00/16] ACPI IORT ARM SMMU support
From: Lorenzo Pieralisi @ 2016-10-18 16:03 UTC (permalink / raw)
To: linux-arm-kernel
This patch series is v6 of a previous posting:
https://lkml.org/lkml/2016/9/9/418
v5 -> v6
- Rebased against v4.9-rc1
- Changed FWNODE_IOMMU to FWNODE_ACPI_STATIC
- Moved platform devices creation into IORT code
- Updated fwnode handling
- Added default dma masks initialization
v4 -> v5
- Added SMMUv1/v2 support
- Rebased against v4.8-rc5 and dependencies series
- Consolidated IORT platform devices creation
v3 -> v4
- Added single mapping API (for IORT named components)
- Fixed arm_smmu_iort_xlate() return value
- Reworked fwnode registration and platform device creation
ordering to fix probe ordering dependencies
- Added code to keep device_node ref count with new iommu
fwspec API
- Added patch to make iommu_fwspec arch agnostic
- Dropped RFC status
- Rebased against v4.8-rc2
v2 -> v3
- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
- Added back reliance on ACPI early probing infrastructure
- Patch[1-3] merged through other dependent series
- Added back IOMMU fwnode generalization
- Move SMMU v3 static functions configuration to IORT code
- Implemented generic IOMMU fwspec API
- Added code to implement fwnode platform device look-up
v1 -> v2:
- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
- Removed IOMMU fwnode generalization
- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
owing to patch series dependencies [1]
- Moved platform device creation logic to IORT code to
generalize its usage for ARM SMMU v1-v2-v3 components
- Removed reliance on ACPI early device probing
- Created IORT specific iommu_xlate() translation hook leaving
OF code unchanged according to v1 reviews
The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).
http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
Building on basic IORT support, this patchset enables ARM SMMUs support
on ACPI systems.
Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.
PATCH (1) adds a FWNODE_ACPI_STATIC type to the struct fwnode_handle type.
It is required to attach a fwnode identifier to platform
devices allocated/detected through static ACPI table entries
(ie IORT tables entries).
IOMMU devices have to have an identifier to look them up
eg IOMMU core layer carrying out id translation. This can be
done through a fwnode_handle (ie IOMMU platform devices created
out of IORT tables are not ACPI devices hence they can't be
allocated as such, otherwise they would have a fwnode_handle of
type FWNODE_ACPI).
PATCH (2) makes use of the ACPI early probing API to add a linker script
section for probing devices via IORT ACPI kernel code.
PATCH (3) provides IORT support for registering IOMMU IORT node through
their fwnode handle.
PATCH (4) make of_iommu_{set/get}_ops() functions DT agnostic.
PATCH (5) convert ARM SMMU driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (6) convert ARM SMMU v3 driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (7) implements the of_dma_configure() API in ACPI world -
acpi_dma_configure() - and patches PCI and ACPI core code to
start making use of it.
PATCH (8) provides an IORT function to detect existence of specific type
of IORT components.
PATCH (9) creates the kernel infrastructure required to create ARM SMMU
platform devices for IORT nodes.
PATCH (10) refactors the ARM SMMU v3 driver so that the init functions are
split in a way that groups together code that probes through DT
and code that carries out HW registers FW agnostic probing, in
preparation for adding the ACPI probing path.
PATCH (11) adds ARM SMMU v3 IORT IOMMU operations to create and probe
ARM SMMU v3 components.
PATCH (12) refactors the ARM SMMU v1/v2 driver so that the init functions
are split in a way that groups together code that probes
through DT and code that carries out HW registers FW agnostic
probing, in preparation for adding the ACPI probing path.
PATCH (13) adds ARM SMMU v1/v2 IORT IOMMU operations to create and
probe ARM SMMU v1/v2 components.
PATCH (14) Extend the IORT iort_node_map_rid() to work on a type mask
instead of a single type so that the translation API can
be used on a range of components.
PATCH (15) Add IORT API to carry out id mappings for components that do
do not have an input identifier/RIDs (ie named components).
PATCH (16) provides IORT infrastructure to carry out IOMMU configuration
for devices and hook it up to the previously introduced ACPI
DMA configure API.
This patchset is provided for review/testing purposes here:
git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v6
Tested on Juno and FVP models for ARM SMMU v1 and v3 probing path.
Lorenzo Pieralisi (16):
drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
drivers: acpi: iort: introduce linker section for IORT entries probing
drivers: acpi: iort: add support for IOMMU fwnode registration
drivers: iommu: make of_iommu_set/get_ops() DT agnostic
drivers: iommu: arm-smmu: convert struct device of_node to fwnode
usage
drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode
usage
drivers: acpi: implement acpi_dma_configure
drivers: acpi: iort: add node match function
drivers: acpi: iort: add support for ARM SMMU platform devices
creation
drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu-v3: add IORT configuration
drivers: iommu: arm-smmu: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu: add IORT configuration
drivers: acpi: iort: replace rid map type with type mask
drivers: acpi: iort: add single mapping function
drivers: acpi: iort: introduce iort_iommu_configure
drivers/acpi/arm64/iort.c | 586 +++++++++++++++++++++++++++++++++++++-
drivers/acpi/glue.c | 4 +-
drivers/acpi/scan.c | 45 +++
drivers/iommu/arm-smmu-v3.c | 105 +++++--
drivers/iommu/arm-smmu.c | 155 ++++++++--
drivers/iommu/iommu.c | 43 +++
drivers/iommu/of_iommu.c | 39 ---
drivers/pci/probe.c | 3 +-
include/acpi/acpi_bus.h | 2 +
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi.h | 26 ++
include/linux/acpi_iort.h | 14 +
include/linux/fwnode.h | 3 +-
include/linux/iommu.h | 14 +
include/linux/of_iommu.h | 12 +-
15 files changed, 951 insertions(+), 101 deletions(-)
--
2.10.0
^ permalink raw reply
* [RFC PATCH 1/3] ARM: dts: Add support for OX820 and Pogoplug V3
From: Rob Herring @ 2016-10-18 16:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017124001.23820-2-narmstrong@baylibre.com>
On Mon, Oct 17, 2016 at 02:39:59PM +0200, Neil Armstrong wrote:
> Add device tree for the Oxford Seminconductor OX820 SoC and the
> Cloud Engines PogoPlug v3 board.
> Add the SoC and board compatible strings to oxnas bindings.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
> Documentation/devicetree/bindings/arm/oxnas.txt | 5 +
> arch/arm/boot/dts/Makefile | 3 +-
> .../boot/dts/cloudengines-pogoplug-series-3.dts | 60 +++++
> arch/arm/boot/dts/ox820.dtsi | 259 +++++++++++++++++++++
> 4 files changed, 326 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts
> create mode 100644 arch/arm/boot/dts/ox820.dtsi
>
> diff --git a/Documentation/devicetree/bindings/arm/oxnas.txt b/Documentation/devicetree/bindings/arm/oxnas.txt
> index b9e4971..ac64e60 100644
> --- a/Documentation/devicetree/bindings/arm/oxnas.txt
> +++ b/Documentation/devicetree/bindings/arm/oxnas.txt
> @@ -5,5 +5,10 @@ Boards with the OX810SE SoC shall have the following properties:
> Required root node property:
> compatible: "oxsemi,ox810se"
>
> +Boards with the OX820 SoC shall have the following properties:
> + Required root node property:
> + compatible: "oxsemi,ox820"
> +
> Board compatible values:
> - "wd,mbwe" (OX810SE)
> + - "cloudengines,pogoplugv3" (OX820)
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index faacd52..5d9e8d5 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -588,7 +588,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
> dtb-$(CONFIG_ARCH_PRIMA2) += \
> prima2-evb.dtb
> dtb-$(CONFIG_ARCH_OXNAS) += \
> - wd-mbwe.dtb
> + wd-mbwe.dtb \
> + cloudengines-pogoplug-series-3.dtb
> dtb-$(CONFIG_ARCH_QCOM) += \
> qcom-apq8060-dragonboard.dtb \
> qcom-apq8064-arrow-sd-600eval.dtb \
> diff --git a/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts b/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts
> new file mode 100644
> index 0000000..78d9149
> --- /dev/null
> +++ b/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts
> @@ -0,0 +1,60 @@
> +/*
> + * cloudengines-pogoplug-series-3.dtsi - Device tree file for Cloud Engines PogoPlug Series 3
> + *
> + * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
> + *
> + * Licensed under GPLv2 or later
> + */
> +
> +/dts-v1/;
> +#include "ox820.dtsi"
> +
> +/ {
> + model = "Cloud Engines PogoPlug Series 3";
> +
> + compatible = "cloudengines,pogoplugv3", "oxsemi,ox820";
> +
> + chosen {
> + bootargs = "console=ttyS0,115200n8 earlyprintk=serial";
Use stdout-path and I don't think "earlyprintk=serial" is valid.
With that,
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 2/3] clk: hisilicon: add CRG driver for Hi3516CV300 SoC
From: Rob Herring @ 2016-10-18 15:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017120705.3726-3-wenpan@hisilicon.com>
On Mon, Oct 17, 2016 at 08:07:04PM +0800, Pan Wen wrote:
> Add CRG driver for Hi3516CV300 SoC. CRG(Clock and Reset
> Generator) module generates clock and reset signals used
> by other module blocks on SoC.
>
> Signed-off-by: Pan Wen <wenpan@hisilicon.com>
> ---
> .../devicetree/bindings/clock/hisi-crg.txt | 50 ++++
> drivers/clk/hisilicon/Kconfig | 8 +
> drivers/clk/hisilicon/Makefile | 1 +
> drivers/clk/hisilicon/crg-hi3516cv300.c | 330 +++++++++++++++++++++
> drivers/clk/hisilicon/crg.h | 34 +++
> include/dt-bindings/clock/hi3516cv300-clock.h | 48 +++
> 6 files changed, 471 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/hisi-crg.txt
> create mode 100644 drivers/clk/hisilicon/crg-hi3516cv300.c
> create mode 100644 drivers/clk/hisilicon/crg.h
> create mode 100644 include/dt-bindings/clock/hi3516cv300-clock.h
>
> diff --git a/Documentation/devicetree/bindings/clock/hisi-crg.txt b/Documentation/devicetree/bindings/clock/hisi-crg.txt
> new file mode 100644
> index 0000000..cc60b3d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/hisi-crg.txt
> @@ -0,0 +1,50 @@
> +* HiSilicon Clock and Reset Generator(CRG)
Seems kind of generic given there's already various HiSi clock bindings
documented.
> +
> +The CRG module provides clock and reset signals to various
> +modules within the SoC.
> +
> +This binding uses the following bindings:
> + Documentation/devicetree/bindings/clock/clock-bindings.txt
> + Documentation/devicetree/bindings/reset/reset.txt
> +
> +Required Properties:
> +
> +- compatible: should be one of the following.
> + - "hisilicon,hi3516cv300-crg"
> + - "hisilicon,hi3516cv300-sysctrl"
> + - "hisilicon,hi3519-crg"
There is already a binding for this. Please merge them.
> + - "hisilicon,hi3798cv200-crg"
> + - "hisilicon,hi3798cv200-sysctrl"
> +
> +- reg: physical base address of the controller and length of memory mapped
> + region.
> +
> +- #clock-cells: should be 1.
> +
> +Each clock is assigned an identifier and client nodes use this identifier
> +to specify the clock which they consume.
> +
> +All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
> +
> +- #reset-cells: should be 2.
> +
> +A reset signal can be controlled by writing a bit register in the CRG module.
> +The reset specifier consists of two cells. The first cell represents the
> +register offset relative to the base address. The second cell represents the
> +bit index in the register.
> +
> +Example: CRG nodes
> +CRG: clock-reset-controller at 12010000 {
> + compatible = "hisilicon,hi3519-crg";
> + reg = <0x12010000 0x10000>;
> + #clock-cells = <1>;
> + #reset-cells = <2>;
> +};
> +
> +Example: consumer nodes
> +i2c0: i2c at 12110000 {
> + compatible = "hisilicon,hi3519-i2c";
> + reg = <0x12110000 0x1000>;
> + clocks = <&CRG HI3519_I2C0_RST>;
> + resets = <&CRG 0xe4 0>;
> +};
^ permalink raw reply
* [PATCH 2/2] scripts/gdb: fixup some pep8 errors in proc.py
From: Peter Griffin @ 2016-10-18 15:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <477b66cc-05dc-57fa-38fb-f80510935c2e@bingham.xyz>
Hi Kieran,
On Tue, 18 Oct 2016, Kieran Bingham wrote:
> Hi Pete,
>
> On 18/10/16 16:07, Peter Griffin wrote:
> > proc.py:22:1: E302 expected 2 blank lines, found 1
> > proc.py:200:1: E302 expected 2 blank lines, found 1
> >
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> > scripts/gdb/linux/proc.py | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
> > index f20fcfa..2d6f74e 100644
> > --- a/scripts/gdb/linux/proc.py
> > +++ b/scripts/gdb/linux/proc.py
> > @@ -18,6 +18,7 @@ from linux import tasks
> > from linux import lists
> > from struct import *
> >
> > +
>
> This was added by patch 1, and can be squashed there.
Doh, I had deliberately done it as a separate commit, as I thought it was
a pre-existing pep8 error.
Will squash in v2.
regards,
Peter.
^ permalink raw reply
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Kieran Bingham @ 2016-10-18 15:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476803249-23328-1-git-send-email-peter.griffin@linaro.org>
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?
> (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 ?
> +
> +LxFdtDump()
>
--
Regards
Kieran Bingham
^ permalink raw reply
* [PATCH 1/2] scripts/gdb: add lx-fdtdump command
From: Jan Kiszka @ 2016-10-18 15:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476803249-23328-1-git-send-email-peter.griffin@linaro.org>
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.
> +
> + 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")
> +
> +LxFdtDump()
>
Jan
--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
^ permalink raw reply
* [PATCHv4 15/15] clk: ti: omap4: cleanup unnecessary clock aliases
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Cleanup any unnecessary DT_CLK() alias entries from the OMAP4 clock file.
Most of these are now handled dynamically by the driver code.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/clk/ti/clk-44xx.c | 186 ----------------------------------------------
1 file changed, 186 deletions(-)
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index b482047..72a3622 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -1435,196 +1435,13 @@
};
static struct ti_dt_clk omap44xx_clks[] = {
- DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
- DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
- DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"),
- DT_CLK(NULL, "pad_slimbus_core_clks_ck", "pad_slimbus_core_clks_ck"),
- DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"),
- DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"),
- DT_CLK(NULL, "slimbus_clk", "slimbus_clk"),
- DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
- DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"),
- DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"),
- DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"),
- DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
- DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
- DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"),
- DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"),
- DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"),
- DT_CLK(NULL, "tie_low_clock_ck", "tie_low_clock_ck"),
- DT_CLK(NULL, "utmi_phy_clkout_ck", "utmi_phy_clkout_ck"),
- DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"),
- DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"),
- DT_CLK(NULL, "xclk60motg_ck", "xclk60motg_ck"),
- DT_CLK(NULL, "abe_dpll_bypass_clk_mux_ck", "abe_dpll_bypass_clk_mux_ck"),
- DT_CLK(NULL, "abe_dpll_refclk_mux_ck", "abe_dpll_refclk_mux_ck"),
- DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"),
- DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"),
- DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"),
- DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"),
- DT_CLK(NULL, "abe_clk", "abe_clk"),
- DT_CLK(NULL, "aess_fclk", "aess_fclk"),
- DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"),
- DT_CLK(NULL, "core_hsd_byp_clk_mux_ck", "core_hsd_byp_clk_mux_ck"),
- DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
- DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
- DT_CLK(NULL, "dpll_core_m6x2_ck", "dpll_core_m6x2_ck"),
- DT_CLK(NULL, "dbgclk_mux_ck", "dbgclk_mux_ck"),
- DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"),
- DT_CLK(NULL, "ddrphy_ck", "ddrphy_ck"),
- DT_CLK(NULL, "dpll_core_m5x2_ck", "dpll_core_m5x2_ck"),
- DT_CLK(NULL, "div_core_ck", "div_core_ck"),
- DT_CLK(NULL, "div_iva_hs_clk", "div_iva_hs_clk"),
- DT_CLK(NULL, "div_mpu_hs_clk", "div_mpu_hs_clk"),
- DT_CLK(NULL, "dpll_core_m4x2_ck", "dpll_core_m4x2_ck"),
- DT_CLK(NULL, "dll_clk_div_ck", "dll_clk_div_ck"),
- DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"),
- DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"),
- DT_CLK(NULL, "dpll_core_m7x2_ck", "dpll_core_m7x2_ck"),
- DT_CLK(NULL, "iva_hsd_byp_clk_mux_ck", "iva_hsd_byp_clk_mux_ck"),
- DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"),
- DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"),
- DT_CLK(NULL, "dpll_iva_m4x2_ck", "dpll_iva_m4x2_ck"),
- DT_CLK(NULL, "dpll_iva_m5x2_ck", "dpll_iva_m5x2_ck"),
- DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
- DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
- DT_CLK(NULL, "per_hs_clk_div_ck", "per_hs_clk_div_ck"),
- DT_CLK(NULL, "per_hsd_byp_clk_mux_ck", "per_hsd_byp_clk_mux_ck"),
- DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
- DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
- DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"),
- DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"),
- DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"),
- DT_CLK(NULL, "dpll_per_m4x2_ck", "dpll_per_m4x2_ck"),
- DT_CLK(NULL, "dpll_per_m5x2_ck", "dpll_per_m5x2_ck"),
- DT_CLK(NULL, "dpll_per_m6x2_ck", "dpll_per_m6x2_ck"),
- DT_CLK(NULL, "dpll_per_m7x2_ck", "dpll_per_m7x2_ck"),
- DT_CLK(NULL, "usb_hs_clk_div_ck", "usb_hs_clk_div_ck"),
- DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"),
- DT_CLK(NULL, "dpll_usb_clkdcoldo_ck", "dpll_usb_clkdcoldo_ck"),
- DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"),
- DT_CLK(NULL, "ducati_clk_mux_ck", "ducati_clk_mux_ck"),
- DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"),
- DT_CLK(NULL, "func_24m_clk", "func_24m_clk"),
- DT_CLK(NULL, "func_24mc_fclk", "func_24mc_fclk"),
- DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"),
- DT_CLK(NULL, "func_48mc_fclk", "func_48mc_fclk"),
- DT_CLK(NULL, "func_64m_fclk", "func_64m_fclk"),
- DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"),
- DT_CLK(NULL, "init_60m_fclk", "init_60m_fclk"),
- DT_CLK(NULL, "l3_div_ck", "l3_div_ck"),
- DT_CLK(NULL, "l4_div_ck", "l4_div_ck"),
- DT_CLK(NULL, "lp_clk_div_ck", "lp_clk_div_ck"),
- DT_CLK(NULL, "l4_wkup_clk_mux_ck", "l4_wkup_clk_mux_ck"),
DT_CLK("smp_twd", NULL, "mpu_periphclk"),
- DT_CLK(NULL, "ocp_abe_iclk", "ocp_abe_iclk"),
- DT_CLK(NULL, "per_abe_24m_fclk", "per_abe_24m_fclk"),
- DT_CLK(NULL, "per_abe_nc_fclk", "per_abe_nc_fclk"),
- DT_CLK(NULL, "syc_clk_div_ck", "syc_clk_div_ck"),
- DT_CLK(NULL, "aes1_fck", "aes1_fck"),
- DT_CLK(NULL, "aes2_fck", "aes2_fck"),
- DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"),
- DT_CLK(NULL, "func_dmic_abe_gfclk", "func_dmic_abe_gfclk"),
- DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"),
- DT_CLK(NULL, "dss_tv_clk", "dss_tv_clk"),
- DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"),
- DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"),
- DT_CLK(NULL, "dss_fck", "dss_fck"),
DT_CLK("omapdss_dss", "ick", "dss_fck"),
- DT_CLK(NULL, "fdif_fck", "fdif_fck"),
- DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
- DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
- DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
- DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
- DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
- DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"),
- DT_CLK(NULL, "sgx_clk_mux", "sgx_clk_mux"),
- DT_CLK(NULL, "hsi_fck", "hsi_fck"),
- DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"),
- DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"),
- DT_CLK(NULL, "func_mcasp_abe_gfclk", "func_mcasp_abe_gfclk"),
- DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"),
- DT_CLK(NULL, "func_mcbsp1_gfclk", "func_mcbsp1_gfclk"),
- DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"),
- DT_CLK(NULL, "func_mcbsp2_gfclk", "func_mcbsp2_gfclk"),
- DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"),
- DT_CLK(NULL, "func_mcbsp3_gfclk", "func_mcbsp3_gfclk"),
- DT_CLK(NULL, "mcbsp4_sync_mux_ck", "mcbsp4_sync_mux_ck"),
- DT_CLK(NULL, "per_mcbsp4_gfclk", "per_mcbsp4_gfclk"),
- DT_CLK(NULL, "hsmmc1_fclk", "hsmmc1_fclk"),
- DT_CLK(NULL, "hsmmc2_fclk", "hsmmc2_fclk"),
- DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "ocp2scp_usb_phy_phy_48m"),
- DT_CLK(NULL, "sha2md5_fck", "sha2md5_fck"),
- DT_CLK(NULL, "slimbus1_fclk_1", "slimbus1_fclk_1"),
- DT_CLK(NULL, "slimbus1_fclk_0", "slimbus1_fclk_0"),
- DT_CLK(NULL, "slimbus1_fclk_2", "slimbus1_fclk_2"),
- DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"),
- DT_CLK(NULL, "slimbus2_fclk_1", "slimbus2_fclk_1"),
- DT_CLK(NULL, "slimbus2_fclk_0", "slimbus2_fclk_0"),
- DT_CLK(NULL, "slimbus2_slimbus_clk", "slimbus2_slimbus_clk"),
- DT_CLK(NULL, "smartreflex_core_fck", "smartreflex_core_fck"),
- DT_CLK(NULL, "smartreflex_iva_fck", "smartreflex_iva_fck"),
- DT_CLK(NULL, "smartreflex_mpu_fck", "smartreflex_mpu_fck"),
- DT_CLK(NULL, "dmt1_clk_mux", "dmt1_clk_mux"),
- DT_CLK(NULL, "cm2_dm10_mux", "cm2_dm10_mux"),
- DT_CLK(NULL, "cm2_dm11_mux", "cm2_dm11_mux"),
- DT_CLK(NULL, "cm2_dm2_mux", "cm2_dm2_mux"),
- DT_CLK(NULL, "cm2_dm3_mux", "cm2_dm3_mux"),
- DT_CLK(NULL, "cm2_dm4_mux", "cm2_dm4_mux"),
- DT_CLK(NULL, "timer5_sync_mux", "timer5_sync_mux"),
- DT_CLK(NULL, "timer6_sync_mux", "timer6_sync_mux"),
- DT_CLK(NULL, "timer7_sync_mux", "timer7_sync_mux"),
- DT_CLK(NULL, "timer8_sync_mux", "timer8_sync_mux"),
- DT_CLK(NULL, "cm2_dm9_mux", "cm2_dm9_mux"),
- DT_CLK(NULL, "usb_host_fs_fck", "usb_host_fs_fck"),
DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
- DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"),
- DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"),
- DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"),
- DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"),
- DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"),
- DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"),
- DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"),
- DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"),
- DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"),
- DT_CLK(NULL, "usb_host_hs_func48mclk", "usb_host_hs_func48mclk"),
- DT_CLK(NULL, "usb_host_hs_fck", "usb_host_hs_fck"),
DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
- DT_CLK(NULL, "otg_60m_gfclk", "otg_60m_gfclk"),
- DT_CLK(NULL, "usb_otg_hs_xclk", "usb_otg_hs_xclk"),
- DT_CLK(NULL, "usb_otg_hs_ick", "usb_otg_hs_ick"),
DT_CLK("musb-omap2430", "ick", "usb_otg_hs_ick"),
- DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"),
- DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"),
- DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"),
- DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"),
- DT_CLK(NULL, "usb_tll_hs_ick", "usb_tll_hs_ick"),
DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
- DT_CLK(NULL, "usim_ck", "usim_ck"),
- DT_CLK(NULL, "usim_fclk", "usim_fclk"),
- DT_CLK(NULL, "pmd_stm_clock_mux_ck", "pmd_stm_clock_mux_ck"),
- DT_CLK(NULL, "pmd_trace_clk_mux_ck", "pmd_trace_clk_mux_ck"),
- DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"),
- DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"),
- DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"),
- DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"),
- DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"),
- DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"),
- DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"),
- DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"),
- DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"),
- DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"),
- DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"),
- DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"),
- DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"),
- DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"),
- DT_CLK(NULL, "auxclk4_src_ck", "auxclk4_src_ck"),
- DT_CLK(NULL, "auxclk4_ck", "auxclk4_ck"),
- DT_CLK(NULL, "auxclkreq4_ck", "auxclkreq4_ck"),
- DT_CLK(NULL, "auxclk5_src_ck", "auxclk5_src_ck"),
- DT_CLK(NULL, "auxclk5_ck", "auxclk5_ck"),
- DT_CLK(NULL, "auxclkreq5_ck", "auxclkreq5_ck"),
DT_CLK("omap_i2c.1", "ick", "dummy_ck"),
DT_CLK("omap_i2c.2", "ick", "dummy_ck"),
DT_CLK("omap_i2c.3", "ick", "dummy_ck"),
@@ -1664,9 +1481,6 @@
DT_CLK("4013c000.timer", "timer_sys_ck", "syc_clk_div_ck"),
DT_CLK("4013e000.timer", "timer_sys_ck", "syc_clk_div_ck"),
DT_CLK(NULL, "cpufreq_ck", "dpll_mpu_ck"),
- DT_CLK(NULL, "bandgap_fclk", "bandgap_fclk"),
- DT_CLK(NULL, "div_ts_ck", "div_ts_ck"),
- DT_CLK(NULL, "bandgap_ts_fclk", "bandgap_ts_fclk"),
{ .node_name = NULL },
};
--
1.9.1
^ permalink raw reply related
* [PATCHv4 14/15] clk: ti: omap4: add hwmod clock data
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Add hwmod clock data for omap4 SoC. This data is basically a conversion
of the existing hwmod data to clock format.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/clk/ti/clk-44xx.c | 1403 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1403 insertions(+)
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index 7a8b51b..b482047 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk/ti.h>
+#include <dt-bindings/clock/ti,omap44xx.h>
#include "clock.h"
@@ -33,6 +34,1406 @@
*/
#define OMAP4_DPLL_USB_DEFFREQ 960000000
+static struct ti_clk_hwmod mpu_mod_ck_data = {
+ .reg = OMAP44XX_MPUSS_MPU,
+ .parent = "dpll_mpu_m2_ck",
+};
+
+static struct ti_clk mpu_mod_ck = {
+ .name = "mpu_mod_ck",
+ .clkdm_name = "mpuss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mpu_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dsp_mod_ck_data = {
+ .reg = OMAP44XX_TESLA_DSP,
+ .parent = "dpll_iva_m4x2_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk dsp_mod_ck = {
+ .name = "dsp_mod_ck",
+ .clkdm_name = "tesla_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dsp_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmu_dsp_mod_ck_data = {
+ .reg = OMAP44XX_TESLA_MMU_DSP,
+ .parent = "dpll_iva_m4x2_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk mmu_dsp_mod_ck = {
+ .name = "mmu_dsp_mod_ck",
+ .clkdm_name = "tesla_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmu_dsp_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l4_abe_mod_ck_data = {
+ .reg = OMAP44XX_ABE_L4_ABE,
+ .parent = "ocp_abe_iclk",
+};
+
+static struct ti_clk l4_abe_mod_ck = {
+ .name = "l4_abe_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l4_abe_mod_ck_data,
+};
+
+static struct ti_clk_hwmod aess_mod_ck_data = {
+ .reg = OMAP44XX_ABE_AESS,
+ .parent = "aess_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk aess_mod_ck = {
+ .name = "aess_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &aess_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcpdm_mod_ck_data = {
+ .reg = OMAP44XX_ABE_MCPDM,
+ .parent = "pad_clks_ck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcpdm_mod_ck = {
+ .name = "mcpdm_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcpdm_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dmic_mod_ck_data = {
+ .reg = OMAP44XX_ABE_DMIC,
+ .parent = "func_dmic_abe_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk dmic_mod_ck = {
+ .name = "dmic_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dmic_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcasp_mod_ck_data = {
+ .reg = OMAP44XX_ABE_MCASP,
+ .parent = "func_mcasp_abe_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcasp_mod_ck = {
+ .name = "mcasp_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcasp_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcbsp1_mod_ck_data = {
+ .reg = OMAP44XX_ABE_MCBSP1,
+ .parent = "func_mcbsp1_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcbsp1_mod_ck = {
+ .name = "mcbsp1_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcbsp1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcbsp2_mod_ck_data = {
+ .reg = OMAP44XX_ABE_MCBSP2,
+ .parent = "func_mcbsp2_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcbsp2_mod_ck = {
+ .name = "mcbsp2_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcbsp2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcbsp3_mod_ck_data = {
+ .reg = OMAP44XX_ABE_MCBSP3,
+ .parent = "func_mcbsp3_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcbsp3_mod_ck = {
+ .name = "mcbsp3_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcbsp3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod slimbus1_mod_ck_data = {
+ .reg = OMAP44XX_ABE_SLIMBUS1,
+ .parent = "slimbus1_fclk_0",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk slimbus1_mod_ck = {
+ .name = "slimbus1_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &slimbus1_mod_ck_data,
+};
+
+static const char * const timer5_mod_ck_parents[] = {
+ "syc_clk_div_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer5_mod_ck_data = {
+ .mod_reg = OMAP44XX_ABE_TIMER5,
+ .mux_reg = OMAP44XX_ABE_TIMER5,
+ .shift = 24,
+ .parents = timer5_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer5_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer5_mod_ck = {
+ .name = "timer5_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer5_mod_ck_data,
+};
+
+static const char * const timer6_mod_ck_parents[] = {
+ "syc_clk_div_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer6_mod_ck_data = {
+ .mod_reg = OMAP44XX_ABE_TIMER6,
+ .mux_reg = OMAP44XX_ABE_TIMER6,
+ .shift = 24,
+ .parents = timer6_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer6_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer6_mod_ck = {
+ .name = "timer6_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer6_mod_ck_data,
+};
+
+static const char * const timer7_mod_ck_parents[] = {
+ "syc_clk_div_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer7_mod_ck_data = {
+ .mod_reg = OMAP44XX_ABE_TIMER7,
+ .mux_reg = OMAP44XX_ABE_TIMER7,
+ .shift = 24,
+ .parents = timer7_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer7_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer7_mod_ck = {
+ .name = "timer7_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer7_mod_ck_data,
+};
+
+static const char * const timer8_mod_ck_parents[] = {
+ "syc_clk_div_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer8_mod_ck_data = {
+ .mod_reg = OMAP44XX_ABE_TIMER8,
+ .mux_reg = OMAP44XX_ABE_TIMER8,
+ .shift = 24,
+ .parents = timer8_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer8_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer8_mod_ck = {
+ .name = "timer8_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer8_mod_ck_data,
+};
+
+static struct ti_clk_hwmod wd_timer3_mod_ck_data = {
+ .reg = OMAP44XX_ABE_WD_TIMER3,
+ .parent = "sys_32k_ck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk wd_timer3_mod_ck = {
+ .name = "wd_timer3_mod_ck",
+ .clkdm_name = "abe_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &wd_timer3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l4_wkup_mod_ck_data = {
+ .reg = OMAP44XX_L4_WKUP_L4_WKUP,
+ .parent = "l4_wkup_clk_mux_ck",
+};
+
+static struct ti_clk l4_wkup_mod_ck = {
+ .name = "l4_wkup_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l4_wkup_mod_ck_data,
+};
+
+static struct ti_clk_hwmod wd_timer2_mod_ck_data = {
+ .reg = OMAP44XX_L4_WKUP_WD_TIMER2,
+ .parent = "sys_32k_ck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk wd_timer2_mod_ck = {
+ .name = "wd_timer2_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &wd_timer2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio1_mod_ck_data = {
+ .reg = OMAP44XX_L4_WKUP_GPIO1,
+ .parent = "l4_wkup_clk_mux_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio1_mod_ck = {
+ .name = "gpio1_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio1_mod_ck_data,
+};
+
+static const char * const timer1_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer1_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_WKUP_TIMER1,
+ .mux_reg = OMAP44XX_L4_WKUP_TIMER1,
+ .shift = 24,
+ .parents = timer1_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer1_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer1_mod_ck = {
+ .name = "timer1_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod counter_32k_mod_ck_data = {
+ .reg = OMAP44XX_L4_WKUP_COUNTER_32K,
+ .parent = "sys_32k_ck",
+};
+
+static struct ti_clk counter_32k_mod_ck = {
+ .name = "counter_32k_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &counter_32k_mod_ck_data,
+};
+
+static struct ti_clk_hwmod kbd_mod_ck_data = {
+ .reg = OMAP44XX_L4_WKUP_KBD,
+ .parent = "sys_32k_ck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk kbd_mod_ck = {
+ .name = "kbd_mod_ck",
+ .clkdm_name = "l4_wkup_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &kbd_mod_ck_data,
+};
+
+static struct ti_clk_hwmod debugss_mod_ck_data = {
+ .reg = OMAP44XX_EMU_SYS_DEBUGSS,
+ .parent = "trace_clk_div_ck",
+};
+
+static struct ti_clk debugss_mod_ck = {
+ .name = "debugss_mod_ck",
+ .clkdm_name = "emu_sys_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &debugss_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_core_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_CORE,
+ .parent = "dss_dss_clk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk dss_core_mod_ck = {
+ .name = "dss_core_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_core_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_venc_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_VENC,
+ .parent = "dss_tv_clk",
+};
+
+static struct ti_clk dss_venc_mod_ck = {
+ .name = "dss_venc_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_venc_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_dispc_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_DISPC,
+ .parent = "dss_dss_clk",
+};
+
+static struct ti_clk dss_dispc_mod_ck = {
+ .name = "dss_dispc_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_dispc_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_dsi1_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_DSI1,
+ .parent = "dss_dss_clk",
+};
+
+static struct ti_clk dss_dsi1_mod_ck = {
+ .name = "dss_dsi1_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_dsi1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_rfbi_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_RFBI,
+ .parent = "dss_dss_clk",
+};
+
+static struct ti_clk dss_rfbi_mod_ck = {
+ .name = "dss_rfbi_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_rfbi_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_dsi2_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_DSI2,
+ .parent = "dss_dss_clk",
+};
+
+static struct ti_clk dss_dsi2_mod_ck = {
+ .name = "dss_dsi2_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_dsi2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dss_hdmi_mod_ck_data = {
+ .reg = OMAP44XX_L3_DSS_DSS_HDMI,
+ .parent = "dss_48mhz_clk",
+};
+
+static struct ti_clk dss_hdmi_mod_ck = {
+ .name = "dss_hdmi_mod_ck",
+ .clkdm_name = "l3_dss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dss_hdmi_mod_ck_data,
+};
+
+static struct ti_clk_hwmod fdif_mod_ck_data = {
+ .reg = OMAP44XX_ISS_FDIF,
+ .parent = "fdif_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk fdif_mod_ck = {
+ .name = "fdif_mod_ck",
+ .clkdm_name = "iss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &fdif_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio2_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_GPIO2,
+ .parent = "l4_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio2_mod_ck = {
+ .name = "gpio2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio3_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_GPIO3,
+ .parent = "l4_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio3_mod_ck = {
+ .name = "gpio3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_GPIO4,
+ .parent = "l4_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio4_mod_ck = {
+ .name = "gpio4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio5_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_GPIO5,
+ .parent = "l4_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio5_mod_ck = {
+ .name = "gpio5_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio5_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpio6_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_GPIO6,
+ .parent = "l4_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpio6_mod_ck = {
+ .name = "gpio6_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpio6_mod_ck_data,
+};
+
+static struct ti_clk_hwmod hdq1w_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_HDQ1W,
+ .parent = "func_12m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk hdq1w_mod_ck = {
+ .name = "hdq1w_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &hdq1w_mod_ck_data,
+};
+
+static struct ti_clk_hwmod i2c1_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_I2C1,
+ .parent = "func_96m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk i2c1_mod_ck = {
+ .name = "i2c1_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &i2c1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod i2c2_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_I2C2,
+ .parent = "func_96m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk i2c2_mod_ck = {
+ .name = "i2c2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &i2c2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod i2c3_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_I2C3,
+ .parent = "func_96m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk i2c3_mod_ck = {
+ .name = "i2c3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &i2c3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod i2c4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_I2C4,
+ .parent = "func_96m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk i2c4_mod_ck = {
+ .name = "i2c4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &i2c4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l4_per_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_L4_PER,
+ .parent = "l4_div_ck",
+};
+
+static struct ti_clk l4_per_mod_ck = {
+ .name = "l4_per_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l4_per_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpu_mod_ck_data = {
+ .reg = OMAP44XX_L3_GFX_GPU,
+ .parent = "sgx_clk_mux",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk gpu_mod_ck = {
+ .name = "gpu_mod_ck",
+ .clkdm_name = "l3_gfx_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpu_mod_ck_data,
+};
+
+static struct ti_clk_hwmod hsi_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_HSI,
+ .parent = "hsi_fck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk hsi_mod_ck = {
+ .name = "hsi_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &hsi_mod_ck_data,
+};
+
+static struct ti_clk_hwmod iss_mod_ck_data = {
+ .reg = OMAP44XX_ISS_ISS,
+ .parent = "ducati_clk_mux_ck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk iss_mod_ck = {
+ .name = "iss_mod_ck",
+ .clkdm_name = "iss_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &iss_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcbsp4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MCBSP4,
+ .parent = "per_mcbsp4_gfclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcbsp4_mod_ck = {
+ .name = "mcbsp4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcbsp4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcspi1_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MCSPI1,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcspi1_mod_ck = {
+ .name = "mcspi1_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcspi1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcspi2_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MCSPI2,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcspi2_mod_ck = {
+ .name = "mcspi2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcspi2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcspi3_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MCSPI3,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcspi3_mod_ck = {
+ .name = "mcspi3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcspi3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mcspi4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MCSPI4,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mcspi4_mod_ck = {
+ .name = "mcspi4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mcspi4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmc3_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MMC3,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mmc3_mod_ck = {
+ .name = "mmc3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmc3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmc4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MMC4,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mmc4_mod_ck = {
+ .name = "mmc4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmc4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmc1_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_MMC1,
+ .parent = "hsmmc1_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mmc1_mod_ck = {
+ .name = "mmc1_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmc1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmc2_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_MMC2,
+ .parent = "hsmmc2_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mmc2_mod_ck = {
+ .name = "mmc2_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmc2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod ocp2scp_usb_phy_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_OCP2SCP_USB_PHY,
+ .parent = "ocp2scp_usb_phy_phy_48m",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk ocp2scp_usb_phy_mod_ck = {
+ .name = "ocp2scp_usb_phy_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &ocp2scp_usb_phy_mod_ck_data,
+};
+
+static const char * const timer10_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer10_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER10,
+ .mux_reg = OMAP44XX_L4_PER_TIMER10,
+ .shift = 24,
+ .parents = timer10_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer10_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer10_mod_ck = {
+ .name = "timer10_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer10_mod_ck_data,
+};
+
+static const char * const timer11_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer11_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER11,
+ .mux_reg = OMAP44XX_L4_PER_TIMER11,
+ .shift = 24,
+ .parents = timer11_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer11_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer11_mod_ck = {
+ .name = "timer11_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer11_mod_ck_data,
+};
+
+static const char * const timer2_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer2_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER2,
+ .mux_reg = OMAP44XX_L4_PER_TIMER2,
+ .shift = 24,
+ .parents = timer2_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer2_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer2_mod_ck = {
+ .name = "timer2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer2_mod_ck_data,
+};
+
+static const char * const timer3_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer3_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER3,
+ .mux_reg = OMAP44XX_L4_PER_TIMER3,
+ .shift = 24,
+ .parents = timer3_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer3_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer3_mod_ck = {
+ .name = "timer3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer3_mod_ck_data,
+};
+
+static const char * const timer4_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer4_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER4,
+ .mux_reg = OMAP44XX_L4_PER_TIMER4,
+ .shift = 24,
+ .parents = timer4_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer4_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer4_mod_ck = {
+ .name = "timer4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer4_mod_ck_data,
+};
+
+static const char * const timer9_mod_ck_parents[] = {
+ "sys_clkin_ck",
+ "sys_32k_ck",
+};
+
+static struct ti_clk_hwmod_mux timer9_mod_ck_data = {
+ .mod_reg = OMAP44XX_L4_PER_TIMER9,
+ .mux_reg = OMAP44XX_L4_PER_TIMER9,
+ .shift = 24,
+ .parents = timer9_mod_ck_parents,
+ .num_parents = ARRAY_SIZE(timer9_mod_ck_parents),
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk timer9_mod_ck = {
+ .name = "timer9_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD_MUX,
+ .data = &timer9_mod_ck_data,
+};
+
+static struct ti_clk_hwmod elm_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_ELM,
+ .parent = "l4_div_ck",
+};
+
+static struct ti_clk elm_mod_ck = {
+ .name = "elm_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &elm_mod_ck_data,
+};
+
+static struct ti_clk_hwmod slimbus2_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_SLIMBUS2,
+ .parent = "slimbus2_fclk_0",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk slimbus2_mod_ck = {
+ .name = "slimbus2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &slimbus2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod uart1_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_UART1,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk uart1_mod_ck = {
+ .name = "uart1_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &uart1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod uart2_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_UART2,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk uart2_mod_ck = {
+ .name = "uart2_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &uart2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod uart3_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_UART3,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk uart3_mod_ck = {
+ .name = "uart3_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &uart3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod uart4_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_UART4,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk uart4_mod_ck = {
+ .name = "uart4_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &uart4_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmc5_mod_ck_data = {
+ .reg = OMAP44XX_L4_PER_MMC5,
+ .parent = "func_48m_fclk",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk mmc5_mod_ck = {
+ .name = "mmc5_mod_ck",
+ .clkdm_name = "l4_per_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmc5_mod_ck_data,
+};
+
+static struct ti_clk_hwmod smartreflex_core_mod_ck_data = {
+ .reg = OMAP44XX_L4_AO_SMARTREFLEX_CORE,
+ .parent = "smartreflex_core_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk smartreflex_core_mod_ck = {
+ .name = "smartreflex_core_mod_ck",
+ .clkdm_name = "l4_ao_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &smartreflex_core_mod_ck_data,
+};
+
+static struct ti_clk_hwmod smartreflex_iva_mod_ck_data = {
+ .reg = OMAP44XX_L4_AO_SMARTREFLEX_IVA,
+ .parent = "smartreflex_iva_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk smartreflex_iva_mod_ck = {
+ .name = "smartreflex_iva_mod_ck",
+ .clkdm_name = "l4_ao_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &smartreflex_iva_mod_ck_data,
+};
+
+static struct ti_clk_hwmod smartreflex_mpu_mod_ck_data = {
+ .reg = OMAP44XX_L4_AO_SMARTREFLEX_MPU,
+ .parent = "smartreflex_mpu_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk smartreflex_mpu_mod_ck = {
+ .name = "smartreflex_mpu_mod_ck",
+ .clkdm_name = "l4_ao_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &smartreflex_mpu_mod_ck_data,
+};
+
+static struct ti_clk_hwmod usb_host_fs_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_USB_HOST_FS,
+ .parent = "usb_host_fs_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk usb_host_fs_mod_ck = {
+ .name = "usb_host_fs_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &usb_host_fs_mod_ck_data,
+};
+
+static struct ti_clk_hwmod usb_host_hs_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_USB_HOST_HS,
+ .parent = "usb_host_hs_fck",
+ .flags = CLKF_SW_SUP,
+};
+
+static struct ti_clk usb_host_hs_mod_ck = {
+ .name = "usb_host_hs_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &usb_host_hs_mod_ck_data,
+};
+
+static struct ti_clk_hwmod usb_otg_hs_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_USB_OTG_HS,
+ .parent = "usb_otg_hs_ick",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk usb_otg_hs_mod_ck = {
+ .name = "usb_otg_hs_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &usb_otg_hs_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l3_main_1_mod_ck_data = {
+ .reg = OMAP44XX_L3_1_L3_MAIN_1,
+ .parent = "l3_div_ck",
+};
+
+static struct ti_clk l3_main_1_mod_ck = {
+ .name = "l3_main_1_mod_ck",
+ .clkdm_name = "l3_1_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l3_main_1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l3_main_2_mod_ck_data = {
+ .reg = OMAP44XX_L3_2_L3_MAIN_2,
+ .parent = "l3_div_ck",
+};
+
+static struct ti_clk l3_main_2_mod_ck = {
+ .name = "l3_main_2_mod_ck",
+ .clkdm_name = "l3_2_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l3_main_2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod gpmc_mod_ck_data = {
+ .reg = OMAP44XX_L3_2_GPMC,
+ .parent = "l3_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk gpmc_mod_ck = {
+ .name = "gpmc_mod_ck",
+ .clkdm_name = "l3_2_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &gpmc_mod_ck_data,
+};
+
+static struct ti_clk_hwmod ocmc_ram_mod_ck_data = {
+ .reg = OMAP44XX_L3_2_OCMC_RAM,
+ .parent = "l3_div_ck",
+};
+
+static struct ti_clk ocmc_ram_mod_ck = {
+ .name = "ocmc_ram_mod_ck",
+ .clkdm_name = "l3_2_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &ocmc_ram_mod_ck_data,
+};
+
+static struct ti_clk_hwmod ipu_mod_ck_data = {
+ .reg = OMAP44XX_DUCATI_IPU,
+ .parent = "ducati_clk_mux_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk ipu_mod_ck = {
+ .name = "ipu_mod_ck",
+ .clkdm_name = "ducati_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &ipu_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mmu_ipu_mod_ck_data = {
+ .reg = OMAP44XX_DUCATI_MMU_IPU,
+ .parent = "ducati_clk_mux_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk mmu_ipu_mod_ck = {
+ .name = "mmu_ipu_mod_ck",
+ .clkdm_name = "ducati_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mmu_ipu_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dma_system_mod_ck_data = {
+ .reg = OMAP44XX_L3_DMA_DMA_SYSTEM,
+ .parent = "l3_div_ck",
+};
+
+static struct ti_clk dma_system_mod_ck = {
+ .name = "dma_system_mod_ck",
+ .clkdm_name = "l3_dma_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dma_system_mod_ck_data,
+};
+
+static struct ti_clk_hwmod dmm_mod_ck_data = {
+ .reg = OMAP44XX_L3_EMIF_DMM,
+ .parent = "l3_div_ck",
+};
+
+static struct ti_clk dmm_mod_ck = {
+ .name = "dmm_mod_ck",
+ .clkdm_name = "l3_emif_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &dmm_mod_ck_data,
+};
+
+static struct ti_clk_hwmod emif1_mod_ck_data = {
+ .reg = OMAP44XX_L3_EMIF_EMIF1,
+ .parent = "ddrphy_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk emif1_mod_ck = {
+ .name = "emif1_mod_ck",
+ .clkdm_name = "l3_emif_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &emif1_mod_ck_data,
+};
+
+static struct ti_clk_hwmod emif2_mod_ck_data = {
+ .reg = OMAP44XX_L3_EMIF_EMIF2,
+ .parent = "ddrphy_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk emif2_mod_ck = {
+ .name = "emif2_mod_ck",
+ .clkdm_name = "l3_emif_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &emif2_mod_ck_data,
+};
+
+static struct ti_clk_hwmod c2c_mod_ck_data = {
+ .reg = OMAP44XX_D2D_C2C,
+ .parent = "div_core_ck",
+};
+
+static struct ti_clk c2c_mod_ck = {
+ .name = "c2c_mod_ck",
+ .clkdm_name = "d2d_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &c2c_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l4_cfg_mod_ck_data = {
+ .reg = OMAP44XX_L4_CFG_L4_CFG,
+ .parent = "l4_div_ck",
+};
+
+static struct ti_clk l4_cfg_mod_ck = {
+ .name = "l4_cfg_mod_ck",
+ .clkdm_name = "l4_cfg_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l4_cfg_mod_ck_data,
+};
+
+static struct ti_clk_hwmod spinlock_mod_ck_data = {
+ .reg = OMAP44XX_L4_CFG_SPINLOCK,
+ .parent = "l4_div_ck",
+};
+
+static struct ti_clk spinlock_mod_ck = {
+ .name = "spinlock_mod_ck",
+ .clkdm_name = "l4_cfg_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &spinlock_mod_ck_data,
+};
+
+static struct ti_clk_hwmod mailbox_mod_ck_data = {
+ .reg = OMAP44XX_L4_CFG_MAILBOX,
+ .parent = "l4_div_ck",
+};
+
+static struct ti_clk mailbox_mod_ck = {
+ .name = "mailbox_mod_ck",
+ .clkdm_name = "l4_cfg_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &mailbox_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l3_main_3_mod_ck_data = {
+ .reg = OMAP44XX_L3_INSTR_L3_MAIN_3,
+ .parent = "l3_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk l3_main_3_mod_ck = {
+ .name = "l3_main_3_mod_ck",
+ .clkdm_name = "l3_instr_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l3_main_3_mod_ck_data,
+};
+
+static struct ti_clk_hwmod l3_instr_mod_ck_data = {
+ .reg = OMAP44XX_L3_INSTR_L3_INSTR,
+ .parent = "l3_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk l3_instr_mod_ck = {
+ .name = "l3_instr_mod_ck",
+ .clkdm_name = "l3_instr_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &l3_instr_mod_ck_data,
+};
+
+static struct ti_clk_hwmod ocp_wp_noc_mod_ck_data = {
+ .reg = OMAP44XX_L3_INSTR_OCP_WP_NOC,
+ .parent = "l3_div_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk ocp_wp_noc_mod_ck = {
+ .name = "ocp_wp_noc_mod_ck",
+ .clkdm_name = "l3_instr_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &ocp_wp_noc_mod_ck_data,
+};
+
+static struct ti_clk_hwmod iva_mod_ck_data = {
+ .reg = OMAP44XX_IVAHD_IVA,
+ .parent = "dpll_iva_m5x2_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk iva_mod_ck = {
+ .name = "iva_mod_ck",
+ .clkdm_name = "ivahd_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &iva_mod_ck_data,
+};
+
+static struct ti_clk_hwmod sl2if_mod_ck_data = {
+ .reg = OMAP44XX_IVAHD_SL2IF,
+ .parent = "dpll_iva_m5x2_ck",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk sl2if_mod_ck = {
+ .name = "sl2if_mod_ck",
+ .clkdm_name = "ivahd_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &sl2if_mod_ck_data,
+};
+
+static struct ti_clk_hwmod usb_tll_hs_mod_ck_data = {
+ .reg = OMAP44XX_L3_INIT_USB_TLL_HS,
+ .parent = "usb_tll_hs_ick",
+ .flags = CLKF_HW_SUP,
+};
+
+static struct ti_clk usb_tll_hs_mod_ck = {
+ .name = "usb_tll_hs_mod_ck",
+ .clkdm_name = "l3_init_clkdm",
+ .type = TI_CLK_HWMOD,
+ .data = &usb_tll_hs_mod_ck_data,
+};
+
+static struct ti_clk_alias omap44xx_hwmod_clks[] = {
+ CLK(NULL, "mpu_mod_ck", &mpu_mod_ck),
+ CLK(NULL, "dsp_mod_ck", &dsp_mod_ck),
+ CLK(NULL, "mmu_dsp_mod_ck", &mmu_dsp_mod_ck),
+ CLK(NULL, "l4_abe_mod_ck", &l4_abe_mod_ck),
+ CLK(NULL, "aess_mod_ck", &aess_mod_ck),
+ CLK(NULL, "mcpdm_mod_ck", &mcpdm_mod_ck),
+ CLK(NULL, "dmic_mod_ck", &dmic_mod_ck),
+ CLK(NULL, "mcasp_mod_ck", &mcasp_mod_ck),
+ CLK(NULL, "mcbsp1_mod_ck", &mcbsp1_mod_ck),
+ CLK(NULL, "mcbsp2_mod_ck", &mcbsp2_mod_ck),
+ CLK(NULL, "mcbsp3_mod_ck", &mcbsp3_mod_ck),
+ CLK(NULL, "slimbus1_mod_ck", &slimbus1_mod_ck),
+ CLK(NULL, "timer5_mod_ck", &timer5_mod_ck),
+ CLK(NULL, "timer6_mod_ck", &timer6_mod_ck),
+ CLK(NULL, "timer7_mod_ck", &timer7_mod_ck),
+ CLK(NULL, "timer8_mod_ck", &timer8_mod_ck),
+ CLK(NULL, "wd_timer3_mod_ck", &wd_timer3_mod_ck),
+ CLK(NULL, "l4_wkup_mod_ck", &l4_wkup_mod_ck),
+ CLK(NULL, "wd_timer2_mod_ck", &wd_timer2_mod_ck),
+ CLK(NULL, "gpio1_mod_ck", &gpio1_mod_ck),
+ CLK(NULL, "timer1_mod_ck", &timer1_mod_ck),
+ CLK(NULL, "counter_32k_mod_ck", &counter_32k_mod_ck),
+ CLK(NULL, "kbd_mod_ck", &kbd_mod_ck),
+ CLK(NULL, "debugss_mod_ck", &debugss_mod_ck),
+ CLK(NULL, "dss_core_mod_ck", &dss_core_mod_ck),
+ CLK(NULL, "dss_venc_mod_ck", &dss_venc_mod_ck),
+ CLK(NULL, "dss_dispc_mod_ck", &dss_dispc_mod_ck),
+ CLK(NULL, "dss_dsi1_mod_ck", &dss_dsi1_mod_ck),
+ CLK(NULL, "dss_rfbi_mod_ck", &dss_rfbi_mod_ck),
+ CLK(NULL, "dss_dsi2_mod_ck", &dss_dsi2_mod_ck),
+ CLK(NULL, "dss_hdmi_mod_ck", &dss_hdmi_mod_ck),
+ CLK(NULL, "fdif_mod_ck", &fdif_mod_ck),
+ CLK(NULL, "gpio2_mod_ck", &gpio2_mod_ck),
+ CLK(NULL, "gpio3_mod_ck", &gpio3_mod_ck),
+ CLK(NULL, "gpio4_mod_ck", &gpio4_mod_ck),
+ CLK(NULL, "gpio5_mod_ck", &gpio5_mod_ck),
+ CLK(NULL, "gpio6_mod_ck", &gpio6_mod_ck),
+ CLK(NULL, "hdq1w_mod_ck", &hdq1w_mod_ck),
+ CLK(NULL, "i2c1_mod_ck", &i2c1_mod_ck),
+ CLK(NULL, "i2c2_mod_ck", &i2c2_mod_ck),
+ CLK(NULL, "i2c3_mod_ck", &i2c3_mod_ck),
+ CLK(NULL, "i2c4_mod_ck", &i2c4_mod_ck),
+ CLK(NULL, "l4_per_mod_ck", &l4_per_mod_ck),
+ CLK(NULL, "gpu_mod_ck", &gpu_mod_ck),
+ CLK(NULL, "hsi_mod_ck", &hsi_mod_ck),
+ CLK(NULL, "iss_mod_ck", &iss_mod_ck),
+ CLK(NULL, "mcbsp4_mod_ck", &mcbsp4_mod_ck),
+ CLK(NULL, "mcspi1_mod_ck", &mcspi1_mod_ck),
+ CLK(NULL, "mcspi2_mod_ck", &mcspi2_mod_ck),
+ CLK(NULL, "mcspi3_mod_ck", &mcspi3_mod_ck),
+ CLK(NULL, "mcspi4_mod_ck", &mcspi4_mod_ck),
+ CLK(NULL, "mmc3_mod_ck", &mmc3_mod_ck),
+ CLK(NULL, "mmc4_mod_ck", &mmc4_mod_ck),
+ CLK(NULL, "mmc1_mod_ck", &mmc1_mod_ck),
+ CLK(NULL, "mmc2_mod_ck", &mmc2_mod_ck),
+ CLK(NULL, "ocp2scp_usb_phy_mod_ck", &ocp2scp_usb_phy_mod_ck),
+ CLK(NULL, "timer10_mod_ck", &timer10_mod_ck),
+ CLK(NULL, "timer11_mod_ck", &timer11_mod_ck),
+ CLK(NULL, "timer2_mod_ck", &timer2_mod_ck),
+ CLK(NULL, "timer3_mod_ck", &timer3_mod_ck),
+ CLK(NULL, "timer4_mod_ck", &timer4_mod_ck),
+ CLK(NULL, "timer9_mod_ck", &timer9_mod_ck),
+ CLK(NULL, "elm_mod_ck", &elm_mod_ck),
+ CLK(NULL, "slimbus2_mod_ck", &slimbus2_mod_ck),
+ CLK(NULL, "uart1_mod_ck", &uart1_mod_ck),
+ CLK(NULL, "uart2_mod_ck", &uart2_mod_ck),
+ CLK(NULL, "uart3_mod_ck", &uart3_mod_ck),
+ CLK(NULL, "uart4_mod_ck", &uart4_mod_ck),
+ CLK(NULL, "mmc5_mod_ck", &mmc5_mod_ck),
+ CLK(NULL, "smartreflex_core_mod_ck", &smartreflex_core_mod_ck),
+ CLK(NULL, "smartreflex_iva_mod_ck", &smartreflex_iva_mod_ck),
+ CLK(NULL, "smartreflex_mpu_mod_ck", &smartreflex_mpu_mod_ck),
+ CLK(NULL, "usb_host_fs_mod_ck", &usb_host_fs_mod_ck),
+ CLK(NULL, "usb_host_hs_mod_ck", &usb_host_hs_mod_ck),
+ CLK(NULL, "usb_otg_hs_mod_ck", &usb_otg_hs_mod_ck),
+ CLK(NULL, "l3_main_1_mod_ck", &l3_main_1_mod_ck),
+ CLK(NULL, "l3_main_2_mod_ck", &l3_main_2_mod_ck),
+ CLK(NULL, "gpmc_mod_ck", &gpmc_mod_ck),
+ CLK(NULL, "ocmc_ram_mod_ck", &ocmc_ram_mod_ck),
+ CLK(NULL, "ipu_mod_ck", &ipu_mod_ck),
+ CLK(NULL, "mmu_ipu_mod_ck", &mmu_ipu_mod_ck),
+ CLK(NULL, "dma_system_mod_ck", &dma_system_mod_ck),
+ CLK(NULL, "dmm_mod_ck", &dmm_mod_ck),
+ CLK(NULL, "emif1_mod_ck", &emif1_mod_ck),
+ CLK(NULL, "emif2_mod_ck", &emif2_mod_ck),
+ CLK(NULL, "c2c_mod_ck", &c2c_mod_ck),
+ CLK(NULL, "l4_cfg_mod_ck", &l4_cfg_mod_ck),
+ CLK(NULL, "spinlock_mod_ck", &spinlock_mod_ck),
+ CLK(NULL, "mailbox_mod_ck", &mailbox_mod_ck),
+ CLK(NULL, "l3_main_3_mod_ck", &l3_main_3_mod_ck),
+ CLK(NULL, "l3_instr_mod_ck", &l3_instr_mod_ck),
+ CLK(NULL, "ocp_wp_noc_mod_ck", &ocp_wp_noc_mod_ck),
+ CLK(NULL, "iva_mod_ck", &iva_mod_ck),
+ CLK(NULL, "sl2if_mod_ck", &sl2if_mod_ck),
+ CLK(NULL, "usb_tll_hs_mod_ck", &usb_tll_hs_mod_ck),
+ { NULL },
+};
+
static struct ti_dt_clk omap44xx_clks[] = {
DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
@@ -276,6 +1677,8 @@ int __init omap4xxx_dt_clk_init(void)
ti_dt_clocks_register(omap44xx_clks);
+ ti_clk_register_clks(omap44xx_hwmod_clks);
+
omap2_clk_disable_autoidle_all();
/*
--
1.9.1
^ permalink raw reply related
* [PATCHv4 13/15] clk: ti: add support for omap4 module clocks
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Previously, hwmod core has been used for controlling the hwmod level
clocks. This has certain drawbacks, like being unable to share the
clocks for multiple users, missing usecounting and generally being
totally incompatible with common clock framework.
Add support for new clock type under the TI clock driver, which will
be used to convert all the existing hwmod clocks to.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/clk/ti/Makefile | 3 +-
drivers/clk/ti/clk.c | 6 +
drivers/clk/ti/clkt_mod.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/ti/clock.h | 24 ++++
include/linux/clk/ti.h | 2 +
5 files changed, 378 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/ti/clkt_mod.c
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 0deac98..15886ef 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -3,7 +3,8 @@ ifeq ($(CONFIG_ARCH_OMAP2PLUS), y)
obj-y += clk.o autoidle.o clockdomain.o
clk-common = dpll.o composite.o divider.o gate.o \
fixed-factor.o mux.o apll.o \
- clkt_dpll.o clkt_iclk.o clkt_dflt.o
+ clkt_dpll.o clkt_iclk.o clkt_dflt.o \
+ clkt_mod.o
obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o
obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-814x.o clk-816x.o
obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 8bebda4..3a75d8e 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -372,6 +372,12 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
case TI_CLK_DPLL:
clk = ti_clk_register_dpll(setup);
break;
+ case TI_CLK_HWMOD:
+ clk = ti_clk_register_hwmod(setup);
+ break;
+ case TI_CLK_HWMOD_MUX:
+ clk = ti_clk_register_hwmod_mux(setup);
+ break;
default:
pr_err("bad type for %s!\n", setup->name);
clk = ERR_PTR(-EINVAL);
diff --git a/drivers/clk/ti/clkt_mod.c b/drivers/clk/ti/clkt_mod.c
new file mode 100644
index 0000000..dc86109
--- /dev/null
+++ b/drivers/clk/ti/clkt_mod.c
@@ -0,0 +1,344 @@
+/*
+ * OMAP hardware module clock support
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+#include "clock.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define NO_IDLEST 0x1
+
+#define OMAP4_MODULEMODE_MASK 0x3
+
+#define MODULEMODE_HWCTRL 0x1
+#define MODULEMODE_SWCTRL 0x2
+
+#define OMAP4_IDLEST_MASK (0x3 << 16)
+#define OMAP4_IDLEST_SHIFT 16
+
+#define CLKCTRL_IDLEST_FUNCTIONAL 0x0
+#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
+#define CLKCTRL_IDLEST_DISABLED 0x3
+
+/* These timeouts are in us */
+#define OMAP4_MAX_MODULE_READY_TIME 2000
+#define OMAP4_MAX_MODULE_DISABLE_TIME 5000
+
+static bool _early_timeout = true;
+
+union omap4_timeout {
+ u32 cycles;
+ ktime_t start;
+};
+
+static u32 _omap4_idlest(u32 val)
+{
+ val &= OMAP4_IDLEST_MASK;
+ val >>= OMAP4_IDLEST_SHIFT;
+
+ return val;
+}
+
+static bool _omap4_is_idle(u32 val)
+{
+ val = _omap4_idlest(val);
+
+ return val == CLKCTRL_IDLEST_DISABLED;
+}
+
+static bool _omap4_is_ready(u32 val)
+{
+ val = _omap4_idlest(val);
+
+ return val == CLKCTRL_IDLEST_FUNCTIONAL ||
+ val == CLKCTRL_IDLEST_INTERFACE_IDLE;
+}
+
+static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
+{
+ if (unlikely(_early_timeout)) {
+ if (time->cycles++ < timeout) {
+ udelay(1);
+ return false;
+ }
+ } else {
+ if (!ktime_to_ns(time->start)) {
+ time->start = ktime_get();
+ return false;
+ }
+
+ if (ktime_us_delta(ktime_get(), time->start) < timeout) {
+ cpu_relax();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int __init _omap4_disable_early_timeout(void)
+{
+ _early_timeout = false;
+
+ return 0;
+}
+arch_initcall(_omap4_disable_early_timeout);
+
+static int _omap4_hwmod_clk_enable(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ u32 val;
+ int ret;
+ union omap4_timeout timeout = { 0 };
+
+ if (!clk->enable_bit)
+ return 0;
+
+ if (clk->clkdm) {
+ ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+ if (ret) {
+ WARN(1,
+ "%s: could not enable %s's clockdomain %s: %d\n",
+ __func__, clk_hw_get_name(hw),
+ clk->clkdm_name, ret);
+ return ret;
+ }
+ }
+
+ val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+ val &= ~OMAP4_MODULEMODE_MASK;
+ val |= clk->enable_bit;
+
+ ti_clk_ll_ops->clk_writel(val, clk->enable_reg);
+
+ if (clk->flags & NO_IDLEST)
+ return 0;
+
+ /* Wait until module is enabled */
+ while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(clk->enable_reg))) {
+ if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
+ pr_err("%s: failed to enable\n", clk_hw_get_name(hw));
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+static void _omap4_hwmod_clk_disable(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ u32 val;
+ union omap4_timeout timeout = { 0 };
+
+ if (!clk->enable_bit)
+ return;
+
+ val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+ val &= ~OMAP4_MODULEMODE_MASK;
+
+ ti_clk_ll_ops->clk_writel(val, clk->enable_reg);
+
+ if (clk->flags & NO_IDLEST)
+ return;
+
+ /* Wait until module is disabled */
+ while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(clk->enable_reg))) {
+ if (_omap4_is_timeout(&timeout,
+ OMAP4_MAX_MODULE_DISABLE_TIME)) {
+ pr_err("%s: failed to disable\n", clk_hw_get_name(hw));
+ break;
+ }
+ }
+
+ if (clk->clkdm)
+ ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
+static int _omap4_hwmod_clk_is_enabled(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ u32 val;
+
+ val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+ if (val & clk->enable_bit)
+ return 1;
+
+ return 0;
+}
+
+static const struct clk_ops omap4_module_clk_ops = {
+ .enable = _omap4_hwmod_clk_enable,
+ .disable = _omap4_hwmod_clk_disable,
+ .is_enabled = _omap4_hwmod_clk_is_enabled,
+};
+
+struct clk *ti_clk_register_hwmod(struct ti_clk *setup)
+{
+ struct ti_clk_hwmod *data = setup->data;
+ struct clk_init_data init = { NULL };
+ struct clk_hw_omap *hw;
+ struct clk *clk;
+ int ret;
+
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ if (!hw) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ hw->enable_reg = ti_clk_get_reg_addr_clkdm(setup->clkdm_name,
+ data->reg);
+ if (!hw->enable_reg) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (data->flags & CLKF_SW_SUP)
+ hw->enable_bit = MODULEMODE_SWCTRL;
+ if (data->flags & CLKF_HW_SUP)
+ hw->enable_bit = MODULEMODE_HWCTRL;
+ if (data->flags & CLKF_NO_IDLEST)
+ hw->flags |= NO_IDLEST;
+
+ init.parent_names = &data->parent;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = setup->name;
+ init.ops = &omap4_module_clk_ops;
+ hw->hw.init = &init;
+
+ clk = ti_clk_register(NULL, &hw->hw, setup->name);
+ if (!IS_ERR(clk))
+ return clk;
+err:
+ kfree(hw);
+ return ERR_PTR(ret);
+}
+
+static u8 _omap4_mux_mod_get_parent(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ struct clk_hw *mux_hw = clk->mux;
+
+ __clk_hw_set_clk(mux_hw, hw);
+
+ return ti_clk_mux_get_parent(mux_hw);
+}
+
+static int _omap4_mux_mod_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ struct clk_hw *mux_hw = clk->mux;
+
+ __clk_hw_set_clk(mux_hw, hw);
+
+ return ti_clk_mux_set_parent(mux_hw, index);
+}
+
+static int _omap4_mux_mod_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ struct clk_hw *mux_hw = clk->mux;
+
+ __clk_hw_set_clk(mux_hw, hw);
+
+ return __clk_mux_determine_rate(mux_hw, req);
+}
+
+static const struct clk_ops omap4_mux_module_clk_ops = {
+ .enable = _omap4_hwmod_clk_enable,
+ .disable = _omap4_hwmod_clk_disable,
+ .is_enabled = _omap4_hwmod_clk_is_enabled,
+ .get_parent = _omap4_mux_mod_get_parent,
+ .set_parent = _omap4_mux_mod_set_parent,
+ .determine_rate = _omap4_mux_mod_determine_rate,
+};
+
+struct clk *ti_clk_register_hwmod_mux(struct ti_clk *setup)
+{
+ struct ti_clk_hwmod_mux *data = setup->data;
+ struct clk_init_data init = { NULL };
+ struct clk_mux *mux;
+ struct clk_hw_omap *gate;
+ struct clk *clk;
+ int ret;
+ u8 modulemode;
+
+ if (data->num_parents < 2) {
+ pr_err("%s: must have parents\n", setup->name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+
+ if (!mux || !gate) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ gate->mux = &mux->hw;
+ mux->shift = data->shift;
+
+ if (data->flags & CLKF_INDEX_STARTS_AT_ONE)
+ mux->flags |= CLK_MUX_INDEX_ONE;
+
+ if (data->flags & CLKF_SW_SUP)
+ modulemode = MODULEMODE_SWCTRL;
+ if (data->flags & CLKF_HW_SUP)
+ modulemode = MODULEMODE_HWCTRL;
+
+ gate->enable_bit = modulemode;
+ gate->enable_reg = ti_clk_get_reg_addr_clkdm(setup->clkdm_name,
+ data->mod_reg);
+ mux->reg = ti_clk_get_reg_addr_clkdm(setup->clkdm_name, data->mux_reg);
+
+ if (!gate->enable_reg || !mux->reg) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ init.num_parents = data->num_parents;
+ init.parent_names = data->parents;
+ init.flags = 0;
+
+ init.name = setup->name;
+ init.ops = &omap4_mux_module_clk_ops;
+ gate->hw.init = &init;
+
+ clk = ti_clk_register(NULL, &gate->hw, setup->name);
+
+ if (!IS_ERR(clk))
+ return clk;
+
+err:
+ kfree(gate);
+ kfree(mux);
+
+ return ERR_PTR(ret);
+}
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 2e5fab8..ebcd81b 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -26,6 +26,8 @@ enum {
TI_CLK_FIXED_FACTOR,
TI_CLK_GATE,
TI_CLK_DPLL,
+ TI_CLK_HWMOD,
+ TI_CLK_HWMOD_MUX,
};
/* Global flags */
@@ -54,6 +56,11 @@ enum {
#define CLKF_CORE (1 << 9)
#define CLKF_J_TYPE (1 << 10)
+/* HWMOD clk flags */
+#define CLKF_SW_SUP BIT(5)
+#define CLKF_HW_SUP BIT(6)
+#define CLKF_NO_IDLEST BIT(7)
+
#define CLK(dev, con, ck) \
{ \
.lk = { \
@@ -156,6 +163,21 @@ struct ti_clk_dpll {
u8 recal_st_bit;
};
+struct ti_clk_hwmod {
+ u16 reg;
+ u16 flags;
+ const char *parent;
+};
+
+struct ti_clk_hwmod_mux {
+ u16 mux_reg;
+ u16 mod_reg;
+ u16 flags;
+ u8 shift;
+ u8 num_parents;
+ const char * const *parents;
+};
+
/* Composite clock component types */
enum {
CLK_COMPONENT_TYPE_GATE = 0,
@@ -191,6 +213,8 @@ struct ti_dt_clk {
struct clk *ti_clk_register_divider(struct ti_clk *setup);
struct clk *ti_clk_register_composite(struct ti_clk *setup);
struct clk *ti_clk_register_dpll(struct ti_clk *setup);
+struct clk *ti_clk_register_hwmod(struct ti_clk *setup);
+struct clk *ti_clk_register_hwmod_mux(struct ti_clk *setup);
struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
const char *con);
int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index afccb48..5c7c24c 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -130,6 +130,7 @@ struct clk_hw_omap_ops {
* @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
* @flags: see "struct clk.flags possibilities" above
* @clksel_reg: for clksel clks, register va containing src/divisor select
+ * @mux: for module clocks, pointer to the optional mux component
* @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
* @clkdm_name: clockdomain name that this clock is contained in
* @clkdm: pointer to struct clockdomain, resolved from @clkdm_name@runtime
@@ -145,6 +146,7 @@ struct clk_hw_omap {
u8 enable_bit;
u8 flags;
void __iomem *clksel_reg;
+ struct clk_hw *mux;
struct dpll_data *dpll_data;
const char *clkdm_name;
struct clockdomain *clkdm;
--
1.9.1
^ permalink raw reply related
* [PATCHv4 12/15] clk: ti: enforce const types on string arrays
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Constant string arrays should use const char * const instead of just
const char *. Change the implementations using these to proper type.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/clk/ti/clock.h | 2 +-
drivers/clk/ti/composite.c | 2 +-
drivers/clk/ti/mux.c | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index f6383ab..2e5fab8 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -88,7 +88,7 @@ struct ti_clk_mux {
int num_parents;
u16 reg;
u8 module;
- const char **parents;
+ const char * const *parents;
u16 flags;
};
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 3f60f99..beea894 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -124,7 +124,7 @@ struct clk *ti_clk_register_composite(struct ti_clk *setup)
struct clk_hw *mux;
struct clk_hw *div;
int num_parents = 1;
- const char **parent_names = NULL;
+ const char * const *parent_names = NULL;
struct clk *clk;
int ret;
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 774098e..520a18e 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -97,10 +97,10 @@ int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
};
static struct clk *_register_mux(struct device *dev, const char *name,
- const char **parent_names, u8 num_parents,
- unsigned long flags, void __iomem *reg,
- u8 shift, u32 mask, u8 clk_mux_flags,
- u32 *table)
+ const char * const *parent_names,
+ u8 num_parents, unsigned long flags,
+ void __iomem *reg, u8 shift, u32 mask,
+ u8 clk_mux_flags, u32 *table)
{
struct clk_mux *mux;
struct clk *clk;
--
1.9.1
^ permalink raw reply related
* [PATCHv4 11/15] clk: ti: clockdomain: add clock provider support to clockdomains
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Clockdomains can now be used as clock providers in the system. This
patch initializes the provider data during init, and parses the clocks
while they are being registered. An xlate function for the provider
is also given.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
.../devicetree/bindings/arm/omap/prcm.txt | 13 ++
.../devicetree/bindings/clock/ti/clockdomain.txt | 12 +-
arch/arm/mach-omap2/io.c | 2 +
drivers/clk/ti/clock.h | 1 +
drivers/clk/ti/clockdomain.c | 147 +++++++++++++++++++++
include/linux/clk/ti.h | 3 +
6 files changed, 177 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/omap/prcm.txt b/Documentation/devicetree/bindings/arm/omap/prcm.txt
index 3eb6d7a..301f576 100644
--- a/Documentation/devicetree/bindings/arm/omap/prcm.txt
+++ b/Documentation/devicetree/bindings/arm/omap/prcm.txt
@@ -47,6 +47,19 @@ cm: cm at 48004000 {
};
}
+cm2: cm2 at 8000 {
+ compatible = "ti,omap4-cm2";
+ reg = <0x8000 0x3000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x8000 0x3000>;
+
+ l4_per_clkdm: l4_per_clkdm {
+ compatible = "ti,clockdomain";
+ reg = <0x1400 0x200>;
+ };
+};
+
&cm_clocks {
omap2_32k_fck: omap_32k_fck {
#clock-cells = <0>;
diff --git a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
index cb76b3f..5d8ca61 100644
--- a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
+++ b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
@@ -14,11 +14,21 @@ hardware hierarchy.
Required properties:
- compatible : shall be "ti,clockdomain"
-- #clock-cells : from common clock binding; shall be set to 0.
+- #clock-cells : from common clock binding; shall be set to 1 if this
+ clockdomain acts as a clock provider.
+
+Optional properties:
- clocks : link phandles of clocks within this domain
+- reg : address for the clockdomain
Examples:
dss_clkdm: dss_clkdm {
compatible = "ti,clockdomain";
clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
};
+
+ l4_per_clkdm: l4_per_clkdm {
+ compatible = "ti,clockdomain";
+ #clock-cells = <1>;
+ reg = <0x1400 0x200>;
+ };
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 0e9acdd..c1a5cfb 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -794,6 +794,8 @@ int __init omap_clk_init(void)
if (ret)
return ret;
+ ti_dt_clockdomains_early_setup();
+
of_clk_init(NULL);
ti_dt_clk_init_retry_clks();
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 9b8a5f2..f6383ab 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -205,6 +205,7 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
int ti_clk_get_memmap_index(struct device_node *node);
void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
+void __iomem *ti_clk_get_reg_addr_clkdm(const char *clkdm_name, u16 offset);
void ti_dt_clocks_register(struct ti_dt_clk *oclks);
int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
ti_of_clk_init_cb_t func);
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index 704157d..7b0a6c3 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -28,6 +28,23 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
/**
+ * struct ti_clkdm - TI clockdomain data structure
+ * @name: name of the clockdomain
+ * @index: index of the clk_iomap struct for this clkdm
+ * @offset: clockdomain offset from the beginning of the iomap
+ * @link: link to the list
+ */
+struct ti_clkdm {
+ const char *name;
+ int index;
+ u32 offset;
+ struct list_head link;
+ struct list_head clocks;
+};
+
+static LIST_HEAD(clkdms);
+
+/**
* omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
* @hw: struct clk_hw * of the clock being enabled
*
@@ -116,6 +133,8 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct clockdomain *clkdm;
const char *clk_name;
+ struct ti_clkdm *ti_clkdm;
+ bool match = false;
if (!clk->clkdm_name)
return;
@@ -130,7 +149,21 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
} else {
pr_debug("clock: could not associate clk %s to clkdm %s\n",
clk_name, clk->clkdm_name);
+ return;
}
+
+ list_for_each_entry(ti_clkdm, &clkdms, link) {
+ if (!strcmp(ti_clkdm->name, clk->clkdm_name)) {
+ match = true;
+ break;
+ }
+ }
+
+ if (!match)
+ return;
+
+ /* Add clock to the list of provided clocks */
+ list_add(&clk->clkdm_link, &ti_clkdm->clocks);
}
static void __init of_ti_clockdomain_setup(struct device_node *node)
@@ -161,11 +194,125 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
}
}
+static struct clk_hw *clkdm_clk_xlate(struct of_phandle_args *clkspec,
+ void *data)
+{
+ struct ti_clkdm *clkdm = data;
+ struct clk_hw_omap *clk;
+ u16 offset = clkspec->args[0];
+
+ list_for_each_entry(clk, &clkdm->clocks, clkdm_link)
+ if (((u32)clk->enable_reg & 0xffff) - clkdm->offset == offset)
+ return &clk->hw;
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int ti_clk_register_clkdm(struct device_node *node)
+{
+ u64 clkdm_addr;
+ u64 inst_addr;
+ const __be32 *reg;
+ u32 offset;
+ int idx;
+ struct ti_clkdm *clkdm;
+ int ret;
+
+ reg = of_get_address(node, 0, NULL, NULL);
+ if (!reg)
+ return -ENOENT;
+
+ clkdm_addr = of_translate_address(node, reg);
+
+ reg = of_get_address(node->parent, 0, NULL, NULL);
+ if (!reg)
+ return -EINVAL;
+
+ inst_addr = of_translate_address(node->parent, reg);
+
+ offset = clkdm_addr - inst_addr;
+
+ idx = ti_clk_get_memmap_index(node->parent);
+
+ if (idx < 0) {
+ pr_err("bad memmap index for %s\n", node->name);
+ return idx;
+ }
+
+ clkdm = kzalloc(sizeof(*clkdm), GFP_KERNEL);
+ if (!clkdm)
+ return -ENOMEM;
+
+ clkdm->name = node->name;
+ clkdm->index = idx;
+ clkdm->offset = offset;
+
+ INIT_LIST_HEAD(&clkdm->clocks);
+
+ list_add(&clkdm->link, &clkdms);
+
+ ret = of_clk_add_hw_provider(node, clkdm_clk_xlate, clkdm);
+ if (ret) {
+ list_del(&clkdm->link);
+ kfree(clkdm);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_clk_get_reg_addr_clkdm - get register address relative to clockdomain
+ * @clkdm_name: parent clockdomain
+ * @offset: offset from the clockdomain
+ *
+ * Gets a register address relative to parent clockdomain. Searches the
+ * list of available clockdomain, and if match is found, calculates the
+ * register address from the iomap relative to the clockdomain.
+ * Returns the register address, or NULL if not found.
+ */
+void __iomem *ti_clk_get_reg_addr_clkdm(const char *clkdm_name, u16 offset)
+{
+ u32 reg;
+ struct clk_omap_reg *reg_setup;
+ struct ti_clkdm *clkdm;
+ bool match = false;
+
+ reg_setup = (struct clk_omap_reg *)®
+
+ /* XXX: get offset from clkdm, get base for instance */
+ list_for_each_entry(clkdm, &clkdms, link) {
+ if (!strcmp(clkdm->name, clkdm_name)) {
+ match = true;
+ break;
+ }
+ }
+
+ if (!match) {
+ pr_err("%s: no entry for %s\n", __func__, clkdm_name);
+ return NULL;
+ }
+
+ reg_setup->offset = clkdm->offset + offset;
+ reg_setup->index = clkdm->index;
+
+ return (void __iomem *)reg;
+}
+
static const struct of_device_id ti_clkdm_match_table[] __initconst = {
{ .compatible = "ti,clockdomain" },
{ }
};
+void __init ti_dt_clockdomains_early_setup(void)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, ti_clkdm_match_table) {
+ ti_clk_register_clkdm(np);
+ }
+}
+
/**
* ti_dt_clockdomains_setup - setup device tree clockdomains
*
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 626ae94..afccb48 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -125,6 +125,7 @@ struct clk_hw_omap_ops {
/**
* struct clk_hw_omap - OMAP struct clk
* @node: list_head connecting this clock into the full clock list
+ * @clkdm_link: list_head connecting this clock into the clockdomain
* @enable_reg: register to write to enable the clock (see @enable_bit)
* @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
* @flags: see "struct clk.flags possibilities" above
@@ -137,6 +138,7 @@ struct clk_hw_omap_ops {
struct clk_hw_omap {
struct clk_hw hw;
struct list_head node;
+ struct list_head clkdm_link;
unsigned long fixed_rate;
u8 fixed_div;
void __iomem *enable_reg;
@@ -251,6 +253,7 @@ int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
void ti_dt_clk_init_retry_clks(void);
+void ti_dt_clockdomains_early_setup(void);
void ti_dt_clockdomains_setup(void);
int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops);
--
1.9.1
^ permalink raw reply related
* [PATCHv4 10/15] clk: ti: add support API for fetching memmap index
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
Searches for a memmap index for a given node. Checks against all the
registered iomaps and sees if the node is registered for this.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/clk/ti/clk.c | 24 ++++++++++++++++++++++++
drivers/clk/ti/clock.h | 1 +
2 files changed, 25 insertions(+)
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 7a445f4..8bebda4 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -39,6 +39,7 @@
struct clk_iomap {
struct regmap *regmap;
void __iomem *mem;
+ struct device_node *node;
};
static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
@@ -199,6 +200,28 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
}
/**
+ * ti_clk_get_memmap_index - get memory mapping index for a node
+ * @node: device node pointer to find memmap index for
+ *
+ * Finds a matching memory mapping index for a node. Returns the index
+ * to the mapping, or negative error value in failure.
+ */
+int ti_clk_get_memmap_index(struct device_node *node)
+{
+ int i;
+
+ for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
+ if (!clk_memmaps[i])
+ continue;
+
+ if (clk_memmaps[i]->node == node)
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+/**
* omap2_clk_provider_init - init master clock provider
* @parent: master node
* @index: internal index for clk_reg_ops
@@ -234,6 +257,7 @@ int __init omap2_clk_provider_init(struct device_node *parent, int index,
io->regmap = syscon;
io->mem = mem;
+ io->node = parent;
clk_memmaps[index] = io;
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 9c85a51..9b8a5f2 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -203,6 +203,7 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
struct clk *ti_clk_register_clk(struct ti_clk *setup);
int ti_clk_register_clks(struct ti_clk_alias *clks);
+int ti_clk_get_memmap_index(struct device_node *node);
void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
void ti_dt_clocks_register(struct ti_dt_clk *oclks);
int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
--
1.9.1
^ permalink raw reply related
* [PATCHv4 09/15] clk: ti: move omap2_init_clk_clkdm under TI clock driver
From: Tero Kristo @ 2016-10-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476805568-19264-1-git-send-email-t-kristo@ti.com>
This is not needed outside the driver, so move it inside it and remove
the prototype from the public header also.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
arch/arm/mach-omap2/clock.c | 34 ----------------------------------
drivers/clk/ti/clock.h | 1 +
drivers/clk/ti/clockdomain.c | 30 ++++++++++++++++++++++++++++++
include/linux/clk/ti.h | 1 -
4 files changed, 31 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 5391b66..ce8e804 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -79,40 +79,6 @@ int __init omap2_clk_setup_ll_ops(void)
* OMAP2+ specific clock functions
*/
-/* Private functions */
-
-/* Public functions */
-
-/**
- * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
- * @clk: OMAP clock struct ptr to use
- *
- * Convert a clockdomain name stored in a struct clk 'clk' into a
- * clockdomain pointer, and save it into the struct clk. Intended to be
- * called during clk_register(). No return value.
- */
-void omap2_init_clk_clkdm(struct clk_hw *hw)
-{
- struct clk_hw_omap *clk = to_clk_hw_omap(hw);
- struct clockdomain *clkdm;
- const char *clk_name;
-
- if (!clk->clkdm_name)
- return;
-
- clk_name = __clk_get_name(hw->clk);
-
- clkdm = clkdm_lookup(clk->clkdm_name);
- if (clkdm) {
- pr_debug("clock: associated clk %s to clkdm %s\n",
- clk_name, clk->clkdm_name);
- clk->clkdm = clkdm;
- } else {
- pr_debug("clock: could not associate clk %s to clkdm %s\n",
- clk_name, clk->clkdm_name);
- }
-}
-
static int __initdata mpurate;
/*
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 5675e37..9c85a51 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -232,6 +232,7 @@ int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
u8 ti_clk_mux_get_parent(struct clk_hw *hw);
int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index);
+void omap2_init_clk_clkdm(struct clk_hw *hw);
int omap2_clkops_enable_clkdm(struct clk_hw *hw);
void omap2_clkops_disable_clkdm(struct clk_hw *hw);
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index 6cf9dd1..704157d 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -103,6 +103,36 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw)
ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
}
+/**
+ * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
+ * @clk: OMAP clock struct ptr to use
+ *
+ * Convert a clockdomain name stored in a struct clk 'clk' into a
+ * clockdomain pointer, and save it into the struct clk. Intended to be
+ * called during clk_register(). No return value.
+ */
+void omap2_init_clk_clkdm(struct clk_hw *hw)
+{
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+ struct clockdomain *clkdm;
+ const char *clk_name;
+
+ if (!clk->clkdm_name)
+ return;
+
+ clk_name = __clk_get_name(hw->clk);
+
+ clkdm = ti_clk_ll_ops->clkdm_lookup(clk->clkdm_name);
+ if (clkdm) {
+ pr_debug("clock: associated clk %s to clkdm %s\n",
+ clk_name, clk->clkdm_name);
+ clk->clkdm = clkdm;
+ } else {
+ pr_debug("clock: could not associate clk %s to clkdm %s\n",
+ clk_name, clk->clkdm_name);
+ }
+}
+
static void __init of_ti_clockdomain_setup(struct device_node *node)
{
struct clk *clk;
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index bc7fd8f..626ae94 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -238,7 +238,6 @@ struct ti_clk_ll_ops {
#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
-void omap2_init_clk_clkdm(struct clk_hw *clk);
int omap2_clk_disable_autoidle_all(void);
int omap2_clk_enable_autoidle_all(void);
int omap2_clk_allow_idle(struct clk *clk);
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox