diff options
Diffstat (limited to 'arch/arm/mach-integrator/core.c')
| -rw-r--r-- | arch/arm/mach-integrator/core.c | 319 |
1 files changed, 144 insertions, 175 deletions
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index b8e884b450d..e3f3aca43ef 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -11,223 +11,192 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/irq.h> #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 <linux/clkdev.h> - -#include <mach/hardware.h> -#include <mach/platform.h> -#include <asm/irq.h> -#include <mach/cm.h> -#include <asm/system.h> -#include <asm/leds.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> -static struct amba_pl010_data integrator_uart_data; - -static struct amba_device rtc_device = { - .dev = { - .init_name = "mb:15", - }, - .res = { - .start = INTEGRATOR_RTC_BASE, - .end = INTEGRATOR_RTC_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { IRQ_RTCINT, NO_IRQ }, - .periphid = 0x00041030, -}; +#include "hardware.h" +#include "cm.h" +#include "common.h" -static struct amba_device uart0_device = { - .dev = { - .init_name = "mb:16", - .platform_data = &integrator_uart_data, - }, - .res = { - .start = INTEGRATOR_UART0_BASE, - .end = INTEGRATOR_UART0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { IRQ_UARTINT0, NO_IRQ }, - .periphid = 0x0041010, -}; +static DEFINE_RAW_SPINLOCK(cm_lock); +static void __iomem *cm_base; -static struct amba_device uart1_device = { - .dev = { - .init_name = "mb:17", - .platform_data = &integrator_uart_data, - }, - .res = { - .start = INTEGRATOR_UART1_BASE, - .end = INTEGRATOR_UART1_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { IRQ_UARTINT1, NO_IRQ }, - .periphid = 0x0041010, -}; +/** + * cm_get - get the value from the CM_CTRL register + */ +u32 cm_get(void) +{ + return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET); +} -static struct amba_device kmi0_device = { - .dev = { - .init_name = "mb:18", - }, - .res = { - .start = KMI0_BASE, - .end = KMI0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { IRQ_KMIINT0, NO_IRQ }, - .periphid = 0x00041050, -}; +/** + * cm_control - update the CM_CTRL register. + * @mask: bits to change + * @set: bits to set + */ +void cm_control(u32 mask, u32 set) +{ + unsigned long flags; + u32 val; -static struct amba_device kmi1_device = { - .dev = { - .init_name = "mb:19", - }, - .res = { - .start = KMI1_BASE, - .end = KMI1_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { IRQ_KMIINT1, NO_IRQ }, - .periphid = 0x00041050, -}; + raw_spin_lock_irqsave(&cm_lock, flags); + 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); +} -static struct amba_device *amba_devs[] __initdata = { - &rtc_device, - &uart0_device, - &uart1_device, - &kmi0_device, - &kmi1_device, -}; +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"; + } +} -/* - * These are fixed clocks. - */ -static struct clk clk24mhz = { - .rate = 24000000, -}; +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"; + } +} -static struct clk uartclk = { - .rate = 14745600, -}; +void cm_clear_irqs(void) +{ + /* disable core module IRQs */ + writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET + + IRQ_ENABLE_CLEAR); +} -static struct clk dummy_apb_pclk; - -static struct clk_lookup lookups[] = { - { /* Bus clock */ - .con_id = "apb_pclk", - .clk = &dummy_apb_pclk, - }, { /* UART0 */ - .dev_id = "mb:16", - .clk = &uartclk, - }, { /* UART1 */ - .dev_id = "mb:17", - .clk = &uartclk, - }, { /* KMI0 */ - .dev_id = "mb:18", - .clk = &clk24mhz, - }, { /* KMI1 */ - .dev_id = "mb:19", - .clk = &clk24mhz, - }, { /* MMCI - IntegratorCP */ - .dev_id = "mb:1c", - .clk = &uartclk, - } +static const struct of_device_id cm_match[] = { + { .compatible = "arm,core-module-integrator"}, + { }, }; -static int __init integrator_init(void) +void cm_init(void) { - int i; - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + struct device_node *cm = of_find_matching_node(NULL, cm_match); + u32 val; - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); + if (!cm) { + pr_crit("no core module node found in device tree\n"); + return; } - - return 0; + 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))); } -arch_initcall(integrator_init); - /* - * 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 + * We need to stop things allocating the low memory; ideally we need a + * better implementation of GFP_DMA which does not assume that DMA-able + * memory starts at zero. */ -#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) +void __init integrator_reserve(void) { - unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; - - if (dev == &uart0_device) { - rts_mask = 1 << 4; - dtr_mask = 1 << 5; - } else { - rts_mask = 1 << 6; - dtr_mask = 1 << 7; - } + memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); +} - if (mctrl & TIOCM_RTS) - ctrlc |= rts_mask; - else - ctrls |= rts_mask; +/* + * To reset, we hit the on-board reset register in the system FPGA + */ +void integrator_restart(enum reboot_mode mode, const char *cmd) +{ + cm_control(CM_CTRL_RESET, CM_CTRL_RESET); +} - if (mctrl & TIOCM_DTR) - ctrlc |= dtr_mask; - else - ctrls |= dtr_mask; +static u32 integrator_id; - __raw_writel(ctrls, SC_CTRLS); - __raw_writel(ctrlc, SC_CTRLC); +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 amba_pl010_data integrator_uart_data = { - .set_mctrl = integrator_uart_set_mctrl, -}; +static struct device_attribute intcp_manf_attr = + __ATTR(manufacturer, S_IRUGO, intcp_get_manf, NULL); -#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) +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 DEFINE_SPINLOCK(cm_lock); +static struct device_attribute intcp_arch_attr = + __ATTR(architecture, S_IRUGO, intcp_get_arch, NULL); -/** - * cm_control - update the CM_CTRL register. - * @mask: bits to change - * @set: bits to set - */ -void cm_control(u32 mask, u32 set) +static ssize_t intcp_get_fpga(struct device *dev, + struct device_attribute *attr, + char *buf) { - unsigned long flags; - u32 val; + return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id)); +} - spin_lock_irqsave(&cm_lock, flags); - val = readl(CM_CTRL) & ~mask; - writel(val | set, CM_CTRL); - spin_unlock_irqrestore(&cm_lock, flags); +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); } -EXPORT_SYMBOL(cm_control); +static struct device_attribute intcp_build_attr = + __ATTR(build, S_IRUGO, intcp_get_build, NULL); -/* - * We need to stop things allocating the low memory; ideally we need a - * better implementation of GFP_DMA which does not assume that DMA-able - * memory starts at zero. - */ -void __init integrator_reserve(void) + + +void integrator_init_sysfs(struct device *parent, u32 id) { - memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); + 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); } |
