1/* 2 * linux/arch/arm/mach-integrator/core.c 3 * 4 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2, as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/types.h> 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/device.h> 14#include <linux/spinlock.h> 15#include <linux/interrupt.h> 16#include <linux/irq.h> 17#include <linux/memblock.h> 18#include <linux/sched.h> 19#include <linux/smp.h> 20#include <linux/termios.h> 21#include <linux/amba/bus.h> 22#include <linux/amba/serial.h> 23#include <linux/io.h> 24 25#include <asm/clkdev.h> 26#include <mach/clkdev.h> 27#include <mach/hardware.h> 28#include <mach/platform.h> 29#include <asm/irq.h> 30#include <mach/cm.h> 31#include <asm/system.h> 32#include <asm/leds.h> 33#include <asm/mach/time.h> 34#include <asm/pgtable.h> 35 36static struct amba_pl010_data integrator_uart_data; 37 38static struct amba_device rtc_device = { 39 .dev = { 40 .init_name = "mb:15", 41 }, 42 .res = { 43 .start = INTEGRATOR_RTC_BASE, 44 .end = INTEGRATOR_RTC_BASE + SZ_4K - 1, 45 .flags = IORESOURCE_MEM, 46 }, 47 .irq = { IRQ_RTCINT, NO_IRQ }, 48 .periphid = 0x00041030, 49}; 50 51static struct amba_device uart0_device = { 52 .dev = { 53 .init_name = "mb:16", 54 .platform_data = &integrator_uart_data, 55 }, 56 .res = { 57 .start = INTEGRATOR_UART0_BASE, 58 .end = INTEGRATOR_UART0_BASE + SZ_4K - 1, 59 .flags = IORESOURCE_MEM, 60 }, 61 .irq = { IRQ_UARTINT0, NO_IRQ }, 62 .periphid = 0x0041010, 63}; 64 65static struct amba_device uart1_device = { 66 .dev = { 67 .init_name = "mb:17", 68 .platform_data = &integrator_uart_data, 69 }, 70 .res = { 71 .start = INTEGRATOR_UART1_BASE, 72 .end = INTEGRATOR_UART1_BASE + SZ_4K - 1, 73 .flags = IORESOURCE_MEM, 74 }, 75 .irq = { IRQ_UARTINT1, NO_IRQ }, 76 .periphid = 0x0041010, 77}; 78 79static struct amba_device kmi0_device = { 80 .dev = { 81 .init_name = "mb:18", 82 }, 83 .res = { 84 .start = KMI0_BASE, 85 .end = KMI0_BASE + SZ_4K - 1, 86 .flags = IORESOURCE_MEM, 87 }, 88 .irq = { IRQ_KMIINT0, NO_IRQ }, 89 .periphid = 0x00041050, 90}; 91 92static struct amba_device kmi1_device = { 93 .dev = { 94 .init_name = "mb:19", 95 }, 96 .res = { 97 .start = KMI1_BASE, 98 .end = KMI1_BASE + SZ_4K - 1, 99 .flags = IORESOURCE_MEM, 100 }, 101 .irq = { IRQ_KMIINT1, NO_IRQ }, 102 .periphid = 0x00041050, 103}; 104 105static struct amba_device *amba_devs[] __initdata = { 106 &rtc_device, 107 &uart0_device, 108 &uart1_device, 109 &kmi0_device, 110 &kmi1_device, 111}; 112 113/* 114 * These are fixed clocks. 115 */ 116static struct clk clk24mhz = { 117 .rate = 24000000, 118}; 119 120static struct clk uartclk = { 121 .rate = 14745600, 122}; 123 124static struct clk dummy_apb_pclk; 125 126static struct clk_lookup lookups[] = { 127 { /* Bus clock */ 128 .con_id = "apb_pclk", 129 .clk = &dummy_apb_pclk, 130 }, { /* UART0 */ 131 .dev_id = "mb:16", 132 .clk = &uartclk, 133 }, { /* UART1 */ 134 .dev_id = "mb:17", 135 .clk = &uartclk, 136 }, { /* KMI0 */ 137 .dev_id = "mb:18", 138 .clk = &clk24mhz, 139 }, { /* KMI1 */ 140 .dev_id = "mb:19", 141 .clk = &clk24mhz, 142 }, { /* MMCI - IntegratorCP */ 143 .dev_id = "mb:1c", 144 .clk = &uartclk, 145 } 146}; 147 148static int __init integrator_init(void) 149{ 150 int i; 151 152 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 153 154 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 155 struct amba_device *d = amba_devs[i]; 156 amba_device_register(d, &iomem_resource); 157 } 158 159 return 0; 160} 161 162arch_initcall(integrator_init); 163 164/* 165 * On the Integrator platform, the port RTS and DTR are provided by 166 * bits in the following SC_CTRLS register bits: 167 * RTS DTR 168 * UART0 7 6 169 * UART1 5 4 170 */ 171#define SC_CTRLC IO_ADDRESS(INTEGRATOR_SC_CTRLC) 172#define SC_CTRLS IO_ADDRESS(INTEGRATOR_SC_CTRLS) 173 174static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) 175{ 176 unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; 177 178 if (dev == &uart0_device) { 179 rts_mask = 1 << 4; 180 dtr_mask = 1 << 5; 181 } else { 182 rts_mask = 1 << 6; 183 dtr_mask = 1 << 7; 184 } 185 186 if (mctrl & TIOCM_RTS) 187 ctrlc |= rts_mask; 188 else 189 ctrls |= rts_mask; 190 191 if (mctrl & TIOCM_DTR) 192 ctrlc |= dtr_mask; 193 else 194 ctrls |= dtr_mask; 195 196 __raw_writel(ctrls, SC_CTRLS); 197 __raw_writel(ctrlc, SC_CTRLC); 198} 199 200static struct amba_pl010_data integrator_uart_data = { 201 .set_mctrl = integrator_uart_set_mctrl, 202}; 203 204#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) 205 206static DEFINE_SPINLOCK(cm_lock); 207 208/** 209 * cm_control - update the CM_CTRL register. 210 * @mask: bits to change 211 * @set: bits to set 212 */ 213void cm_control(u32 mask, u32 set) 214{ 215 unsigned long flags; 216 u32 val; 217 218 spin_lock_irqsave(&cm_lock, flags); 219 val = readl(CM_CTRL) & ~mask; 220 writel(val | set, CM_CTRL); 221 spin_unlock_irqrestore(&cm_lock, flags); 222} 223 224EXPORT_SYMBOL(cm_control); 225 226/* 227 * We need to stop things allocating the low memory; ideally we need a 228 * better implementation of GFP_DMA which does not assume that DMA-able 229 * memory starts at zero. 230 */ 231void __init integrator_reserve(void) 232{ 233 memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); 234} 235