* [PATCH 08/20] ARM64 / ACPI: Select ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
ACPI reduced hardware mode is disabled by default, but ARM64 can
only run properly in ACPI hardware reduced mode at now, so select
ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64.
Signed-off-by: Al Stone <al.stone@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2b1fb1d..741692c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1,5 +1,6 @@
config ARM64
def_bool y
+ select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANT_OPTIONAL_GPIOLIB
--
1.7.9.5
^ permalink raw reply related
* [PATCH 09/20] ARM64 / ACPI: Implement core functions for parsing MADT table
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
Implement core functions for parsing MADT table to get the information
about GIC cpu interface and GIC distributor to prepare for SMP and GIC
initialization.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/include/asm/acpi.h | 3 +
drivers/acpi/plat/arm-core.c | 139 ++++++++++++++++++++++++++++++++++++++++-
drivers/acpi/tables.c | 21 +++++++
3 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index e108d9c..c335c6d 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -83,6 +83,9 @@ void arch_fix_phys_package_id(int num, u32 slot);
extern int (*acpi_suspend_lowlevel)(void);
#define acpi_wakeup_address (0)
+#define MAX_GIC_CPU_INTERFACE 256
+#define MAX_GIC_DISTRIBUTOR 1 /* should be the same as MAX_GIC_NR */
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1 /* ACPI sometimes enabled on ARM */
#define acpi_noirq 1 /* ACPI sometimes enabled on ARM */
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 1835b21..8ba3e6f 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -46,6 +46,16 @@ EXPORT_SYMBOL(acpi_disabled);
int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */
EXPORT_SYMBOL(acpi_pci_disabled);
+/*
+ * Local interrupt controller address,
+ * GIC cpu interface base address on ARM/ARM64
+ */
+static u64 acpi_lapic_addr __initdata;
+
+#define BAD_MADT_ENTRY(entry, end) ( \
+ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \
+ ((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
+
#define PREFIX "ACPI: "
/* FIXME: this function should be moved to topology.c when it is ready */
@@ -92,6 +102,115 @@ void __init __acpi_unmap_table(char *map, unsigned long size)
return;
}
+static int __init acpi_parse_madt(struct acpi_table_header *table)
+{
+ struct acpi_table_madt *madt = NULL;
+
+ madt = (struct acpi_table_madt *)table;
+ if (!madt) {
+ pr_warn(PREFIX "Unable to map MADT\n");
+ return -ENODEV;
+ }
+
+ if (madt->address) {
+ acpi_lapic_addr = (u64) madt->address;
+
+ pr_info(PREFIX "Local APIC address 0x%08x\n", madt->address);
+ }
+
+ return 0;
+}
+
+/*
+ * GIC structures on ARM are somthing like Local APIC structures on x86,
+ * which means GIC cpu interfaces for GICv2/v3. Every GIC structure in
+ * MADT table represents a cpu in the system.
+ *
+ * GIC distributor structures are somthing like IOAPIC on x86. GIC can
+ * be initialized with information in this structure.
+ *
+ * Please refer to chapter5.2.12.14/15 of ACPI 5.0
+ */
+
+static int __init
+acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
+{
+ struct acpi_madt_generic_interrupt *processor = NULL;
+
+ processor = (struct acpi_madt_generic_interrupt *)header;
+
+ if (BAD_MADT_ENTRY(processor, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ return 0;
+}
+
+static int __init
+acpi_parse_gic_distributor(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+ struct acpi_madt_generic_distributor *distributor = NULL;
+
+ distributor = (struct acpi_madt_generic_distributor *)header;
+
+ if (BAD_MADT_ENTRY(distributor, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ return 0;
+}
+
+/*
+ * Parse GIC cpu interface related entries in MADT
+ * returns 0 on success, < 0 on error
+ */
+static int __init acpi_parse_madt_gic_entries(void)
+{
+ int count;
+
+ /*
+ * do a partial walk of MADT to determine how many CPUs
+ * we have including disabled CPUs
+ */
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+ acpi_parse_gic, MAX_GIC_CPU_INTERFACE);
+
+ if (!count) {
+ pr_err(PREFIX "No GIC entries present\n");
+ return -ENODEV;
+ } else if (count < 0) {
+ pr_err(PREFIX "Error parsing GIC entry\n");
+ return count;
+ }
+
+ return 0;
+}
+
+/*
+ * Parse GIC distributor related entries in MADT
+ * returns 0 on success, < 0 on error
+ */
+static int __init acpi_parse_madt_gic_distributor_entries(void)
+{
+ int count;
+
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+ acpi_parse_gic_distributor, MAX_GIC_DISTRIBUTOR);
+
+ if (!count) {
+ pr_err(PREFIX "No GIC distributor entries present\n");
+ return -ENODEV;
+ } else if (count < 0) {
+ pr_err(PREFIX "Error parsing GIC distributor entry\n");
+ return count;
+ }
+
+ return 0;
+}
+
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
*irq = gsi_to_irq(gsi);
@@ -141,11 +260,29 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
static void __init early_acpi_process_madt(void)
{
- return;
+ acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt);
}
static void __init acpi_process_madt(void)
{
+ int error;
+
+ if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
+
+ /*
+ * Parse MADT GIC cpu interface entries
+ */
+ error = acpi_parse_madt_gic_entries();
+ if (!error) {
+ /*
+ * Parse MADT GIC distributor entries
+ */
+ acpi_parse_madt_gic_distributor_entries();
+ }
+ }
+
+ pr_info("Using ACPI for processor (GIC) configuration information\n");
+
return;
}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index d67a1fe..b3e4615 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -191,6 +191,27 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;
+ case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
+ {
+ struct acpi_madt_generic_interrupt *p =
+ (struct acpi_madt_generic_interrupt *)header;
+ printk(KERN_INFO PREFIX
+ "GIC (acpi_id[0x%04x] gic_id[0x%04x] %s)\n",
+ p->uid, p->gic_id,
+ (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+ }
+ break;
+
+ case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
+ {
+ struct acpi_madt_generic_distributor *p =
+ (struct acpi_madt_generic_distributor *)header;
+ printk(KERN_INFO PREFIX
+ "GIC Distributor (id[0x%04x] address[0x%08llx] gsi_base[%d])\n",
+ p->gic_id, p->base_address, p->global_irq_base);
+ }
+ break;
+
default:
printk(KERN_WARNING PREFIX
"Found unsupported MADT entry (type = 0x%x)\n",
--
1.7.9.5
^ permalink raw reply related
* [PATCH 10/20] ARM64 / ACPI: Enumerate possible/present CPU set and map logical cpu id to APIC id
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
When boot the kernel with MADT, the cpu possible and present sets should
be enumerated for later smp initialization.
The logic cpu id maps to APIC id (GIC id) is also implemented, it is
needed for acpi processor drivers.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/include/asm/acpi.h | 7 ++--
drivers/acpi/plat/arm-core.c | 83 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index c335c6d..7edd39e 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -76,9 +76,6 @@ static inline void acpi_disable_pci(void)
/* FIXME: this function should be moved to topology.h when it's ready */
void arch_fix_phys_package_id(int num, u32 slot);
-/* temperally define -1 to make acpi core compilerable */
-#define cpu_physical_id(cpu) -1
-
/* Low-level suspend routine. */
extern int (*acpi_suspend_lowlevel)(void);
#define acpi_wakeup_address (0)
@@ -86,6 +83,10 @@ extern int (*acpi_suspend_lowlevel)(void);
#define MAX_GIC_CPU_INTERFACE 256
#define MAX_GIC_DISTRIBUTOR 1 /* should be the same as MAX_GIC_NR */
+/* map logic cpu id to physical GIC id */
+extern int arm_cpu_to_apicid[NR_CPUS];
+#define cpu_physical_id(cpu) arm_cpu_to_apicid[cpu]
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1 /* ACPI sometimes enabled on ARM */
#define acpi_noirq 1 /* ACPI sometimes enabled on ARM */
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 8ba3e6f..1d9b789 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -31,6 +31,7 @@
#include <linux/smp.h>
#include <asm/pgtable.h>
+#include <asm/cputype.h>
/*
* We never plan to use RSDT on arm/arm64 as its deprecated in spec but this
@@ -52,6 +53,13 @@ EXPORT_SYMBOL(acpi_pci_disabled);
*/
static u64 acpi_lapic_addr __initdata;
+/* available_cpus here means enabled cpu in MADT */
+static int available_cpus;
+
+/* Map logic cpu id to physical GIC id (physical CPU id). */
+int arm_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 };
+static int boot_cpu_apic_id = -1;
+
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
@@ -132,6 +140,55 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
* Please refer to chapter5.2.12.14/15 of ACPI 5.0
*/
+/**
+ * acpi_register_gic_cpu_interface - register a gic cpu interface and
+ * generates a logic cpu number
+ * @id: gic cpu interface id to register
+ * @enabled: this cpu is enabled or not
+ *
+ * Returns the logic cpu number which maps to the gic cpu interface
+ */
+static int acpi_register_gic_cpu_interface(int id, u8 enabled)
+{
+ int cpu;
+
+ if (id >= MAX_GIC_CPU_INTERFACE) {
+ pr_info(PREFIX "skipped apicid that is too big\n");
+ return -EINVAL;
+ }
+
+ total_cpus++;
+ if (!enabled)
+ return -EINVAL;
+
+ if (available_cpus >= NR_CPUS) {
+ pr_warn(PREFIX "NR_CPUS limit of %d reached,"
+ " Processor %d/0x%x ignored.\n", NR_CPUS, total_cpus, id);
+ return -EINVAL;
+ }
+
+ available_cpus++;
+
+ /* allocate a logic cpu id for the new comer */
+ if (boot_cpu_apic_id == id) {
+ /*
+ * boot_cpu_init() already hold bit 0 in cpu_present_mask
+ * for BSP, no need to allocte again.
+ */
+ cpu = 0;
+ } else {
+ cpu = cpumask_next_zero(-1, cpu_present_mask);
+ }
+
+ /* map the logic cpu id to APIC id */
+ arm_cpu_to_apicid[cpu] = id;
+
+ set_cpu_present(cpu, true);
+ set_cpu_possible(cpu, true);
+
+ return cpu;
+}
+
static int __init
acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
{
@@ -144,6 +201,16 @@ acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
acpi_table_print_madt_entry(header);
+ /*
+ * We need to register disabled CPU as well to permit
+ * counting disabled CPUs. This allows us to size
+ * cpus_possible_map more accurately, to permit
+ * to not preallocating memory for all NR_CPUS
+ * when we use CPU hotplug.
+ */
+ acpi_register_gic_cpu_interface(processor->gic_id,
+ processor->flags & ACPI_MADT_ENABLED);
+
return 0;
}
@@ -186,6 +253,19 @@ static int __init acpi_parse_madt_gic_entries(void)
return count;
}
+#ifdef CONFIG_SMP
+ if (available_cpus == 0) {
+ pr_info(PREFIX "Found 0 CPUs; assuming 1\n");
+ arm_cpu_to_apicid[available_cpus] =
+ read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+ available_cpus = 1; /* We've got at least one of these */
+ }
+#endif
+
+ /* Make boot-up look pretty */
+ pr_info("%d CPUs available, %d CPUs total\n", available_cpus,
+ total_cpus);
+
return 0;
}
@@ -321,6 +401,9 @@ int __init early_acpi_boot_init(void)
if (acpi_disabled)
return -ENODEV;
+ /* Get the boot CPU's GIC cpu interface id before MADT parsing */
+ boot_cpu_apic_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+
/*
* Process the Multiple APIC Description Table (MADT), if present
*/
--
1.7.9.5
^ permalink raw reply related
* [PATCH 11/20] ARM64 / ACPI: Get the enable method for SMP initialization
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
ACPI has no flag to indicate different enable methods for SMP
initialization, but it indicates that spin-table is supported
at now because of the Parked Protocol shows that there is
parked address in GIC structure.
In order to boot the system with ACPI if DT is not available,
we set the default enable method as spin-table since PSCI is
not available in ACPI spec at now.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/include/asm/acpi.h | 8 ++++++++
arch/arm64/include/asm/cpu_ops.h | 1 +
arch/arm64/include/asm/smp.h | 2 +-
arch/arm64/kernel/cpu_ops.c | 2 +-
arch/arm64/kernel/smp.c | 42 ++++++++++++++++++++++++++++++++++++--
drivers/acpi/plat/arm-core.c | 26 +++++++++++++++++++++++
6 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 7edd39e..097394c 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -87,11 +87,19 @@ extern int (*acpi_suspend_lowlevel)(void);
extern int arm_cpu_to_apicid[NR_CPUS];
#define cpu_physical_id(cpu) arm_cpu_to_apicid[cpu]
+extern const char *acpi_get_enable_method(int cpu);
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1 /* ACPI sometimes enabled on ARM */
#define acpi_noirq 1 /* ACPI sometimes enabled on ARM */
#define acpi_pci_disabled 1 /* ACPI PCI sometimes enabled on ARM */
#define acpi_strict 1 /* no ACPI spec workarounds on ARM */
+
+static inline const char *acpi_get_enable_method(int cpu)
+{
+ return NULL;
+}
+
#endif
#endif /*_ASM_ARM64_ACPI_H*/
diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
index c4cdb5e..08c8f07 100644
--- a/arch/arm64/include/asm/cpu_ops.h
+++ b/arch/arm64/include/asm/cpu_ops.h
@@ -53,6 +53,7 @@ struct cpu_operations {
};
extern const struct cpu_operations *cpu_ops[NR_CPUS];
+extern const struct cpu_operations * __init cpu_get_ops(const char *name);
extern int __init cpu_read_ops(struct device_node *dn, int cpu);
extern void __init cpu_read_bootcpu_ops(void);
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index a498f2c..a5cea56 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -39,7 +39,7 @@ extern void show_ipi_list(struct seq_file *p, int prec);
extern void handle_IPI(int ipinr, struct pt_regs *regs);
/*
- * Setup the set of possible CPUs (via set_cpu_possible)
+ * Platform specific SMP operations
*/
extern void smp_init_cpus(void);
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index d62d12f..531f2cc 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -35,7 +35,7 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = {
NULL,
};
-static const struct cpu_operations * __init cpu_get_ops(const char *name)
+const struct cpu_operations * __init cpu_get_ops(const char *name)
{
const struct cpu_operations **ops = supported_cpu_ops;
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index a0c2ca6..7719d46 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -48,6 +48,7 @@
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
+#include <asm/acpi.h>
/*
* as from 2.5, kernels no longer have an init_tasks structure
@@ -280,7 +281,7 @@ static void (*smp_cross_call)(const struct cpumask *, unsigned int);
* cpu logical map array containing MPIDR values related to logical
* cpus. Assumes that cpu_logical_map(0) has already been initialized.
*/
-void __init smp_init_cpus(void)
+static int __init of_smp_init_cpus(void)
{
struct device_node *dn = NULL;
unsigned int i, cpu = 1;
@@ -364,6 +365,10 @@ next:
cpu++;
}
+ /* No device tree or no CPU node in DT */
+ if (cpu == 1 && !bootcpu_valid)
+ return -ENODEV;
+
/* sanity check */
if (cpu > NR_CPUS)
pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n",
@@ -371,7 +376,7 @@ next:
if (!bootcpu_valid) {
pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n");
- return;
+ return -EINVAL;
}
/*
@@ -381,6 +386,39 @@ next:
for (i = 0; i < NR_CPUS; i++)
if (cpu_logical_map(i) != INVALID_HWID)
set_cpu_possible(i, true);
+
+ return 0;
+}
+
+/*
+ * In ACPI mode, the cpu possible map was enumerated before SMP
+ * initialization when MADT table was parsed, so we can get the
+ * possible map here to initialize CPUs.
+ */
+static void __init acpi_smp_init_cpus(void)
+{
+ int cpu;
+ const char *enable_method;
+
+ for_each_possible_cpu(cpu) {
+ enable_method = acpi_get_enable_method(cpu);
+ if (!enable_method)
+ continue;
+
+ cpu_ops[cpu] = cpu_get_ops(enable_method);
+ if (!cpu_ops[cpu])
+ continue;
+
+ cpu_ops[cpu]->cpu_init(NULL, cpu);
+ }
+}
+
+void __init smp_init_cpus(void)
+{
+ if (!of_smp_init_cpus())
+ return;
+
+ acpi_smp_init_cpus();
}
void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 1d9b789..2704633 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -367,6 +367,32 @@ static void __init acpi_process_madt(void)
}
/*
+ * To see PCSI is enabled or not.
+ *
+ * PSCI is not available for ACPI 5.0, return FALSE for now.
+ *
+ * FIXME: should we introduce early_param("psci", func) for test purpose?
+ */
+static bool acpi_psci_smp_available(int cpu)
+{
+ return FALSE;
+}
+
+static const char *enable_method[] = {
+ "psci",
+ "spin-table",
+ NULL
+};
+
+const char *acpi_get_enable_method(int cpu)
+{
+ if (acpi_psci_smp_available(cpu))
+ return enable_method[0];
+ else
+ return enable_method[1];
+}
+
+/*
* acpi_boot_table_init() and acpi_boot_init()
* called from setup_arch(), always.
* 1. checksums all tables
--
1.7.9.5
^ permalink raw reply related
* [PATCH 12/20] ARM64 / ACPI: Use Parked Address in GIC structure for spin table SMP initialisation
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
Parked Address in GIC structure can be used as cpu release address
for spin table SMP initialisation.
This patch gets parked address from MADT and use it for SMP
initialisation when DT is not available.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/include/asm/acpi.h | 7 +++++++
arch/arm64/kernel/smp_spin_table.c | 12 ++++++++----
drivers/acpi/plat/arm-core.c | 24 +++++++++++++++++++++++-
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 097394c..856a2e7 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -89,6 +89,8 @@ extern int arm_cpu_to_apicid[NR_CPUS];
extern const char *acpi_get_enable_method(int cpu);
+extern int acpi_get_cpu_release_address(int cpu, u64 *release_address);
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1 /* ACPI sometimes enabled on ARM */
#define acpi_noirq 1 /* ACPI sometimes enabled on ARM */
@@ -100,6 +102,11 @@ static inline const char *acpi_get_enable_method(int cpu)
return NULL;
}
+static inline int acpi_get_cpu_release_address(int cpu, u64 *release_address)
+{
+ return -ENODEV;
+}
+
#endif
#endif /*_ASM_ARM64_ACPI_H*/
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 44c2280..ce86189 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -25,6 +25,7 @@
#include <asm/cpu_ops.h>
#include <asm/cputype.h>
#include <asm/smp_plat.h>
+#include <asm/acpi.h>
extern void secondary_holding_pen(void);
volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
@@ -47,7 +48,6 @@ static void write_pen_release(u64 val)
__flush_dcache_area(start, size);
}
-
static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
{
/*
@@ -55,10 +55,14 @@ static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
*/
if (of_property_read_u64(dn, "cpu-release-addr",
&cpu_release_addr[cpu])) {
- pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
- cpu);
- return -1;
+ /* try ACPI way */
+ if (acpi_get_cpu_release_address(cpu, &cpu_release_addr[cpu])) {
+ pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
+ cpu);
+
+ return -1;
+ }
}
return 0;
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 2704633..7f1d709 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -60,6 +60,9 @@ static int available_cpus;
int arm_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 };
static int boot_cpu_apic_id = -1;
+/* Parked Address in ACPI GIC structure */
+static u64 parked_address[NR_CPUS];
+
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
@@ -193,6 +196,7 @@ static int __init
acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
{
struct acpi_madt_generic_interrupt *processor = NULL;
+ int cpu;
processor = (struct acpi_madt_generic_interrupt *)header;
@@ -208,9 +212,16 @@ acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
* to not preallocating memory for all NR_CPUS
* when we use CPU hotplug.
*/
- acpi_register_gic_cpu_interface(processor->gic_id,
+ cpu = acpi_register_gic_cpu_interface(processor->gic_id,
processor->flags & ACPI_MADT_ENABLED);
+ /*
+ * We need the parked address for SMP initialization with
+ * spin-table enable method
+ */
+ if (cpu >= 0 && processor->parked_address)
+ parked_address[cpu] = processor->parked_address;
+
return 0;
}
@@ -269,6 +280,17 @@ static int __init acpi_parse_madt_gic_entries(void)
return 0;
}
+/* Parked Address in ACPI GIC structure can be used as cpu release addr */
+int acpi_get_cpu_release_address(int cpu, u64 *release_address)
+{
+ if (!release_address || !parked_address[cpu])
+ return -EINVAL;
+
+ *release_address = parked_address[cpu];
+
+ return 0;
+}
+
/*
* Parse GIC distributor related entries in MADT
* returns 0 on success, < 0 on error
--
1.7.9.5
^ permalink raw reply related
* [PATCH 13/20] ARM64 / ACPI: Define ACPI_IRQ_MODEL_GIC needed for arm
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
Needed because arm uses GIC which is defined in ACPI 5.0 spec.
Signed-off-by: Al Stone <al.stone@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
drivers/acpi/bus.c | 3 +++
drivers/acpi/plat/arm-core.c | 6 +++++-
include/linux/acpi.h | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 0710004..246b40c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -487,6 +487,9 @@ static int __init acpi_bus_init_irq(void)
case ACPI_IRQ_MODEL_IOSAPIC:
message = "IOSAPIC";
break;
+ case ACPI_IRQ_MODEL_GIC:
+ message = "GIC";
+ break;
case ACPI_IRQ_MODEL_PLATFORM:
message = "platform specific model";
break;
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 7f1d709..2ff00b0 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -76,7 +76,11 @@ void arch_fix_phys_package_id(int num, u32 slot)
}
EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
-enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
+/*
+ * Since we're on ARM, the default interrupt routing model
+ * clearly has to be GIC.
+ */
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_GIC;
static unsigned int gsi_to_irq(unsigned int gsi)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d9099b1..da55da2 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -63,6 +63,7 @@ enum acpi_irq_model_id {
ACPI_IRQ_MODEL_IOAPIC,
ACPI_IRQ_MODEL_IOSAPIC,
ACPI_IRQ_MODEL_PLATFORM,
+ ACPI_IRQ_MODEL_GIC,
ACPI_IRQ_MODEL_COUNT
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 14/20] Irqchip / gic: Set as default domain so we can access from ACPI
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
Only one GIC is supported in ACPI 5.0, even cascade GIC is not supported.
So if we set the GIC as the default domain then we can access it for IRQ
mapping within the ACPI code.
Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
drivers/irqchip/irq-gic.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 341c601..40fde7b 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -963,6 +963,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
register_cpu_notifier(&gic_cpu_notifier);
#endif
set_handle_irq(gic_handle_irq);
+
+ /*
+ * do not set default host for GIC domain multi-times.
+ * FIXME: This probably needs revisited when multi GICs
+ * supported
+ */
+ irq_set_default_host(gic->domain);
}
gic_chip.flags |= gic_arch_extn.flags;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 15/20] ACPI / ARM64: Update acpi_register_gsi to register with the core IRQ subsystem
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
This API is similar to DT based irq_of_parse_and_map but does link
parent/child IRQ controllers. This is tested for primary GIC PPI and GIC SPI
interrupts and not for secondary child irq controllers.
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
---
drivers/acpi/plat/arm-core.c | 48 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
index 2ff00b0..22c8235 100644
--- a/drivers/acpi/plat/arm-core.c
+++ b/drivers/acpi/plat/arm-core.c
@@ -84,7 +84,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_GIC;
static unsigned int gsi_to_irq(unsigned int gsi)
{
- int irq = irq_create_mapping(NULL, gsi);
+ int irq = irq_find_mapping(NULL, gsi);
return irq;
}
@@ -350,7 +350,51 @@ EXPORT_SYMBOL(acpi_unregister_ioapic);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- return -1;
+ unsigned int irq;
+ unsigned int irq_type;
+
+ /*
+ * ACPI have no bindings to indicate SPI or PPI, so we
+ * use different mappings from DT in ACPI.
+ *
+ * For FDT
+ * PPI interrupt: in the range [0, 15];
+ * SPI interrupt: in the range [0, 987];
+ *
+ * For ACPI, GSI should be unique so using
+ * identity mapping for hwirq:
+ * PPI interrupt: in the range [16, 31];
+ * SPI interrupt: in the range [32, 1019];
+ */
+
+ if (trigger == ACPI_EDGE_SENSITIVE &&
+ polarity == ACPI_ACTIVE_LOW)
+ irq_type = IRQ_TYPE_EDGE_FALLING;
+ else if (trigger == ACPI_EDGE_SENSITIVE &&
+ polarity == ACPI_ACTIVE_HIGH)
+ irq_type = IRQ_TYPE_EDGE_RISING;
+ else if (trigger == ACPI_LEVEL_SENSITIVE &&
+ polarity == ACPI_ACTIVE_LOW)
+ irq_type = IRQ_TYPE_LEVEL_LOW;
+ else if (trigger == ACPI_LEVEL_SENSITIVE &&
+ polarity == ACPI_ACTIVE_HIGH)
+ irq_type = IRQ_TYPE_LEVEL_HIGH;
+ else
+ irq_type = IRQ_TYPE_NONE;
+
+ /*
+ * Since only one GIC is supported in ACPI 5.0, we can
+ * create mapping refer to the default domain
+ */
+ irq = irq_create_mapping(NULL, gsi);
+ if (!irq)
+ return irq;
+
+ /* Set irq type if specified and different than the current one */
+ if (irq_type != IRQ_TYPE_NONE &&
+ irq_type != irq_get_trigger_type(irq))
+ irq_set_irq_type(irq, irq_type);
+ return irq;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 17/20] clocksource / arch_timer: Use ACPI GTDT table to initialize arch timer
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
ACPI GTDT (Generic Timer Description Table) contains information for
arch timer initialization, this patch use this table to probe arm timer.
GTDT table is used for ARM/ARM64 only, please refer to chapter 5.2.24
of ACPI 5.0 spec for detailed inforamtion
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
drivers/clocksource/arm_arch_timer.c | 100 +++++++++++++++++++++++++++++-----
1 file changed, 85 insertions(+), 15 deletions(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 95fb944..1fa5f67 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/sched_clock.h>
+#include <linux/acpi.h>
#include <asm/arch_timer.h>
#include <asm/virt.h>
@@ -632,20 +633,8 @@ static void __init arch_timer_common_init(void)
arch_timer_arch_init();
}
-static void __init arch_timer_init(struct device_node *np)
+static void __init arch_timer_init(void)
{
- int i;
-
- if (arch_timers_present & ARCH_CP15_TIMER) {
- pr_warn("arch_timer: multiple nodes in dt, skipping\n");
- return;
- }
-
- arch_timers_present |= ARCH_CP15_TIMER;
- for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
- arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
- arch_timer_detect_rate(NULL, np);
-
/*
* If HYP mode is available, we know that the physical timer
* has been configured to be accessible from PL1. Use it, so
@@ -667,8 +656,89 @@ static void __init arch_timer_init(struct device_node *np)
arch_timer_register();
arch_timer_common_init();
}
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init);
-CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init);
+
+static void __init arch_timer_of_init(struct device_node *np)
+{
+ int i;
+
+ if (arch_timers_present & ARCH_CP15_TIMER) {
+ pr_warn("arch_timer: multiple nodes in dt, skipping\n");
+ return;
+ }
+
+ arch_timers_present |= ARCH_CP15_TIMER;
+ for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
+ arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
+ arch_timer_detect_rate(NULL, np);
+
+ arch_timer_init();
+}
+CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
+
+#ifdef CONFIG_ACPI
+static void __init register_arch_interrupt(u32 interrupt, u32 flags,
+ int *arch_timer_ppi)
+{
+ int trigger, polarity;
+
+ if (!interrupt || !arch_timer_ppi)
+ return;
+
+ trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+ : ACPI_LEVEL_SENSITIVE;
+
+ polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+ : ACPI_ACTIVE_HIGH;
+
+ *arch_timer_ppi = acpi_register_gsi(NULL, interrupt, trigger,
+ polarity);
+}
+
+static int __init acpi_parse_gtdt(struct acpi_table_header *table)
+{
+ struct acpi_table_gtdt *gtdt;
+
+ gtdt = (struct acpi_table_gtdt *)table;
+ if (!gtdt)
+ return -EINVAL;
+
+ arch_timer_rate = arch_timer_get_cntfrq();
+
+ if (!arch_timer_rate) {
+ pr_warn("arch_timer: Could not get frequency from CNTFREG\n");
+ return -EINVAL;
+ }
+
+ register_arch_interrupt(gtdt->secure_pl1_interrupt,
+ gtdt->secure_pl1_flags, &arch_timer_ppi[PHYS_SECURE_PPI]);
+
+ register_arch_interrupt(gtdt->non_secure_pl1_interrupt,
+ gtdt->non_secure_pl1_flags, &arch_timer_ppi[PHYS_NONSECURE_PPI]);
+
+ register_arch_interrupt(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags, &arch_timer_ppi[VIRT_PPI]);
+
+ register_arch_interrupt(gtdt->non_secure_pl2_interrupt,
+ gtdt->non_secure_pl2_flags, &arch_timer_ppi[HYP_PPI]);
+
+ return 0;
+}
+
+void __init arch_timer_acpi_init(struct acpi_table_header *table)
+{
+ if (arch_timers_present & ARCH_CP15_TIMER) {
+ pr_warn("arch_timer: already initialized, skipping\n");
+ return;
+ }
+
+ if (acpi_parse_gtdt(table))
+ return;
+
+ arch_timers_present |= ARCH_CP15_TIMER;
+ arch_timer_init();
+}
+#endif
static void __init arch_timer_mem_init(struct device_node *np)
{
--
1.7.9.5
^ permalink raw reply related
* [PATCH 18/20] clocksource / acpi: Add macro CLOCKSOURCE_ACPI_DECLARE
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
From: Amit Daniel Kachhap <amit.daniel@samsung.com>
This macro does the same job as CLOCKSOURCE_OF_DECLARE. The device
name from the ACPI timer table is matched with all the registered
timer controllers and matching initialisation routine is invoked.
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
include/asm-generic/vmlinux.lds.h | 10 ++++++++++
include/linux/clocksource.h | 12 ++++++++++++
2 files changed, 22 insertions(+)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bc2121f..3216bee 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -148,6 +148,15 @@
#define CLKSRC_OF_TABLES()
#endif
+#ifdef CONFIG_ACPI
+#define CLKSRC_ACPI_TABLES() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__clksrc_acpi_table) = .; \
+ *(__clksrc_acpi_table) \
+ *(__clksrc_acpi_table_end)
+#else
+#define CLKSRC_ACPI_TABLES()
+#endif
+
#ifdef CONFIG_IRQCHIP
#define IRQCHIP_OF_MATCH_TABLE() \
. = ALIGN(8); \
@@ -491,6 +500,7 @@
MEM_DISCARD(init.rodata) \
CLK_OF_TABLES() \
CLKSRC_OF_TABLES() \
+ CLKSRC_ACPI_TABLES() \
KERNEL_DTB() \
IRQCHIP_OF_MATCH_TABLE()
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 67301a4..1d500cf 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -341,6 +341,8 @@ extern int clocksource_i8253_init(void);
struct device_node;
typedef void(*clocksource_of_init_fn)(struct device_node *);
+typedef void(*clocksource_acpi_init_fn)(void);
+
#ifdef CONFIG_CLKSRC_OF
extern void clocksource_of_init(void);
@@ -358,4 +360,14 @@ static inline void clocksource_of_init(void) {}
.data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
#endif
+#ifdef CONFIG_ACPI
+#define CLOCKSOURCE_ACPI_DECLARE(name, compat, fn) \
+ static const struct acpi_device_id __clksrc_acpi_table_##name \
+ __used __section(__clksrc_acpi_table) \
+ = { .id = compat, \
+ .driver_data = (kernel_ulong_t)fn }
+#else
+#define CLOCKSOURCE_ACPI_DECLARE(name, compat, fn)
+#endif
+
#endif /* _LINUX_CLOCKSOURCE_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 19/20] clocksource / ACPI: Introduce clocksource_acpi_init() using CLOCKSOURCE_ACPI_DECLARE
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
acpi_table_parse() will find table with table id and run handler
on it. So we use CLOCKSOURCE_ACPI_DECLARE to decalare timer tables
and glue its handler, then initialize them in clocksource_acpi_init().
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
---
drivers/clocksource/Makefile | 1 +
drivers/clocksource/arm_arch_timer.c | 1 +
drivers/clocksource/clksrc-acpi.c | 36 ++++++++++++++++++++++++++++++++++
include/linux/clocksource.h | 3 +++
4 files changed, 41 insertions(+)
create mode 100644 drivers/clocksource/clksrc-acpi.c
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 33621ef..2304c99 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
+obj-$(CONFIG_ACPI) += clksrc-acpi.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 1fa5f67..6489037 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -738,6 +738,7 @@ void __init arch_timer_acpi_init(struct acpi_table_header *table)
arch_timers_present |= ARCH_CP15_TIMER;
arch_timer_init();
}
+CLOCKSOURCE_ACPI_DECLARE(armv8_arch_timer, "GTDT", arch_timer_acpi_init);
#endif
static void __init arch_timer_mem_init(struct device_node *np)
diff --git a/drivers/clocksource/clksrc-acpi.c b/drivers/clocksource/clksrc-acpi.c
new file mode 100644
index 0000000..41efc83
--- /dev/null
+++ b/drivers/clocksource/clksrc-acpi.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, Hanjun Guo <hanjun.guo@linaro.org>
+ * Copyright (c) 2014, Amit Daniel Kachhap <amit.daniel@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/clocksource.h>
+
+extern struct acpi_device_id __clksrc_acpi_table[];
+
+static const struct acpi_device_id __clksrc_acpi_table_sentinel
+ __used __section(__clksrc_acpi_table_end);
+
+void __init clocksource_acpi_init(void)
+{
+ const struct acpi_device_id *id;
+ acpi_tbl_table_handler init_func;
+
+ for (id = __clksrc_acpi_table; id->id[0]; id++) {
+ init_func = (acpi_tbl_table_handler)id->driver_data;
+ acpi_table_parse(id->id, init_func);
+ }
+}
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 1d500cf..9bee8b3 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -361,12 +361,15 @@ static inline void clocksource_of_init(void) {}
#endif
#ifdef CONFIG_ACPI
+extern void clocksource_acpi_init(void);
+
#define CLOCKSOURCE_ACPI_DECLARE(name, compat, fn) \
static const struct acpi_device_id __clksrc_acpi_table_##name \
__used __section(__clksrc_acpi_table) \
= { .id = compat, \
.driver_data = (kernel_ulong_t)fn }
#else
+static inline void clocksource_acpi_init(void) { return; }
#define CLOCKSOURCE_ACPI_DECLARE(name, compat, fn)
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH 20/20] ARM64 / clocksource: Use clocksource_acpi_init()
From: Hanjun Guo @ 2014-01-17 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389961514-13562-1-git-send-email-hanjun.guo@linaro.org>
Use clocksource_acpi_init() on ARM64 to initialise timers
in ACPI way when DT is not available.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
arch/arm64/kernel/time.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 29c39d5..6e453ac 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -67,6 +67,12 @@ void __init time_init(void)
clocksource_of_init();
+ /*
+ * Since ACPI or FDT will only one be available in the system,
+ * we can use clocksource_acpi_init() here safely
+ */
+ clocksource_acpi_init();
+
arch_timer_rate = arch_timer_get_rate();
if (!arch_timer_rate)
panic("Unable to initialise architected timer.\n");
--
1.7.9.5
^ permalink raw reply related
* [PATCH] audit: Modify a set of system calls in audit class definitions
From: Will Deacon @ 2014-01-17 12:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389945903-4326-1-git-send-email-takahiro.akashi@linaro.org>
On Fri, Jan 17, 2014 at 08:05:03AM +0000, AKASHI Takahiro wrote:
> Each asm-generic/audit_xx.h defines a set of system calls for respective
> audit permssion class (read, write, change attribute or exec).
permission
> This patch changes two entries:
>
> 1) fchown in audit_change_attr.h
> Make fchown included by its own because in asm-generic/unistd.h, for example,
> fchown always exists while chown is optional. This change is necessary at
> least for arm64.
>
> 2) truncate64 in audit_write.h
> Add missing truncate64/ftruncate64 as well as truncate/ftruncate
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Will
^ permalink raw reply
* imx6dl/imx6q fec rmii mode with external ref_clk
From: Fabio Estevam @ 2014-01-17 12:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140115105517.GA1776@frolo.macqel>
On Wed, Jan 15, 2014 at 8:55 AM, Philippe De Muyter <phdm@macq.eu> wrote:
> On Wed, Jan 15, 2014 at 08:13:15AM -0200, Fabio Estevam wrote:
>> On Wed, Jan 15, 2014 at 7:45 AM, Philippe De Muyter <phdm@macq.eu> wrote:
>>
>> > Here are my patches (I have called my board imx6dl-p6-2094):
>> > Do I need to replace the hex value after MX6QDL_PAD_GPIO_16__ENET_REF_CLK
>> > by something else ?
>>
>> hummingboard uses:
>>
>> MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000
>>
>> Check arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi in linux-next.
>
> They use RGMII, while I have RMII :(
Are you able to do TFTP in the bootloader? Maybe it is easier to debug
from the bootloader and check if the PHY is being properly powered and
clocked.
You can check mx6slevk which uses RMII.
Regards,
Fabio Estevam
^ permalink raw reply
* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
From: Seungwon Jeon @ 2014-01-17 12:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87y52fok4r.fsf@linaro.org>
On Fri, January 17, 2014, Kevin Hilman wrote:
> Zhangfei Gao <zhangfei.gao@linaro.org> writes:
>
> > Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> > CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> > can not be checked by IS_ERR_VALUE.
> > Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> > otherwise sd detect may occasionally fail.
> >
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> > Reported-by: Kevin Hilman <khilman@linaro.org>
> > Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> > Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
>
> I didn't look at the patch in detail, but can at least confirm that
> Arndale boots again in -next with this patch applied.
>
> Tested-by: Kevin Hilman <khilman@linaro.org>
Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Thanks,
Seungwon Jeon
^ permalink raw reply
* [PATCH REPOST] ARM: Fix incorrect FDT initrd parameter override
From: Ben Peddell @ 2014-01-17 12:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqJNPbQVKtW0amaOSc1is9oKrGapaHR=YJGJy6TrGQeKYw@mail.gmail.com>
On Thu, Jan 16, 2014 at 10:04 AM -0600, Rob Herring wrote:
>> Signed-off-by: Ben Peddell <klightspeed@killerwolves.net>
>
> I'd really like to see phys_initrd_* removed, but that would be more
> invasive, so:
>
> Acked-by: Rob Herring <robh@kernel.org>
>
> Please submit to Russell's patch system and mark for stable. I don't
> think there is time before 3.13 is released.
This patch (7941/2) was submitted on 14 Jan after being acked by Jason Cooper.
<http://lists.infradead.org/pipermail/linux-arm-kernel/2014-January/225272.html>
I apologise for the duplicate patch post.
^ permalink raw reply
* New randconfig build failure: rx51 asoc / gpiolib
From: Russell King - ARM Linux @ 2014-01-17 13:12 UTC (permalink / raw)
To: linux-arm-kernel
Last night's omap randconfig found this. This has only appeared in the
builds in the last few days, so it's a new regression for the changes
queued up for merge window:
sound/soc/omap/rx51.c:220:33: error: array type has incomplete element type
sound/soc/omap/rx51.c:222:3: error: field name not in record or union initializer
sound/soc/omap/rx51.c:222:3: error: (near initialization for 'rx51_av_jack_gpios')
sound/soc/omap/rx51.c:223:3: error: field name not in record or union initializer
sound/soc/omap/rx51.c:223:3: error: (near initialization for 'rx51_av_jack_gpios')
sound/soc/omap/rx51.c:224:3: error: field name not in record or union initializer
...
sound/soc/omap/rx51.c: In function 'rx51_aic34_init':
sound/soc/omap/rx51.c:325:2: error: implicit declaration of function 'snd_soc_jack_add_gpios'
sound/soc/omap/rx51.c:326:89: error: type defaults to 'int' in type name
sound/soc/omap/rx51.c:326:89: error: type defaults to 'int' in type name
sound/soc/omap/rx51.c:326:89: error: negative width in bit-field '<anonymous>'
sound/soc/omap/rx51.c: In function 'rx51_soc_exit':
sound/soc/omap/rx51.c:437:2: error: implicit declaration of function 'snd_soc_jack_free_gpios'
sound/soc/omap/rx51.c:437:120: error: type defaults to 'int' in type name
sound/soc/omap/rx51.c:437:120: error: type defaults to 'int' in type name
sound/soc/omap/rx51.c:437:120: error: negative width in bit-field '<anonymous>'
which is caused by "struct snd_soc_jack_gpio" not being defined. For
some reason, this structure is defined in sound/soc.h, but is
conditionalised upon CONFIG_GPIOLIB.
This means either the dependencies on SND_OMAP_SOC_RX51 are incorrect
(they don't include a dependency on GPIOLIB) or ASoC is wrong to make
the definitions conditional upon GPIOLIB.
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* [PATCH 06/18] ARM: dts: omap3-overo: Enable MMC2
From: Florian Vaussard @ 2014-01-17 13:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABxcv=nO1ZtC7wjVSq+Qw9AmFGahpDUSjOZOO1+tYHhqo9P0Pw@mail.gmail.com>
Hello Javier
On 01/09/2014 09:43 PM, Javier Martinez Canillas wrote:
> [adding Enric Balletbo to cc]
>
> Hello Florian,
>
> On Thu, Jan 9, 2014 at 1:48 PM, Florian Vaussard
> <florian.vaussard@epfl.ch> wrote:
>> MMC2 is used by the on-board WiFi module populated on some boards
>> (based on Marvell Libertas 8688 SDIO).
>>
>> Note: currently WiFi only works on cold boot, as the module is not
>> properly reset (missing binding for the GPIO reset).
>>
>
> Have you looked at commit 0e9fd777 ("ARM: dts: omap3-igep: Add support
> for LBEE1USJYC WiFi connected to SDIO") ?
>
> If I remember correctly the LBEE1USJYC Wifi/BT combo module is
> basically a Marvell Libertas 8688 Wlan and Enric got soft reset
> working too by adding a GPIO property to the regulator for the reset
> GPIO.
>
> Hope it helps,
Thank you, I got it working. It is a bit messy, as I have 3 GPIOs
(poweron, wifi-reset and bt-reset). As a regulator can control only one
GPIO, I had to define 3 regulators, and assigning them to the vmmc,
vqmmc, and vmmc_aux. I hope that a better solution will pop-up in this
thread [1]. It is a pity that the previous version of the GPIO-reset
controller was not merged.
Florian
[1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/294907
^ permalink raw reply
* Randconfig build failure: screwed dependencies for phy-msm-usb.c
From: Russell King - ARM Linux @ 2014-01-17 13:22 UTC (permalink / raw)
To: linux-arm-kernel
drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_suspend':
drivers/usb/phy/phy-msm-usb.c:1691:2: error: implicit declaration of function 'msm_otg_suspend'
drivers/usb/phy/phy-msm-usb.c: In function 'msm_otg_runtime_resume':
drivers/usb/phy/phy-msm-usb.c:1699:2: error: implicit declaration of function 'msm_otg_resume'
#ifdef CONFIG_PM_SLEEP
static int msm_otg_suspend(struct msm_otg *motg)
{
...
}
static int msm_otg_resume(struct msm_otg *motg)
{
...
}
#endif
...
#ifdef CONFIG_PM_RUNTIME
...
static int msm_otg_runtime_suspend(struct device *dev)
{
struct msm_otg *motg = dev_get_drvdata(dev);
dev_dbg(dev, "OTG runtime suspend\n");
return msm_otg_suspend(motg);
}
static int msm_otg_runtime_resume(struct device *dev)
{
struct msm_otg *motg = dev_get_drvdata(dev);
dev_dbg(dev, "OTG runtime resume\n");
return msm_otg_resume(motg);
}
#endif
So, if runtime PM is enabled, but PM sleep isn't, this fails as above.
If the msm_otg_* functions are required for runtime PM, they shouldn't
be conditional on CONfIG_PM_SLEEP.
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* [PATCH net-next v3 0/8] net: stmmac: Add Allwinner A20 GMAC ethernet
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This is v3 of the Allwinner A20 GMAC glue layer for stmmac.
I have split the series into stmmac driver changes for net-next,
and clock and DT patches for their respective trees.
The Allwinner A20 SoC integrates an early version of dwmac
IP from Synopsys. On top of that is a hardware glue layer.
This layer needs to be configured before the dwmac can be
used.
Part of the glue layer is a clock mux, which controls the
source and direction of the TX clock used by GMAC.
The glue layer is implemented with existing feature flags
and callbacks found in stmmac driver core. A new stmmac_of_data
structure, which is a subset of the original platform data,
has been added to tie these values with compatible strings.
The purpose of this is to avoid future glue layers assuming
they can pass other data or directly modify values used by
the driver core. This is found in patch #7.
The callbacks have also been extended to pass board specific
data. This is found in patch #3.
This version of dwmac IP requires store and forward DMA mode.
The relevant device tree property was documented, but not
implemented. Patch #6 adds this to stmmac platform driver.
Changes since v2:
* Dropped non CONFIG_RESET_CONTROLLER routines, make stmmac
select CONFIG_RESET_CONTROLLER
* Split out "Deprecate snps,phy-addr and auto-detect PHY address"
from "Use driver data and callbacks tied with compatible strings"
* Added comments on how sunxi glue layer uses GMAC clock
* Rebased onto net-next
* Corrected typo in blackfin commit message
Changes since v1:
* Added optional reset control to stmmac driver core
* Added non CONFIG_RESET_CONROLLER routines for the above change
* Extended callback API, as discussed with Srinivas
* Used new stmmac_of_data to pass features and callbacks,
instead of platform data, as discussed
* Seperated clock module glue layer into clock driver
Cheers,
ChenYu
Chen-Yu Tsai (8):
net: stmmac: Enable stmmac main clock when probing hardware
net: stmmac: Add support for optional reset control
net: stmmac: Allocate and pass soc/board specific data to callbacks
blackfin: Update stmmac callback signatures
net: stmmac: Honor DT parameter to force DMA store and forward mode
net: stmmac: Deprecate snps,phy-addr and auto-detect PHY address
net: stmmac: Use driver data and callbacks tied with compatible
strings
net: stmmac: sunxi platform extensions for GMAC in Allwinner A20 SoC's
.../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++
Documentation/devicetree/bindings/net/stmmac.txt | 4 +-
Documentation/networking/stmmac.txt | 12 +-
arch/blackfin/mach-bf609/boards/ezkit.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 141 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 5 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 45 +++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 +-
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 80 +++++++++---
include/linux/stmmac.h | 24 +++-
12 files changed, 316 insertions(+), 41 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
--
1.8.5.2
^ permalink raw reply
* [PATCH net-next v3 1/8] net: stmmac: Enable stmmac main clock when probing hardware
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389965087-21971-1-git-send-email-wens@csie.org>
The stmmac driver does not enable the main clock during the probe phase.
If the clock was not enabled by the boot loader or was disabled by the
kernel, hardware features and the MDIO bus would not be probed properly.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index cddcf76..0d2c4cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1680,8 +1680,6 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- clk_prepare_enable(priv->stmmac_clk);
-
stmmac_check_ether_addr(priv);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
@@ -1819,7 +1817,6 @@ static int stmmac_release(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
stmmac_exit_fs();
#endif
- clk_disable_unprepare(priv->stmmac_clk);
stmmac_release_ptp(priv);
@@ -2727,10 +2724,18 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if ((phyaddr >= 0) && (phyaddr <= 31))
priv->plat->phy_addr = phyaddr;
+ priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_clk)) {
+ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
+ __func__);
+ goto error_clk_get;
+ }
+ clk_prepare_enable(priv->stmmac_clk);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
- goto error_free_netdev;
+ goto error_hw_init;
ndev->netdev_ops = &stmmac_netdev_ops;
@@ -2768,12 +2773,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
goto error_netdev_register;
}
- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
- if (IS_ERR(priv->stmmac_clk)) {
- pr_warn("%s: warning: cannot get CSR clock\n", __func__);
- goto error_clk_get;
- }
-
/* If a specific clk_csr value is passed from the platform
* this means that the CSR Clock Range selection cannot be
* changed at run-time and it is fixed. Viceversa the driver'll try to
@@ -2801,12 +2800,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
return priv;
error_mdio_register:
- clk_put(priv->stmmac_clk);
-error_clk_get:
unregister_netdev(ndev);
error_netdev_register:
netif_napi_del(&priv->napi);
-error_free_netdev:
+error_hw_init:
+ clk_disable_unprepare(priv->stmmac_clk);
+error_clk_get:
free_netdev(ndev);
return NULL;
@@ -2833,6 +2832,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
return 0;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 2/8] net: stmmac: Add support for optional reset control
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389965087-21971-1-git-send-email-wens@csie.org>
The DWMAC has a reset assert line, which is used on some SoCs. Add an
optional reset control to stmmac driver core.
To support reset control deferred probing, this patch changes the driver
probe function to return the actual error, instead of just -EINVAL.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
Documentation/devicetree/bindings/net/stmmac.txt | 3 +++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 ++--
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
6 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index eba0e5e..d132513 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -30,6 +30,9 @@ Required properties:
Optional properties:
- mac-address: 6 bytes, mac address
+- resets: Should contain a phandle to the STMMAC reset signal, if any
+- reset-names: Should contain the reset signal name "stmmaceth", if a
+ reset phandle is given
Examples:
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 6e52c0f..b59d1ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -5,6 +5,7 @@ config STMMAC_ETH
select PHYLIB
select CRC32
select PTP_1588_CLOCK
+ select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
Synopsys IP Core and only tested on the STMicroelectronics
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 73709e9..c1c141f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -32,6 +32,7 @@
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
+#include <linux/reset.h>
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
@@ -91,6 +92,7 @@ struct stmmac_priv {
int wolopts;
int wol_irq;
struct clk *stmmac_clk;
+ struct reset_control *stmmac_rst;
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0d2c4cb..0c5c120 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -51,6 +51,7 @@
#include <linux/net_tstamp.h>
#include "stmmac_ptp.h"
#include "stmmac.h"
+#include <linux/reset.h>
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
#define JUMBO_LEN 9000
@@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (IS_ERR(priv->stmmac_clk)) {
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
__func__);
+ ret = PTR_ERR(priv->stmmac_clk);
goto error_clk_get;
}
clk_prepare_enable(priv->stmmac_clk);
+ priv->stmmac_rst = devm_reset_control_get(priv->device,
+ STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_rst)) {
+ if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto error_hw_init;
+ }
+ dev_info(priv->device, "no reset control found\n");
+ priv->stmmac_rst = NULL;
+ }
+ if (priv->stmmac_rst)
+ reset_control_deassert(priv->stmmac_rst);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
@@ -2808,7 +2823,7 @@ error_hw_init:
error_clk_get:
free_netdev(ndev);
- return NULL;
+ return ERR_PTR(ret);
}
/**
@@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ if (priv->stmmac_rst)
+ reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 37ba2e0..2916089 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
stmmac_default_data();
priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- ret = -ENODEV;
+ ret = PTR_ERR(priv);
goto err_out;
}
priv->dev->irq = pdev->irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 6d0bf22..cc6b89a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- return -ENODEV;
+ return PTR_ERR(priv);
}
/* Get MAC address if available (DT) */
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 3/8] net: stmmac: Allocate and pass soc/board specific data to callbacks
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389965087-21971-1-git-send-email-wens@csie.org>
The current .init and .exit callbacks requires access to driver
private data structures. This is not a good seperation and abstraction.
Instead, we add a new .setup callback for allocating private data, and
pass the returned pointer to the other callbacks.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
Documentation/networking/stmmac.txt | 12 ++++++++----
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 18 ++++++++++++++----
include/linux/stmmac.h | 6 ++++--
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index cdd916d..2090895 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -127,8 +127,9 @@ struct plat_stmmacenet_data {
int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
@@ -169,10 +170,13 @@ Where:
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
this field is used to configure the AMBA bridge to generate more
efficient STBus traffic.
- o init/exit: callbacks used for calling a custom initialization;
+ o setup/init/exit: callbacks used for calling a custom initialization;
this is sometime necessary on some platforms (e.g. ST boxes)
where the HW needs to have set some PIO lines or system cfg
- registers.
+ registers. setup should return a pointer to private data,
+ which will be stored in bsp_priv, and then passed to init and
+ exit callbacks. init/exit callbacks should not use or modify
+ platform data.
o custom_cfg/custom_data: this is a custom configuration that can be passed
while initializing the resources.
o bsp_priv: another private pointer.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index cc6b89a7..704a5e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -144,9 +144,16 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
}
+ /* Custom setup (if needed) */
+ if (plat_dat->setup) {
+ plat_dat->bsp_priv = plat_dat->setup(pdev);
+ if (IS_ERR(plat_dat->bsp_priv))
+ return PTR_ERR(plat_dat->bsp_priv);
+ }
+
/* Custom initialisation (if needed)*/
if (plat_dat->init) {
- ret = plat_dat->init(pdev);
+ ret = plat_dat->init(pdev, plat_dat->bsp_priv);
if (unlikely(ret))
return ret;
}
@@ -203,7 +210,10 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
int ret = stmmac_dvr_remove(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
+
+ if (priv->plat->free)
+ priv->plat->free(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -218,7 +228,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
ret = stmmac_suspend(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -230,7 +240,7 @@ static int stmmac_pltfr_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
if (priv->plat->init)
- priv->plat->init(pdev);
+ priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(ndev);
}
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 33ace71..0a5a7ac 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -113,8 +113,10 @@ struct plat_stmmacenet_data {
int max_speed;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ void (*free)(struct platform_device *pdev, void *priv);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 4/8] blackfin: Update stmmac callback signatures
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389965087-21971-1-git-send-email-wens@csie.org>
stmmac callbacks have been extended for better separation.
Update them to avoid breakage.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/blackfin/mach-bf609/boards/ezkit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index 82beedd..05194e9 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -117,7 +117,7 @@ static struct stmmac_dma_cfg eth_dma_cfg = {
.pbl = 2,
};
-int stmmac_ptp_clk_init(struct platform_device *pdev)
+int stmmac_ptp_clk_init(struct platform_device *pdev, void *priv)
{
bfin_write32(PADS0_EMAC_PTP_CLKSEL, 0);
return 0;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 5/8] net: stmmac: Honor DT parameter to force DMA store and forward mode
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389965087-21971-1-git-send-email-wens@csie.org>
"snps,force_sf_dma_mode" is documented in stmmac device tree bindings,
but is never handled by the driver.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 704a5e0..634260e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -56,6 +56,8 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
sizeof(struct stmmac_mdio_bus_data),
GFP_KERNEL);
+ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
+
/*
* Currently only the properties needed on SPEAr600
* are provided. All other properties should be added
--
1.8.5.2
^ 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