core.c 4.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  linux/arch/arm/mach-integrator/core.c
 *
 *  Copyright (C) 2000-2003 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.
 */
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
14
#include <linux/export.h>
L
Linus Torvalds 已提交
15 16
#include <linux/spinlock.h>
#include <linux/interrupt.h>
17
#include <linux/irq.h>
18
#include <linux/memblock.h>
L
Linus Torvalds 已提交
19
#include <linux/sched.h>
20
#include <linux/smp.h>
21
#include <linux/termios.h>
22
#include <linux/amba/bus.h>
23
#include <linux/amba/serial.h>
24
#include <linux/io.h>
L
Linus Torvalds 已提交
25

26
#include <mach/hardware.h>
27
#include <mach/platform.h>
28
#include <mach/cm.h>
29 30
#include <mach/irqs.h>

L
Linus Torvalds 已提交
31
#include <asm/leds.h>
32
#include <asm/mach-types.h>
L
Linus Torvalds 已提交
33
#include <asm/mach/time.h>
34
#include <asm/pgtable.h>
L
Linus Torvalds 已提交
35

36 37
static struct amba_pl010_data integrator_uart_data;

38 39 40 41 42
#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 }
L
Linus Torvalds 已提交
43

44
static AMBA_APB_DEVICE(rtc, "rtc", 0,
45
	INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL);
L
Linus Torvalds 已提交
46

47
static AMBA_APB_DEVICE(uart0, "uart0", 0,
48
	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, &integrator_uart_data);
L
Linus Torvalds 已提交
49

50
static AMBA_APB_DEVICE(uart1, "uart1", 0,
51
	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data);
L
Linus Torvalds 已提交
52

53 54
static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL);
static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL);
L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67

static struct amba_device *amba_devs[] __initdata = {
	&rtc_device,
	&uart0_device,
	&uart1_device,
	&kmi0_device,
	&kmi1_device,
};

static int __init integrator_init(void)
{
	int i;

68 69 70 71 72 73 74 75 76 77 78 79 80
	/*
	 * 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 (machine_is_integrator()) {
		rtc_device.periphid	= 0x00041030;
		uart0_device.periphid	= 0x00041010;
		uart1_device.periphid	= 0x00041010;
		kmi0_device.periphid	= 0x00041050;
		kmi1_device.periphid	= 0x00041050;
	}

L
Linus Torvalds 已提交
81 82 83 84 85 86 87 88 89 90
	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
		struct amba_device *d = amba_devs[i];
		amba_device_register(d, &iomem_resource);
	}

	return 0;
}

arch_initcall(integrator_init);

91 92 93 94 95 96 97
/*
 * 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
 */
98 99
#define SC_CTRLC	IO_ADDRESS(INTEGRATOR_SC_CTRLC)
#define SC_CTRLS	IO_ADDRESS(INTEGRATOR_SC_CTRLS)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

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;

	if (dev == &uart0_device) {
		rts_mask = 1 << 4;
		dtr_mask = 1 << 5;
	} else {
		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);
}

static struct amba_pl010_data integrator_uart_data = {
	.set_mctrl = integrator_uart_set_mctrl,
};

131
#define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL)
L
Linus Torvalds 已提交
132

133
static DEFINE_RAW_SPINLOCK(cm_lock);
L
Linus Torvalds 已提交
134 135 136 137 138 139 140 141 142 143 144

/**
 * 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;

145
	raw_spin_lock_irqsave(&cm_lock, flags);
L
Linus Torvalds 已提交
146 147
	val = readl(CM_CTRL) & ~mask;
	writel(val | set, CM_CTRL);
148
	raw_spin_unlock_irqrestore(&cm_lock, flags);
L
Linus Torvalds 已提交
149 150 151
}

EXPORT_SYMBOL(cm_control);
152 153 154 155 156 157 158 159

/*
 * 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)
{
160
	memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
161
}
162 163 164 165 166 167 168 169

/*
 * To reset, we hit the on-board reset register in the system FPGA
 */
void integrator_restart(char mode, const char *cmd)
{
	cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
}