linux/arch/arm/mach-at91/include/mach/uncompress.h
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-at91/include/mach/uncompress.h
   3 *
   4 * Copyright (C) 2003 SAN People
   5 * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21
  22#ifndef __ASM_ARCH_UNCOMPRESS_H
  23#define __ASM_ARCH_UNCOMPRESS_H
  24
  25#include <linux/io.h>
  26#include <linux/atmel_serial.h>
  27#include <mach/hardware.h>
  28
  29#include <mach/at91_dbgu.h>
  30#include <mach/cpu.h>
  31
  32void __iomem *at91_uart;
  33
  34#if !defined(CONFIG_ARCH_AT91X40)
  35static const u32 uarts_rm9200[] = {
  36        AT91_BASE_DBGU0,
  37        AT91RM9200_BASE_US0,
  38        AT91RM9200_BASE_US1,
  39        AT91RM9200_BASE_US2,
  40        AT91RM9200_BASE_US3,
  41        0,
  42};
  43
  44static const u32 uarts_sam9260[] = {
  45        AT91_BASE_DBGU0,
  46        AT91SAM9260_BASE_US0,
  47        AT91SAM9260_BASE_US1,
  48        AT91SAM9260_BASE_US2,
  49        AT91SAM9260_BASE_US3,
  50        AT91SAM9260_BASE_US4,
  51        AT91SAM9260_BASE_US5,
  52        0,
  53};
  54
  55static const u32 uarts_sam9261[] = {
  56        AT91_BASE_DBGU0,
  57        AT91SAM9261_BASE_US0,
  58        AT91SAM9261_BASE_US1,
  59        AT91SAM9261_BASE_US2,
  60        0,
  61};
  62
  63static const u32 uarts_sam9263[] = {
  64        AT91_BASE_DBGU1,
  65        AT91SAM9263_BASE_US0,
  66        AT91SAM9263_BASE_US1,
  67        AT91SAM9263_BASE_US2,
  68        0,
  69};
  70
  71static const u32 uarts_sam9g45[] = {
  72        AT91_BASE_DBGU1,
  73        AT91SAM9G45_BASE_US0,
  74        AT91SAM9G45_BASE_US1,
  75        AT91SAM9G45_BASE_US2,
  76        AT91SAM9G45_BASE_US3,
  77        0,
  78};
  79
  80static const u32 uarts_sam9rl[] = {
  81        AT91_BASE_DBGU0,
  82        AT91SAM9RL_BASE_US0,
  83        AT91SAM9RL_BASE_US1,
  84        AT91SAM9RL_BASE_US2,
  85        AT91SAM9RL_BASE_US3,
  86        0,
  87};
  88
  89static const u32 uarts_sam9x5[] = {
  90        AT91_BASE_DBGU0,
  91        AT91SAM9X5_BASE_USART0,
  92        AT91SAM9X5_BASE_USART1,
  93        AT91SAM9X5_BASE_USART2,
  94        0,
  95};
  96
  97static inline const u32* decomp_soc_detect(void __iomem *dbgu_base)
  98{
  99        u32 cidr, socid;
 100
 101        cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
 102        socid = cidr & ~AT91_CIDR_VERSION;
 103
 104        switch (socid) {
 105        case ARCH_ID_AT91RM9200:
 106                return uarts_rm9200;
 107
 108        case ARCH_ID_AT91SAM9G20:
 109        case ARCH_ID_AT91SAM9260:
 110                return uarts_sam9260;
 111
 112        case ARCH_ID_AT91SAM9261:
 113                return uarts_sam9261;
 114
 115        case ARCH_ID_AT91SAM9263:
 116                return uarts_sam9263;
 117
 118        case ARCH_ID_AT91SAM9G45:
 119                return uarts_sam9g45;
 120
 121        case ARCH_ID_AT91SAM9RL64:
 122                return uarts_sam9rl;
 123
 124        case ARCH_ID_AT91SAM9X5:
 125                return uarts_sam9x5;
 126        }
 127
 128        /* at91sam9g10 */
 129        if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
 130                return uarts_sam9261;
 131        }
 132        /* at91sam9xe */
 133        else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
 134                return uarts_sam9260;
 135        }
 136
 137        return NULL;
 138}
 139
 140static inline void arch_decomp_setup(void)
 141{
 142        int i = 0;
 143        const u32* usarts;
 144
 145        usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU0);
 146
 147        if (!usarts)
 148                usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU1);
 149        if (!usarts) {
 150                at91_uart = NULL;
 151                return;
 152        }
 153
 154        do {
 155                /* physical address */
 156                at91_uart = (void __iomem *)usarts[i];
 157
 158                if (__raw_readl(at91_uart + ATMEL_US_BRGR))
 159                        return;
 160                i++;
 161        } while (usarts[i]);
 162
 163        at91_uart = NULL;
 164}
 165#else
 166static inline void arch_decomp_setup(void)
 167{
 168        at91_uart = NULL;
 169}
 170#endif
 171
 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 * your bootloader then nothing will appear (which might be desired).
 176 *
 177 * This does not append a newline
 178 */
 179static void putc(int c)
 180{
 181        if (!at91_uart)
 182                return;
 183
 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
 189static inline void flush(void)
 190{
 191        if (!at91_uart)
 192                return;
 193
 194        /* wait for transmission to complete */
 195        while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
 196                barrier();
 197}
 198
 199#endif
 200