163a19091SAlexander Graf /*
263a19091SAlexander Graf * ePAPR hcall interface
363a19091SAlexander Graf *
463a19091SAlexander Graf * Copyright 2008-2011 Freescale Semiconductor, Inc.
563a19091SAlexander Graf *
663a19091SAlexander Graf * Author: Timur Tabi <timur@freescale.com>
763a19091SAlexander Graf *
863a19091SAlexander Graf * This file is provided under a dual BSD/GPL license. When using or
963a19091SAlexander Graf * redistributing this file, you may do so under either license.
1063a19091SAlexander Graf *
1163a19091SAlexander Graf * Redistribution and use in source and binary forms, with or without
1263a19091SAlexander Graf * modification, are permitted provided that the following conditions are met:
1363a19091SAlexander Graf * * Redistributions of source code must retain the above copyright
1463a19091SAlexander Graf * notice, this list of conditions and the following disclaimer.
1563a19091SAlexander Graf * * Redistributions in binary form must reproduce the above copyright
1663a19091SAlexander Graf * notice, this list of conditions and the following disclaimer in the
1763a19091SAlexander Graf * documentation and/or other materials provided with the distribution.
1863a19091SAlexander Graf * * Neither the name of Freescale Semiconductor nor the
1963a19091SAlexander Graf * names of its contributors may be used to endorse or promote products
2063a19091SAlexander Graf * derived from this software without specific prior written permission.
2163a19091SAlexander Graf *
2263a19091SAlexander Graf *
2363a19091SAlexander Graf * ALTERNATIVELY, this software may be distributed under the terms of the
2463a19091SAlexander Graf * GNU General Public License ("GPL") as published by the Free Software
2563a19091SAlexander Graf * Foundation, either version 2 of that License or (at your option) any
2663a19091SAlexander Graf * later version.
2763a19091SAlexander Graf *
2863a19091SAlexander Graf * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
2963a19091SAlexander Graf * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3063a19091SAlexander Graf * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3163a19091SAlexander Graf * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
3263a19091SAlexander Graf * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3363a19091SAlexander Graf * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3463a19091SAlexander Graf * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3563a19091SAlexander Graf * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3663a19091SAlexander Graf * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3763a19091SAlexander Graf * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3863a19091SAlexander Graf */
3963a19091SAlexander Graf
408965aa4bSRandy Dunlap /* A "hypercall" is an "sc 1" instruction. This header file provides C
4163a19091SAlexander Graf * wrapper functions for the ePAPR hypervisor interface. It is inteded
4263a19091SAlexander Graf * for use by Linux device drivers and other operating systems.
4363a19091SAlexander Graf *
4463a19091SAlexander Graf * The hypercalls are implemented as inline assembly, rather than assembly
4563a19091SAlexander Graf * language functions in a .S file, for optimization. It allows
4663a19091SAlexander Graf * the caller to issue the hypercall instruction directly, improving both
4763a19091SAlexander Graf * performance and memory footprint.
4863a19091SAlexander Graf */
4963a19091SAlexander Graf
5063a19091SAlexander Graf #ifndef _EPAPR_HCALLS_H
5163a19091SAlexander Graf #define _EPAPR_HCALLS_H
5263a19091SAlexander Graf
5363a19091SAlexander Graf #include <uapi/asm/epapr_hcalls.h>
5463a19091SAlexander Graf
5563a19091SAlexander Graf #ifndef __ASSEMBLY__
5663a19091SAlexander Graf #include <linux/types.h>
5763a19091SAlexander Graf #include <linux/errno.h>
5863a19091SAlexander Graf #include <asm/byteorder.h>
5963a19091SAlexander Graf
6063a19091SAlexander Graf /*
6163a19091SAlexander Graf * Hypercall register clobber list
6263a19091SAlexander Graf *
6363a19091SAlexander Graf * These macros are used to define the list of clobbered registers during a
6463a19091SAlexander Graf * hypercall. Technically, registers r0 and r3-r12 are always clobbered,
6563a19091SAlexander Graf * but the gcc inline assembly syntax does not allow us to specify registers
6663a19091SAlexander Graf * on the clobber list that are also on the input/output list. Therefore,
6763a19091SAlexander Graf * the lists of clobbered registers depends on the number of register
68*a1c41409SBhaskar Chowdhury * parameters ("+r" and "=r") passed to the hypercall.
6963a19091SAlexander Graf *
7063a19091SAlexander Graf * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a
7163a19091SAlexander Graf * general rule, 'x' is the number of parameters passed to the assembly
7263a19091SAlexander Graf * block *except* for r11.
7363a19091SAlexander Graf *
7463a19091SAlexander Graf * If you're not sure, just use the smallest value of 'x' that does not
7563a19091SAlexander Graf * generate a compilation error. Because these are static inline functions,
7663a19091SAlexander Graf * the compiler will only check the clobber list for a function if you
7763a19091SAlexander Graf * compile code that calls that function.
7863a19091SAlexander Graf *
7963a19091SAlexander Graf * r3 and r11 are not included in any clobbers list because they are always
8063a19091SAlexander Graf * listed as output registers.
8163a19091SAlexander Graf *
8263a19091SAlexander Graf * XER, CTR, and LR are currently listed as clobbers because it's uncertain
8363a19091SAlexander Graf * whether they will be clobbered.
8463a19091SAlexander Graf *
8563a19091SAlexander Graf * Note that r11 can be used as an output parameter.
8663a19091SAlexander Graf *
8763a19091SAlexander Graf * The "memory" clobber is only necessary for hcalls where the Hypervisor
8863a19091SAlexander Graf * will read or write guest memory. However, we add it to all hcalls because
8963a19091SAlexander Graf * the impact is minimal, and we want to ensure that it's present for the
9063a19091SAlexander Graf * hcalls that need it.
9163a19091SAlexander Graf */
9263a19091SAlexander Graf
9363a19091SAlexander Graf /* List of common clobbered registers. Do not use this macro. */
9463a19091SAlexander Graf #define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory"
9563a19091SAlexander Graf
9663a19091SAlexander Graf #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
9763a19091SAlexander Graf #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
9863a19091SAlexander Graf #define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9"
9963a19091SAlexander Graf #define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8"
10063a19091SAlexander Graf #define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7"
10163a19091SAlexander Graf #define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6"
10263a19091SAlexander Graf #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
10363a19091SAlexander Graf #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
10463a19091SAlexander Graf
10563a19091SAlexander Graf extern bool epapr_paravirt_enabled;
10663a19091SAlexander Graf extern u32 epapr_hypercall_start[];
10763a19091SAlexander Graf
1084e21b94cSLaurentiu TUDOR #ifdef CONFIG_EPAPR_PARAVIRT
1094e21b94cSLaurentiu TUDOR int __init epapr_paravirt_early_init(void);
1104e21b94cSLaurentiu TUDOR #else
epapr_paravirt_early_init(void)1114e21b94cSLaurentiu TUDOR static inline int epapr_paravirt_early_init(void) { return 0; }
1124e21b94cSLaurentiu TUDOR #endif
1134e21b94cSLaurentiu TUDOR
11463a19091SAlexander Graf /*
11563a19091SAlexander Graf * We use "uintptr_t" to define a register because it's guaranteed to be a
11663a19091SAlexander Graf * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
11763a19091SAlexander Graf * platform.
11863a19091SAlexander Graf *
11963a19091SAlexander Graf * All registers are either input/output or output only. Registers that are
12063a19091SAlexander Graf * initialized before making the hypercall are input/output. All
12163a19091SAlexander Graf * input/output registers are represented with "+r". Output-only registers
12263a19091SAlexander Graf * are represented with "=r". Do not specify any unused registers. The
12363a19091SAlexander Graf * clobber list will tell the compiler that the hypercall modifies those
12463a19091SAlexander Graf * registers, which is good enough.
12563a19091SAlexander Graf */
12663a19091SAlexander Graf
12763a19091SAlexander Graf /**
12863a19091SAlexander Graf * ev_int_set_config - configure the specified interrupt
12963a19091SAlexander Graf * @interrupt: the interrupt number
13063a19091SAlexander Graf * @config: configuration for this interrupt
13163a19091SAlexander Graf * @priority: interrupt priority
13263a19091SAlexander Graf * @destination: destination CPU number
13363a19091SAlexander Graf *
13463a19091SAlexander Graf * Returns 0 for success, or an error code.
13563a19091SAlexander Graf */
ev_int_set_config(unsigned int interrupt,uint32_t config,unsigned int priority,uint32_t destination)13663a19091SAlexander Graf static inline unsigned int ev_int_set_config(unsigned int interrupt,
13763a19091SAlexander Graf uint32_t config, unsigned int priority, uint32_t destination)
13863a19091SAlexander Graf {
13963a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
14063a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
14163a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
14263a19091SAlexander Graf register uintptr_t r5 __asm__("r5");
14363a19091SAlexander Graf register uintptr_t r6 __asm__("r6");
14463a19091SAlexander Graf
14563a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
14663a19091SAlexander Graf r3 = interrupt;
14763a19091SAlexander Graf r4 = config;
14863a19091SAlexander Graf r5 = priority;
14963a19091SAlexander Graf r6 = destination;
15063a19091SAlexander Graf
15163a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
15263a19091SAlexander Graf : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
15363a19091SAlexander Graf : : EV_HCALL_CLOBBERS4
15463a19091SAlexander Graf );
15563a19091SAlexander Graf
15663a19091SAlexander Graf return r3;
15763a19091SAlexander Graf }
15863a19091SAlexander Graf
15963a19091SAlexander Graf /**
16063a19091SAlexander Graf * ev_int_get_config - return the config of the specified interrupt
16163a19091SAlexander Graf * @interrupt: the interrupt number
16263a19091SAlexander Graf * @config: returned configuration for this interrupt
16363a19091SAlexander Graf * @priority: returned interrupt priority
16463a19091SAlexander Graf * @destination: returned destination CPU number
16563a19091SAlexander Graf *
16663a19091SAlexander Graf * Returns 0 for success, or an error code.
16763a19091SAlexander Graf */
ev_int_get_config(unsigned int interrupt,uint32_t * config,unsigned int * priority,uint32_t * destination)16863a19091SAlexander Graf static inline unsigned int ev_int_get_config(unsigned int interrupt,
16963a19091SAlexander Graf uint32_t *config, unsigned int *priority, uint32_t *destination)
17063a19091SAlexander Graf {
17163a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
17263a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
17363a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
17463a19091SAlexander Graf register uintptr_t r5 __asm__("r5");
17563a19091SAlexander Graf register uintptr_t r6 __asm__("r6");
17663a19091SAlexander Graf
17763a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
17863a19091SAlexander Graf r3 = interrupt;
17963a19091SAlexander Graf
18063a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
18163a19091SAlexander Graf : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
18263a19091SAlexander Graf : : EV_HCALL_CLOBBERS4
18363a19091SAlexander Graf );
18463a19091SAlexander Graf
18563a19091SAlexander Graf *config = r4;
18663a19091SAlexander Graf *priority = r5;
18763a19091SAlexander Graf *destination = r6;
18863a19091SAlexander Graf
18963a19091SAlexander Graf return r3;
19063a19091SAlexander Graf }
19163a19091SAlexander Graf
19263a19091SAlexander Graf /**
19363a19091SAlexander Graf * ev_int_set_mask - sets the mask for the specified interrupt source
19463a19091SAlexander Graf * @interrupt: the interrupt number
19563a19091SAlexander Graf * @mask: 0=enable interrupts, 1=disable interrupts
19663a19091SAlexander Graf *
19763a19091SAlexander Graf * Returns 0 for success, or an error code.
19863a19091SAlexander Graf */
ev_int_set_mask(unsigned int interrupt,unsigned int mask)19963a19091SAlexander Graf static inline unsigned int ev_int_set_mask(unsigned int interrupt,
20063a19091SAlexander Graf unsigned int mask)
20163a19091SAlexander Graf {
20263a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
20363a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
20463a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
20563a19091SAlexander Graf
20663a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
20763a19091SAlexander Graf r3 = interrupt;
20863a19091SAlexander Graf r4 = mask;
20963a19091SAlexander Graf
21063a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
21163a19091SAlexander Graf : "+r" (r11), "+r" (r3), "+r" (r4)
21263a19091SAlexander Graf : : EV_HCALL_CLOBBERS2
21363a19091SAlexander Graf );
21463a19091SAlexander Graf
21563a19091SAlexander Graf return r3;
21663a19091SAlexander Graf }
21763a19091SAlexander Graf
21863a19091SAlexander Graf /**
21963a19091SAlexander Graf * ev_int_get_mask - returns the mask for the specified interrupt source
22063a19091SAlexander Graf * @interrupt: the interrupt number
22163a19091SAlexander Graf * @mask: returned mask for this interrupt (0=enabled, 1=disabled)
22263a19091SAlexander Graf *
22363a19091SAlexander Graf * Returns 0 for success, or an error code.
22463a19091SAlexander Graf */
ev_int_get_mask(unsigned int interrupt,unsigned int * mask)22563a19091SAlexander Graf static inline unsigned int ev_int_get_mask(unsigned int interrupt,
22663a19091SAlexander Graf unsigned int *mask)
22763a19091SAlexander Graf {
22863a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
22963a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
23063a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
23163a19091SAlexander Graf
23263a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
23363a19091SAlexander Graf r3 = interrupt;
23463a19091SAlexander Graf
23563a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
23663a19091SAlexander Graf : "+r" (r11), "+r" (r3), "=r" (r4)
23763a19091SAlexander Graf : : EV_HCALL_CLOBBERS2
23863a19091SAlexander Graf );
23963a19091SAlexander Graf
24063a19091SAlexander Graf *mask = r4;
24163a19091SAlexander Graf
24263a19091SAlexander Graf return r3;
24363a19091SAlexander Graf }
24463a19091SAlexander Graf
24563a19091SAlexander Graf /**
24663a19091SAlexander Graf * ev_int_eoi - signal the end of interrupt processing
24763a19091SAlexander Graf * @interrupt: the interrupt number
24863a19091SAlexander Graf *
2498965aa4bSRandy Dunlap * This function signals the end of processing for the specified
25063a19091SAlexander Graf * interrupt, which must be the interrupt currently in service. By
25163a19091SAlexander Graf * definition, this is also the highest-priority interrupt.
25263a19091SAlexander Graf *
25363a19091SAlexander Graf * Returns 0 for success, or an error code.
25463a19091SAlexander Graf */
ev_int_eoi(unsigned int interrupt)25563a19091SAlexander Graf static inline unsigned int ev_int_eoi(unsigned int interrupt)
25663a19091SAlexander Graf {
25763a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
25863a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
25963a19091SAlexander Graf
26063a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_EOI);
26163a19091SAlexander Graf r3 = interrupt;
26263a19091SAlexander Graf
26363a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
26463a19091SAlexander Graf : "+r" (r11), "+r" (r3)
26563a19091SAlexander Graf : : EV_HCALL_CLOBBERS1
26663a19091SAlexander Graf );
26763a19091SAlexander Graf
26863a19091SAlexander Graf return r3;
26963a19091SAlexander Graf }
27063a19091SAlexander Graf
27163a19091SAlexander Graf /**
27263a19091SAlexander Graf * ev_byte_channel_send - send characters to a byte stream
27363a19091SAlexander Graf * @handle: byte stream handle
27463a19091SAlexander Graf * @count: (input) num of chars to send, (output) num chars sent
27563a19091SAlexander Graf * @buffer: pointer to a 16-byte buffer
27663a19091SAlexander Graf *
27763a19091SAlexander Graf * @buffer must be at least 16 bytes long, because all 16 bytes will be
27863a19091SAlexander Graf * read from memory into registers, even if count < 16.
27963a19091SAlexander Graf *
28063a19091SAlexander Graf * Returns 0 for success, or an error code.
28163a19091SAlexander Graf */
ev_byte_channel_send(unsigned int handle,unsigned int * count,const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])28263a19091SAlexander Graf static inline unsigned int ev_byte_channel_send(unsigned int handle,
28363a19091SAlexander Graf unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
28463a19091SAlexander Graf {
28563a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
28663a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
28763a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
28863a19091SAlexander Graf register uintptr_t r5 __asm__("r5");
28963a19091SAlexander Graf register uintptr_t r6 __asm__("r6");
29063a19091SAlexander Graf register uintptr_t r7 __asm__("r7");
29163a19091SAlexander Graf register uintptr_t r8 __asm__("r8");
29263a19091SAlexander Graf const uint32_t *p = (const uint32_t *) buffer;
29363a19091SAlexander Graf
29463a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
29563a19091SAlexander Graf r3 = handle;
29663a19091SAlexander Graf r4 = *count;
29763a19091SAlexander Graf r5 = be32_to_cpu(p[0]);
29863a19091SAlexander Graf r6 = be32_to_cpu(p[1]);
29963a19091SAlexander Graf r7 = be32_to_cpu(p[2]);
30063a19091SAlexander Graf r8 = be32_to_cpu(p[3]);
30163a19091SAlexander Graf
30263a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
30363a19091SAlexander Graf : "+r" (r11), "+r" (r3),
30463a19091SAlexander Graf "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
30563a19091SAlexander Graf : : EV_HCALL_CLOBBERS6
30663a19091SAlexander Graf );
30763a19091SAlexander Graf
30863a19091SAlexander Graf *count = r4;
30963a19091SAlexander Graf
31063a19091SAlexander Graf return r3;
31163a19091SAlexander Graf }
31263a19091SAlexander Graf
31363a19091SAlexander Graf /**
31463a19091SAlexander Graf * ev_byte_channel_receive - fetch characters from a byte channel
31563a19091SAlexander Graf * @handle: byte channel handle
31663a19091SAlexander Graf * @count: (input) max num of chars to receive, (output) num chars received
31763a19091SAlexander Graf * @buffer: pointer to a 16-byte buffer
31863a19091SAlexander Graf *
31963a19091SAlexander Graf * The size of @buffer must be at least 16 bytes, even if you request fewer
32063a19091SAlexander Graf * than 16 characters, because we always write 16 bytes to @buffer. This is
32163a19091SAlexander Graf * for performance reasons.
32263a19091SAlexander Graf *
32363a19091SAlexander Graf * Returns 0 for success, or an error code.
32463a19091SAlexander Graf */
ev_byte_channel_receive(unsigned int handle,unsigned int * count,char buffer[EV_BYTE_CHANNEL_MAX_BYTES])32563a19091SAlexander Graf static inline unsigned int ev_byte_channel_receive(unsigned int handle,
32663a19091SAlexander Graf unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
32763a19091SAlexander Graf {
32863a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
32963a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
33063a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
33163a19091SAlexander Graf register uintptr_t r5 __asm__("r5");
33263a19091SAlexander Graf register uintptr_t r6 __asm__("r6");
33363a19091SAlexander Graf register uintptr_t r7 __asm__("r7");
33463a19091SAlexander Graf register uintptr_t r8 __asm__("r8");
33563a19091SAlexander Graf uint32_t *p = (uint32_t *) buffer;
33663a19091SAlexander Graf
33763a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
33863a19091SAlexander Graf r3 = handle;
33963a19091SAlexander Graf r4 = *count;
34063a19091SAlexander Graf
34163a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
34263a19091SAlexander Graf : "+r" (r11), "+r" (r3), "+r" (r4),
34363a19091SAlexander Graf "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
34463a19091SAlexander Graf : : EV_HCALL_CLOBBERS6
34563a19091SAlexander Graf );
34663a19091SAlexander Graf
34763a19091SAlexander Graf *count = r4;
34863a19091SAlexander Graf p[0] = cpu_to_be32(r5);
34963a19091SAlexander Graf p[1] = cpu_to_be32(r6);
35063a19091SAlexander Graf p[2] = cpu_to_be32(r7);
35163a19091SAlexander Graf p[3] = cpu_to_be32(r8);
35263a19091SAlexander Graf
35363a19091SAlexander Graf return r3;
35463a19091SAlexander Graf }
35563a19091SAlexander Graf
35663a19091SAlexander Graf /**
35763a19091SAlexander Graf * ev_byte_channel_poll - returns the status of the byte channel buffers
35863a19091SAlexander Graf * @handle: byte channel handle
35963a19091SAlexander Graf * @rx_count: returned count of bytes in receive queue
36063a19091SAlexander Graf * @tx_count: returned count of free space in transmit queue
36163a19091SAlexander Graf *
36263a19091SAlexander Graf * This function reports the amount of data in the receive queue (i.e. the
36363a19091SAlexander Graf * number of bytes you can read), and the amount of free space in the transmit
36463a19091SAlexander Graf * queue (i.e. the number of bytes you can write).
36563a19091SAlexander Graf *
36663a19091SAlexander Graf * Returns 0 for success, or an error code.
36763a19091SAlexander Graf */
ev_byte_channel_poll(unsigned int handle,unsigned int * rx_count,unsigned int * tx_count)36863a19091SAlexander Graf static inline unsigned int ev_byte_channel_poll(unsigned int handle,
36963a19091SAlexander Graf unsigned int *rx_count, unsigned int *tx_count)
37063a19091SAlexander Graf {
37163a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
37263a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
37363a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
37463a19091SAlexander Graf register uintptr_t r5 __asm__("r5");
37563a19091SAlexander Graf
37663a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
37763a19091SAlexander Graf r3 = handle;
37863a19091SAlexander Graf
37963a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
38063a19091SAlexander Graf : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
38163a19091SAlexander Graf : : EV_HCALL_CLOBBERS3
38263a19091SAlexander Graf );
38363a19091SAlexander Graf
38463a19091SAlexander Graf *rx_count = r4;
38563a19091SAlexander Graf *tx_count = r5;
38663a19091SAlexander Graf
38763a19091SAlexander Graf return r3;
38863a19091SAlexander Graf }
38963a19091SAlexander Graf
39063a19091SAlexander Graf /**
39163a19091SAlexander Graf * ev_int_iack - acknowledge an interrupt
39263a19091SAlexander Graf * @handle: handle to the target interrupt controller
39363a19091SAlexander Graf * @vector: returned interrupt vector
39463a19091SAlexander Graf *
39563a19091SAlexander Graf * If handle is zero, the function returns the next interrupt source
39663a19091SAlexander Graf * number to be handled irrespective of the hierarchy or cascading
39763a19091SAlexander Graf * of interrupt controllers. If non-zero, specifies a handle to the
39863a19091SAlexander Graf * interrupt controller that is the target of the acknowledge.
39963a19091SAlexander Graf *
40063a19091SAlexander Graf * Returns 0 for success, or an error code.
40163a19091SAlexander Graf */
ev_int_iack(unsigned int handle,unsigned int * vector)40263a19091SAlexander Graf static inline unsigned int ev_int_iack(unsigned int handle,
40363a19091SAlexander Graf unsigned int *vector)
40463a19091SAlexander Graf {
40563a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
40663a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
40763a19091SAlexander Graf register uintptr_t r4 __asm__("r4");
40863a19091SAlexander Graf
40963a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_INT_IACK);
41063a19091SAlexander Graf r3 = handle;
41163a19091SAlexander Graf
41263a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
41363a19091SAlexander Graf : "+r" (r11), "+r" (r3), "=r" (r4)
41463a19091SAlexander Graf : : EV_HCALL_CLOBBERS2
41563a19091SAlexander Graf );
41663a19091SAlexander Graf
41763a19091SAlexander Graf *vector = r4;
41863a19091SAlexander Graf
41963a19091SAlexander Graf return r3;
42063a19091SAlexander Graf }
42163a19091SAlexander Graf
42263a19091SAlexander Graf /**
42363a19091SAlexander Graf * ev_doorbell_send - send a doorbell to another partition
42463a19091SAlexander Graf * @handle: doorbell send handle
42563a19091SAlexander Graf *
42663a19091SAlexander Graf * Returns 0 for success, or an error code.
42763a19091SAlexander Graf */
ev_doorbell_send(unsigned int handle)42863a19091SAlexander Graf static inline unsigned int ev_doorbell_send(unsigned int handle)
42963a19091SAlexander Graf {
43063a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
43163a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
43263a19091SAlexander Graf
43363a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
43463a19091SAlexander Graf r3 = handle;
43563a19091SAlexander Graf
43663a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
43763a19091SAlexander Graf : "+r" (r11), "+r" (r3)
43863a19091SAlexander Graf : : EV_HCALL_CLOBBERS1
43963a19091SAlexander Graf );
44063a19091SAlexander Graf
44163a19091SAlexander Graf return r3;
44263a19091SAlexander Graf }
44363a19091SAlexander Graf
44463a19091SAlexander Graf /**
44563a19091SAlexander Graf * ev_idle -- wait for next interrupt on this core
44663a19091SAlexander Graf *
44763a19091SAlexander Graf * Returns 0 for success, or an error code.
44863a19091SAlexander Graf */
ev_idle(void)44963a19091SAlexander Graf static inline unsigned int ev_idle(void)
45063a19091SAlexander Graf {
45163a19091SAlexander Graf register uintptr_t r11 __asm__("r11");
45263a19091SAlexander Graf register uintptr_t r3 __asm__("r3");
45363a19091SAlexander Graf
45463a19091SAlexander Graf r11 = EV_HCALL_TOKEN(EV_IDLE);
45563a19091SAlexander Graf
45663a19091SAlexander Graf asm volatile("bl epapr_hypercall_start"
45763a19091SAlexander Graf : "+r" (r11), "=r" (r3)
45863a19091SAlexander Graf : : EV_HCALL_CLOBBERS1
45963a19091SAlexander Graf );
46063a19091SAlexander Graf
46163a19091SAlexander Graf return r3;
46263a19091SAlexander Graf }
4631820a8d2SBharat Bhushan
4641820a8d2SBharat Bhushan #ifdef CONFIG_EPAPR_PARAVIRT
epapr_hypercall(unsigned long * in,unsigned long * out,unsigned long nr)4651820a8d2SBharat Bhushan static inline unsigned long epapr_hypercall(unsigned long *in,
4661820a8d2SBharat Bhushan unsigned long *out,
4671820a8d2SBharat Bhushan unsigned long nr)
4681820a8d2SBharat Bhushan {
46965e13c20SMathieu Malaterre register unsigned long r0 asm("r0");
47065e13c20SMathieu Malaterre register unsigned long r3 asm("r3") = in[0];
47165e13c20SMathieu Malaterre register unsigned long r4 asm("r4") = in[1];
47265e13c20SMathieu Malaterre register unsigned long r5 asm("r5") = in[2];
47365e13c20SMathieu Malaterre register unsigned long r6 asm("r6") = in[3];
47465e13c20SMathieu Malaterre register unsigned long r7 asm("r7") = in[4];
47565e13c20SMathieu Malaterre register unsigned long r8 asm("r8") = in[5];
47665e13c20SMathieu Malaterre register unsigned long r9 asm("r9") = in[6];
47765e13c20SMathieu Malaterre register unsigned long r10 asm("r10") = in[7];
47865e13c20SMathieu Malaterre register unsigned long r11 asm("r11") = nr;
47965e13c20SMathieu Malaterre register unsigned long r12 asm("r12");
4801820a8d2SBharat Bhushan
4811820a8d2SBharat Bhushan asm volatile("bl epapr_hypercall_start"
4821820a8d2SBharat Bhushan : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6),
4831820a8d2SBharat Bhushan "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11),
4841820a8d2SBharat Bhushan "=r"(r12)
4851820a8d2SBharat Bhushan : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8),
4861820a8d2SBharat Bhushan "r"(r9), "r"(r10), "r"(r11)
4871820a8d2SBharat Bhushan : "memory", "cc", "xer", "ctr", "lr");
4881820a8d2SBharat Bhushan
4891820a8d2SBharat Bhushan out[0] = r4;
4901820a8d2SBharat Bhushan out[1] = r5;
4911820a8d2SBharat Bhushan out[2] = r6;
4921820a8d2SBharat Bhushan out[3] = r7;
4931820a8d2SBharat Bhushan out[4] = r8;
4941820a8d2SBharat Bhushan out[5] = r9;
4951820a8d2SBharat Bhushan out[6] = r10;
4961820a8d2SBharat Bhushan out[7] = r11;
4971820a8d2SBharat Bhushan
4981820a8d2SBharat Bhushan return r3;
4991820a8d2SBharat Bhushan }
5001820a8d2SBharat Bhushan #else
epapr_hypercall(unsigned long * in,unsigned long * out,unsigned long nr)5011820a8d2SBharat Bhushan static unsigned long epapr_hypercall(unsigned long *in,
5021820a8d2SBharat Bhushan unsigned long *out,
5031820a8d2SBharat Bhushan unsigned long nr)
5041820a8d2SBharat Bhushan {
5051820a8d2SBharat Bhushan return EV_UNIMPLEMENTED;
5061820a8d2SBharat Bhushan }
5071820a8d2SBharat Bhushan #endif
5081820a8d2SBharat Bhushan
epapr_hypercall0_1(unsigned int nr,unsigned long * r2)509b1f0d94cSBharat Bhushan static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2)
510b1f0d94cSBharat Bhushan {
511186b8f15SSeth Forshee unsigned long in[8] = {0};
512b1f0d94cSBharat Bhushan unsigned long out[8];
513b1f0d94cSBharat Bhushan unsigned long r;
514b1f0d94cSBharat Bhushan
515b1f0d94cSBharat Bhushan r = epapr_hypercall(in, out, nr);
516b1f0d94cSBharat Bhushan *r2 = out[0];
517b1f0d94cSBharat Bhushan
518b1f0d94cSBharat Bhushan return r;
519b1f0d94cSBharat Bhushan }
520b1f0d94cSBharat Bhushan
epapr_hypercall0(unsigned int nr)521b1f0d94cSBharat Bhushan static inline long epapr_hypercall0(unsigned int nr)
522b1f0d94cSBharat Bhushan {
523186b8f15SSeth Forshee unsigned long in[8] = {0};
524b1f0d94cSBharat Bhushan unsigned long out[8];
525b1f0d94cSBharat Bhushan
526b1f0d94cSBharat Bhushan return epapr_hypercall(in, out, nr);
527b1f0d94cSBharat Bhushan }
528b1f0d94cSBharat Bhushan
epapr_hypercall1(unsigned int nr,unsigned long p1)529b1f0d94cSBharat Bhushan static inline long epapr_hypercall1(unsigned int nr, unsigned long p1)
530b1f0d94cSBharat Bhushan {
531186b8f15SSeth Forshee unsigned long in[8] = {0};
532b1f0d94cSBharat Bhushan unsigned long out[8];
533b1f0d94cSBharat Bhushan
534b1f0d94cSBharat Bhushan in[0] = p1;
535b1f0d94cSBharat Bhushan return epapr_hypercall(in, out, nr);
536b1f0d94cSBharat Bhushan }
537b1f0d94cSBharat Bhushan
epapr_hypercall2(unsigned int nr,unsigned long p1,unsigned long p2)538b1f0d94cSBharat Bhushan static inline long epapr_hypercall2(unsigned int nr, unsigned long p1,
539b1f0d94cSBharat Bhushan unsigned long p2)
540b1f0d94cSBharat Bhushan {
541186b8f15SSeth Forshee unsigned long in[8] = {0};
542b1f0d94cSBharat Bhushan unsigned long out[8];
543b1f0d94cSBharat Bhushan
544b1f0d94cSBharat Bhushan in[0] = p1;
545b1f0d94cSBharat Bhushan in[1] = p2;
546b1f0d94cSBharat Bhushan return epapr_hypercall(in, out, nr);
547b1f0d94cSBharat Bhushan }
548b1f0d94cSBharat Bhushan
epapr_hypercall3(unsigned int nr,unsigned long p1,unsigned long p2,unsigned long p3)549b1f0d94cSBharat Bhushan static inline long epapr_hypercall3(unsigned int nr, unsigned long p1,
550b1f0d94cSBharat Bhushan unsigned long p2, unsigned long p3)
551b1f0d94cSBharat Bhushan {
552186b8f15SSeth Forshee unsigned long in[8] = {0};
553b1f0d94cSBharat Bhushan unsigned long out[8];
554b1f0d94cSBharat Bhushan
555b1f0d94cSBharat Bhushan in[0] = p1;
556b1f0d94cSBharat Bhushan in[1] = p2;
557b1f0d94cSBharat Bhushan in[2] = p3;
558b1f0d94cSBharat Bhushan return epapr_hypercall(in, out, nr);
559b1f0d94cSBharat Bhushan }
560b1f0d94cSBharat Bhushan
epapr_hypercall4(unsigned int nr,unsigned long p1,unsigned long p2,unsigned long p3,unsigned long p4)561b1f0d94cSBharat Bhushan static inline long epapr_hypercall4(unsigned int nr, unsigned long p1,
562b1f0d94cSBharat Bhushan unsigned long p2, unsigned long p3,
563b1f0d94cSBharat Bhushan unsigned long p4)
564b1f0d94cSBharat Bhushan {
565186b8f15SSeth Forshee unsigned long in[8] = {0};
566b1f0d94cSBharat Bhushan unsigned long out[8];
567b1f0d94cSBharat Bhushan
568b1f0d94cSBharat Bhushan in[0] = p1;
569b1f0d94cSBharat Bhushan in[1] = p2;
570b1f0d94cSBharat Bhushan in[2] = p3;
571b1f0d94cSBharat Bhushan in[3] = p4;
572b1f0d94cSBharat Bhushan return epapr_hypercall(in, out, nr);
573b1f0d94cSBharat Bhushan }
57463a19091SAlexander Graf #endif /* !__ASSEMBLY__ */
57563a19091SAlexander Graf #endif /* _EPAPR_HCALLS_H */
576