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