1 /* 2 * Copyright (C) 2004-2007 ARM Limited. 3 * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License version 2 7 * as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * 18 * As a special exception, if other files instantiate templates or use macros 19 * or inline functions from this file, or you compile this file and link it 20 * with other works to produce a work based on this file, this file does not 21 * by itself cause the resulting work to be covered by the GNU General Public 22 * License. However the source code for this file must still be made available 23 * in accordance with section (3) of the GNU General Public License. 24 25 * This exception does not invalidate any other reasons why a work based on 26 * this file might be covered by the GNU General Public License. 27 */ 28 29 #include <common.h> 30 #include <devices.h> 31 32 #define DCC_ARM9_RBIT (1 << 0) 33 #define DCC_ARM9_WBIT (1 << 1) 34 #define DCC_ARM11_RBIT (1 << 30) 35 #define DCC_ARM11_WBIT (1 << 29) 36 37 #define read_core_id(x) do { \ 38 __asm__ ("mrc p15, 0, %0, c0, c0, 0\n" : "=r" (x)); \ 39 x = (x >> 4) & 0xFFF; \ 40 } while (0); 41 42 /* 43 * ARM9 44 */ 45 #define write_arm9_dcc(x) \ 46 __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x)) 47 48 #define read_arm9_dcc(x) \ 49 __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x)) 50 51 #define status_arm9_dcc(x) \ 52 __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x)) 53 54 #define can_read_arm9_dcc(x) do { \ 55 status_arm9_dcc(x); \ 56 x &= DCC_ARM9_RBIT; \ 57 } while (0); 58 59 #define can_write_arm9_dcc(x) do { \ 60 status_arm9_dcc(x); \ 61 x &= DCC_ARM9_WBIT; \ 62 x = (x == 0); \ 63 } while (0); 64 65 /* 66 * ARM11 67 */ 68 #define write_arm11_dcc(x) \ 69 __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x)) 70 71 #define read_arm11_dcc(x) \ 72 __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x)) 73 74 #define status_arm11_dcc(x) \ 75 __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x)) 76 77 #define can_read_arm11_dcc(x) do { \ 78 status_arm11_dcc(x); \ 79 x &= DCC_ARM11_RBIT; \ 80 } while (0); 81 82 #define can_write_arm11_dcc(x) do { \ 83 status_arm11_dcc(x); \ 84 x &= DCC_ARM11_WBIT; \ 85 x = (x == 0); \ 86 } while (0); 87 88 #define TIMEOUT_COUNT 0x4000000 89 90 static enum { 91 arm9_and_earlier, 92 arm11_and_later 93 } arm_type = arm9_and_earlier; 94 95 #ifndef CONFIG_ARM_DCC_MULTI 96 #define arm_dcc_init serial_init 97 void serial_setbrg(void) {} 98 #define arm_dcc_getc serial_getc 99 #define arm_dcc_putc serial_putc 100 #define arm_dcc_puts serial_puts 101 #define arm_dcc_tstc serial_tstc 102 #endif 103 104 int arm_dcc_init(void) 105 { 106 register unsigned int id; 107 108 read_core_id(id); 109 110 if (id >= 0xb00) 111 arm_type = arm11_and_later; 112 else 113 arm_type = arm9_and_earlier; 114 115 return 0; 116 } 117 118 int arm_dcc_getc(void) 119 { 120 int ch; 121 register unsigned int reg; 122 123 switch (arm_type) { 124 case arm11_and_later: 125 do { 126 can_read_arm11_dcc(reg); 127 } while (!reg); 128 read_arm11_dcc(ch); 129 break; 130 131 case arm9_and_earlier: 132 default: 133 do { 134 can_read_arm9_dcc(reg); 135 } while (!reg); 136 read_arm9_dcc(ch); 137 break; 138 } 139 140 return ch; 141 } 142 143 void arm_dcc_putc(char ch) 144 { 145 register unsigned int reg; 146 unsigned int timeout_count = TIMEOUT_COUNT; 147 148 switch (arm_type) { 149 case arm11_and_later: 150 while (--timeout_count) { 151 can_write_arm11_dcc(reg); 152 if (reg) 153 break; 154 } 155 if (timeout_count == 0) 156 return; 157 else 158 write_arm11_dcc(ch); 159 break; 160 161 case arm9_and_earlier: 162 default: 163 while (--timeout_count) { 164 can_write_arm9_dcc(reg); 165 if (reg) 166 break; 167 } 168 if (timeout_count == 0) 169 return; 170 else 171 write_arm9_dcc(ch); 172 break; 173 } 174 } 175 176 void arm_dcc_puts(const char *s) 177 { 178 while (*s) 179 arm_dcc_putc(*s++); 180 } 181 182 int arm_dcc_tstc(void) 183 { 184 register unsigned int reg; 185 186 switch (arm_type) { 187 case arm11_and_later: 188 can_read_arm11_dcc(reg); 189 break; 190 case arm9_and_earlier: 191 default: 192 can_read_arm9_dcc(reg); 193 break; 194 } 195 196 return reg; 197 } 198 199 #ifdef CONFIG_ARM_DCC_MULTI 200 static device_t arm_dcc_dev; 201 202 int drv_arm_dcc_init(void) 203 { 204 int rc; 205 206 /* Device initialization */ 207 memset(&arm_dcc_dev, 0, sizeof(arm_dcc_dev)); 208 209 strcpy(arm_dcc_dev.name, "dcc"); 210 arm_dcc_dev.ext = 0; /* No extensions */ 211 arm_dcc_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; 212 arm_dcc_dev.tstc = arm_dcc_tstc; /* 'tstc' function */ 213 arm_dcc_dev.getc = arm_dcc_getc; /* 'getc' function */ 214 arm_dcc_dev.putc = arm_dcc_putc; /* 'putc' function */ 215 arm_dcc_dev.puts = arm_dcc_puts; /* 'puts' function */ 216 217 rc = device_register(&arm_dcc_dev); 218 219 if (rc == 0) { 220 arm_dcc_init(); 221 return 1; 222 } 223 224 return 0; 225 } 226 #endif 227