xref: /openbmc/linux/drivers/misc/ibmasm/ibmasm.h (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds 
31da177e4SLinus Torvalds /*
41da177e4SLinus Torvalds  * IBM ASM Service Processor Device Driver
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (C) IBM Corporation, 2004
71da177e4SLinus Torvalds  *
8d36b6910SAl Viro  * Author: Max Asböck <amax@us.ibm.com>
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/types.h>
131da177e4SLinus Torvalds #include <linux/errno.h>
141da177e4SLinus Torvalds #include <linux/list.h>
151da177e4SLinus Torvalds #include <linux/wait.h>
161da177e4SLinus Torvalds #include <linux/spinlock.h>
171da177e4SLinus Torvalds #include <linux/slab.h>
181da177e4SLinus Torvalds #include <linux/module.h>
191da177e4SLinus Torvalds #include <linux/interrupt.h>
20a045171fSGreg Kroah-Hartman #include <linux/kref.h>
211da177e4SLinus Torvalds #include <linux/device.h>
22278d72aeSMax Asbock #include <linux/input.h>
2346d83a87SAmitoj Kaur Chawla #include <linux/time64.h>
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* Driver identification */
261da177e4SLinus Torvalds #define DRIVER_NAME	"ibmasm"
27278d72aeSMax Asbock #define DRIVER_VERSION  "1.0"
28278d72aeSMax Asbock #define DRIVER_AUTHOR   "Max Asbock <masbock@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
291da177e4SLinus Torvalds #define DRIVER_DESC     "IBM ASM Service Processor Driver"
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)
321da177e4SLinus Torvalds #define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)
331da177e4SLinus Torvalds 
34278d72aeSMax Asbock extern int ibmasm_debug;
35278d72aeSMax Asbock #define dbg(STR, ARGS...)					\
36278d72aeSMax Asbock 	do {							\
37278d72aeSMax Asbock 		if (ibmasm_debug)				\
38278d72aeSMax Asbock 			printk(KERN_DEBUG STR , ##ARGS);	\
39278d72aeSMax Asbock 	} while (0)
40278d72aeSMax Asbock 
get_timestamp(char * buf)41278d72aeSMax Asbock static inline char *get_timestamp(char *buf)
42278d72aeSMax Asbock {
4346d83a87SAmitoj Kaur Chawla 	struct timespec64 now;
4446d83a87SAmitoj Kaur Chawla 
4546d83a87SAmitoj Kaur Chawla 	ktime_get_real_ts64(&now);
4646d83a87SAmitoj Kaur Chawla 	sprintf(buf, "%llu.%.08lu", (long long)now.tv_sec,
4746d83a87SAmitoj Kaur Chawla 				now.tv_nsec / NSEC_PER_USEC);
48278d72aeSMax Asbock 	return buf;
49278d72aeSMax Asbock }
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds #define IBMASM_CMD_PENDING	0
521da177e4SLinus Torvalds #define IBMASM_CMD_COMPLETE	1
531da177e4SLinus Torvalds #define IBMASM_CMD_FAILED	2
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds #define IBMASM_CMD_TIMEOUT_NORMAL	45
561da177e4SLinus Torvalds #define IBMASM_CMD_TIMEOUT_EXTRA	240
571da177e4SLinus Torvalds 
58f5ccc842SMax Asbock #define IBMASM_CMD_MAX_BUFFER_SIZE	0x8000
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds #define REVERSE_HEARTBEAT_TIMEOUT	120
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds #define HEARTBEAT_BUFFER_SIZE		0x400
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds #ifdef IA64
651da177e4SLinus Torvalds #define IBMASM_DRIVER_VPD "Lin64 6.08      "
661da177e4SLinus Torvalds #else
671da177e4SLinus Torvalds #define IBMASM_DRIVER_VPD "Lin32 6.08      "
681da177e4SLinus Torvalds #endif
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds #define SYSTEM_STATE_OS_UP      5
711da177e4SLinus Torvalds #define SYSTEM_STATE_OS_DOWN    4
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds #define IBMASM_NAME_SIZE	16
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds #define IBMASM_NUM_EVENTS	10
761da177e4SLinus Torvalds #define IBMASM_EVENT_MAX_SIZE	2048u
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds struct command {
801da177e4SLinus Torvalds 	struct list_head	queue_node;
811da177e4SLinus Torvalds 	wait_queue_head_t	wait;
821da177e4SLinus Torvalds 	unsigned char		*buffer;
831da177e4SLinus Torvalds 	size_t			buffer_size;
841da177e4SLinus Torvalds 	int			status;
85a045171fSGreg Kroah-Hartman 	struct kref		kref;
8688187605SMax Asbock 	spinlock_t		*lock;
871da177e4SLinus Torvalds };
88a045171fSGreg Kroah-Hartman #define to_command(c) container_of(c, struct command, kref)
891da177e4SLinus Torvalds 
90a045171fSGreg Kroah-Hartman void ibmasm_free_command(struct kref *kref);
command_put(struct command * cmd)911da177e4SLinus Torvalds static inline void command_put(struct command *cmd)
921da177e4SLinus Torvalds {
9388187605SMax Asbock 	unsigned long flags;
946a88231fSMax Asbock 	spinlock_t *lock = cmd->lock;
9588187605SMax Asbock 
966a88231fSMax Asbock 	spin_lock_irqsave(lock, flags);
97a045171fSGreg Kroah-Hartman 	kref_put(&cmd->kref, ibmasm_free_command);
986a88231fSMax Asbock 	spin_unlock_irqrestore(lock, flags);
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds 
command_get(struct command * cmd)1011da177e4SLinus Torvalds static inline void command_get(struct command *cmd)
1021da177e4SLinus Torvalds {
103a045171fSGreg Kroah-Hartman 	kref_get(&cmd->kref);
1041da177e4SLinus Torvalds }
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds struct ibmasm_event {
1081da177e4SLinus Torvalds 	unsigned int	serial_number;
1091da177e4SLinus Torvalds 	unsigned int	data_size;
1101da177e4SLinus Torvalds 	unsigned char	data[IBMASM_EVENT_MAX_SIZE];
1111da177e4SLinus Torvalds };
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds struct event_buffer {
1141da177e4SLinus Torvalds 	struct ibmasm_event	events[IBMASM_NUM_EVENTS];
1151da177e4SLinus Torvalds 	unsigned int		next_serial_number;
1161da177e4SLinus Torvalds 	unsigned int		next_index;
1171da177e4SLinus Torvalds 	struct list_head	readers;
1181da177e4SLinus Torvalds };
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds struct event_reader {
121b8acb808SMax Asbock 	int			cancelled;
1221da177e4SLinus Torvalds 	unsigned int		next_serial_number;
1231da177e4SLinus Torvalds 	wait_queue_head_t	wait;
1241da177e4SLinus Torvalds 	struct list_head	node;
1251da177e4SLinus Torvalds 	unsigned int		data_size;
1261da177e4SLinus Torvalds 	unsigned char		data[IBMASM_EVENT_MAX_SIZE];
1271da177e4SLinus Torvalds };
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds struct reverse_heartbeat {
1301da177e4SLinus Torvalds 	wait_queue_head_t	wait;
1311da177e4SLinus Torvalds 	unsigned int		stopped;
1321da177e4SLinus Torvalds };
1331da177e4SLinus Torvalds 
134278d72aeSMax Asbock struct ibmasm_remote {
135736ce432SVernon Mauery 	struct input_dev *keybd_dev;
136736ce432SVernon Mauery 	struct input_dev *mouse_dev;
1371da177e4SLinus Torvalds };
1381da177e4SLinus Torvalds 
1391da177e4SLinus Torvalds struct service_processor {
1401da177e4SLinus Torvalds 	struct list_head	node;
1411da177e4SLinus Torvalds 	spinlock_t		lock;
1421da177e4SLinus Torvalds 	void __iomem		*base_address;
1431da177e4SLinus Torvalds 	unsigned int		irq;
1441da177e4SLinus Torvalds 	struct command		*current_command;
1451da177e4SLinus Torvalds 	struct command		*heartbeat;
1461da177e4SLinus Torvalds 	struct list_head	command_queue;
1471da177e4SLinus Torvalds 	struct event_buffer	*event_buffer;
1481da177e4SLinus Torvalds 	char			dirname[IBMASM_NAME_SIZE];
1491da177e4SLinus Torvalds 	char			devname[IBMASM_NAME_SIZE];
1501da177e4SLinus Torvalds 	unsigned int		number;
151736ce432SVernon Mauery 	struct ibmasm_remote	remote;
1521da177e4SLinus Torvalds 	int			serial_line;
1531da177e4SLinus Torvalds 	struct device		*dev;
1541da177e4SLinus Torvalds };
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds /* command processing */
157da6b9c92SDmitry Torokhov struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
158da6b9c92SDmitry Torokhov void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
159da6b9c92SDmitry Torokhov void ibmasm_wait_for_response(struct command *cmd, int timeout);
160da6b9c92SDmitry Torokhov void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds /* event processing */
163da6b9c92SDmitry Torokhov int ibmasm_event_buffer_init(struct service_processor *sp);
164da6b9c92SDmitry Torokhov void ibmasm_event_buffer_exit(struct service_processor *sp);
165da6b9c92SDmitry Torokhov void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);
166da6b9c92SDmitry Torokhov void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
167da6b9c92SDmitry Torokhov void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
168da6b9c92SDmitry Torokhov int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
169da6b9c92SDmitry Torokhov void ibmasm_cancel_next_event(struct event_reader *reader);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /* heartbeat - from SP to OS */
172da6b9c92SDmitry Torokhov void ibmasm_register_panic_notifier(void);
173da6b9c92SDmitry Torokhov void ibmasm_unregister_panic_notifier(void);
174da6b9c92SDmitry Torokhov int ibmasm_heartbeat_init(struct service_processor *sp);
175da6b9c92SDmitry Torokhov void ibmasm_heartbeat_exit(struct service_processor *sp);
176da6b9c92SDmitry Torokhov void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds /* reverse heartbeat - from OS to SP */
179da6b9c92SDmitry Torokhov void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
180da6b9c92SDmitry Torokhov int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);
181da6b9c92SDmitry Torokhov void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);
1821da177e4SLinus Torvalds 
1831da177e4SLinus Torvalds /* dot commands */
184da6b9c92SDmitry Torokhov void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);
185da6b9c92SDmitry Torokhov int ibmasm_send_driver_vpd(struct service_processor *sp);
186da6b9c92SDmitry Torokhov int ibmasm_send_os_state(struct service_processor *sp, int os_state);
1871da177e4SLinus Torvalds 
1881da177e4SLinus Torvalds /* low level message processing */
189da6b9c92SDmitry Torokhov int ibmasm_send_i2o_message(struct service_processor *sp);
190da6b9c92SDmitry Torokhov irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds /* remote console */
193da6b9c92SDmitry Torokhov void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
194da6b9c92SDmitry Torokhov int ibmasm_init_remote_input_dev(struct service_processor *sp);
195da6b9c92SDmitry Torokhov void ibmasm_free_remote_input_dev(struct service_processor *sp);
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds /* file system */
198da6b9c92SDmitry Torokhov int ibmasmfs_register(void);
199da6b9c92SDmitry Torokhov void ibmasmfs_unregister(void);
200da6b9c92SDmitry Torokhov void ibmasmfs_add_sp(struct service_processor *sp);
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds /* uart */
203cf4f2193SMichal Marek #if IS_ENABLED(CONFIG_SERIAL_8250)
204da6b9c92SDmitry Torokhov void ibmasm_register_uart(struct service_processor *sp);
205da6b9c92SDmitry Torokhov void ibmasm_unregister_uart(struct service_processor *sp);
2061da177e4SLinus Torvalds #else
2071da177e4SLinus Torvalds #define ibmasm_register_uart(sp)	do { } while(0)
2081da177e4SLinus Torvalds #define ibmasm_unregister_uart(sp)	do { } while(0)
2091da177e4SLinus Torvalds #endif
210