Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/kernel/machvec.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* arch/sh/kernel/machvec.c
4
*
5
* The SuperH machine vector setup handlers, yanked from setup.c
6
*
7
* Copyright (C) 1999 Niibe Yutaka
8
* Copyright (C) 2002 - 2007 Paul Mundt
9
*/
10
#include <linux/init.h>
11
#include <linux/string.h>
12
#include <asm/machvec.h>
13
#include <asm/sections.h>
14
#include <asm/addrspace.h>
15
#include <asm/setup.h>
16
#include <asm/io.h>
17
#include <asm/irq.h>
18
#include <asm/processor.h>
19
20
#define MV_NAME_SIZE 32
21
22
#define for_each_mv(mv) \
23
for ((mv) = (struct sh_machine_vector *)__machvec_start; \
24
(mv) && (unsigned long)(mv) < (unsigned long)__machvec_end; \
25
(mv)++)
26
27
static struct sh_machine_vector * __init get_mv_byname(const char *name)
28
{
29
struct sh_machine_vector *mv;
30
31
for_each_mv(mv)
32
if (strcasecmp(name, mv->mv_name) == 0)
33
return mv;
34
35
return NULL;
36
}
37
38
static unsigned int __initdata machvec_selected;
39
40
static int __init early_parse_mv(char *from)
41
{
42
char mv_name[MV_NAME_SIZE] = "";
43
char *mv_end;
44
char *mv_comma;
45
int mv_len;
46
struct sh_machine_vector *mvp;
47
48
mv_end = strchr(from, ' ');
49
if (mv_end == NULL)
50
mv_end = from + strlen(from);
51
52
mv_comma = strchr(from, ',');
53
mv_len = mv_end - from;
54
if (mv_len > (MV_NAME_SIZE-1))
55
mv_len = MV_NAME_SIZE-1;
56
memcpy(mv_name, from, mv_len);
57
mv_name[mv_len] = '\0';
58
from = mv_end;
59
60
machvec_selected = 1;
61
62
/* Boot with the generic vector */
63
if (strcmp(mv_name, "generic") == 0)
64
return 0;
65
66
mvp = get_mv_byname(mv_name);
67
if (unlikely(!mvp)) {
68
pr_info("Available vectors:\n\n\t'%s', ", sh_mv.mv_name);
69
for_each_mv(mvp)
70
pr_cont("'%s', ", mvp->mv_name);
71
pr_cont("\n\n");
72
panic("Failed to select machvec '%s' -- halting.\n",
73
mv_name);
74
} else
75
sh_mv = *mvp;
76
77
return 0;
78
}
79
early_param("sh_mv", early_parse_mv);
80
81
void __init sh_mv_setup(void)
82
{
83
/*
84
* Only overload the machvec if one hasn't been selected on
85
* the command line with sh_mv=
86
*/
87
if (!machvec_selected) {
88
unsigned long machvec_size;
89
90
machvec_size = ((unsigned long)__machvec_end -
91
(unsigned long)__machvec_start);
92
93
/*
94
* Sanity check for machvec section alignment. Ensure
95
* __initmv hasn't been misused.
96
*/
97
if (machvec_size % sizeof(struct sh_machine_vector))
98
panic("machvec misaligned, invalid __initmv use?");
99
100
/*
101
* If the machvec hasn't been preselected, use the first
102
* vector (usually the only one) from .machvec.init.
103
*/
104
if (machvec_size >= sizeof(struct sh_machine_vector))
105
sh_mv = *(struct sh_machine_vector *)__machvec_start;
106
}
107
108
pr_notice("Booting machvec: %s\n", get_system_type());
109
110
/*
111
* Manually walk the vec, fill in anything that the board hasn't yet
112
* by hand, wrapping to the generic implementation.
113
*/
114
#define mv_set(elem) do { \
115
if (!sh_mv.mv_##elem) \
116
sh_mv.mv_##elem = generic_##elem; \
117
} while (0)
118
119
mv_set(irq_demux);
120
mv_set(mode_pins);
121
mv_set(mem_init);
122
}
123
124