xref: /openbmc/linux/drivers/char/ipmi/kcs_bmc.h (revision 20d60f61)
120d60f61SHaiyue Wang // SPDX-License-Identifier: GPL-2.0
220d60f61SHaiyue Wang // Copyright (c) 2015-2018, Intel Corporation.
320d60f61SHaiyue Wang 
420d60f61SHaiyue Wang #ifndef __KCS_BMC_H__
520d60f61SHaiyue Wang #define __KCS_BMC_H__
620d60f61SHaiyue Wang 
720d60f61SHaiyue Wang #include <linux/miscdevice.h>
820d60f61SHaiyue Wang 
920d60f61SHaiyue Wang /* Different phases of the KCS BMC module :
1020d60f61SHaiyue Wang  *  KCS_PHASE_IDLE :
1120d60f61SHaiyue Wang  *            BMC should not be expecting nor sending any data.
1220d60f61SHaiyue Wang  *  KCS_PHASE_WRITE_START :
1320d60f61SHaiyue Wang  *            BMC is receiving a WRITE_START command from system software.
1420d60f61SHaiyue Wang  *  KCS_PHASE_WRITE_DATA :
1520d60f61SHaiyue Wang  *            BMC is receiving a data byte from system software.
1620d60f61SHaiyue Wang  *  KCS_PHASE_WRITE_END_CMD :
1720d60f61SHaiyue Wang  *            BMC is waiting a last data byte from system software.
1820d60f61SHaiyue Wang  *  KCS_PHASE_WRITE_DONE :
1920d60f61SHaiyue Wang  *            BMC has received the whole request from system software.
2020d60f61SHaiyue Wang  *  KCS_PHASE_WAIT_READ :
2120d60f61SHaiyue Wang  *            BMC is waiting the response from the upper IPMI service.
2220d60f61SHaiyue Wang  *  KCS_PHASE_READ :
2320d60f61SHaiyue Wang  *            BMC is transferring the response to system software.
2420d60f61SHaiyue Wang  *  KCS_PHASE_ABORT_ERROR1 :
2520d60f61SHaiyue Wang  *            BMC is waiting error status request from system software.
2620d60f61SHaiyue Wang  *  KCS_PHASE_ABORT_ERROR2 :
2720d60f61SHaiyue Wang  *            BMC is waiting for idle status afer error from system software.
2820d60f61SHaiyue Wang  *  KCS_PHASE_ERROR :
2920d60f61SHaiyue Wang  *            BMC has detected a protocol violation at the interface level.
3020d60f61SHaiyue Wang  */
3120d60f61SHaiyue Wang enum kcs_phases {
3220d60f61SHaiyue Wang 	KCS_PHASE_IDLE,
3320d60f61SHaiyue Wang 
3420d60f61SHaiyue Wang 	KCS_PHASE_WRITE_START,
3520d60f61SHaiyue Wang 	KCS_PHASE_WRITE_DATA,
3620d60f61SHaiyue Wang 	KCS_PHASE_WRITE_END_CMD,
3720d60f61SHaiyue Wang 	KCS_PHASE_WRITE_DONE,
3820d60f61SHaiyue Wang 
3920d60f61SHaiyue Wang 	KCS_PHASE_WAIT_READ,
4020d60f61SHaiyue Wang 	KCS_PHASE_READ,
4120d60f61SHaiyue Wang 
4220d60f61SHaiyue Wang 	KCS_PHASE_ABORT_ERROR1,
4320d60f61SHaiyue Wang 	KCS_PHASE_ABORT_ERROR2,
4420d60f61SHaiyue Wang 	KCS_PHASE_ERROR
4520d60f61SHaiyue Wang };
4620d60f61SHaiyue Wang 
4720d60f61SHaiyue Wang /* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */
4820d60f61SHaiyue Wang enum kcs_errors {
4920d60f61SHaiyue Wang 	KCS_NO_ERROR                = 0x00,
5020d60f61SHaiyue Wang 	KCS_ABORTED_BY_COMMAND      = 0x01,
5120d60f61SHaiyue Wang 	KCS_ILLEGAL_CONTROL_CODE    = 0x02,
5220d60f61SHaiyue Wang 	KCS_LENGTH_ERROR            = 0x06,
5320d60f61SHaiyue Wang 	KCS_UNSPECIFIED_ERROR       = 0xFF
5420d60f61SHaiyue Wang };
5520d60f61SHaiyue Wang 
5620d60f61SHaiyue Wang /* IPMI 2.0 - 9.5, KCS Interface Registers
5720d60f61SHaiyue Wang  * @idr : Input Data Register
5820d60f61SHaiyue Wang  * @odr : Output Data Register
5920d60f61SHaiyue Wang  * @str : Status Register
6020d60f61SHaiyue Wang  */
6120d60f61SHaiyue Wang struct kcs_ioreg {
6220d60f61SHaiyue Wang 	u32 idr;
6320d60f61SHaiyue Wang 	u32 odr;
6420d60f61SHaiyue Wang 	u32 str;
6520d60f61SHaiyue Wang };
6620d60f61SHaiyue Wang 
6720d60f61SHaiyue Wang struct kcs_bmc {
6820d60f61SHaiyue Wang 	spinlock_t lock;
6920d60f61SHaiyue Wang 
7020d60f61SHaiyue Wang 	u32 channel;
7120d60f61SHaiyue Wang 	int running;
7220d60f61SHaiyue Wang 
7320d60f61SHaiyue Wang 	/* Setup by BMC KCS controller driver */
7420d60f61SHaiyue Wang 	struct kcs_ioreg ioreg;
7520d60f61SHaiyue Wang 	u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg);
7620d60f61SHaiyue Wang 	void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b);
7720d60f61SHaiyue Wang 
7820d60f61SHaiyue Wang 	enum kcs_phases phase;
7920d60f61SHaiyue Wang 	enum kcs_errors error;
8020d60f61SHaiyue Wang 
8120d60f61SHaiyue Wang 	wait_queue_head_t queue;
8220d60f61SHaiyue Wang 	bool data_in_avail;
8320d60f61SHaiyue Wang 	int  data_in_idx;
8420d60f61SHaiyue Wang 	u8  *data_in;
8520d60f61SHaiyue Wang 
8620d60f61SHaiyue Wang 	int  data_out_idx;
8720d60f61SHaiyue Wang 	int  data_out_len;
8820d60f61SHaiyue Wang 	u8  *data_out;
8920d60f61SHaiyue Wang 
9020d60f61SHaiyue Wang 	struct mutex mutex;
9120d60f61SHaiyue Wang 	u8 *kbuffer;
9220d60f61SHaiyue Wang 
9320d60f61SHaiyue Wang 	struct miscdevice miscdev;
9420d60f61SHaiyue Wang 
9520d60f61SHaiyue Wang 	unsigned long priv[];
9620d60f61SHaiyue Wang };
9720d60f61SHaiyue Wang 
9820d60f61SHaiyue Wang static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc)
9920d60f61SHaiyue Wang {
10020d60f61SHaiyue Wang 	return kcs_bmc->priv;
10120d60f61SHaiyue Wang }
10220d60f61SHaiyue Wang 
10320d60f61SHaiyue Wang int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc);
10420d60f61SHaiyue Wang struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv,
10520d60f61SHaiyue Wang 					u32 channel);
10620d60f61SHaiyue Wang #endif
107