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 { 7020d60f61SHaiyue Wang spinlock_t lock; 7120d60f61SHaiyue Wang 7220d60f61SHaiyue Wang u32 channel; 7320d60f61SHaiyue Wang int running; 7420d60f61SHaiyue Wang 7520d60f61SHaiyue Wang /* Setup by BMC KCS controller driver */ 7620d60f61SHaiyue Wang struct kcs_ioreg ioreg; 7720d60f61SHaiyue Wang u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); 7820d60f61SHaiyue Wang void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); 79ec6f0cf1SAndrew Jeffery void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val); 8020d60f61SHaiyue Wang 8120d60f61SHaiyue Wang enum kcs_phases phase; 8220d60f61SHaiyue Wang enum kcs_errors error; 8320d60f61SHaiyue Wang 8420d60f61SHaiyue Wang wait_queue_head_t queue; 8520d60f61SHaiyue Wang bool data_in_avail; 8620d60f61SHaiyue Wang int data_in_idx; 8720d60f61SHaiyue Wang u8 *data_in; 8820d60f61SHaiyue Wang 8920d60f61SHaiyue Wang int data_out_idx; 9020d60f61SHaiyue Wang int data_out_len; 9120d60f61SHaiyue Wang u8 *data_out; 9220d60f61SHaiyue Wang 9320d60f61SHaiyue Wang struct mutex mutex; 9420d60f61SHaiyue Wang u8 *kbuffer; 9520d60f61SHaiyue Wang 9620d60f61SHaiyue Wang struct miscdevice miscdev; 9720d60f61SHaiyue Wang 9820d60f61SHaiyue Wang unsigned long priv[]; 9920d60f61SHaiyue Wang }; 10020d60f61SHaiyue Wang 10120d60f61SHaiyue Wang static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) 10220d60f61SHaiyue Wang { 10320d60f61SHaiyue Wang return kcs_bmc->priv; 10420d60f61SHaiyue Wang } 10520d60f61SHaiyue Wang 10620d60f61SHaiyue Wang int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); 107*55ab48b4SAndrew Jeffery struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel); 108*55ab48b4SAndrew Jeffery 109*55ab48b4SAndrew Jeffery u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); 110*55ab48b4SAndrew Jeffery void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); 111*55ab48b4SAndrew Jeffery u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); 112*55ab48b4SAndrew Jeffery void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); 113*55ab48b4SAndrew Jeffery void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); 114*55ab48b4SAndrew Jeffery 1153b6d082fSHaiyue Wang #endif /* __KCS_BMC_H__ */ 116