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