xref: /linux/arch/powerpc/platforms/pseries/firmware.c (revision 0388c79c99ccb43f711af57d2e14fcd6a5f45a06)
11965746bSMichael Ellerman /*
21965746bSMichael Ellerman  *  pSeries firmware setup code.
31965746bSMichael Ellerman  *
41965746bSMichael Ellerman  *  Portions from arch/powerpc/platforms/pseries/setup.c:
51965746bSMichael Ellerman  *   Copyright (C) 1995  Linus Torvalds
61965746bSMichael Ellerman  *   Adapted from 'alpha' version by Gary Thomas
71965746bSMichael Ellerman  *   Modified by Cort Dougan (cort@cs.nmt.edu)
81965746bSMichael Ellerman  *   Modified by PPC64 Team, IBM Corp
91965746bSMichael Ellerman  *
101965746bSMichael Ellerman  *  Portions from arch/powerpc/kernel/firmware.c
111965746bSMichael Ellerman  *   Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
121965746bSMichael Ellerman  *   Modifications for ppc64:
131965746bSMichael Ellerman  *    Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
141965746bSMichael Ellerman  *    Copyright (C) 2005 Stephen Rothwell, IBM Corporation
151965746bSMichael Ellerman  *
161965746bSMichael Ellerman  *  Copyright 2006 IBM Corporation.
171965746bSMichael Ellerman  *
181965746bSMichael Ellerman  * This program is free software; you can redistribute it and/or
191965746bSMichael Ellerman  * modify it under the terms of the GNU General Public License
201965746bSMichael Ellerman  * as published by the Free Software Foundation; either version
211965746bSMichael Ellerman  * 2 of the License, or (at your option) any later version.
221965746bSMichael Ellerman  */
231965746bSMichael Ellerman 
241965746bSMichael Ellerman 
251965746bSMichael Ellerman #include <asm/firmware.h>
261965746bSMichael Ellerman #include <asm/prom.h>
27aa39be09Swill schmidt #include <asm/udbg.h>
281965746bSMichael Ellerman 
293ff1999bSMichael Ellerman #include "pseries.h"
301965746bSMichael Ellerman 
311965746bSMichael Ellerman typedef struct {
321965746bSMichael Ellerman     unsigned long val;
331965746bSMichael Ellerman     char * name;
341965746bSMichael Ellerman } firmware_feature_t;
351965746bSMichael Ellerman 
362f1d4ea7SMichael Neuling /*
372f1d4ea7SMichael Neuling  * The names in this table match names in rtas/ibm,hypertas-functions.  If the
382f1d4ea7SMichael Neuling  * entry ends in a '*', only upto the '*' is matched.  Otherwise the entire
392f1d4ea7SMichael Neuling  * string must match.
402f1d4ea7SMichael Neuling  */
411965746bSMichael Ellerman static __initdata firmware_feature_t
421965746bSMichael Ellerman firmware_features_table[FIRMWARE_MAX_FEATURES] = {
431965746bSMichael Ellerman 	{FW_FEATURE_PFT,		"hcall-pft"},
441965746bSMichael Ellerman 	{FW_FEATURE_TCE,		"hcall-tce"},
451965746bSMichael Ellerman 	{FW_FEATURE_SPRG0,		"hcall-sprg0"},
461965746bSMichael Ellerman 	{FW_FEATURE_DABR,		"hcall-dabr"},
471965746bSMichael Ellerman 	{FW_FEATURE_COPY,		"hcall-copy"},
481965746bSMichael Ellerman 	{FW_FEATURE_ASR,		"hcall-asr"},
491965746bSMichael Ellerman 	{FW_FEATURE_DEBUG,		"hcall-debug"},
501965746bSMichael Ellerman 	{FW_FEATURE_PERF,		"hcall-perf"},
511965746bSMichael Ellerman 	{FW_FEATURE_DUMP,		"hcall-dump"},
521965746bSMichael Ellerman 	{FW_FEATURE_INTERRUPT,		"hcall-interrupt"},
531965746bSMichael Ellerman 	{FW_FEATURE_MIGRATE,		"hcall-migrate"},
541965746bSMichael Ellerman 	{FW_FEATURE_PERFMON,		"hcall-perfmon"},
551965746bSMichael Ellerman 	{FW_FEATURE_CRQ,		"hcall-crq"},
561965746bSMichael Ellerman 	{FW_FEATURE_VIO,		"hcall-vio"},
571965746bSMichael Ellerman 	{FW_FEATURE_RDMA,		"hcall-rdma"},
581965746bSMichael Ellerman 	{FW_FEATURE_LLAN,		"hcall-lLAN"},
59b6dcde5cSAnton Blanchard 	{FW_FEATURE_BULK_REMOVE,	"hcall-bulk"},
601965746bSMichael Ellerman 	{FW_FEATURE_XDABR,		"hcall-xdabr"},
611965746bSMichael Ellerman 	{FW_FEATURE_MULTITCE,		"hcall-multi-tce"},
621965746bSMichael Ellerman 	{FW_FEATURE_SPLPAR,		"hcall-splpar"},
6336f567b4SJesse Larrew 	{FW_FEATURE_VPHN,		"hcall-vphn"},
64d8f48eccSIan Munsie 	{FW_FEATURE_SET_MODE,		"hcall-set-mode"},
65*0388c79cSMichael Neuling 	{FW_FEATURE_BEST_ENERGY,	"hcall-best-energy-1*"},
661965746bSMichael Ellerman };
671965746bSMichael Ellerman 
681965746bSMichael Ellerman /* Build up the firmware features bitmask using the contents of
691965746bSMichael Ellerman  * device-tree/ibm,hypertas-functions.  Ultimately this functionality may
701965746bSMichael Ellerman  * be moved into prom.c prom_init().
711965746bSMichael Ellerman  */
72ca8ffc97SMichael Neuling void __init fw_feature_init(const char *hypertas, unsigned long len)
731965746bSMichael Ellerman {
74ca8ffc97SMichael Neuling 	const char *s;
75ca8ffc97SMichael Neuling 	int i;
761965746bSMichael Ellerman 
77f7ebf352SMichael Ellerman 	pr_debug(" -> fw_feature_init()\n");
781965746bSMichael Ellerman 
791965746bSMichael Ellerman 	for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
801965746bSMichael Ellerman 		for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
812f1d4ea7SMichael Neuling 			const char *name = firmware_features_table[i].name;
822f1d4ea7SMichael Neuling 			size_t size;
831965746bSMichael Ellerman 			/* check value against table of strings */
842f1d4ea7SMichael Neuling 			if (!name)
852f1d4ea7SMichael Neuling 				continue;
862f1d4ea7SMichael Neuling 			/*
872f1d4ea7SMichael Neuling 			 * If there is a '*' at the end of name, only check
882f1d4ea7SMichael Neuling 			 * upto there
892f1d4ea7SMichael Neuling 			 */
902f1d4ea7SMichael Neuling 			size = strlen(name);
912f1d4ea7SMichael Neuling 			if (size && name[size - 1] == '*') {
922f1d4ea7SMichael Neuling 				if (strncmp(name, s, size - 1))
932f1d4ea7SMichael Neuling 					continue;
942f1d4ea7SMichael Neuling 			} else if (strcmp(name, s))
951965746bSMichael Ellerman 				continue;
961965746bSMichael Ellerman 
971965746bSMichael Ellerman 			/* we have a match */
98d0160bf0SMichael Ellerman 			powerpc_firmware_features |=
991965746bSMichael Ellerman 				firmware_features_table[i].val;
1001965746bSMichael Ellerman 			break;
1011965746bSMichael Ellerman 		}
1021965746bSMichael Ellerman 	}
1031965746bSMichael Ellerman 
104f7ebf352SMichael Ellerman 	pr_debug(" <- fw_feature_init()\n");
1051965746bSMichael Ellerman }
106