uncompress.h 4.0 KB
Newer Older
1
/*
2
 * arch/arm/mach-at91/include/mach/uncompress.h
3
 *
4 5
 * Copyright (C) 2003 SAN People
 * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H

25
#include <linux/io.h>
26
#include <linux/atmel_serial.h>
27
#include <mach/hardware.h>
28

29 30
#include <mach/at91_dbgu.h>
#include <mach/cpu.h>
31

32 33
void __iomem *at91_uart;

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
#if !defined(CONFIG_ARCH_AT91X40)
static const u32 uarts_rm9200[] = {
	AT91_BASE_DBGU0,
	AT91RM9200_BASE_US0,
	AT91RM9200_BASE_US1,
	AT91RM9200_BASE_US2,
	AT91RM9200_BASE_US3,
	0,
};

static const u32 uarts_sam9260[] = {
	AT91_BASE_DBGU0,
	AT91SAM9260_BASE_US0,
	AT91SAM9260_BASE_US1,
	AT91SAM9260_BASE_US2,
	AT91SAM9260_BASE_US3,
	AT91SAM9260_BASE_US4,
	AT91SAM9260_BASE_US5,
	0,
};

static const u32 uarts_sam9261[] = {
	AT91_BASE_DBGU0,
	AT91SAM9261_BASE_US0,
	AT91SAM9261_BASE_US1,
	AT91SAM9261_BASE_US2,
	0,
};

static const u32 uarts_sam9263[] = {
	AT91_BASE_DBGU1,
	AT91SAM9263_BASE_US0,
	AT91SAM9263_BASE_US1,
	AT91SAM9263_BASE_US2,
	0,
};

static const u32 uarts_sam9g45[] = {
	AT91_BASE_DBGU1,
	AT91SAM9G45_BASE_US0,
	AT91SAM9G45_BASE_US1,
	AT91SAM9G45_BASE_US2,
	AT91SAM9G45_BASE_US3,
	0,
};

static const u32 uarts_sam9rl[] = {
	AT91_BASE_DBGU0,
	AT91SAM9RL_BASE_US0,
	AT91SAM9RL_BASE_US1,
	AT91SAM9RL_BASE_US2,
	AT91SAM9RL_BASE_US3,
	0,
};

static const u32 uarts_sam9x5[] = {
	AT91_BASE_DBGU0,
	AT91SAM9X5_BASE_USART0,
	AT91SAM9X5_BASE_USART1,
	AT91SAM9X5_BASE_USART2,
	0,
};

static inline const u32* decomp_soc_detect(u32 dbgu_base)
{
	u32 cidr, socid;

	cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
	socid = cidr & ~AT91_CIDR_VERSION;

	switch (socid) {
	case ARCH_ID_AT91RM9200:
		return uarts_rm9200;

	case ARCH_ID_AT91SAM9G20:
	case ARCH_ID_AT91SAM9260:
		return uarts_sam9260;

	case ARCH_ID_AT91SAM9261:
		return uarts_sam9261;

	case ARCH_ID_AT91SAM9263:
		return uarts_sam9263;

	case ARCH_ID_AT91SAM9G45:
		return uarts_sam9g45;

	case ARCH_ID_AT91SAM9RL64:
		return uarts_sam9rl;

	case ARCH_ID_AT91SAM9X5:
		return uarts_sam9x5;
	}

	/* at91sam9g10 */
	if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
		return uarts_sam9261;
	}
	/* at91sam9xe */
	else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
		return uarts_sam9260;
	}

	return NULL;
}

140 141
static inline void arch_decomp_setup(void)
{
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
	int i = 0;
	const u32* usarts;

	usarts = decomp_soc_detect(AT91_BASE_DBGU0);

	if (!usarts)
		usarts = decomp_soc_detect(AT91_BASE_DBGU1);
	if (!usarts) {
		at91_uart = NULL;
		return;
	}

	do {
		/* physical address */
		at91_uart = (void __iomem *)usarts[i];

		if (__raw_readl(at91_uart + ATMEL_US_BRGR))
			return;
		i++;
	} while (usarts[i]);

	at91_uart = NULL;
164
}
165 166 167 168 169 170 171
#else
static inline void arch_decomp_setup(void)
{
	at91_uart = NULL;
}
#endif

172 173
/*
 * The following code assumes the serial port has already been
174
 * initialized by the bootloader.  If you didn't setup a port in
175 176 177 178
 * your bootloader then nothing will appear (which might be desired).
 *
 * This does not append a newline
 */
179 180
static void putc(int c)
{
181 182 183
	if (!at91_uart)
		return;

184
	while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXRDY))
185
		barrier();
186
	__raw_writel(c, at91_uart + ATMEL_US_THR);
187 188 189
}

static inline void flush(void)
190
{
191 192 193
	if (!at91_uart)
		return;

194
	/* wait for transmission to complete */
195
	while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
196
		barrier();
197 198 199 200 201
}

#define arch_decomp_wdog()

#endif