diff options
Diffstat (limited to 'arch/arm/mach-integrator')
22 files changed, 926 insertions, 1375 deletions
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index 350e26636a0..64f8e2564a3 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig @@ -6,8 +6,9 @@ config ARCH_INTEGRATOR_AP bool "Support Integrator/AP and Integrator/PP2 platforms" select CLKSRC_MMIO select MIGHT_HAVE_PCI - select SERIAL_AMBA_PL010 - select SERIAL_AMBA_PL010_CONSOLE + select SERIAL_AMBA_PL010 if TTY + select SERIAL_AMBA_PL010_CONSOLE if TTY + select SOC_BUS help Include support for the ARM(R) Integrator/AP and Integrator/PP2 platforms. @@ -17,8 +18,9 @@ config ARCH_INTEGRATOR_CP select ARCH_CINTEGRATOR select ARM_TIMER_SP804 select PLAT_VERSATILE_CLCD - select SERIAL_AMBA_PL011 - select SERIAL_AMBA_PL011_CONSOLE + select SERIAL_AMBA_PL011 if TTY + select SERIAL_AMBA_PL011_CONSOLE if TTY + select SOC_BUS help Include support for the ARM(R) Integrator CP platform. @@ -26,8 +28,11 @@ config ARCH_CINTEGRATOR bool config INTEGRATOR_IMPD1 - tristate "Include support for Integrator/IM-PD1" + bool "Include support for Integrator/IM-PD1" depends on ARCH_INTEGRATOR_AP + select ARCH_REQUIRE_GPIOLIB + select ARM_VIC + select GPIO_PL061 if GPIOLIB help The IM-PD1 is an add-on logic module for the Integrator which allows ARM(R) Ltd PrimeCells to be developed and evaluated. diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile index 5521d18bf19..ec759ded7b6 100644 --- a/arch/arm/mach-integrator/Makefile +++ b/arch/arm/mach-integrator/Makefile @@ -8,6 +8,5 @@ obj-y := core.o lm.o leds.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o -obj-$(CONFIG_PCI) += pci_v3.o pci.o -obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o +obj-$(CONFIG_PCI) += pci_v3.o obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/cm.h index 202e6a57f10..4ecff7bff48 100644 --- a/arch/arm/mach-integrator/include/mach/cm.h +++ b/arch/arm/mach-integrator/cm.h @@ -1,9 +1,12 @@ /* - * update the core module control register. + * access the core module control register. */ +u32 cm_get(void); void cm_control(u32, u32); -#define CM_CTRL __io_address(INTEGRATOR_HDR_CTRL) +struct device_node; +void cm_init(void); +void cm_clear_irqs(void); #define CM_CTRL_LED (1 << 0) #define CM_CTRL_nMBDET (1 << 1) diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h index c3ff21b5ea2..ad0ac5547b2 100644 --- a/arch/arm/mach-integrator/common.h +++ b/arch/arm/mach-integrator/common.h @@ -1,6 +1,8 @@ +#include <linux/reboot.h> #include <linux/amba/serial.h> -extern struct amba_pl010_data integrator_uart_data; +extern struct amba_pl010_data ap_uart_data; void integrator_init_early(void); int integrator_init(bool is_cp); void integrator_reserve(void); -void integrator_restart(char, const char *); +void integrator_restart(enum reboot_mode, const char *); +void integrator_init_sysfs(struct device *parent, u32 id); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index ea22a17246d..e3f3aca43ef 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -18,122 +18,32 @@ #include <linux/memblock.h> #include <linux/sched.h> #include <linux/smp.h> -#include <linux/termios.h> #include <linux/amba/bus.h> #include <linux/amba/serial.h> #include <linux/io.h> - -#include <mach/hardware.h> -#include <mach/platform.h> -#include <mach/cm.h> -#include <mach/irqs.h> +#include <linux/stat.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <asm/mach-types.h> #include <asm/mach/time.h> #include <asm/pgtable.h> +#include "hardware.h" +#include "cm.h" #include "common.h" -#ifdef CONFIG_ATAGS - -#define INTEGRATOR_RTC_IRQ { IRQ_RTCINT } -#define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 } -#define INTEGRATOR_UART1_IRQ { IRQ_UARTINT1 } -#define KMI0_IRQ { IRQ_KMIINT0 } -#define KMI1_IRQ { IRQ_KMIINT1 } - -static AMBA_APB_DEVICE(rtc, "rtc", 0, - INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL); - -static AMBA_APB_DEVICE(uart0, "uart0", 0, - INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, &integrator_uart_data); - -static AMBA_APB_DEVICE(uart1, "uart1", 0, - INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data); - -static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL); -static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL); - -static struct amba_device *amba_devs[] __initdata = { - &rtc_device, - &uart0_device, - &uart1_device, - &kmi0_device, - &kmi1_device, -}; - -int __init integrator_init(bool is_cp) -{ - int i; - - /* - * The Integrator/AP lacks necessary AMBA PrimeCell IDs, so we need to - * hard-code them. The Integator/CP and forward have proper cell IDs. - * Else we leave them undefined to the bus driver can autoprobe them. - */ - if (!is_cp) { - rtc_device.periphid = 0x00041030; - uart0_device.periphid = 0x00041010; - uart1_device.periphid = 0x00041010; - kmi0_device.periphid = 0x00041050; - kmi1_device.periphid = 0x00041050; - } - - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - } - - return 0; -} - -#endif +static DEFINE_RAW_SPINLOCK(cm_lock); +static void __iomem *cm_base; -/* - * On the Integrator platform, the port RTS and DTR are provided by - * bits in the following SC_CTRLS register bits: - * RTS DTR - * UART0 7 6 - * UART1 5 4 +/** + * cm_get - get the value from the CM_CTRL register */ -#define SC_CTRLC __io_address(INTEGRATOR_SC_CTRLC) -#define SC_CTRLS __io_address(INTEGRATOR_SC_CTRLS) - -static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) +u32 cm_get(void) { - unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; - u32 phybase = dev->res.start; - - if (phybase == INTEGRATOR_UART0_BASE) { - /* UART0 */ - rts_mask = 1 << 4; - dtr_mask = 1 << 5; - } else { - /* UART1 */ - rts_mask = 1 << 6; - dtr_mask = 1 << 7; - } - - if (mctrl & TIOCM_RTS) - ctrlc |= rts_mask; - else - ctrls |= rts_mask; - - if (mctrl & TIOCM_DTR) - ctrlc |= dtr_mask; - else - ctrls |= dtr_mask; - - __raw_writel(ctrls, SC_CTRLS); - __raw_writel(ctrlc, SC_CTRLC); + return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET); } -struct amba_pl010_data integrator_uart_data = { - .set_mctrl = integrator_uart_set_mctrl, -}; - -static DEFINE_RAW_SPINLOCK(cm_lock); - /** * cm_control - update the CM_CTRL register. * @mask: bits to change @@ -145,12 +55,80 @@ void cm_control(u32 mask, u32 set) u32 val; raw_spin_lock_irqsave(&cm_lock, flags); - val = readl(CM_CTRL) & ~mask; - writel(val | set, CM_CTRL); + val = readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask; + writel(val | set, cm_base + INTEGRATOR_HDR_CTRL_OFFSET); raw_spin_unlock_irqrestore(&cm_lock, flags); } -EXPORT_SYMBOL(cm_control); +static const char *integrator_arch_str(u32 id) +{ + switch ((id >> 16) & 0xff) { + case 0x00: + return "ASB little-endian"; + case 0x01: + return "AHB little-endian"; + case 0x03: + return "AHB-Lite system bus, bi-endian"; + case 0x04: + return "AHB"; + case 0x08: + return "AHB system bus, ASB processor bus"; + default: + return "Unknown"; + } +} + +static const char *integrator_fpga_str(u32 id) +{ + switch ((id >> 12) & 0xf) { + case 0x01: + return "XC4062"; + case 0x02: + return "XC4085"; + case 0x03: + return "XVC600"; + case 0x04: + return "EPM7256AE (Altera PLD)"; + default: + return "Unknown"; + } +} + +void cm_clear_irqs(void) +{ + /* disable core module IRQs */ + writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET + + IRQ_ENABLE_CLEAR); +} + +static const struct of_device_id cm_match[] = { + { .compatible = "arm,core-module-integrator"}, + { }, +}; + +void cm_init(void) +{ + struct device_node *cm = of_find_matching_node(NULL, cm_match); + u32 val; + + if (!cm) { + pr_crit("no core module node found in device tree\n"); + return; + } + cm_base = of_iomap(cm, 0); + if (!cm_base) { + pr_crit("could not remap core module\n"); + return; + } + cm_clear_irqs(); + val = readl(cm_base + INTEGRATOR_HDR_ID_OFFSET); + pr_info("Detected ARM core module:\n"); + pr_info(" Manufacturer: %02x\n", (val >> 24)); + pr_info(" Architecture: %s\n", integrator_arch_str(val)); + pr_info(" FPGA: %s\n", integrator_fpga_str(val)); + pr_info(" Build: %02x\n", (val >> 4) & 0xFF); + pr_info(" Rev: %c\n", ('A' + (val & 0x03))); +} /* * We need to stop things allocating the low memory; ideally we need a @@ -165,7 +143,60 @@ void __init integrator_reserve(void) /* * To reset, we hit the on-board reset register in the system FPGA */ -void integrator_restart(char mode, const char *cmd) +void integrator_restart(enum reboot_mode mode, const char *cmd) { cm_control(CM_CTRL_RESET, CM_CTRL_RESET); } + +static u32 integrator_id; + +static ssize_t intcp_get_manf(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%02x\n", integrator_id >> 24); +} + +static struct device_attribute intcp_manf_attr = + __ATTR(manufacturer, S_IRUGO, intcp_get_manf, NULL); + +static ssize_t intcp_get_arch(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", integrator_arch_str(integrator_id)); +} + +static struct device_attribute intcp_arch_attr = + __ATTR(architecture, S_IRUGO, intcp_get_arch, NULL); + +static ssize_t intcp_get_fpga(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id)); +} + +static struct device_attribute intcp_fpga_attr = + __ATTR(fpga, S_IRUGO, intcp_get_fpga, NULL); + +static ssize_t intcp_get_build(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF); +} + +static struct device_attribute intcp_build_attr = + __ATTR(build, S_IRUGO, intcp_get_build, NULL); + + + +void integrator_init_sysfs(struct device *parent, u32 id) +{ + integrator_id = id; + device_create_file(parent, &intcp_manf_attr); + device_create_file(parent, &intcp_arch_attr); + device_create_file(parent, &intcp_fpga_attr); + device_create_file(parent, &intcp_build_attr); +} diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c deleted file mode 100644 index 590c192cdf4..00000000000 --- a/arch/arm/mach-integrator/cpu.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * linux/arch/arm/mach-integrator/cpu.c - * - * Copyright (C) 2001-2002 Deep Blue Solutions Ltd. - * - * 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. - * - * CPU support functions - */ -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/cpufreq.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/init.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <mach/platform.h> -#include <asm/mach-types.h> -#include <asm/hardware/icst.h> - -static struct cpufreq_driver integrator_driver; - -#define CM_ID __io_address(INTEGRATOR_HDR_ID) -#define CM_OSC __io_address(INTEGRATOR_HDR_OSC) -#define CM_STAT __io_address(INTEGRATOR_HDR_STAT) -#define CM_LOCK __io_address(INTEGRATOR_HDR_LOCK) - -static const struct icst_params lclk_params = { - .ref = 24000000, - .vco_max = ICST525_VCO_MAX_5V, - .vco_min = ICST525_VCO_MIN, - .vd_min = 8, - .vd_max = 132, - .rd_min = 24, - .rd_max = 24, - .s2div = icst525_s2div, - .idx2s = icst525_idx2s, -}; - -static const struct icst_params cclk_params = { - .ref = 24000000, - .vco_max = ICST525_VCO_MAX_5V, - .vco_min = ICST525_VCO_MIN, - .vd_min = 12, - .vd_max = 160, - .rd_min = 24, - .rd_max = 24, - .s2div = icst525_s2div, - .idx2s = icst525_idx2s, -}; - -/* - * Validate the speed policy. - */ -static int integrator_verify_policy(struct cpufreq_policy *policy) -{ - struct icst_vco vco; - - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - - vco = icst_hz_to_vco(&cclk_params, policy->max * 1000); - policy->max = icst_hz(&cclk_params, vco) / 1000; - - vco = icst_hz_to_vco(&cclk_params, policy->min * 1000); - policy->min = icst_hz(&cclk_params, vco) / 1000; - - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, - policy->cpuinfo.max_freq); - - return 0; -} - - -static int integrator_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - cpumask_t cpus_allowed; - int cpu = policy->cpu; - struct icst_vco vco; - struct cpufreq_freqs freqs; - u_int cm_osc; - - /* - * Save this threads cpus_allowed mask. - */ - cpus_allowed = current->cpus_allowed; - - /* - * Bind to the specified CPU. When this call returns, - * we should be running on the right CPU. - */ - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - BUG_ON(cpu != smp_processor_id()); - - /* get current setting */ - cm_osc = __raw_readl(CM_OSC); - - if (machine_is_integrator()) { - vco.s = (cm_osc >> 8) & 7; - } else if (machine_is_cintegrator()) { - vco.s = 1; - } - vco.v = cm_osc & 255; - vco.r = 22; - freqs.old = icst_hz(&cclk_params, vco) / 1000; - - /* icst_hz_to_vco rounds down -- so we need the next - * larger freq in case of CPUFREQ_RELATION_L. - */ - if (relation == CPUFREQ_RELATION_L) - target_freq += 999; - if (target_freq > policy->max) - target_freq = policy->max; - vco = icst_hz_to_vco(&cclk_params, target_freq * 1000); - freqs.new = icst_hz(&cclk_params, vco) / 1000; - - freqs.cpu = policy->cpu; - - if (freqs.old == freqs.new) { - set_cpus_allowed(current, cpus_allowed); - return 0; - } - - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - cm_osc = __raw_readl(CM_OSC); - - if (machine_is_integrator()) { - cm_osc &= 0xfffff800; - cm_osc |= vco.s << 8; - } else if (machine_is_cintegrator()) { - cm_osc &= 0xffffff00; - } - cm_osc |= vco.v; - - __raw_writel(0xa05f, CM_LOCK); - __raw_writel(cm_osc, CM_OSC); - __raw_writel(0, CM_LOCK); - - /* - * Restore the CPUs allowed mask. - */ - set_cpus_allowed(current, cpus_allowed); - - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return 0; -} - -static unsigned int integrator_get(unsigned int cpu) -{ - cpumask_t cpus_allowed; - unsigned int current_freq; - u_int cm_osc; - struct icst_vco vco; - - cpus_allowed = current->cpus_allowed; - - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - BUG_ON(cpu != smp_processor_id()); - - /* detect memory etc. */ - cm_osc = __raw_readl(CM_OSC); - - if (machine_is_integrator()) { - vco.s = (cm_osc >> 8) & 7; - } else { - vco.s = 1; - } - vco.v = cm_osc & 255; - vco.r = 22; - - current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */ - - set_cpus_allowed(current, cpus_allowed); - - return current_freq; -} - -static int integrator_cpufreq_init(struct cpufreq_policy *policy) -{ - - /* set default policy and cpuinfo */ - policy->cpuinfo.max_freq = 160000; - policy->cpuinfo.min_freq = 12000; - policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */ - policy->cur = policy->min = policy->max = integrator_get(policy->cpu); - - return 0; -} - -static struct cpufreq_driver integrator_driver = { - .verify = integrator_verify_policy, - .target = integrator_set_target, - .get = integrator_get, - .init = integrator_cpufreq_init, - .name = "integrator", -}; - -static int __init integrator_cpu_init(void) -{ - return cpufreq_register_driver(&integrator_driver); -} - -static void __exit integrator_cpu_exit(void) -{ - cpufreq_unregister_driver(&integrator_driver); -} - -MODULE_AUTHOR ("Russell M. King"); -MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs"); -MODULE_LICENSE ("GPL"); - -module_init(integrator_cpu_init); -module_exit(integrator_cpu_exit); diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/hardware.h index efeac5d0bc9..857ca5f8b9a 100644 --- a/arch/arm/mach-integrator/include/mach/platform.h +++ b/arch/arm/mach-integrator/hardware.h @@ -1,4 +1,8 @@ /* + * This file contains the hardware definitions of the Integrator. + * + * Copyright (C) 1998-1999 ARM Limited. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -13,26 +17,28 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/************************************************************************** - * * Copyright © ARM Limited 1998. All rights reserved. - * ***********************************************************************/ -/* ************************************************************************ - * - * Integrator address map - * - * ***********************************************************************/ +#ifndef INTEGRATOR_HARDWARE_H +#define INTEGRATOR_HARDWARE_H + +/* + * Where in virtual memory the IO devices (timers, system controllers + * and so on) + */ +#define IO_BASE 0xF0000000 // VA of IO +#define IO_SIZE 0x0B000000 // How much? +#define IO_START INTEGRATOR_HDR_BASE // PA of IO + +/* macro to get at IO space when running virtually */ +#ifdef CONFIG_MMU +#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE) +#else +#define IO_ADDRESS(x) (x) +#endif -#ifndef __address_h -#define __address_h 1 +#define __io_address(n) ((void __iomem *)IO_ADDRESS(n)) -/* ======================================================================== - * Integrator definitions - * ======================================================================== - * ------------------------------------------------------------------------ - * Memory definitions - * ------------------------------------------------------------------------ +/* * Integrator memory map - * */ #define INTEGRATOR_BOOT_ROM_LO 0x00000000 #define INTEGRATOR_BOOT_ROM_HI 0x20000000 @@ -40,13 +46,13 @@ #define INTEGRATOR_BOOT_ROM_SIZE SZ_512K /* - * New Core Modules have different amounts of SSRAM, the amount of SSRAM - * fitted can be found in HDR_STAT. + * New Core Modules have different amounts of SSRAM, the amount of SSRAM + * fitted can be found in HDR_STAT. * - * The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to - * the minimum amount of SSRAM fitted on any core module. + * The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to + * the minimum amount of SSRAM fitted on any core module. * - * New Core Modules also alias the SSRAM. + * New Core Modules also alias the SSRAM. * */ #define INTEGRATOR_SSRAM_BASE 0x00000000 @@ -61,7 +67,6 @@ /* * SDRAM is a SIMM therefore the size is not known. - * */ #define INTEGRATOR_SDRAM_BASE 0x00040000 @@ -81,10 +86,8 @@ #define INTEGRATOR_LOGIC_MODULE2_BASE 0xE0000000 #define INTEGRATOR_LOGIC_MODULE3_BASE 0xF0000000 -/* ------------------------------------------------------------------------ - * Integrator header card registers - * ------------------------------------------------------------------------ - * +/* + * Integrator header card registers */ #define INTEGRATOR_HDR_ID_OFFSET 0x00 #define INTEGRATOR_HDR_PROC_OFFSET 0x04 @@ -173,16 +176,12 @@ #define INTEGRATOR_HDR_SDRAM_SPD_OK (1 << 5) - -/* ------------------------------------------------------------------------ - * Integrator system registers - * ------------------------------------------------------------------------ - * +/* + * Integrator system registers */ /* * System Controller - * */ #define INTEGRATOR_SC_ID_OFFSET 0x00 #define INTEGRATOR_SC_OSC_OFFSET 0x04 @@ -190,7 +189,6 @@ #define INTEGRATOR_SC_CTRLC_OFFSET 0x0C #define INTEGRATOR_SC_DEC_OFFSET 0x10 #define INTEGRATOR_SC_ARB_OFFSET 0x14 -#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18 #define INTEGRATOR_SC_LOCK_OFFSET 0x1C #define INTEGRATOR_SC_BASE 0x11000000 @@ -224,7 +222,6 @@ /* * External Bus Interface - * */ #define INTEGRATOR_EBI_BASE 0x12000000 @@ -273,7 +270,6 @@ /* * LED's & Switches - * */ #define INTEGRATOR_DBG_ALPHA_OFFSET 0x00 #define INTEGRATOR_DBG_LEDS_OFFSET 0x04 @@ -293,55 +289,25 @@ #define INTEGRATOR_CP_SIC_BASE 0xCA000000 /* SIC */ #define INTEGRATOR_CP_CTL_BASE 0xCB000000 /* CP system control */ -/* ------------------------------------------------------------------------ - * KMI keyboard/mouse definitions - * ------------------------------------------------------------------------ - */ /* PS2 Keyboard interface */ #define KMI0_BASE INTEGRATOR_KBD_BASE /* PS2 Mouse interface */ #define KMI1_BASE INTEGRATOR_MOUSE_BASE -/* KMI definitions are now in include/asm-arm/hardware/amba_kmi.h -- rmk */ - -/* ------------------------------------------------------------------------ - * Where in the memory map does PCI live? - * ------------------------------------------------------------------------ - * This represents a fairly liberal usage of address space. Even though - * the V3 only has two windows (therefore we need to map stuff on the fly), - * we maintain the same addresses, even if they're not mapped. +/* + * Integrator Interrupt Controllers * - */ -#define PHYS_PCI_MEM_BASE 0x40000000 /* 512M to xxx */ -/* unused 256M from A0000000-AFFFFFFF might be used for I2O ??? - */ -#define PHYS_PCI_IO_BASE 0x60000000 /* 16M to xxx */ -/* unused (128-16)M from B1000000-B7FFFFFF - */ -#define PHYS_PCI_CONFIG_BASE 0x61000000 /* 16M to xxx */ -/* unused ((128-16)M - 64K) from XXX - */ -#define PHYS_PCI_V3_BASE 0x62000000 - -#define PCI_MEMORY_VADDR IOMEM(0xe8000000) -#define PCI_CONFIG_VADDR IOMEM(0xec000000) -#define PCI_V3_VADDR IOMEM(0xed000000) - -/* ------------------------------------------------------------------------ - * Integrator Interrupt Controllers - * ------------------------------------------------------------------------ * - * Offsets from interrupt controller base + * Offsets from interrupt controller base * - * System Controller interrupt controller base is + * System Controller interrupt controller base is * * INTEGRATOR_IC_BASE + (header_number << 6) * - * Core Module interrupt controller base is + * Core Module interrupt controller base is * * INTEGRATOR_HDR_IC - * */ #define IRQ_STATUS 0 #define IRQ_RAW_STATUS 0x04 @@ -359,25 +325,8 @@ #define FIQ_ENABLE_CLEAR 0x2C -/* ------------------------------------------------------------------------ - * Interrupts - * ------------------------------------------------------------------------ - * - * - * Each Core Module has two interrupts controllers, one on the core module - * itself and one in the system controller on the motherboard. The - * READ_INT macro in target.s reads both interrupt controllers and returns - * a 32 bit bitmask, bits 0 to 23 are interrupts from the system controller - * and bits 24 to 31 are from the core module. - * - * The following definitions relate to the bitmask returned by READ_INT. - * - */ - -/* ------------------------------------------------------------------------ - * LED's - * ------------------------------------------------------------------------ - * +/* + * LED's */ #define GREEN_LED 0x01 #define YELLOW_LED 0x02 @@ -395,7 +344,6 @@ * * Timer 0 runs at bus frequency */ - #define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE #define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100) #define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200) @@ -403,4 +351,4 @@ #define INTEGRATOR_CSR_BASE 0x10000000 #define INTEGRATOR_CSR_SIZE 0x10000000 -#endif +#endif /* INTEGRATOR_HARDWARE_H */ diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index e428f3ab15c..3ce880729cf 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -21,13 +21,13 @@ #include <linux/amba/bus.h> #include <linux/amba/clcd.h> #include <linux/io.h> +#include <linux/platform_data/clk-integrator.h> #include <linux/slab.h> -#include <linux/clkdev.h> +#include <linux/irqchip/arm-vic.h> -#include <asm/hardware/icst.h> -#include <mach/lm.h> -#include <mach/impd1.h> #include <asm/sizes.h> +#include "lm.h" +#include "impd1.h" static int module_id; @@ -36,45 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position"); struct impd1_module { void __iomem *base; - struct clk vcos[2]; - struct clk_lookup *clks[3]; -}; - -static const struct icst_params impd1_vco_params = { - .ref = 24000000, /* 24 MHz */ - .vco_max = ICST525_VCO_MAX_3V, - .vco_min = ICST525_VCO_MIN, - .vd_min = 12, - .vd_max = 519, - .rd_min = 3, - .rd_max = 120, - .s2div = icst525_s2div, - .idx2s = icst525_idx2s, -}; - -static void impd1_setvco(struct clk *clk, struct icst_vco vco) -{ - struct impd1_module *impd1 = clk->data; - u32 val = vco.v | (vco.r << 9) | (vco.s << 16); - - writel(0xa05f, impd1->base + IMPD1_LOCK); - writel(val, clk->vcoreg); - writel(0, impd1->base + IMPD1_LOCK); - -#ifdef DEBUG - vco.v = val & 0x1ff; - vco.r = (val >> 9) & 0x7f; - vco.s = (val >> 16) & 7; - - pr_debug("IM-PD1: VCO%d clock is %ld Hz\n", - vconr, icst525_hz(&impd1_vco_params, vco)); -#endif -} - -static const struct clk_ops impd1_clk_ops = { - .round = icst_clk_round, - .set = icst_clk_set, - .setvco = impd1_setvco, + void __iomem *vic_base; }; void impd1_tweak_control(struct device *dev, u32 mask, u32 val) @@ -302,9 +264,6 @@ struct impd1_device { static struct impd1_device impd1_devs[] = { { - .offset = 0x03000000, - .id = 0x00041190, - }, { .offset = 0x00100000, .irq = { 1 }, .id = 0x00141011, @@ -344,67 +303,79 @@ static struct impd1_device impd1_devs[] = { } }; -static struct clk fixed_14745600 = { - .rate = 14745600, -}; +/* + * Valid IRQs: 0 thru 9 and 11, 10 unused. + */ +#define IMPD1_VALID_IRQS 0x00000bffU -static int impd1_probe(struct lm_device *dev) +/* + * As this module is bool, it is OK to have this as __init_refok() - no + * probe calls will be done after the initial system bootup, as devices + * are discovered as part of the machine startup. + */ +static int __init_refok impd1_probe(struct lm_device *dev) { struct impd1_module *impd1; - int i, ret; + int irq_base; + int i; if (dev->id != module_id) return -EINVAL; - if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers")) + if (!devm_request_mem_region(&dev->dev, dev->resource.start, + SZ_4K, "LM registers")) return -EBUSY; - impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL); - if (!impd1) { - ret = -ENOMEM; - goto release_lm; - } + impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module), + GFP_KERNEL); + if (!impd1) + return -ENOMEM; - impd1->base = ioremap(dev->resource.start, SZ_4K); - if (!impd1->base) { - ret = -ENOMEM; - goto free_impd1; - } + impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K); + if (!impd1->base) + return -ENOMEM; - lm_set_drvdata(dev, impd1); + integrator_impd1_clk_init(impd1->base, dev->id); - printk("IM-PD1 found at 0x%08lx\n", - (unsigned long)dev->resource.start); + if (!devm_request_mem_region(&dev->dev, + dev->resource.start + 0x03000000, + SZ_4K, "VIC")) + return -EBUSY; - for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { - impd1->vcos[i].ops = &impd1_clk_ops, - impd1->vcos[i].owner = THIS_MODULE, - impd1->vcos[i].params = &impd1_vco_params, - impd1->vcos[i].data = impd1; - } - impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1; - impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2; - - impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000", - dev->id); - impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100", - dev->id); - impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200", - dev->id); - for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) - clkdev_add(impd1->clks[i]); + impd1->vic_base = devm_ioremap(&dev->dev, + dev->resource.start + 0x03000000, + SZ_4K); + if (!impd1->vic_base) + return -ENOMEM; + + irq_base = vic_init_cascaded(impd1->vic_base, dev->irq, + IMPD1_VALID_IRQS, 0); + + lm_set_drvdata(dev, impd1); + + dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n", + (unsigned long)dev->resource.start); for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { struct impd1_device *idev = impd1_devs + i; struct amba_device *d; unsigned long pc_base; char devname[32]; + int irq1 = idev->irq[0]; + int irq2 = idev->irq[1]; + + /* Translate IRQs to IM-PD1 local numberspace */ + if (irq1) + irq1 += irq_base; + if (irq2) + irq2 += irq_base; pc_base = dev->resource.start + idev->offset; snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12); - d = amba_ahb_device_add(&dev->dev, devname, pc_base, SZ_4K, - dev->irq, dev->irq, - idev->platform_data, idev->id); + d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, + irq1, irq2, + idev->platform_data, idev->id, + &dev->resource); if (IS_ERR(d)) { dev_err(&dev->dev, "unable to register device: %ld\n", PTR_ERR(d)); continue; @@ -412,14 +383,6 @@ static int impd1_probe(struct lm_device *dev) } return 0; - - free_impd1: - if (impd1 && impd1->base) - iounmap(impd1->base); - kfree(impd1); - release_lm: - release_mem_region(dev->resource.start, SZ_4K); - return ret; } static int impd1_remove_one(struct device *dev, void *data) @@ -430,24 +393,20 @@ static int impd1_remove_one(struct device *dev, void *data) static void impd1_remove(struct lm_device *dev) { - struct impd1_module *impd1 = lm_get_drvdata(dev); - int i; - device_for_each_child(&dev->dev, NULL, impd1_remove_one); - - for (i = 0; i < ARRAY_SIZE(impd1->clks); i++) - clkdev_drop(impd1->clks[i]); + integrator_impd1_clk_exit(dev->id); lm_set_drvdata(dev, NULL); - - iounmap(impd1->base); - kfree(impd1); - release_mem_region(dev->resource.start, SZ_4K); } static struct lm_driver impd1_driver = { .drv = { .name = "impd1", + /* + * As we're dropping the probe() function, suppress driver + * binding from sysfs. + */ + .suppress_bind_attrs = true, }, .probe = impd1_probe, .remove = impd1_remove, diff --git a/arch/arm/mach-integrator/include/mach/impd1.h b/arch/arm/mach-integrator/impd1.h index d75de4b1423..76de4dc9bee 100644 --- a/arch/arm/mach-integrator/include/mach/impd1.h +++ b/arch/arm/mach-integrator/impd1.h @@ -1,6 +1,3 @@ -#define IMPD1_OSC1 0x00 -#define IMPD1_OSC2 0x04 -#define IMPD1_LOCK 0x08 #define IMPD1_LEDS 0x0c #define IMPD1_INT 0x10 #define IMPD1_SW 0x14 @@ -15,4 +12,3 @@ struct device; void impd1_tweak_control(struct device *dev, u32 mask, u32 val); - diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S deleted file mode 100644 index 411b116077e..00000000000 --- a/arch/arm/mach-integrator/include/mach/debug-macro.S +++ /dev/null @@ -1,20 +0,0 @@ -/* arch/arm/mach-integrator/include/mach/debug-macro.S - * - * Debugging macro include header - * - * Copyright (C) 1994-1999 Russell King - * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks - * - * 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. - * -*/ - - .macro addruart, rp, rv, tmp - mov \rp, #0x16000000 @ physical base address - mov \rv, #0xf0000000 @ virtual base - add \rv, \rv, #0x16000000 >> 4 - .endm - -#include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h deleted file mode 100644 index 65fed7c0eb8..00000000000 --- a/arch/arm/mach-integrator/include/mach/hardware.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * arch/arm/mach-integrator/include/mach/hardware.h - * - * This file contains the hardware definitions of the Integrator. - * - * Copyright (C) 1999 ARM Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include <asm/sizes.h> - -/* - * Where in virtual memory the IO devices (timers, system controllers - * and so on) - */ -#define IO_BASE 0xF0000000 // VA of IO -#define IO_SIZE 0x0B000000 // How much? -#define IO_START INTEGRATOR_HDR_BASE // PA of IO - -/* macro to get at IO space when running virtually */ -#ifdef CONFIG_MMU -#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE) -#else -#define IO_ADDRESS(x) (x) -#endif - -#define __io_address(n) ((void __iomem *)IO_ADDRESS(n)) - -#endif - diff --git a/arch/arm/mach-integrator/include/mach/irqs.h b/arch/arm/mach-integrator/include/mach/irqs.h deleted file mode 100644 index 7371018455d..00000000000 --- a/arch/arm/mach-integrator/include/mach/irqs.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * arch/arm/mach-integrator/include/mach/irqs.h - * - * Copyright (C) 1999 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Interrupt numbers - */ -#define IRQ_PIC_START 1 -#define IRQ_SOFTINT 1 -#define IRQ_UARTINT0 2 -#define IRQ_UARTINT1 3 -#define IRQ_KMIINT0 4 -#define IRQ_KMIINT1 5 -#define IRQ_TIMERINT0 6 -#define IRQ_TIMERINT1 7 -#define IRQ_TIMERINT2 8 -#define IRQ_RTCINT 9 -#define IRQ_AP_EXPINT0 10 -#define IRQ_AP_EXPINT1 11 -#define IRQ_AP_EXPINT2 12 -#define IRQ_AP_EXPINT3 13 -#define IRQ_AP_PCIINT0 14 -#define IRQ_AP_PCIINT1 15 -#define IRQ_AP_PCIINT2 16 -#define IRQ_AP_PCIINT3 17 -#define IRQ_AP_V3INT 18 -#define IRQ_AP_CPINT0 19 -#define IRQ_AP_CPINT1 20 -#define IRQ_AP_LBUSTIMEOUT 21 -#define IRQ_AP_APCINT 22 -#define IRQ_CP_CLCDCINT 23 -#define IRQ_CP_MMCIINT0 24 -#define IRQ_CP_MMCIINT1 25 -#define IRQ_CP_AACIINT 26 -#define IRQ_CP_CPPLDINT 27 -#define IRQ_CP_ETHINT 28 -#define IRQ_CP_TSPENINT 29 -#define IRQ_PIC_END 29 - -#define IRQ_CIC_START 32 -#define IRQ_CM_SOFTINT 32 -#define IRQ_CM_COMMRX 33 -#define IRQ_CM_COMMTX 34 -#define IRQ_CIC_END 34 - -/* - * IntegratorCP only - */ -#define IRQ_SIC_START 35 -#define IRQ_SIC_CP_SOFTINT 35 -#define IRQ_SIC_CP_RI0 36 -#define IRQ_SIC_CP_RI1 37 -#define IRQ_SIC_CP_CARDIN 38 -#define IRQ_SIC_CP_LMINT0 39 -#define IRQ_SIC_CP_LMINT1 40 -#define IRQ_SIC_CP_LMINT2 41 -#define IRQ_SIC_CP_LMINT3 42 -#define IRQ_SIC_CP_LMINT4 43 -#define IRQ_SIC_CP_LMINT5 44 -#define IRQ_SIC_CP_LMINT6 45 -#define IRQ_SIC_CP_LMINT7 46 -#define IRQ_SIC_END 46 - -#define NR_IRQS_INTEGRATOR_AP 34 -#define NR_IRQS_INTEGRATOR_CP 47 diff --git a/arch/arm/mach-integrator/include/mach/timex.h b/arch/arm/mach-integrator/include/mach/timex.h deleted file mode 100644 index 1dcb42028c8..00000000000 --- a/arch/arm/mach-integrator/include/mach/timex.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * arch/arm/mach-integrator/include/mach/timex.h - * - * Integrator architecture timex specifications - * - * Copyright (C) 1999 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * ?? - */ -#define CLOCK_TICK_RATE (50000000 / 16) diff --git a/arch/arm/mach-integrator/include/mach/uncompress.h b/arch/arm/mach-integrator/include/mach/uncompress.h index 30452f00a16..8f3cc9954c1 100644 --- a/arch/arm/mach-integrator/include/mach/uncompress.h +++ b/arch/arm/mach-integrator/include/mach/uncompress.h @@ -46,5 +46,3 @@ static inline void flush(void) * nothing to do */ #define arch_decomp_setup() - -#define arch_decomp_wdog() diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index e6617c134fa..660ca6feff4 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -31,36 +31,42 @@ #include <linux/clockchips.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/irqchip/versatile-fpga.h> #include <linux/mtd/physmap.h> #include <linux/clk.h> #include <linux/platform_data/clk-integrator.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/of_platform.h> -#include <video/vga.h> +#include <linux/stat.h> +#include <linux/sys_soc.h> +#include <linux/termios.h> +#include <linux/sched_clock.h> +#include <linux/clk-provider.h> -#include <mach/hardware.h> -#include <mach/platform.h> #include <asm/hardware/arm_timer.h> #include <asm/setup.h> #include <asm/param.h> /* HZ */ #include <asm/mach-types.h> -#include <asm/sched_clock.h> - -#include <mach/lm.h> -#include <mach/irqs.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> -#include <asm/mach/pci.h> #include <asm/mach/time.h> -#include <plat/fpga-irq.h> - +#include "hardware.h" +#include "cm.h" #include "common.h" +#include "pci_v3.h" +#include "lm.h" + +/* Base address to the AP system controller */ +void __iomem *ap_syscon_base; +/* Base address to the external bus interface */ +static void __iomem *ebi_base; -/* + +/* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx * is the (PA >> 12). * @@ -68,20 +74,11 @@ * just for now). */ #define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE) -#define VA_SC_BASE __io_address(INTEGRATOR_SC_BASE) -#define VA_EBI_BASE __io_address(INTEGRATOR_EBI_BASE) -#define VA_CMIC_BASE __io_address(INTEGRATOR_HDR_IC) /* * Logical Physical - * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M) - * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M) - * ed000000 62000000 PCI V3 regs PHYS_PCI_V3_BASE (max 64k) - * fee00000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M) * ef000000 Cache flush - * f1000000 10000000 Core module registers * f1100000 11000000 System controller registers - * f1200000 12000000 EBI registers * f1300000 13000000 Counter/Timer * f1400000 14000000 Interrupt controller * f1600000 16000000 UART 0 @@ -90,23 +87,8 @@ * f1b00000 1b000000 GPIO */ -static struct map_desc ap_io_desc[] __initdata = { +static struct map_desc ap_io_desc[] __initdata __maybe_unused = { { - .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE), .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE), .length = SZ_4K, @@ -122,11 +104,6 @@ static struct map_desc ap_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE), .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE), .length = SZ_4K, @@ -136,29 +113,13 @@ static struct map_desc ap_io_desc[] __initdata = { .pfn = __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE), .length = SZ_4K, .type = MT_DEVICE - }, { - .virtual = (unsigned long)PCI_MEMORY_VADDR, - .pfn = __phys_to_pfn(PHYS_PCI_MEM_BASE), - .length = SZ_16M, - .type = MT_DEVICE - }, { - .virtual = (unsigned long)PCI_CONFIG_VADDR, - .pfn = __phys_to_pfn(PHYS_PCI_CONFIG_BASE), - .length = SZ_16M, - .type = MT_DEVICE - }, { - .virtual = (unsigned long)PCI_V3_VADDR, - .pfn = __phys_to_pfn(PHYS_PCI_V3_BASE), - .length = SZ_64K, - .type = MT_DEVICE } }; static void __init ap_map_io(void) { iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc)); - vga_base = (unsigned long)PCI_MEMORY_VADDR; - pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE)); + pci_v3_early_init(); } #ifdef CONFIG_PM @@ -173,7 +134,7 @@ static int irq_suspend(void) static void irq_resume(void) { /* disable all irq sources */ - writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); + cm_clear_irqs(); writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); @@ -201,24 +162,22 @@ device_initcall(irq_syscore_init); /* * Flash handling. */ -#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET) -#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET) -#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET) -#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET) - static int ap_flash_init(struct platform_device *dev) { u32 tmp; - writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); + writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, + ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); - tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; - writel(tmp, EBI_CSR1); + tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) | + INTEGRATOR_EBI_WRITE_ENABLE; + writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { - writel(0xa05f, EBI_LOCK); - writel(tmp, EBI_CSR1); - writel(0, EBI_LOCK); + if (!(readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) + & INTEGRATOR_EBI_WRITE_ENABLE)) { + writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); } return 0; } @@ -227,23 +186,29 @@ static void ap_flash_exit(struct platform_device *dev) { u32 tmp; - writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC); + writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, + ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); - tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; - writel(tmp, EBI_CSR1); + tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) & + ~INTEGRATOR_EBI_WRITE_ENABLE; + writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { - writel(0xa05f, EBI_LOCK); - writel(tmp, EBI_CSR1); - writel(0, EBI_LOCK); + if (readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) & + INTEGRATOR_EBI_WRITE_ENABLE) { + writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); } } static void ap_flash_set_vpp(struct platform_device *pdev, int on) { - void __iomem *reg = on ? SC_CTRLS : SC_CTRLC; - - writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); + if (on) + writel(INTEGRATOR_SC_CTRL_nFLVPPEN, + ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); + else + writel(INTEGRATOR_SC_CTRL_nFLVPPEN, + ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); } static struct physmap_flash_data ap_flash_data = { @@ -254,6 +219,45 @@ static struct physmap_flash_data ap_flash_data = { }; /* + * For the PL010 found in the Integrator/AP some of the UART control is + * implemented in the system controller and accessed using a callback + * from the driver. + */ +static void integrator_uart_set_mctrl(struct amba_device *dev, + void __iomem *base, unsigned int mctrl) +{ + unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; + u32 phybase = dev->res.start; + + if (phybase == INTEGRATOR_UART0_BASE) { + /* UART0 */ + rts_mask = 1 << 4; + dtr_mask = 1 << 5; + } else { + /* UART1 */ + rts_mask = 1 << 6; + dtr_mask = 1 << 7; + } + + if (mctrl & TIOCM_RTS) + ctrlc |= rts_mask; + else + ctrls |= rts_mask; + + if (mctrl & TIOCM_DTR) + ctrlc |= dtr_mask; + else + ctrls |= dtr_mask; + + __raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); + __raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); +} + +struct amba_pl010_data ap_uart_data = { + .set_mctrl = integrator_uart_set_mctrl, +}; + +/* * Where is the timer (VA)? */ #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) @@ -262,7 +266,7 @@ static struct physmap_flash_data ap_flash_data = { static unsigned long timer_reload; -static u32 notrace integrator_read_sched_clock(void) +static u64 notrace integrator_read_sched_clock(void) { return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE); } @@ -283,7 +287,7 @@ static void integrator_clocksource_init(unsigned long inrate, clocksource_mmio_init(base + TIMER_VALUE, "timer2", rate, 200, 16, clocksource_mmio_readl_down); - setup_sched_clock(integrator_read_sched_clock, 16, rate); + sched_clock_register(integrator_read_sched_clock, 16, rate); } static void __iomem * clkevt_base; @@ -353,7 +357,7 @@ static struct clock_event_device integrator_clockevent = { static struct irqaction integrator_timer_irq = { .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = integrator_timer_interrupt, .dev_id = &integrator_clockevent, }; @@ -387,9 +391,7 @@ void __init ap_init_early(void) { } -#ifdef CONFIG_OF - -static void __init ap_init_timer_of(void) +static void __init ap_of_timer_init(void) { struct device_node *node; const char *path; @@ -399,10 +401,7 @@ static void __init ap_init_timer_of(void) struct clk *clk; unsigned long rate; - clk = clk_get_sys("ap_timer", NULL); - BUG_ON(IS_ERR(clk)); - clk_prepare_enable(clk); - rate = clk_get_rate(clk); + of_clk_init(NULL); err = of_property_read_string(of_aliases, "arm,timer-primary", &path); @@ -412,6 +411,12 @@ static void __init ap_init_timer_of(void) base = of_iomap(node, 0); if (WARN_ON(!base)) return; + + clk = of_clk_get(node, 0); + BUG_ON(IS_ERR(clk)); + clk_prepare_enable(clk); + rate = clk_get_rate(clk); + writel(0, base + TIMER_CTRL); integrator_clocksource_init(rate, base); @@ -424,14 +429,16 @@ static void __init ap_init_timer_of(void) if (WARN_ON(!base)) return; irq = irq_of_parse_and_map(node, 0); + + clk = of_clk_get(node, 0); + BUG_ON(IS_ERR(clk)); + clk_prepare_enable(clk); + rate = clk_get_rate(clk); + writel(0, base + TIMER_CTRL); integrator_clockevent_init(rate, base, irq); } -static struct sys_timer ap_of_timer = { - .init = ap_init_timer_of, -}; - static const struct of_device_id fpga_irq_of_match[] __initconst = { { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, { /* Sentinel */ } @@ -439,10 +446,8 @@ static const struct of_device_id fpga_irq_of_match[] __initconst = { static void __init ap_init_irq_of(void) { - /* disable core module IRQs */ - writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); + cm_init(); of_irq_init(fpga_irq_of_match); - integrator_clk_init(false); } /* For the Device Tree, add in the UART callbacks as AUXDATA */ @@ -450,9 +455,9 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE, "rtc", NULL), OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE, - "uart0", &integrator_uart_data), + "uart0", &ap_uart_data), OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE, - "uart1", &integrator_uart_data), + "uart1", &ap_uart_data), OF_DEV_AUXDATA("arm,primecell", KMI0_BASE, "kmi0", NULL), OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, @@ -462,15 +467,67 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = { { /* sentinel */ }, }; +static const struct of_device_id ap_syscon_match[] = { + { .compatible = "arm,integrator-ap-syscon"}, + { }, +}; + +static const struct of_device_id ebi_match[] = { + { .compatible = "arm,external-bus-interface"}, + { }, +}; + static void __init ap_init_of(void) { unsigned long sc_dec; + struct device_node *syscon; + struct device_node *ebi; + struct device *parent; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + u32 ap_sc_id; int i; + syscon = of_find_matching_node(NULL, ap_syscon_match); + if (!syscon) + return; + ebi = of_find_matching_node(NULL, ebi_match); + if (!ebi) + return; + + ap_syscon_base = of_iomap(syscon, 0); + if (!ap_syscon_base) + return; + ebi_base = of_iomap(ebi, 0); + if (!ebi_base) + return; + of_platform_populate(NULL, of_default_bus_match_table, ap_auxdata_lookup, NULL); - sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET); + ap_sc_id = readl(ap_syscon_base); + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return; + + soc_dev_attr->soc_id = "XVC"; + soc_dev_attr->machine = "Integrator/AP"; + soc_dev_attr->family = "Integrator"; + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c", + 'A' + (ap_sc_id & 0x0f)); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr); + return; + } + + parent = soc_device_to_device(soc_dev); + integrator_init_sysfs(parent, ap_sc_id); + + sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET); for (i = 0; i < 4; i++) { struct lm_device *lmdev; @@ -484,7 +541,7 @@ static void __init ap_init_of(void) lmdev->resource.start = 0xc0000000 + 0x10000000 * i; lmdev->resource.end = lmdev->resource.start + 0x0fffffff; lmdev->resource.flags = IORESOURCE_MEM; - lmdev->irq = IRQ_AP_EXPINT0 + i; + lmdev->irq = irq_of_parse_and_map(syscon, i); lmdev->id = i; lm_device_register(lmdev); @@ -499,123 +556,11 @@ static const char * ap_dt_board_compat[] = { DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)") .reserve = integrator_reserve, .map_io = ap_map_io, - .nr_irqs = NR_IRQS_INTEGRATOR_AP, .init_early = ap_init_early, .init_irq = ap_init_irq_of, .handle_irq = fpga_handle_irq, - .timer = &ap_of_timer, + .init_time = ap_of_timer_init, .init_machine = ap_init_of, .restart = integrator_restart, .dt_compat = ap_dt_board_compat, MACHINE_END - -#endif - -#ifdef CONFIG_ATAGS - -/* - * This is where non-devicetree initialization code is collected and stashed - * for eventual deletion. - */ - -static struct resource cfi_flash_resource = { - .start = INTEGRATOR_FLASH_BASE, - .end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device cfi_flash_device = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &ap_flash_data, - }, - .num_resources = 1, - .resource = &cfi_flash_resource, -}; - -static void __init ap_init_timer(void) -{ - struct clk *clk; - unsigned long rate; - - clk = clk_get_sys("ap_timer", NULL); - BUG_ON(IS_ERR(clk)); - clk_prepare_enable(clk); - rate = clk_get_rate(clk); - - writel(0, TIMER0_VA_BASE + TIMER_CTRL); - writel(0, TIMER1_VA_BASE + TIMER_CTRL); - writel(0, TIMER2_VA_BASE + TIMER_CTRL); - - integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE); - integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE, - IRQ_TIMERINT1); -} - -static struct sys_timer ap_timer = { - .init = ap_init_timer, -}; - -#define INTEGRATOR_SC_VALID_INT 0x003fffff - -static void __init ap_init_irq(void) -{ - /* Disable all interrupts initially. */ - /* Do the core module ones */ - writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); - - /* do the header card stuff next */ - writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); - writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); - - fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START, - -1, INTEGRATOR_SC_VALID_INT, NULL); - integrator_clk_init(false); -} - -static void __init ap_init(void) -{ - unsigned long sc_dec; - int i; - - platform_device_register(&cfi_flash_device); - - sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET); - for (i = 0; i < 4; i++) { - struct lm_device *lmdev; - - if ((sc_dec & (16 << i)) == 0) - continue; - - lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL); - if (!lmdev) - continue; - - lmdev->resource.start = 0xc0000000 + 0x10000000 * i; - lmdev->resource.end = lmdev->resource.start + 0x0fffffff; - lmdev->resource.flags = IORESOURCE_MEM; - lmdev->irq = IRQ_AP_EXPINT0 + i; - lmdev->id = i; - - lm_device_register(lmdev); - } - - integrator_init(false); -} - -MACHINE_START(INTEGRATOR, "ARM-Integrator") - /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .atag_offset = 0x100, - .reserve = integrator_reserve, - .map_io = ap_map_io, - .nr_irqs = NR_IRQS_INTEGRATOR_AP, - .init_early = ap_init_early, - .init_irq = ap_init_irq, - .handle_irq = fpga_handle_irq, - .timer = &ap_timer, - .init_machine = ap_init, - .restart = integrator_restart, -MACHINE_END - -#endif diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 5b08e8e4cc8..0e57f8f820a 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -20,42 +20,35 @@ #include <linux/amba/clcd.h> #include <linux/amba/mmci.h> #include <linux/io.h> +#include <linux/irqchip/versatile-fpga.h> #include <linux/gfp.h> #include <linux/mtd/physmap.h> -#include <linux/platform_data/clk-integrator.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/of_platform.h> +#include <linux/sys_soc.h> +#include <linux/sched_clock.h> -#include <mach/hardware.h> -#include <mach/platform.h> #include <asm/setup.h> #include <asm/mach-types.h> -#include <asm/hardware/arm_timer.h> -#include <asm/hardware/icst.h> - -#include <mach/cm.h> -#include <mach/lm.h> -#include <mach/irqs.h> - #include <asm/mach/arch.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/timer-sp.h> - #include <plat/clcd.h> -#include <plat/fpga-irq.h> -#include <plat/sched_clock.h> +#include "hardware.h" +#include "cm.h" #include "common.h" +/* Base address to the CP controller */ +static void __iomem *intcp_con_base; + #define INTCP_PA_FLASH_BASE 0x24000000 #define INTCP_PA_CLCD_BASE 0xc0000000 -#define INTCP_VA_CTRL_BASE __io_address(INTEGRATOR_CP_CTL_BASE) #define INTCP_FLASHPROG 0x04 #define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) #define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1) @@ -63,8 +56,6 @@ /* * Logical Physical * f1000000 10000000 Core module registers - * f1100000 11000000 System controller registers - * f1200000 12000000 EBI registers * f1300000 13000000 Counter/Timer * f1400000 14000000 Interrupt controller * f1600000 16000000 UART 0 @@ -72,26 +63,15 @@ * f1a00000 1a000000 Debug LEDs * fc900000 c9000000 GPIO * fca00000 ca000000 SIC - * fcb00000 cb000000 CP system control */ -static struct map_desc intcp_io_desc[] __initdata = { +static struct map_desc intcp_io_desc[] __initdata __maybe_unused = { { .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE), .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE), .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE), .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE), .length = SZ_4K, @@ -107,11 +87,6 @@ static struct map_desc intcp_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE), - .length = SZ_4K, - .type = MT_DEVICE - }, { .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE), .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE), .length = SZ_4K, @@ -126,11 +101,6 @@ static struct map_desc intcp_io_desc[] __initdata = { .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE), .length = SZ_4K, .type = MT_DEVICE - }, { - .virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE), - .length = SZ_4K, - .type = MT_DEVICE } }; @@ -146,9 +116,9 @@ static int intcp_flash_init(struct platform_device *dev) { u32 val; - val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + val = readl(intcp_con_base + INTCP_FLASHPROG); val |= CINTEGRATOR_FLASHPROG_FLWREN; - writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + writel(val, intcp_con_base + INTCP_FLASHPROG); return 0; } @@ -157,21 +127,21 @@ static void intcp_flash_exit(struct platform_device *dev) { u32 val; - val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + val = readl(intcp_con_base + INTCP_FLASHPROG); val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN); - writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + writel(val, intcp_con_base + INTCP_FLASHPROG); } static void intcp_flash_set_vpp(struct platform_device *pdev, int on) { u32 val; - val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + val = readl(intcp_con_base + INTCP_FLASHPROG); if (on) val |= CINTEGRATOR_FLASHPROG_FLVPPEN; else val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN; - writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); + writel(val, intcp_con_base + INTCP_FLASHPROG); } static struct physmap_flash_data intcp_flash_data = { @@ -190,7 +160,7 @@ static struct physmap_flash_data intcp_flash_data = { static unsigned int mmc_status(struct device *dev) { unsigned int status = readl(__io_address(0xca000000 + 4)); - writel(8, __io_address(INTEGRATOR_CP_CTL_BASE + 8)); + writel(8, intcp_con_base + 8); return status & 8; } @@ -211,7 +181,8 @@ static struct mmci_platform_data mmc_data = { static void cp_clcd_enable(struct clcd_fb *fb) { struct fb_var_screeninfo *var = &fb->fb.var; - u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; + u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2 + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1; if (var->bits_per_pixel <= 8 || (var->bits_per_pixel == 16 && var->green.length == 5)) @@ -254,51 +225,16 @@ static struct clcd_board clcd_data = { #define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28) -static void __init intcp_init_early(void) +static u64 notrace intcp_read_sched_clock(void) { -#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK - versatile_sched_clock_init(REFCOUNTER, 24000000); -#endif + return readl(REFCOUNTER); } -#ifdef CONFIG_OF - -static void __init intcp_timer_init_of(void) +static void __init intcp_init_early(void) { - struct device_node *node; - const char *path; - void __iomem *base; - int err; - int irq; - - err = of_property_read_string(of_aliases, - "arm,timer-primary", &path); - if (WARN_ON(err)) - return; - node = of_find_node_by_path(path); - base = of_iomap(node, 0); - if (WARN_ON(!base)) - return; - writel(0, base + TIMER_CTRL); - sp804_clocksource_init(base, node->name); - - err = of_property_read_string(of_aliases, - "arm,timer-secondary", &path); - if (WARN_ON(err)) - return; - node = of_find_node_by_path(path); - base = of_iomap(node, 0); - if (WARN_ON(!base)) - return; - irq = irq_of_parse_and_map(node, 0); - writel(0, base + TIMER_CTRL); - sp804_clockevents_init(base, irq, node->name); + sched_clock_register(intcp_read_sched_clock, 32, 24000000); } -static struct sys_timer cp_of_timer = { - .init = intcp_timer_init_of, -}; - static const struct of_device_id fpga_irq_of_match[] __initconst = { { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, { /* Sentinel */ } @@ -306,8 +242,8 @@ static const struct of_device_id fpga_irq_of_match[] __initconst = { static void __init intcp_init_irq_of(void) { + cm_init(); of_irq_init(fpga_irq_of_match); - integrator_clk_init(true); } /* @@ -318,9 +254,9 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE, "rtc", NULL), OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE, - "uart0", &integrator_uart_data), + "uart0", NULL), OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE, - "uart1", &integrator_uart_data), + "uart1", NULL), OF_DEV_AUXDATA("arm,primecell", KMI0_BASE, "kmi0", NULL), OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, @@ -336,10 +272,51 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = { { /* sentinel */ }, }; +static const struct of_device_id intcp_syscon_match[] = { + { .compatible = "arm,integrator-cp-syscon"}, + { }, +}; + static void __init intcp_init_of(void) { + struct device_node *cpcon; + struct device *parent; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + u32 intcp_sc_id; + + cpcon = of_find_matching_node(NULL, intcp_syscon_match); + if (!cpcon) + return; + + intcp_con_base = of_iomap(cpcon, 0); + if (!intcp_con_base) + return; + of_platform_populate(NULL, of_default_bus_match_table, - intcp_auxdata_lookup, NULL); + intcp_auxdata_lookup, NULL); + + intcp_sc_id = readl(intcp_con_base); + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return; + + soc_dev_attr->soc_id = "XCV"; + soc_dev_attr->machine = "Integrator/CP"; + soc_dev_attr->family = "Integrator"; + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c", + 'A' + (intcp_sc_id & 0x0f)); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr); + return; + } + + parent = soc_device_to_device(soc_dev); + integrator_init_sysfs(parent, intcp_sc_id); } static const char * intcp_dt_board_compat[] = { @@ -350,167 +327,10 @@ static const char * intcp_dt_board_compat[] = { DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)") .reserve = integrator_reserve, .map_io = intcp_map_io, - .nr_irqs = NR_IRQS_INTEGRATOR_CP, .init_early = intcp_init_early, .init_irq = intcp_init_irq_of, .handle_irq = fpga_handle_irq, - .timer = &cp_of_timer, .init_machine = intcp_init_of, .restart = integrator_restart, .dt_compat = intcp_dt_board_compat, MACHINE_END - -#endif - -#ifdef CONFIG_ATAGS - -/* - * This is where non-devicetree initialization code is collected and stashed - * for eventual deletion. - */ - -#define INTCP_FLASH_SIZE SZ_32M - -static struct resource intcp_flash_resource = { - .start = INTCP_PA_FLASH_BASE, - .end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device intcp_flash_device = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &intcp_flash_data, - }, - .num_resources = 1, - .resource = &intcp_flash_resource, -}; - -#define INTCP_ETH_SIZE 0x10 - -static struct resource smc91x_resources[] = { - [0] = { - .start = INTEGRATOR_CP_ETH_BASE, - .end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_CP_ETHINT, - .end = IRQ_CP_ETHINT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device smc91x_device = { - .name = "smc91x", - .id = 0, - .num_resources = ARRAY_SIZE(smc91x_resources), - .resource = smc91x_resources, -}; - -static struct platform_device *intcp_devs[] __initdata = { - &intcp_flash_device, - &smc91x_device, -}; - -#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40) -#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE) -#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE) - -static void __init intcp_init_irq(void) -{ - u32 pic_mask, cic_mask, sic_mask; - - /* These masks are for the HW IRQ registers */ - pic_mask = ~((~0u) << (11 - IRQ_PIC_START)); - pic_mask |= (~((~0u) << (29 - 22))) << 22; - cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)); - sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START)); - - /* - * Disable all interrupt sources - */ - writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); - writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); - writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); - writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); - writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); - writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); - - fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START, - -1, pic_mask, NULL); - - fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START, - -1, cic_mask, NULL); - - fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START, - IRQ_CP_CPPLDINT, sic_mask, NULL); - - integrator_clk_init(true); -} - -#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) -#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE) -#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE) - -static void __init intcp_timer_init(void) -{ - writel(0, TIMER0_VA_BASE + TIMER_CTRL); - writel(0, TIMER1_VA_BASE + TIMER_CTRL); - writel(0, TIMER2_VA_BASE + TIMER_CTRL); - - sp804_clocksource_init(TIMER2_VA_BASE, "timer2"); - sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1"); -} - -static struct sys_timer cp_timer = { - .init = intcp_timer_init, -}; - -#define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 } -#define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT } - -static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE, - INTEGRATOR_CP_MMC_IRQS, &mmc_data); - -static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE, - INTEGRATOR_CP_AACI_IRQS, NULL); - -static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE, - { IRQ_CP_CLCDCINT }, &clcd_data); - -static struct amba_device *amba_devs[] __initdata = { - &mmc_device, - &aaci_device, - &clcd_device, -}; - -static void __init intcp_init(void) -{ - int i; - - platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); - - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - } - integrator_init(true); -} - -MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") - /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .atag_offset = 0x100, - .reserve = integrator_reserve, - .map_io = intcp_map_io, - .nr_irqs = NR_IRQS_INTEGRATOR_CP, - .init_early = intcp_init_early, - .init_irq = intcp_init_irq, - .handle_irq = fpga_handle_irq, - .timer = &cp_timer, - .init_machine = intcp_init, - .restart = integrator_restart, -MACHINE_END - -#endif diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c index 7a7f6d3273b..f1dcb57a59e 100644 --- a/arch/arm/mach-integrator/leds.c +++ b/arch/arm/mach-integrator/leds.c @@ -11,9 +11,8 @@ #include <linux/slab.h> #include <linux/leds.h> -#include <mach/cm.h> -#include <mach/hardware.h> -#include <mach/platform.h> +#include "hardware.h" +#include "cm.h" #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) @@ -78,7 +77,7 @@ static void cm_led_set(struct led_classdev *cdev, static enum led_brightness cm_led_get(struct led_classdev *cdev) { - u32 reg = readl(CM_CTRL); + u32 reg = cm_get(); return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF; } diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c index f52c7af31ea..3f9e9f04316 100644 --- a/arch/arm/mach-integrator/lm.c +++ b/arch/arm/mach-integrator/lm.c @@ -12,7 +12,7 @@ #include <linux/device.h> #include <linux/slab.h> -#include <mach/lm.h> +#include "lm.h" #define to_lm_device(d) container_of(d, struct lm_device, dev) #define to_lm_driver(d) container_of(d, struct lm_driver, drv) diff --git a/arch/arm/mach-integrator/include/mach/lm.h b/arch/arm/mach-integrator/lm.h index 28186b6f2c0..28186b6f2c0 100644 --- a/arch/arm/mach-integrator/include/mach/lm.h +++ b/arch/arm/mach-integrator/lm.h diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c deleted file mode 100644 index 6c1667e728f..00000000000 --- a/arch/arm/mach-integrator/pci.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * linux/arch/arm/mach-integrator/pci-integrator.c - * - * Copyright (C) 1999 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * PCI functions for Integrator - */ -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/init.h> - -#include <asm/mach/pci.h> -#include <asm/mach-types.h> - -#include <mach/irqs.h> - -/* - * A small note about bridges and interrupts. The DECchip 21050 (and - * later) adheres to the PCI-PCI bridge specification. This says that - * the interrupts on the other side of a bridge are swizzled in the - * following manner: - * - * Dev Interrupt Interrupt - * Pin on Pin on - * Device Connector - * - * 4 A A - * B B - * C C - * D D - * - * 5 A B - * B C - * C D - * D A - * - * 6 A C - * B D - * C A - * D B - * - * 7 A D - * B A - * C B - * D C - * - * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A. - * Thus, each swizzle is ((pin-1) + (device#-4)) % 4 - */ - -/* - * This routine handles multiple bridges. - */ -static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp) -{ - if (*pinp == 0) - *pinp = 1; - - return pci_common_swizzle(dev, pinp); -} - -static int irq_tab[4] __initdata = { - IRQ_AP_PCIINT0, IRQ_AP_PCIINT1, IRQ_AP_PCIINT2, IRQ_AP_PCIINT3 -}; - -/* - * map the specified device/slot/pin to an IRQ. This works out such - * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1. - */ -static int __init integrator_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - int intnr = ((slot - 9) + (pin - 1)) & 3; - - return irq_tab[intnr]; -} - -extern void pci_v3_init(void *); - -static struct hw_pci integrator_pci __initdata = { - .swizzle = integrator_swizzle, - .map_irq = integrator_map_irq, - .setup = pci_v3_setup, - .nr_controllers = 1, - .ops = &pci_v3_ops, - .preinit = pci_v3_preinit, - .postinit = pci_v3_postinit, -}; - -static int __init integrator_pci_init(void) -{ - if (machine_is_integrator()) - pci_common_init(&integrator_pci); - return 0; -} - -subsys_initcall(integrator_pci_init); diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index bbeca59df66..05e1f73a1e8 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -27,16 +27,196 @@ #include <linux/spinlock.h> #include <linux/init.h> #include <linux/io.h> - -#include <mach/hardware.h> -#include <mach/platform.h> -#include <mach/irqs.h> - +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_pci.h> +#include <video/vga.h> + +#include <asm/mach/map.h> #include <asm/signal.h> #include <asm/mach/pci.h> #include <asm/irq_regs.h> -#include <asm/hardware/pci_v3.h> +#include "pci_v3.h" +#include "hardware.h" + +/* + * Where in the memory map does PCI live? + * + * This represents a fairly liberal usage of address space. Even though + * the V3 only has two windows (therefore we need to map stuff on the fly), + * we maintain the same addresses, even if they're not mapped. + */ +#define PHYS_PCI_MEM_BASE 0x40000000 /* 256M */ +#define PHYS_PCI_PRE_BASE 0x50000000 /* 256M */ +#define PHYS_PCI_IO_BASE 0x60000000 /* 16M */ +#define PHYS_PCI_CONFIG_BASE 0x61000000 /* 16M */ +#define PHYS_PCI_V3_BASE 0x62000000 /* 64K */ + +#define PCI_MEMORY_VADDR IOMEM(0xe8000000) +#define PCI_CONFIG_VADDR IOMEM(0xec000000) + +/* + * V3 Local Bus to PCI Bridge definitions + * + * Registers (these are taken from page 129 of the EPC User's Manual Rev 1.04 + * All V3 register names are prefaced by V3_ to avoid clashing with any other + * PCI definitions. Their names match the user's manual. + * + * I'm assuming that I20 is disabled. + * + */ +#define V3_PCI_VENDOR 0x00000000 +#define V3_PCI_DEVICE 0x00000002 +#define V3_PCI_CMD 0x00000004 +#define V3_PCI_STAT 0x00000006 +#define V3_PCI_CC_REV 0x00000008 +#define V3_PCI_HDR_CFG 0x0000000C +#define V3_PCI_IO_BASE 0x00000010 +#define V3_PCI_BASE0 0x00000014 +#define V3_PCI_BASE1 0x00000018 +#define V3_PCI_SUB_VENDOR 0x0000002C +#define V3_PCI_SUB_ID 0x0000002E +#define V3_PCI_ROM 0x00000030 +#define V3_PCI_BPARAM 0x0000003C +#define V3_PCI_MAP0 0x00000040 +#define V3_PCI_MAP1 0x00000044 +#define V3_PCI_INT_STAT 0x00000048 +#define V3_PCI_INT_CFG 0x0000004C +#define V3_LB_BASE0 0x00000054 +#define V3_LB_BASE1 0x00000058 +#define V3_LB_MAP0 0x0000005E +#define V3_LB_MAP1 0x00000062 +#define V3_LB_BASE2 0x00000064 +#define V3_LB_MAP2 0x00000066 +#define V3_LB_SIZE 0x00000068 +#define V3_LB_IO_BASE 0x0000006E +#define V3_FIFO_CFG 0x00000070 +#define V3_FIFO_PRIORITY 0x00000072 +#define V3_FIFO_STAT 0x00000074 +#define V3_LB_ISTAT 0x00000076 +#define V3_LB_IMASK 0x00000077 +#define V3_SYSTEM 0x00000078 +#define V3_LB_CFG 0x0000007A +#define V3_PCI_CFG 0x0000007C +#define V3_DMA_PCI_ADR0 0x00000080 +#define V3_DMA_PCI_ADR1 0x00000090 +#define V3_DMA_LOCAL_ADR0 0x00000084 +#define V3_DMA_LOCAL_ADR1 0x00000094 +#define V3_DMA_LENGTH0 0x00000088 +#define V3_DMA_LENGTH1 0x00000098 +#define V3_DMA_CSR0 0x0000008B +#define V3_DMA_CSR1 0x0000009B +#define V3_DMA_CTLB_ADR0 0x0000008C +#define V3_DMA_CTLB_ADR1 0x0000009C +#define V3_DMA_DELAY 0x000000E0 +#define V3_MAIL_DATA 0x000000C0 +#define V3_PCI_MAIL_IEWR 0x000000D0 +#define V3_PCI_MAIL_IERD 0x000000D2 +#define V3_LB_MAIL_IEWR 0x000000D4 +#define V3_LB_MAIL_IERD 0x000000D6 +#define V3_MAIL_WR_STAT 0x000000D8 +#define V3_MAIL_RD_STAT 0x000000DA +#define V3_QBA_MAP 0x000000DC + +/* PCI COMMAND REGISTER bits + */ +#define V3_COMMAND_M_FBB_EN (1 << 9) +#define V3_COMMAND_M_SERR_EN (1 << 8) +#define V3_COMMAND_M_PAR_EN (1 << 6) +#define V3_COMMAND_M_MASTER_EN (1 << 2) +#define V3_COMMAND_M_MEM_EN (1 << 1) +#define V3_COMMAND_M_IO_EN (1 << 0) + +/* SYSTEM REGISTER bits + */ +#define V3_SYSTEM_M_RST_OUT (1 << 15) +#define V3_SYSTEM_M_LOCK (1 << 14) + +/* PCI_CFG bits + */ +#define V3_PCI_CFG_M_I2O_EN (1 << 15) +#define V3_PCI_CFG_M_IO_REG_DIS (1 << 14) +#define V3_PCI_CFG_M_IO_DIS (1 << 13) +#define V3_PCI_CFG_M_EN3V (1 << 12) +#define V3_PCI_CFG_M_RETRY_EN (1 << 10) +#define V3_PCI_CFG_M_AD_LOW1 (1 << 9) +#define V3_PCI_CFG_M_AD_LOW0 (1 << 8) + +/* PCI_BASE register bits (PCI -> Local Bus) + */ +#define V3_PCI_BASE_M_ADR_BASE 0xFFF00000 +#define V3_PCI_BASE_M_ADR_BASEL 0x000FFF00 +#define V3_PCI_BASE_M_PREFETCH (1 << 3) +#define V3_PCI_BASE_M_TYPE (3 << 1) +#define V3_PCI_BASE_M_IO (1 << 0) + +/* PCI MAP register bits (PCI -> Local bus) + */ +#define V3_PCI_MAP_M_MAP_ADR 0xFFF00000 +#define V3_PCI_MAP_M_RD_POST_INH (1 << 15) +#define V3_PCI_MAP_M_ROM_SIZE (3 << 10) +#define V3_PCI_MAP_M_SWAP (3 << 8) +#define V3_PCI_MAP_M_ADR_SIZE 0x000000F0 +#define V3_PCI_MAP_M_REG_EN (1 << 1) +#define V3_PCI_MAP_M_ENABLE (1 << 0) + +/* + * LB_BASE0,1 register bits (Local bus -> PCI) + */ +#define V3_LB_BASE_ADR_BASE 0xfff00000 +#define V3_LB_BASE_SWAP (3 << 8) +#define V3_LB_BASE_ADR_SIZE (15 << 4) +#define V3_LB_BASE_PREFETCH (1 << 3) +#define V3_LB_BASE_ENABLE (1 << 0) + +#define V3_LB_BASE_ADR_SIZE_1MB (0 << 4) +#define V3_LB_BASE_ADR_SIZE_2MB (1 << 4) +#define V3_LB_BASE_ADR_SIZE_4MB (2 << 4) +#define V3_LB_BASE_ADR_SIZE_8MB (3 << 4) +#define V3_LB_BASE_ADR_SIZE_16MB (4 << 4) +#define V3_LB_BASE_ADR_SIZE_32MB (5 << 4) +#define V3_LB_BASE_ADR_SIZE_64MB (6 << 4) +#define V3_LB_BASE_ADR_SIZE_128MB (7 << 4) +#define V3_LB_BASE_ADR_SIZE_256MB (8 << 4) +#define V3_LB_BASE_ADR_SIZE_512MB (9 << 4) +#define V3_LB_BASE_ADR_SIZE_1GB (10 << 4) +#define V3_LB_BASE_ADR_SIZE_2GB (11 << 4) + +#define v3_addr_to_lb_base(a) ((a) & V3_LB_BASE_ADR_BASE) + +/* + * LB_MAP0,1 register bits (Local bus -> PCI) + */ +#define V3_LB_MAP_MAP_ADR 0xfff0 +#define V3_LB_MAP_TYPE (7 << 1) +#define V3_LB_MAP_AD_LOW_EN (1 << 0) + +#define V3_LB_MAP_TYPE_IACK (0 << 1) +#define V3_LB_MAP_TYPE_IO (1 << 1) +#define V3_LB_MAP_TYPE_MEM (3 << 1) +#define V3_LB_MAP_TYPE_CONFIG (5 << 1) +#define V3_LB_MAP_TYPE_MEM_MULTIPLE (6 << 1) + +#define v3_addr_to_lb_map(a) (((a) >> 16) & V3_LB_MAP_MAP_ADR) + +/* + * LB_BASE2 register bits (Local bus -> PCI IO) + */ +#define V3_LB_BASE2_ADR_BASE 0xff00 +#define V3_LB_BASE2_SWAP (3 << 6) +#define V3_LB_BASE2_ENABLE (1 << 0) + +#define v3_addr_to_lb_base2(a) (((a) >> 16) & V3_LB_BASE2_ADR_BASE) + +/* + * LB_MAP2 register bits (Local bus -> PCI IO) + */ +#define V3_LB_MAP2_MAP_ADR 0xff00 + +#define v3_addr_to_lb_map2(a) (((a) >> 16) & V3_LB_MAP2_MAP_ADR) /* * The V3 PCI interface chip in Integrator provides several windows from @@ -101,15 +281,28 @@ * the mappings into PCI memory. */ +/* Filled in by probe */ +static void __iomem *pci_v3_base; +/* CPU side memory ranges */ +static struct resource conf_mem; /* FIXME: remap this instead of static map */ +static struct resource io_mem; +static struct resource non_mem; +static struct resource pre_mem; +/* PCI side memory ranges */ +static u64 non_mem_pci; +static u64 non_mem_pci_sz; +static u64 pre_mem_pci; +static u64 pre_mem_pci_sz; + // V3 access routines -#define v3_writeb(o,v) __raw_writeb(v, PCI_V3_VADDR + (unsigned int)(o)) -#define v3_readb(o) (__raw_readb(PCI_V3_VADDR + (unsigned int)(o))) +#define v3_writeb(o,v) __raw_writeb(v, pci_v3_base + (unsigned int)(o)) +#define v3_readb(o) (__raw_readb(pci_v3_base + (unsigned int)(o))) -#define v3_writew(o,v) __raw_writew(v, PCI_V3_VADDR + (unsigned int)(o)) -#define v3_readw(o) (__raw_readw(PCI_V3_VADDR + (unsigned int)(o))) +#define v3_writew(o,v) __raw_writew(v, pci_v3_base + (unsigned int)(o)) +#define v3_readw(o) (__raw_readw(pci_v3_base + (unsigned int)(o))) -#define v3_writel(o,v) __raw_writel(v, PCI_V3_VADDR + (unsigned int)(o)) -#define v3_readl(o) (__raw_readl(PCI_V3_VADDR + (unsigned int)(o))) +#define v3_writel(o,v) __raw_writel(v, pci_v3_base + (unsigned int)(o)) +#define v3_readl(o) (__raw_readl(pci_v3_base + (unsigned int)(o))) /*============================================================================ * @@ -165,19 +358,6 @@ */ static DEFINE_RAW_SPINLOCK(v3_lock); -#define PCI_BUS_NONMEM_START 0x00000000 -#define PCI_BUS_NONMEM_SIZE SZ_256M - -#define PCI_BUS_PREMEM_START PCI_BUS_NONMEM_START + PCI_BUS_NONMEM_SIZE -#define PCI_BUS_PREMEM_SIZE SZ_256M - -#if PCI_BUS_NONMEM_START & 0x000fffff -#error PCI_BUS_NONMEM_START must be megabyte aligned -#endif -#if PCI_BUS_PREMEM_START & 0x000fffff -#error PCI_BUS_PREMEM_START must be megabyte aligned -#endif - #undef V3_LB_BASE_PREFETCH #define V3_LB_BASE_PREFETCH 0 @@ -191,12 +371,9 @@ static void __iomem *v3_open_config_window(struct pci_bus *bus, /* * Trap out illegal values */ - if (offset > 255) - BUG(); - if (busnr > 255) - BUG(); - if (devfn > 255) - BUG(); + BUG_ON(offset > 255); + BUG_ON(busnr > 255); + BUG_ON(devfn > 255); if (busnr == 0) { int slot = PCI_SLOT(devfn); @@ -246,13 +423,13 @@ static void __iomem *v3_open_config_window(struct pci_bus *bus, * prefetchable), this frees up base1 for re-use by * configuration memory */ - v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | + v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | V3_LB_BASE_ADR_SIZE_512MB | V3_LB_BASE_ENABLE); /* * Set up base1/map1 to point into configuration space. */ - v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_CONFIG_BASE) | + v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(conf_mem.start) | V3_LB_BASE_ADR_SIZE_16MB | V3_LB_BASE_ENABLE); v3_writew(V3_LB_MAP1, mapaddress); @@ -264,16 +441,16 @@ static void v3_close_config_window(void) /* * Reassign base1 for use by prefetchable PCI memory */ - v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) | + v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | V3_LB_BASE_ENABLE); - v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) | + v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(pre_mem_pci) | V3_LB_MAP_TYPE_MEM_MULTIPLE); /* * And shrink base0 back to a 256M window (NOTE: MAP0 already correct) */ - v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | + v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); } @@ -340,25 +517,11 @@ static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, return PCIBIOS_SUCCESSFUL; } -struct pci_ops pci_v3_ops = { +static struct pci_ops pci_v3_ops = { .read = v3_read_config, .write = v3_write_config, }; -static struct resource non_mem = { - .name = "PCI non-prefetchable", - .start = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START, - .end = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START + PCI_BUS_NONMEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct resource pre_mem = { - .name = "PCI prefetchable", - .start = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START, - .end = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START + PCI_BUS_PREMEM_SIZE - 1, - .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, -}; - static int __init pci_v3_setup_resources(struct pci_sys_data *sys) { if (request_resource(&iomem_resource, &non_mem)) { @@ -388,9 +551,10 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys) * means I can't get additional information on the reason for the pm2fb * problems. I suppose I'll just have to mind-meld with the machine. ;) */ -#define SC_PCI __io_address(INTEGRATOR_SC_PCIENABLE) -#define SC_LBFADDR __io_address(INTEGRATOR_SC_BASE + 0x20) -#define SC_LBFCODE __io_address(INTEGRATOR_SC_BASE + 0x24) +static void __iomem *ap_syscon_base; +#define INTEGRATOR_SC_PCIENABLE_OFFSET 0x18 +#define INTEGRATOR_SC_LBFADDR_OFFSET 0x20 +#define INTEGRATOR_SC_LBFCODE_OFFSET 0x24 static int v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -401,13 +565,13 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) char buf[128]; sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n", - addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255, + addr, fsr, pc, instr, __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255, v3_readb(V3_LB_ISTAT)); printk(KERN_DEBUG "%s", buf); #endif v3_writeb(V3_LB_ISTAT, 0); - __raw_writel(3, SC_PCI); + __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); /* * If the instruction being executed was a read, @@ -438,7 +602,7 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) return 1; } -static irqreturn_t v3_irq(int dummy, void *devid) +static irqreturn_t v3_irq(int irq, void *devid) { #ifdef CONFIG_DEBUG_LL struct pt_regs *regs = get_irq_regs(); @@ -448,16 +612,16 @@ static irqreturn_t v3_irq(int dummy, void *devid) extern void printascii(const char *); sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x " - "ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr, - __raw_readl(SC_LBFADDR), - __raw_readl(SC_LBFCODE) & 255, + "ISTAT=%02x\n", irq, pc, instr, + __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), + __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255, v3_readb(V3_LB_ISTAT)); printascii(buf); #endif v3_writew(V3_PCI_STAT, 0xf000); v3_writeb(V3_LB_ISTAT, 0); - __raw_writel(3, SC_PCI); + __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); #ifdef CONFIG_DEBUG_LL /* @@ -473,12 +637,15 @@ static irqreturn_t v3_irq(int dummy, void *devid) return IRQ_HANDLED; } -int __init pci_v3_setup(int nr, struct pci_sys_data *sys) +static int __init pci_v3_setup(int nr, struct pci_sys_data *sys) { int ret = 0; + if (!ap_syscon_base) + return -EINVAL; + if (nr == 0) { - sys->mem_offset = PHYS_PCI_MEM_BASE; + sys->mem_offset = non_mem.start; ret = pci_v3_setup_resources(sys); } @@ -489,11 +656,10 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys) * V3_LB_BASE? - local bus address * V3_LB_MAP? - pci bus address */ -void __init pci_v3_preinit(void) +static void __init pci_v3_preinit(void) { unsigned long flags; unsigned int temp; - int ret; pcibios_min_mem = 0x00100000; @@ -517,25 +683,25 @@ void __init pci_v3_preinit(void) * Setup window 0 - PCI non-prefetchable memory * Local: 0x40000000 Bus: 0x00000000 Size: 256MB */ - v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | + v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); - v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(PCI_BUS_NONMEM_START) | + v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(non_mem_pci) | V3_LB_MAP_TYPE_MEM); /* * Setup window 1 - PCI prefetchable memory * Local: 0x50000000 Bus: 0x10000000 Size: 256MB */ - v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) | + v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) | V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | V3_LB_BASE_ENABLE); - v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) | + v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(pre_mem_pci) | V3_LB_MAP_TYPE_MEM_MULTIPLE); /* * Setup window 2 - PCI IO */ - v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(PHYS_PCI_IO_BASE) | + v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) | V3_LB_BASE_ENABLE); v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0)); @@ -568,20 +734,12 @@ void __init pci_v3_preinit(void) v3_writeb(V3_LB_ISTAT, 0); v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10)); v3_writeb(V3_LB_IMASK, 0x28); - __raw_writel(3, SC_PCI); - - /* - * Grab the PCI error interrupt. - */ - ret = request_irq(IRQ_AP_V3INT, v3_irq, 0, "V3", NULL); - if (ret) - printk(KERN_ERR "PCI: unable to grab PCI error " - "interrupt: %d\n", ret); + __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); raw_spin_unlock_irqrestore(&v3_lock, flags); } -void __init pci_v3_postinit(void) +static void __init pci_v3_postinit(void) { unsigned int pci_cmd; @@ -600,5 +758,194 @@ void __init pci_v3_postinit(void) "interrupt: %d\n", ret); #endif - register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0); + register_isa_ports(non_mem.start, io_mem.start, 0); +} + +/* + * A small note about bridges and interrupts. The DECchip 21050 (and + * later) adheres to the PCI-PCI bridge specification. This says that + * the interrupts on the other side of a bridge are swizzled in the + * following manner: + * + * Dev Interrupt Interrupt + * Pin on Pin on + * Device Connector + * + * 4 A A + * B B + * C C + * D D + * + * 5 A B + * B C + * C D + * D A + * + * 6 A C + * B D + * C A + * D B + * + * 7 A D + * B A + * C B + * D C + * + * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A. + * Thus, each swizzle is ((pin-1) + (device#-4)) % 4 + */ + +/* + * This routine handles multiple bridges. + */ +static u8 __init pci_v3_swizzle(struct pci_dev *dev, u8 *pinp) +{ + if (*pinp == 0) + *pinp = 1; + + return pci_common_swizzle(dev, pinp); +} + +static struct hw_pci pci_v3 __initdata = { + .swizzle = pci_v3_swizzle, + .setup = pci_v3_setup, + .nr_controllers = 1, + .ops = &pci_v3_ops, + .preinit = pci_v3_preinit, + .postinit = pci_v3_postinit, +}; + +static int __init pci_v3_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct of_pci_range_parser parser; + struct of_pci_range range; + struct resource *res; + int irq, ret; + + /* Remap the Integrator system controller */ + ap_syscon_base = devm_ioremap(&pdev->dev, INTEGRATOR_SC_BASE, 0x100); + if (!ap_syscon_base) { + dev_err(&pdev->dev, "unable to remap the AP syscon for PCIv3\n"); + return -ENODEV; + } + + /* Device tree probe path */ + if (!np) { + dev_err(&pdev->dev, "no device tree node for PCIv3\n"); + return -ENODEV; + } + + if (of_pci_range_parser_init(&parser, np)) + return -EINVAL; + + /* Get base for bridge registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "unable to obtain PCIv3 base\n"); + return -ENODEV; + } + pci_v3_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!pci_v3_base) { + dev_err(&pdev->dev, "unable to remap PCIv3 base\n"); + return -ENODEV; + } + + /* Get and request error IRQ resource */ + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "unable to obtain PCIv3 error IRQ\n"); + return -ENODEV; + } + ret = devm_request_irq(&pdev->dev, irq, v3_irq, 0, + "PCIv3 error", NULL); + if (ret < 0) { + dev_err(&pdev->dev, "unable to request PCIv3 error IRQ %d (%d)\n", irq, ret); + return ret; + } + + for_each_of_pci_range(&parser, &range) { + if (!range.flags) { + of_pci_range_to_resource(&range, np, &conf_mem); + conf_mem.name = "PCIv3 config"; + } + if (range.flags & IORESOURCE_IO) { + of_pci_range_to_resource(&range, np, &io_mem); + io_mem.name = "PCIv3 I/O"; + } + if ((range.flags & IORESOURCE_MEM) && + !(range.flags & IORESOURCE_PREFETCH)) { + non_mem_pci = range.pci_addr; + non_mem_pci_sz = range.size; + of_pci_range_to_resource(&range, np, &non_mem); + non_mem.name = "PCIv3 non-prefetched mem"; + } + if ((range.flags & IORESOURCE_MEM) && + (range.flags & IORESOURCE_PREFETCH)) { + pre_mem_pci = range.pci_addr; + pre_mem_pci_sz = range.size; + of_pci_range_to_resource(&range, np, &pre_mem); + pre_mem.name = "PCIv3 prefetched mem"; + } + } + + if (!conf_mem.start || !io_mem.start || + !non_mem.start || !pre_mem.start) { + dev_err(&pdev->dev, "missing ranges in device node\n"); + return -EINVAL; + } + + pci_v3.map_irq = of_irq_parse_and_map_pci; + pci_common_init_dev(&pdev->dev, &pci_v3); + + return 0; +} + +static const struct of_device_id pci_ids[] = { + { .compatible = "v3,v360epc-pci", }, + {}, +}; + +static struct platform_driver pci_v3_driver = { + .driver = { + .name = "pci-v3", + .of_match_table = pci_ids, + }, +}; + +static int __init pci_v3_init(void) +{ + return platform_driver_probe(&pci_v3_driver, pci_v3_probe); +} + +subsys_initcall(pci_v3_init); + +/* + * Static mappings for the PCIv3 bridge + * + * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M) + * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M) + * fee00000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M) + */ +static struct map_desc pci_v3_io_desc[] __initdata __maybe_unused = { + { + .virtual = (unsigned long)PCI_MEMORY_VADDR, + .pfn = __phys_to_pfn(PHYS_PCI_MEM_BASE), + .length = SZ_16M, + .type = MT_DEVICE + }, { + .virtual = (unsigned long)PCI_CONFIG_VADDR, + .pfn = __phys_to_pfn(PHYS_PCI_CONFIG_BASE), + .length = SZ_16M, + .type = MT_DEVICE + } +}; + +int __init pci_v3_early_init(void) +{ + iotable_init(pci_v3_io_desc, ARRAY_SIZE(pci_v3_io_desc)); + vga_base = (unsigned long)PCI_MEMORY_VADDR; + pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE)); + return 0; } diff --git a/arch/arm/mach-integrator/pci_v3.h b/arch/arm/mach-integrator/pci_v3.h new file mode 100644 index 00000000000..06a9e2e7d00 --- /dev/null +++ b/arch/arm/mach-integrator/pci_v3.h @@ -0,0 +1,9 @@ +/* Simple oneliner include to the PCIv3 early init */ +#ifdef CONFIG_PCI +extern int pci_v3_early_init(void); +#else +static inline int pci_v3_early_init(void) +{ + return 0; +} +#endif |
