19655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt/* 29655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * arch/sh/kernel/machvec.c 39655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * 49655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * The SuperH machine vector setup handlers, yanked from setup.c 59655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * 69655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * Copyright (C) 1999 Niibe Yutaka 79655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * Copyright (C) 2002 - 2007 Paul Mundt 89655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * 99655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * This file is subject to the terms and conditions of the GNU General Public 109655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * License. See the file "COPYING" in the main directory of this archive 119655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * for more details. 129655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt */ 139655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <linux/init.h> 149655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <linux/string.h> 159655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <asm/machvec.h> 169655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <asm/sections.h> 17d44ee12ad61ff7aa7a6344560bd430cb72fcbc27Paul Mundt#include <asm/addrspace.h> 18fa43972fab24a3c050e880a7831f9378c6cebc0bPaul Mundt#include <asm/setup.h> 199655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <asm/io.h> 209655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#include <asm/irq.h> 219655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 229655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#define MV_NAME_SIZE 32 239655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 249655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#define for_each_mv(mv) \ 259655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt for ((mv) = (struct sh_machine_vector *)&__machvec_start; \ 269655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \ 279655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt (mv)++) 289655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 299655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundtstatic struct sh_machine_vector * __init get_mv_byname(const char *name) 309655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt{ 319655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt struct sh_machine_vector *mv; 329655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 339655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt for_each_mv(mv) 3482f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt if (strcasecmp(name, mv->mv_name) == 0) 359655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt return mv; 369655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 379655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt return NULL; 389655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt} 399655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 40fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundtstatic unsigned int __initdata machvec_selected; 41fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt 429655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundtstatic int __init early_parse_mv(char *from) 439655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt{ 449655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt char mv_name[MV_NAME_SIZE] = ""; 459655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt char *mv_end; 469655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt char *mv_comma; 479655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt int mv_len; 489655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt struct sh_machine_vector *mvp; 499655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 509655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_end = strchr(from, ' '); 519655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt if (mv_end == NULL) 529655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_end = from + strlen(from); 539655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 549655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_comma = strchr(from, ','); 559655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_len = mv_end - from; 569655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt if (mv_len > (MV_NAME_SIZE-1)) 579655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_len = MV_NAME_SIZE-1; 589655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt memcpy(mv_name, from, mv_len); 599655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_name[mv_len] = '\0'; 609655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt from = mv_end; 619655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 62fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt machvec_selected = 1; 63fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt 64fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt /* Boot with the generic vector */ 65fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt if (strcmp(mv_name, "generic") == 0) 66fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt return 0; 67fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt 6882f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt mvp = get_mv_byname(mv_name); 6982f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt if (unlikely(!mvp)) { 70fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name); 7182f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt for_each_mv(mvp) 7282f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt printk("'%s', ", mvp->mv_name); 7382f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt printk("\n\n"); 7482f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt panic("Failed to select machvec '%s' -- halting.\n", 7582f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt mv_name); 7682f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt } else 7782f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt sh_mv = *mvp; 789655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 799655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt return 0; 809655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt} 819655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundtearly_param("sh_mv", early_parse_mv); 829655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 839655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundtvoid __init sh_mv_setup(void) 849655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt{ 859655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt /* 8682f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt * Only overload the machvec if one hasn't been selected on 8782f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt * the command line with sh_mv= 8882f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt */ 89fd8f20e8e2f8f1d9201086bff444c8d35f0a6a45Paul Mundt if (!machvec_selected) { 9082f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt unsigned long machvec_size; 9182f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt 9282f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt machvec_size = ((unsigned long)&__machvec_end - 9382f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt (unsigned long)&__machvec_start); 9482f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt 9582f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt /* 965556410e2203877e7606bb1008f2e024fe87953aPaul Mundt * Sanity check for machvec section alignment. Ensure 975556410e2203877e7606bb1008f2e024fe87953aPaul Mundt * __initmv hasn't been misused. 985556410e2203877e7606bb1008f2e024fe87953aPaul Mundt */ 995556410e2203877e7606bb1008f2e024fe87953aPaul Mundt if (machvec_size % sizeof(struct sh_machine_vector)) 1005556410e2203877e7606bb1008f2e024fe87953aPaul Mundt panic("machvec misaligned, invalid __initmv use?"); 1015556410e2203877e7606bb1008f2e024fe87953aPaul Mundt 1025556410e2203877e7606bb1008f2e024fe87953aPaul Mundt /* 10382f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt * If the machvec hasn't been preselected, use the first 10482f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt * vector (usually the only one) from .machvec.init. 10582f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt */ 10682f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt if (machvec_size >= sizeof(struct sh_machine_vector)) 10782f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt sh_mv = *(struct sh_machine_vector *)&__machvec_start; 10882f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt } 10982f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt 11082f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type()); 11182f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt 11282f81f4784479df17a80caff4a7156da0a2f7deaPaul Mundt /* 1139655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * Manually walk the vec, fill in anything that the board hasn't yet 1149655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt * by hand, wrapping to the generic implementation. 1159655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt */ 1169655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt#define mv_set(elem) do { \ 1179655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt if (!sh_mv.mv_##elem) \ 1189655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt sh_mv.mv_##elem = generic_##elem; \ 1199655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt} while (0) 1209655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt 1219655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt mv_set(irq_demux); 122eb9b9b56eed280e65a9e194aaeb50a5a75111859Magnus Damm mv_set(mode_pins); 12319d8f84f86af867abee174be8bf1e4941a59143dPaul Mundt mv_set(mem_init); 1249655ad03af2d232c3b26e7562ab4f8c29b107e49Paul Mundt} 125