18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2015-2018, Intel Corporation.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef __KCS_BMC_H__
78c2ecf20Sopenharmony_ci#define __KCS_BMC_H__
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* Different phases of the KCS BMC module.
128c2ecf20Sopenharmony_ci *  KCS_PHASE_IDLE:
138c2ecf20Sopenharmony_ci *            BMC should not be expecting nor sending any data.
148c2ecf20Sopenharmony_ci *  KCS_PHASE_WRITE_START:
158c2ecf20Sopenharmony_ci *            BMC is receiving a WRITE_START command from system software.
168c2ecf20Sopenharmony_ci *  KCS_PHASE_WRITE_DATA:
178c2ecf20Sopenharmony_ci *            BMC is receiving a data byte from system software.
188c2ecf20Sopenharmony_ci *  KCS_PHASE_WRITE_END_CMD:
198c2ecf20Sopenharmony_ci *            BMC is waiting a last data byte from system software.
208c2ecf20Sopenharmony_ci *  KCS_PHASE_WRITE_DONE:
218c2ecf20Sopenharmony_ci *            BMC has received the whole request from system software.
228c2ecf20Sopenharmony_ci *  KCS_PHASE_WAIT_READ:
238c2ecf20Sopenharmony_ci *            BMC is waiting the response from the upper IPMI service.
248c2ecf20Sopenharmony_ci *  KCS_PHASE_READ:
258c2ecf20Sopenharmony_ci *            BMC is transferring the response to system software.
268c2ecf20Sopenharmony_ci *  KCS_PHASE_ABORT_ERROR1:
278c2ecf20Sopenharmony_ci *            BMC is waiting error status request from system software.
288c2ecf20Sopenharmony_ci *  KCS_PHASE_ABORT_ERROR2:
298c2ecf20Sopenharmony_ci *            BMC is waiting for idle status afer error from system software.
308c2ecf20Sopenharmony_ci *  KCS_PHASE_ERROR:
318c2ecf20Sopenharmony_ci *            BMC has detected a protocol violation at the interface level.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_cienum kcs_phases {
348c2ecf20Sopenharmony_ci	KCS_PHASE_IDLE,
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	KCS_PHASE_WRITE_START,
378c2ecf20Sopenharmony_ci	KCS_PHASE_WRITE_DATA,
388c2ecf20Sopenharmony_ci	KCS_PHASE_WRITE_END_CMD,
398c2ecf20Sopenharmony_ci	KCS_PHASE_WRITE_DONE,
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	KCS_PHASE_WAIT_READ,
428c2ecf20Sopenharmony_ci	KCS_PHASE_READ,
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	KCS_PHASE_ABORT_ERROR1,
458c2ecf20Sopenharmony_ci	KCS_PHASE_ABORT_ERROR2,
468c2ecf20Sopenharmony_ci	KCS_PHASE_ERROR
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */
508c2ecf20Sopenharmony_cienum kcs_errors {
518c2ecf20Sopenharmony_ci	KCS_NO_ERROR                = 0x00,
528c2ecf20Sopenharmony_ci	KCS_ABORTED_BY_COMMAND      = 0x01,
538c2ecf20Sopenharmony_ci	KCS_ILLEGAL_CONTROL_CODE    = 0x02,
548c2ecf20Sopenharmony_ci	KCS_LENGTH_ERROR            = 0x06,
558c2ecf20Sopenharmony_ci	KCS_UNSPECIFIED_ERROR       = 0xFF
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* IPMI 2.0 - 9.5, KCS Interface Registers
598c2ecf20Sopenharmony_ci * @idr: Input Data Register
608c2ecf20Sopenharmony_ci * @odr: Output Data Register
618c2ecf20Sopenharmony_ci * @str: Status Register
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_cistruct kcs_ioreg {
648c2ecf20Sopenharmony_ci	u32 idr;
658c2ecf20Sopenharmony_ci	u32 odr;
668c2ecf20Sopenharmony_ci	u32 str;
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistruct kcs_bmc {
708c2ecf20Sopenharmony_ci	spinlock_t lock;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	u32 channel;
738c2ecf20Sopenharmony_ci	int running;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Setup by BMC KCS controller driver */
768c2ecf20Sopenharmony_ci	struct kcs_ioreg ioreg;
778c2ecf20Sopenharmony_ci	u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg);
788c2ecf20Sopenharmony_ci	void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	enum kcs_phases phase;
818c2ecf20Sopenharmony_ci	enum kcs_errors error;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	wait_queue_head_t queue;
848c2ecf20Sopenharmony_ci	bool data_in_avail;
858c2ecf20Sopenharmony_ci	int  data_in_idx;
868c2ecf20Sopenharmony_ci	u8  *data_in;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	int  data_out_idx;
898c2ecf20Sopenharmony_ci	int  data_out_len;
908c2ecf20Sopenharmony_ci	u8  *data_out;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	struct mutex mutex;
938c2ecf20Sopenharmony_ci	u8 *kbuffer;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	struct miscdevice miscdev;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	unsigned long priv[];
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	return kcs_bmc->priv;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciint kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc);
1068c2ecf20Sopenharmony_cistruct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv,
1078c2ecf20Sopenharmony_ci					u32 channel);
1088c2ecf20Sopenharmony_ci#endif /* __KCS_BMC_H__ */
109