summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-sa1100/hw.c
blob: a28b28177e2be7c3a3019adcbac1196d9893ade5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * arch/arm/kernel/hw-sa1100.c
 *
 * SA1100-dependent machine specifics
 *
 * Copyright (C) 2000 Nicolas Pitre <nico@cam.org>
 *
 * This will certainly contain more stuff with time... like power management,
 * special hardware autodetection, etc.
 *
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>

#include <asm/delay.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>

/*
 * SA1100 GPIO edge detection for IRQs:
 * IRQs are generated on Falling-Edge, Rising-Edge, or both.
 * This must be called *before* the appropriate IRQ is registered.
 * Use this instead of directly setting GRER/GFER.
 */

int GPIO_IRQ_rising_edge;
int GPIO_IRQ_falling_edge;

void set_GPIO_IRQ_edge( int gpio_mask, int edge )
{
	if( edge & GPIO_FALLING_EDGE )
		GPIO_IRQ_falling_edge |= gpio_mask;
	else
		GPIO_IRQ_falling_edge &= ~gpio_mask;
	if( edge & GPIO_RISING_EDGE )
		GPIO_IRQ_rising_edge |= gpio_mask;
	else
		GPIO_IRQ_rising_edge &= ~gpio_mask;
}

EXPORT_SYMBOL(set_GPIO_IRQ_edge);


#ifdef CONFIG_SA1100_ASSABET

unsigned long BCR_value = BCR_DB1110;
unsigned long SCR_value = SCR_INIT;
EXPORT_SYMBOL(BCR_value);
EXPORT_SYMBOL(SCR_value);

/*
 * Read System Configuration "Register"
 * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
 * User's Guide", section 4.4.1)
 *
 * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S
 * to set up the serial port for decompression status messages. We 
 * repeat it here because the kernel may not be loaded as a zImage, and
 * also because it's a hassle to communicate the SCR value to the kernel
 * from the decompressor.
 */

void __init get_assabet_scr(void)
{
	unsigned long flags, scr, i;

	local_irq_save(flags);
	GPDR |= 0x3fc;			/* Configure GPIO 9:2 as outputs */
	GPSR = 0x3fc;			/* Write 0xFF to GPIO 9:2 */
	GPDR &= ~(0x3fc);		/* Configure GPIO 9:2 as inputs */
	for(i = 100; i--; scr = GPLR);	/* Read GPIO 9:2 */
	GPDR |= 0x3fc;			/*  restore correct pin direction */
	local_irq_restore(flags);
	scr &= 0x3fc;			/* save as system configuration byte. */

	SCR_value = scr;
}

#endif  /* CONFIG_SA1100_ASSABET */


#if defined(CONFIG_SA1100_BITSY)
/*
 * Bitsy has extended, write-only memory-mapped GPIO's
 */
static int bitsy_egpio = EGPIO_BITSY_RS232_ON;
void clr_bitsy_egpio(unsigned long x) 
{
  bitsy_egpio &= ~x;
  BITSY_EGPIO = bitsy_egpio;
}
void set_bitsy_egpio(unsigned long x) 
{
  bitsy_egpio |= x;
  BITSY_EGPIO = bitsy_egpio;
}
EXPORT_SYMBOL(clr_bitsy_egpio);
EXPORT_SYMBOL(set_bitsy_egpio);
#endif


#ifdef CONFIG_SA1111

static void __init sa1111_init(void){
  unsigned long id=SKID;

  if((id & SKID_ID_MASK) == SKID_SA1111_ID)
    printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: "
	   "silicon revision %x, metal revision %x\n",
	   (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
  else {
    printk(KERN_ERR "Could not detect SA-1111!\n");
    return;
  }

  /* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
   * (SA-1110 Developer's Manual, section 9.1.2.1)
   */
  GAFR |= GPIO_32_768kHz;
  GPDR |= GPIO_32_768kHz;
  TUCR = TUCR_3_6864MHz;

  /* Now, set up the PLL and RCLK in the SA-1111: */
  SKCR = SKCR_PLL_BYPASS | SKCR_RDYEN | SKCR_OE_EN;
  udelay(100);
  SKCR = SKCR_PLL_BYPASS | SKCR_RCLKEN | SKCR_RDYEN | SKCR_OE_EN;

  /* SA-1111 Register Access Bus should now be available. Clocks for
   * any other SA-1111 functional blocks must be enabled separately
   * using the SKPCR.
   */

  /* If the system is going to use the SA-1111 DMA engines, set up
   * the memory bus request/grant pins. Also configure the shared
   * memory controller on the SA-1111 (SA-1111 Developer's Manual,
   * section 3.2.3) and power up the DMA bus clock:
   */
  if(machine_is_assabet()){

    GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
    GPDR |= GPIO_MBGNT;
    GPDR &= ~GPIO_MBREQ;
    TUCR |= TUCR_MR;

    /* Assabet is populated by default with two Samsung KM416S8030T-G8
     * 128Mb SDRAMs, which are organized as 12-bit (row addr) x 9-bit
     * (column addr), according to the data sheet. Apparently, the 
     * bank selects factor into the row address, as Angel sets up the
     * SA-1110 to use 14x9 addresses. The SDRAM datasheet specifies
     * that when running at 100-125MHz, the CAS latency for -8 parts
     * is 3 cycles, which is consistent with Angel.
     */

    SMCR = (SMCR_DTIM | SMCR_MBGE | 
	    FInsrt(FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), SMCR_DRAC) |
	    ((FExtr(MDCNFG, MDCNFG_SA1110_TDL0)==3) ? SMCR_CLAT : 0));

    SKPCR |= SKPCR_DCLKEN;
  }
}

#else
#define sa1111_init()  printk( "Warning: missing SA1111 support\n" )
#endif


static int __init hw_sa1100_init(void)
{
	if( machine_is_assabet() ){
		if(machine_has_neponset()){
#ifdef CONFIG_ASSABET_NEPONSET
			LEDS = WHOAMI;
			sa1111_init();
#else
			printk( "Warning: Neponset detected but full support "
				"hasn't been configured in the kernel\n" );
#endif
		}
	} else if (machine_is_xp860()) {
		sa1111_init();
	}
	return 0;
}

module_init(hw_sa1100_init);