Lines Matching +full:ipmi +full:- +full:smic
1 // SPDX-License-Identifier: GPL-2.0+
5 * The state-machine driver for an IPMI SMIC driver
8 * and the kernel patch "mmcdev-patch-245" by HP
11 * ipmi@schwaar.com
18 * the kernel patch "mmcdev-patch-245" by HP has the following
21 * 2001 Hewlett-Packard Company
33 /* smic_debug is a bit-field
34 * SMIC_DEBUG_ENABLE - turned on for now
35 * SMIC_DEBUG_MSG - commands and their responses
36 * SMIC_DEBUG_STATES - state machine
67 /* SMIC Flags Register Bits */
82 /* SMIC Error Codes */
104 static unsigned int init_smic_data(struct si_sm_data *smic, in init_smic_data() argument
107 smic->state = SMIC_IDLE; in init_smic_data()
108 smic->io = io; in init_smic_data()
109 smic->write_pos = 0; in init_smic_data()
110 smic->write_count = 0; in init_smic_data()
111 smic->orig_write_count = 0; in init_smic_data()
112 smic->read_pos = 0; in init_smic_data()
113 smic->error_retries = 0; in init_smic_data()
114 smic->truncated = 0; in init_smic_data()
115 smic->smic_timeout = SMIC_RETRY_TIMEOUT; in init_smic_data()
121 static int start_smic_transaction(struct si_sm_data *smic, in start_smic_transaction() argument
131 if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) { in start_smic_transaction()
132 dev_warn(smic->io->dev, in start_smic_transaction()
133 "SMIC in invalid state %d\n", smic->state); in start_smic_transaction()
138 dev_dbg(smic->io->dev, "%s -", __func__); in start_smic_transaction()
143 smic->error_retries = 0; in start_smic_transaction()
144 memcpy(smic->write_data, data, size); in start_smic_transaction()
145 smic->write_count = size; in start_smic_transaction()
146 smic->orig_write_count = size; in start_smic_transaction()
147 smic->write_pos = 0; in start_smic_transaction()
148 smic->read_pos = 0; in start_smic_transaction()
149 smic->state = SMIC_START_OP; in start_smic_transaction()
150 smic->smic_timeout = SMIC_RETRY_TIMEOUT; in start_smic_transaction()
154 static int smic_get_result(struct si_sm_data *smic, in smic_get_result() argument
160 dev_dbg(smic->io->dev, "smic_get result -"); in smic_get_result()
161 for (i = 0; i < smic->read_pos; i++) in smic_get_result()
162 pr_cont(" %02x", smic->read_data[i]); in smic_get_result()
165 if (length < smic->read_pos) { in smic_get_result()
166 smic->read_pos = length; in smic_get_result()
167 smic->truncated = 1; in smic_get_result()
169 memcpy(data, smic->read_data, smic->read_pos); in smic_get_result()
171 if ((length >= 3) && (smic->read_pos < 3)) { in smic_get_result()
173 smic->read_pos = 3; in smic_get_result()
175 if (smic->truncated) { in smic_get_result()
177 smic->truncated = 0; in smic_get_result()
179 return smic->read_pos; in smic_get_result()
182 static inline unsigned char read_smic_flags(struct si_sm_data *smic) in read_smic_flags() argument
184 return smic->io->inputb(smic->io, 2); in read_smic_flags()
187 static inline unsigned char read_smic_status(struct si_sm_data *smic) in read_smic_status() argument
189 return smic->io->inputb(smic->io, 1); in read_smic_status()
192 static inline unsigned char read_smic_data(struct si_sm_data *smic) in read_smic_data() argument
194 return smic->io->inputb(smic->io, 0); in read_smic_data()
197 static inline void write_smic_flags(struct si_sm_data *smic, in write_smic_flags() argument
200 smic->io->outputb(smic->io, 2, flags); in write_smic_flags()
203 static inline void write_smic_control(struct si_sm_data *smic, in write_smic_control() argument
206 smic->io->outputb(smic->io, 1, control); in write_smic_control()
209 static inline void write_si_sm_data(struct si_sm_data *smic, in write_si_sm_data() argument
212 smic->io->outputb(smic->io, 0, data); in write_si_sm_data()
215 static inline void start_error_recovery(struct si_sm_data *smic, char *reason) in start_error_recovery() argument
217 (smic->error_retries)++; in start_error_recovery()
218 if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) { in start_error_recovery()
220 pr_warn("ipmi_smic_drv: smic hosed: %s\n", reason); in start_error_recovery()
221 smic->state = SMIC_HOSED; in start_error_recovery()
223 smic->write_count = smic->orig_write_count; in start_error_recovery()
224 smic->write_pos = 0; in start_error_recovery()
225 smic->read_pos = 0; in start_error_recovery()
226 smic->state = SMIC_START_OP; in start_error_recovery()
227 smic->smic_timeout = SMIC_RETRY_TIMEOUT; in start_error_recovery()
231 static inline void write_next_byte(struct si_sm_data *smic) in write_next_byte() argument
233 write_si_sm_data(smic, smic->write_data[smic->write_pos]); in write_next_byte()
234 (smic->write_pos)++; in write_next_byte()
235 (smic->write_count)--; in write_next_byte()
238 static inline void read_next_byte(struct si_sm_data *smic) in read_next_byte() argument
240 if (smic->read_pos >= MAX_SMIC_READ_SIZE) { in read_next_byte()
241 read_smic_data(smic); in read_next_byte()
242 smic->truncated = 1; in read_next_byte()
244 smic->read_data[smic->read_pos] = read_smic_data(smic); in read_next_byte()
245 smic->read_pos++; in read_next_byte()
249 /* SMIC Control/Status Code Components */
268 /* SMIC Control Codes */
285 /* SMIC Status Codes */
320 static enum si_sm_result smic_event(struct si_sm_data *smic, long time) in smic_event() argument
326 if (smic->state == SMIC_HOSED) { in smic_event()
327 init_smic_data(smic, smic->io); in smic_event()
330 if (smic->state != SMIC_IDLE) { in smic_event()
332 dev_dbg(smic->io->dev, in smic_event()
333 "%s - smic->smic_timeout = %ld, time = %ld\n", in smic_event()
334 __func__, smic->smic_timeout, time); in smic_event()
340 smic->smic_timeout -= time; in smic_event()
341 if (smic->smic_timeout < 0) { in smic_event()
342 start_error_recovery(smic, "smic timed out."); in smic_event()
347 flags = read_smic_flags(smic); in smic_event()
351 status = read_smic_status(smic); in smic_event()
353 dev_dbg(smic->io->dev, in smic_event()
354 "%s - state = %d, flags = 0x%02x, status = 0x%02x\n", in smic_event()
355 __func__, smic->state, flags, status); in smic_event()
357 switch (smic->state) { in smic_event()
365 /* sanity check whether smic is really idle */ in smic_event()
366 write_smic_control(smic, SMIC_CC_SMS_GET_STATUS); in smic_event()
367 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
368 smic->state = SMIC_OP_OK; in smic_event()
374 start_error_recovery(smic, in smic_event()
379 /* OK so far; smic is idle let us start ... */ in smic_event()
380 write_smic_control(smic, SMIC_CC_SMS_WR_START); in smic_event()
381 write_next_byte(smic); in smic_event()
382 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
383 smic->state = SMIC_WRITE_START; in smic_event()
388 start_error_recovery(smic, in smic_event()
398 if (smic->write_count == 1) { in smic_event()
400 write_smic_control(smic, SMIC_CC_SMS_WR_END); in smic_event()
401 smic->state = SMIC_WRITE_END; in smic_event()
403 write_smic_control(smic, SMIC_CC_SMS_WR_NEXT); in smic_event()
404 smic->state = SMIC_WRITE_NEXT; in smic_event()
406 write_next_byte(smic); in smic_event()
407 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
414 start_error_recovery(smic, in smic_event()
421 if (smic->write_count == 1) { in smic_event()
422 write_smic_control(smic, SMIC_CC_SMS_WR_END); in smic_event()
423 smic->state = SMIC_WRITE_END; in smic_event()
425 write_smic_control(smic, SMIC_CC_SMS_WR_NEXT); in smic_event()
426 smic->state = SMIC_WRITE_NEXT; in smic_event()
428 write_next_byte(smic); in smic_event()
429 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
436 start_error_recovery(smic, in smic_event()
442 data = read_smic_data(smic); in smic_event()
445 dev_dbg(smic->io->dev, in smic_event()
448 start_error_recovery(smic, in smic_event()
453 smic->state = SMIC_WRITE2READ; in smic_event()
462 write_smic_control(smic, SMIC_CC_SMS_RD_START); in smic_event()
463 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
464 smic->state = SMIC_READ_START; in smic_event()
471 start_error_recovery(smic, in smic_event()
477 read_next_byte(smic); in smic_event()
478 write_smic_control(smic, SMIC_CC_SMS_RD_NEXT); in smic_event()
479 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
480 smic->state = SMIC_READ_NEXT; in smic_event()
488 * smic tells us that this is the last byte to be read in smic_event()
489 * --> clean up in smic_event()
492 read_next_byte(smic); in smic_event()
493 write_smic_control(smic, SMIC_CC_SMS_RD_END); in smic_event()
494 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
495 smic->state = SMIC_READ_END; in smic_event()
499 read_next_byte(smic); in smic_event()
500 write_smic_control(smic, SMIC_CC_SMS_RD_NEXT); in smic_event()
501 write_smic_flags(smic, flags | SMIC_FLAG_BSY); in smic_event()
502 smic->state = SMIC_READ_NEXT; in smic_event()
508 smic, in smic_event()
517 start_error_recovery(smic, in smic_event()
522 data = read_smic_data(smic); in smic_event()
526 dev_dbg(smic->io->dev, in smic_event()
529 start_error_recovery(smic, in smic_event()
534 smic->state = SMIC_IDLE; in smic_event()
539 init_smic_data(smic, smic->io); in smic_event()
544 dev_dbg(smic->io->dev, in smic_event()
545 "smic->state = %d\n", smic->state); in smic_event()
546 start_error_recovery(smic, "state = UNKNOWN"); in smic_event()
550 smic->smic_timeout = SMIC_RETRY_TIMEOUT; in smic_event()
554 static int smic_detect(struct si_sm_data *smic) in smic_detect() argument
557 * It's impossible for the SMIC fnags register to be all 1's, in smic_detect()
558 * (assuming a properly functioning, self-initialized BMC) in smic_detect()
562 if (read_smic_flags(smic) == 0xff) in smic_detect()