1*20d60f61SHaiyue Wang // SPDX-License-Identifier: GPL-2.0 2*20d60f61SHaiyue Wang // Copyright (c) 2015-2018, Intel Corporation. 3*20d60f61SHaiyue Wang 4*20d60f61SHaiyue Wang #ifndef __KCS_BMC_H__ 5*20d60f61SHaiyue Wang #define __KCS_BMC_H__ 6*20d60f61SHaiyue Wang 7*20d60f61SHaiyue Wang #include <linux/miscdevice.h> 8*20d60f61SHaiyue Wang 9*20d60f61SHaiyue Wang /* Different phases of the KCS BMC module : 10*20d60f61SHaiyue Wang * KCS_PHASE_IDLE : 11*20d60f61SHaiyue Wang * BMC should not be expecting nor sending any data. 12*20d60f61SHaiyue Wang * KCS_PHASE_WRITE_START : 13*20d60f61SHaiyue Wang * BMC is receiving a WRITE_START command from system software. 14*20d60f61SHaiyue Wang * KCS_PHASE_WRITE_DATA : 15*20d60f61SHaiyue Wang * BMC is receiving a data byte from system software. 16*20d60f61SHaiyue Wang * KCS_PHASE_WRITE_END_CMD : 17*20d60f61SHaiyue Wang * BMC is waiting a last data byte from system software. 18*20d60f61SHaiyue Wang * KCS_PHASE_WRITE_DONE : 19*20d60f61SHaiyue Wang * BMC has received the whole request from system software. 20*20d60f61SHaiyue Wang * KCS_PHASE_WAIT_READ : 21*20d60f61SHaiyue Wang * BMC is waiting the response from the upper IPMI service. 22*20d60f61SHaiyue Wang * KCS_PHASE_READ : 23*20d60f61SHaiyue Wang * BMC is transferring the response to system software. 24*20d60f61SHaiyue Wang * KCS_PHASE_ABORT_ERROR1 : 25*20d60f61SHaiyue Wang * BMC is waiting error status request from system software. 26*20d60f61SHaiyue Wang * KCS_PHASE_ABORT_ERROR2 : 27*20d60f61SHaiyue Wang * BMC is waiting for idle status afer error from system software. 28*20d60f61SHaiyue Wang * KCS_PHASE_ERROR : 29*20d60f61SHaiyue Wang * BMC has detected a protocol violation at the interface level. 30*20d60f61SHaiyue Wang */ 31*20d60f61SHaiyue Wang enum kcs_phases { 32*20d60f61SHaiyue Wang KCS_PHASE_IDLE, 33*20d60f61SHaiyue Wang 34*20d60f61SHaiyue Wang KCS_PHASE_WRITE_START, 35*20d60f61SHaiyue Wang KCS_PHASE_WRITE_DATA, 36*20d60f61SHaiyue Wang KCS_PHASE_WRITE_END_CMD, 37*20d60f61SHaiyue Wang KCS_PHASE_WRITE_DONE, 38*20d60f61SHaiyue Wang 39*20d60f61SHaiyue Wang KCS_PHASE_WAIT_READ, 40*20d60f61SHaiyue Wang KCS_PHASE_READ, 41*20d60f61SHaiyue Wang 42*20d60f61SHaiyue Wang KCS_PHASE_ABORT_ERROR1, 43*20d60f61SHaiyue Wang KCS_PHASE_ABORT_ERROR2, 44*20d60f61SHaiyue Wang KCS_PHASE_ERROR 45*20d60f61SHaiyue Wang }; 46*20d60f61SHaiyue Wang 47*20d60f61SHaiyue Wang /* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ 48*20d60f61SHaiyue Wang enum kcs_errors { 49*20d60f61SHaiyue Wang KCS_NO_ERROR = 0x00, 50*20d60f61SHaiyue Wang KCS_ABORTED_BY_COMMAND = 0x01, 51*20d60f61SHaiyue Wang KCS_ILLEGAL_CONTROL_CODE = 0x02, 52*20d60f61SHaiyue Wang KCS_LENGTH_ERROR = 0x06, 53*20d60f61SHaiyue Wang KCS_UNSPECIFIED_ERROR = 0xFF 54*20d60f61SHaiyue Wang }; 55*20d60f61SHaiyue Wang 56*20d60f61SHaiyue Wang /* IPMI 2.0 - 9.5, KCS Interface Registers 57*20d60f61SHaiyue Wang * @idr : Input Data Register 58*20d60f61SHaiyue Wang * @odr : Output Data Register 59*20d60f61SHaiyue Wang * @str : Status Register 60*20d60f61SHaiyue Wang */ 61*20d60f61SHaiyue Wang struct kcs_ioreg { 62*20d60f61SHaiyue Wang u32 idr; 63*20d60f61SHaiyue Wang u32 odr; 64*20d60f61SHaiyue Wang u32 str; 65*20d60f61SHaiyue Wang }; 66*20d60f61SHaiyue Wang 67*20d60f61SHaiyue Wang struct kcs_bmc { 68*20d60f61SHaiyue Wang spinlock_t lock; 69*20d60f61SHaiyue Wang 70*20d60f61SHaiyue Wang u32 channel; 71*20d60f61SHaiyue Wang int running; 72*20d60f61SHaiyue Wang 73*20d60f61SHaiyue Wang /* Setup by BMC KCS controller driver */ 74*20d60f61SHaiyue Wang struct kcs_ioreg ioreg; 75*20d60f61SHaiyue Wang u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); 76*20d60f61SHaiyue Wang void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); 77*20d60f61SHaiyue Wang 78*20d60f61SHaiyue Wang enum kcs_phases phase; 79*20d60f61SHaiyue Wang enum kcs_errors error; 80*20d60f61SHaiyue Wang 81*20d60f61SHaiyue Wang wait_queue_head_t queue; 82*20d60f61SHaiyue Wang bool data_in_avail; 83*20d60f61SHaiyue Wang int data_in_idx; 84*20d60f61SHaiyue Wang u8 *data_in; 85*20d60f61SHaiyue Wang 86*20d60f61SHaiyue Wang int data_out_idx; 87*20d60f61SHaiyue Wang int data_out_len; 88*20d60f61SHaiyue Wang u8 *data_out; 89*20d60f61SHaiyue Wang 90*20d60f61SHaiyue Wang struct mutex mutex; 91*20d60f61SHaiyue Wang u8 *kbuffer; 92*20d60f61SHaiyue Wang 93*20d60f61SHaiyue Wang struct miscdevice miscdev; 94*20d60f61SHaiyue Wang 95*20d60f61SHaiyue Wang unsigned long priv[]; 96*20d60f61SHaiyue Wang }; 97*20d60f61SHaiyue Wang 98*20d60f61SHaiyue Wang static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) 99*20d60f61SHaiyue Wang { 100*20d60f61SHaiyue Wang return kcs_bmc->priv; 101*20d60f61SHaiyue Wang } 102*20d60f61SHaiyue Wang 103*20d60f61SHaiyue Wang int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); 104*20d60f61SHaiyue Wang struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, 105*20d60f61SHaiyue Wang u32 channel); 106*20d60f61SHaiyue Wang #endif 107