xref: /linux/arch/powerpc/platforms/pseries/firmware.c (revision 1965746bce49ddf001af52c7985e16343c768021)
1*1965746bSMichael Ellerman /*
2*1965746bSMichael Ellerman  *  pSeries firmware setup code.
3*1965746bSMichael Ellerman  *
4*1965746bSMichael Ellerman  *  Portions from arch/powerpc/platforms/pseries/setup.c:
5*1965746bSMichael Ellerman  *   Copyright (C) 1995  Linus Torvalds
6*1965746bSMichael Ellerman  *   Adapted from 'alpha' version by Gary Thomas
7*1965746bSMichael Ellerman  *   Modified by Cort Dougan (cort@cs.nmt.edu)
8*1965746bSMichael Ellerman  *   Modified by PPC64 Team, IBM Corp
9*1965746bSMichael Ellerman  *
10*1965746bSMichael Ellerman  *  Portions from arch/powerpc/kernel/firmware.c
11*1965746bSMichael Ellerman  *   Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
12*1965746bSMichael Ellerman  *   Modifications for ppc64:
13*1965746bSMichael Ellerman  *    Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
14*1965746bSMichael Ellerman  *    Copyright (C) 2005 Stephen Rothwell, IBM Corporation
15*1965746bSMichael Ellerman  *
16*1965746bSMichael Ellerman  *  Copyright 2006 IBM Corporation.
17*1965746bSMichael Ellerman  *
18*1965746bSMichael Ellerman  * This program is free software; you can redistribute it and/or
19*1965746bSMichael Ellerman  * modify it under the terms of the GNU General Public License
20*1965746bSMichael Ellerman  * as published by the Free Software Foundation; either version
21*1965746bSMichael Ellerman  * 2 of the License, or (at your option) any later version.
22*1965746bSMichael Ellerman  */
23*1965746bSMichael Ellerman 
24*1965746bSMichael Ellerman #undef DEBUG
25*1965746bSMichael Ellerman 
26*1965746bSMichael Ellerman #include <asm/firmware.h>
27*1965746bSMichael Ellerman #include <asm/prom.h>
28*1965746bSMichael Ellerman 
29*1965746bSMichael Ellerman #ifdef DEBUG
30*1965746bSMichael Ellerman #define DBG(fmt...) udbg_printf(fmt)
31*1965746bSMichael Ellerman #else
32*1965746bSMichael Ellerman #define DBG(fmt...)
33*1965746bSMichael Ellerman #endif
34*1965746bSMichael Ellerman 
35*1965746bSMichael Ellerman typedef struct {
36*1965746bSMichael Ellerman     unsigned long val;
37*1965746bSMichael Ellerman     char * name;
38*1965746bSMichael Ellerman } firmware_feature_t;
39*1965746bSMichael Ellerman 
40*1965746bSMichael Ellerman static __initdata firmware_feature_t
41*1965746bSMichael Ellerman firmware_features_table[FIRMWARE_MAX_FEATURES] = {
42*1965746bSMichael Ellerman 	{FW_FEATURE_PFT,		"hcall-pft"},
43*1965746bSMichael Ellerman 	{FW_FEATURE_TCE,		"hcall-tce"},
44*1965746bSMichael Ellerman 	{FW_FEATURE_SPRG0,		"hcall-sprg0"},
45*1965746bSMichael Ellerman 	{FW_FEATURE_DABR,		"hcall-dabr"},
46*1965746bSMichael Ellerman 	{FW_FEATURE_COPY,		"hcall-copy"},
47*1965746bSMichael Ellerman 	{FW_FEATURE_ASR,		"hcall-asr"},
48*1965746bSMichael Ellerman 	{FW_FEATURE_DEBUG,		"hcall-debug"},
49*1965746bSMichael Ellerman 	{FW_FEATURE_PERF,		"hcall-perf"},
50*1965746bSMichael Ellerman 	{FW_FEATURE_DUMP,		"hcall-dump"},
51*1965746bSMichael Ellerman 	{FW_FEATURE_INTERRUPT,		"hcall-interrupt"},
52*1965746bSMichael Ellerman 	{FW_FEATURE_MIGRATE,		"hcall-migrate"},
53*1965746bSMichael Ellerman 	{FW_FEATURE_PERFMON,		"hcall-perfmon"},
54*1965746bSMichael Ellerman 	{FW_FEATURE_CRQ,		"hcall-crq"},
55*1965746bSMichael Ellerman 	{FW_FEATURE_VIO,		"hcall-vio"},
56*1965746bSMichael Ellerman 	{FW_FEATURE_RDMA,		"hcall-rdma"},
57*1965746bSMichael Ellerman 	{FW_FEATURE_LLAN,		"hcall-lLAN"},
58*1965746bSMichael Ellerman 	{FW_FEATURE_BULK,		"hcall-bulk"},
59*1965746bSMichael Ellerman 	{FW_FEATURE_XDABR,		"hcall-xdabr"},
60*1965746bSMichael Ellerman 	{FW_FEATURE_MULTITCE,		"hcall-multi-tce"},
61*1965746bSMichael Ellerman 	{FW_FEATURE_SPLPAR,		"hcall-splpar"},
62*1965746bSMichael Ellerman };
63*1965746bSMichael Ellerman 
64*1965746bSMichael Ellerman /* Build up the firmware features bitmask using the contents of
65*1965746bSMichael Ellerman  * device-tree/ibm,hypertas-functions.  Ultimately this functionality may
66*1965746bSMichael Ellerman  * be moved into prom.c prom_init().
67*1965746bSMichael Ellerman  */
68*1965746bSMichael Ellerman void __init fw_feature_init(void)
69*1965746bSMichael Ellerman {
70*1965746bSMichael Ellerman 	struct device_node *dn;
71*1965746bSMichael Ellerman 	char *hypertas, *s;
72*1965746bSMichael Ellerman 	int len, i;
73*1965746bSMichael Ellerman 
74*1965746bSMichael Ellerman 	DBG(" -> fw_feature_init()\n");
75*1965746bSMichael Ellerman 
76*1965746bSMichael Ellerman 	dn = of_find_node_by_path("/rtas");
77*1965746bSMichael Ellerman 	if (dn == NULL) {
78*1965746bSMichael Ellerman 		printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n");
79*1965746bSMichael Ellerman 		goto out;
80*1965746bSMichael Ellerman 	}
81*1965746bSMichael Ellerman 
82*1965746bSMichael Ellerman 	hypertas = get_property(dn, "ibm,hypertas-functions", &len);
83*1965746bSMichael Ellerman 	if (hypertas == NULL)
84*1965746bSMichael Ellerman 		goto out;
85*1965746bSMichael Ellerman 
86*1965746bSMichael Ellerman 	for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
87*1965746bSMichael Ellerman 		for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
88*1965746bSMichael Ellerman 			/* check value against table of strings */
89*1965746bSMichael Ellerman 			if (!firmware_features_table[i].name ||
90*1965746bSMichael Ellerman 			    strcmp(firmware_features_table[i].name, s))
91*1965746bSMichael Ellerman 				continue;
92*1965746bSMichael Ellerman 
93*1965746bSMichael Ellerman 			/* we have a match */
94*1965746bSMichael Ellerman 			ppc64_firmware_features |=
95*1965746bSMichael Ellerman 				firmware_features_table[i].val;
96*1965746bSMichael Ellerman 			break;
97*1965746bSMichael Ellerman 		}
98*1965746bSMichael Ellerman 	}
99*1965746bSMichael Ellerman 
100*1965746bSMichael Ellerman out:
101*1965746bSMichael Ellerman 	of_node_put(dn);
102*1965746bSMichael Ellerman 	DBG(" <- fw_feature_init()\n");
103*1965746bSMichael Ellerman }
104