source: mainline/kernel/arch/arm32/src/cpu/cpu.c@ 04cb6957

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 04cb6957 was 04cb6957, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

arm32: Minor fixes.

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[d630139]1/*
[6b781c0]2 * Copyright (c) 2007 Michal Kebrt
[d630139]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup arm32
30 * @{
31 */
32/** @file
[6b781c0]33 * @brief CPU identification.
[d630139]34 */
35
[6b781c0]36#include <arch/cpu.h>
[d630139]37#include <cpu.h>
[6b781c0]38#include <arch.h>
[e762b43]39#include <print.h>
[3412e844]40#include <fpu_context.h>
[d630139]41
[6b781c0]42/** Number of indexes left out in the #imp_data array */
43#define IMP_DATA_START_OFFSET 0x40
44
[04cb6957]45/** Implementors (vendor) names */
[a000878c]46static const char *imp_data[] = {
[79e84c9]47 "?", /* IMP_DATA_START_OFFSET */
48 "ARM Limited", /* 0x41 */
49 "", "", /* 0x42 - 0x43 */
50 "Digital Equipment Corporation", /* 0x44 */
51 "", "", "", "", "", "", "", "", /* 0x45 - 0x4c */
52 "Motorola, Freescale Semicondutor Inc.", /* 0x4d */
53 "", "", "", /* 0x4e - 0x50 */
54 "Qualcomm Inc.", /* 0x51 */
55 "", "", "", "", /* 0x52 - 0x55 */
56 "Marvell Semiconductor", /* 0x56 */
57 "", "", "", "", "", "", "", "", "", "", /* 0x57 - 0x60 */
58 "", "", "", "", "", "", "", "", /* 0x61 - 0x68 */
59 "Intel Corporation" /* 0x69 */
[6b781c0]60};
61
62/** Length of the #imp_data array */
[04cb6957]63static const unsigned int imp_data_length = sizeof(imp_data) / sizeof(char *);
[6b781c0]64
65/** Architecture names */
[a000878c]66static const char *arch_data[] = {
[6b781c0]67 "?", /* 0x0 */
68 "4", /* 0x1 */
69 "4T", /* 0x2 */
70 "5", /* 0x3 */
71 "5T", /* 0x4 */
72 "5TE", /* 0x5 */
73 "5TEJ", /* 0x6 */
74 "6" /* 0x7 */
75};
76
77/** Length of the #arch_data array */
[04cb6957]78static const unsigned int arch_data_length = sizeof(arch_data) / sizeof(char *);
[6b781c0]79
80
81/** Retrieves processor identification from CP15 register 0.
[04cb6957]82 *
[6b781c0]83 * @param cpu Structure for storing CPU identification.
84 */
85static void arch_cpu_identify(cpu_arch_t *cpu)
86{
87 uint32_t ident;
88 asm volatile (
[e762b43]89 "mrc p15, 0, %[ident], c0, c0, 0\n"
90 : [ident] "=r" (ident)
[6b781c0]91 );
[e762b43]92
[6b781c0]93 cpu->imp_num = ident >> 24;
94 cpu->variant_num = (ident << 8) >> 28;
95 cpu->arch_num = (ident << 12) >> 28;
96 cpu->prim_part_num = (ident << 16) >> 20;
97 cpu->rev_num = (ident << 28) >> 28;
98}
99
[8316547f]100/** Enables unaligned access and caching for armv6+ */
[d630139]101void cpu_arch_init(void)
102{
[f94b95b1]103#if defined(PROCESSOR_armv7_a) | defined(PROCESSOR_armv6)
[1bd99214]104 uint32_t control_reg = 0;
105 asm volatile (
106 "mrc p15, 0, %[control_reg], c1, c0"
107 : [control_reg] "=r" (control_reg)
108 );
109
[8316547f]110 /* Turn off tex remap, RAZ ignores writes prior to armv7 */
[4bd3f45]111 control_reg &= ~CP15_R1_TEX_REMAP_EN;
[8316547f]112 /* Turn off accessed flag, RAZ ignores writes prior to armv7 */
[4bd3f45]113 control_reg &= ~(CP15_R1_ACCESS_FLAG_EN | CP15_R1_HW_ACCESS_FLAG_EN);
[8316547f]114 /* Enable unaligned access, RAZ ignores writes prior to armv6
115 * switchable on armv6, RAO ignores writes on armv7,
116 * see ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
117 * L.3.1 (p. 2456) */
[4bd3f45]118 control_reg |= CP15_R1_UNALIGNED_EN;
[8316547f]119 /* Disable alignment checks, this turns unaligned access to undefined,
120 * unless U bit is set. */
[4bd3f45]121 control_reg &= ~CP15_R1_ALIGN_CHECK_EN;
[8316547f]122 /* Enable caching, On arm prior to armv7 there is only one level
123 * of caches. Data cache is coherent.
124 * "This means that the behavior of accesses from the same observer to
125 * different VAs, that are translated to the same PA
126 * with the same memory attributes, is fully coherent."
127 * ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition
128 * B3.11.1 (p. 1383)
129 * ICache coherency is elaborate on in barrier.h.
130 * We are safe to turn these on.
131 */
[1a1b05b]132 control_reg |= CP15_R1_CACHE_EN | CP15_R1_INST_CACHE_EN;
[1bd99214]133
134 asm volatile (
135 "mcr p15, 0, %[control_reg], c1, c0"
136 :: [control_reg] "r" (control_reg)
137 );
138#endif
[d630139]139}
140
[3412e844]141void fpu_init(void)
142{
143 //TODO: Identify FPU unit
144 //and set correct functions to save/restore ctx
145}
146
147void fpu_enable(void)
148{
149 /* Enable FPU instructions */
150 asm volatile (
151 "ldr r1, =0x40000000\n"
152 "vmsr fpexc, r1\n"
153 ::: "r1"
154 );
155}
156
157void fpu_disable(void)
158{
159 /* Disable FPU instructions */
160 asm volatile (
161 "ldr r1, =0x00000000\n"
162 "vmsr fpexc, r1\n"
163 ::: "r1"
164 );
165}
166
167void fpu_context_save(fpu_context_t *ctx)
168{
169 // TODO check and complete. What about fpexc?
170 asm volatile (
171 "vmrs r1, fpscr\n"
172// "vmrs r2, fpexc\n"
173 "stm %0, {r1, r2}\n"
[28f81d21]174 "vstm %0, {d0-d15}\n"
[3412e844]175 ::"r" (ctx): "r1","r2","memory"
176 );
177}
178
179void fpu_context_restore(fpu_context_t *ctx)
180{
181 // TODO check and complete. What about fpexc?
182 asm volatile (
183 "ldm %0, {r1, r2}\n"
184 "vmsr fpscr, r1\n"
185// "vmsr fpexc, r2\n"
[28f81d21]186 "vldm %0, {d0-d15}\n"
[3412e844]187 ::"r" (ctx): "r1","r2"
188 );
189}
190
[6b781c0]191/** Retrieves processor identification and stores it to #CPU.arch */
[f94b95b1]192void cpu_identify(void)
[d630139]193{
[6b781c0]194 arch_cpu_identify(&CPU->arch);
[d630139]195}
196
[6b781c0]197/** Prints CPU identification. */
[d630139]198void cpu_print_report(cpu_t *m)
199{
[a000878c]200 const char *vendor = imp_data[0];
201 const char *architecture = arch_data[0];
[6b781c0]202 cpu_arch_t * cpu_arch = &m->arch;
203
[79e84c9]204 const unsigned imp_offset = cpu_arch->imp_num - IMP_DATA_START_OFFSET;
205
206 if (imp_offset < imp_data_length) {
[6b781c0]207 vendor = imp_data[cpu_arch->imp_num - IMP_DATA_START_OFFSET];
208 }
209
[79e84c9]210 // TODO CPUs with arch_num == 0xf use CPUID scheme for identification
211 if (cpu_arch->arch_num < arch_data_length) {
[6b781c0]212 architecture = arch_data[cpu_arch->arch_num];
213 }
214
[04cb6957]215 printf("cpu%d: vendor=%s, architecture=ARMv%s, part number=%x, "
[6b781c0]216 "variant=%x, revision=%x\n",
217 m->id, vendor, architecture, cpu_arch->prim_part_num,
218 cpu_arch->variant_num, cpu_arch->rev_num);
[d630139]219}
220
221/** @}
222 */
Note: See TracBrowser for help on using the repository browser.