Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * IBM Hot Plug Controller Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Written By: Jyoti Shah, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Copyright (C) 2001-2003 IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * Send feedback to <gregkh@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *                  <jshah@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include "ibmphp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) static int to_debug = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #define debug_polling(fmt, arg...)	do { if (to_debug) debug(fmt, arg); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) // timeout values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define CMD_COMPLETE_TOUT_SEC	60	// give HPC 60 sec to finish cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #define HPC_CTLR_WORKING_TOUT	60	// give HPC 60 sec to finish cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #define HPC_GETACCESS_TIMEOUT	60	// seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define POLL_INTERVAL_SEC	2	// poll HPC every 2 seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define POLL_LATCH_CNT		5	// poll latch 5 times, then poll slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) // Winnipeg Architected Register Offsets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define WPG_I2CMBUFL_OFFSET	0x08	// I2C Message Buffer Low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #define WPG_I2CMOSUP_OFFSET	0x10	// I2C Master Operation Setup Reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define WPG_I2CMCNTL_OFFSET	0x20	// I2C Master Control Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #define WPG_I2CPARM_OFFSET	0x40	// I2C Parameter Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define WPG_I2CSTAT_OFFSET	0x70	// I2C Status Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) // Winnipeg Store Type commands (Add this commands to the register offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #define WPG_I2C_AND		0x1000	// I2C AND operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define WPG_I2C_OR		0x2000	// I2C OR operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) // Command set for I2C Master Operation Setup Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define WPG_READATADDR_MASK	0x00010000	// read,bytes,I2C shifted,index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define WPG_WRITEATADDR_MASK	0x40010000	// write,bytes,I2C shifted,index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define WPG_READDIRECT_MASK	0x10010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define WPG_WRITEDIRECT_MASK	0x60010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) // bit masks for I2C Master Control Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define WPG_I2CMCNTL_STARTOP_MASK	0x00000002	// Start the Operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define WPG_I2C_IOREMAP_SIZE	0x2044	// size of linear address interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) // command index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define WPG_1ST_SLOT_INDEX	0x01	// index - 1st slot for ctlr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #define WPG_CTLR_INDEX		0x0F	// index - ctlr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define WPG_1ST_EXTSLOT_INDEX	0x10	// index - 1st ext slot for ctlr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define WPG_1ST_BUS_INDEX	0x1F	// index - 1st bus for ctlr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) // macro utilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) // if bits 20,22,25,26,27,29,30 are OFF return 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define HPC_I2CSTATUS_CHECK(s)	((u8)((s & 0x00000A76) ? 0 : 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) // global variables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) static DEFINE_MUTEX(sem_hpcaccess);	// lock access to HPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) static DEFINE_MUTEX(operations_mutex);	// lock all operations and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 					// access to data structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static DECLARE_COMPLETION(exit_complete); // make sure polling thread goes away
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static struct task_struct *ibmphp_poll_thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) // local function prototypes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static u8 i2c_ctrl_read(struct controller *, void __iomem *, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) static u8 i2c_ctrl_write(struct controller *, void __iomem *, u8, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static u8 hpc_writecmdtoindex(u8, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static u8 hpc_readcmdtoindex(u8, u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) static void get_hpc_access(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) static void free_hpc_access(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) static int poll_hpc(void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) static int process_changeinstatus(struct slot *, struct slot *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static int process_changeinlatch(u8, u8, struct controller *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static int hpc_wait_ctlr_notworking(int, struct controller *, void __iomem *, u8 *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) //----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) * Name:    i2c_ctrl_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) * Action:  read from HPC over I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) static u8 i2c_ctrl_read(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	void __iomem *wpg_addr;	// base addr + offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	unsigned long wpg_data;	// data to/from WPG LOHI format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	unsigned long ultemp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	unsigned long data;	// actual data HILO format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	debug_polling("%s - Entry WPGBbar[%p] index[%x] \n", __func__, WPGBbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	// READ - step 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	// read at address, byte length, I2C address (shifted), index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	// or read direct, byte length, index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	if (ctlr_ptr->ctlr_type == 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		data = WPG_READATADDR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 		// fill in I2C address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		ultemp = ultemp >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 		data |= (ultemp << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 		// fill in index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 		data |= (unsigned long)index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	} else if (ctlr_ptr->ctlr_type == 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		data = WPG_READDIRECT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		// fill in index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		ultemp = (unsigned long)index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		ultemp = ultemp << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		data |= ultemp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		err("this controller type is not supported \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		return HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	wpg_data = swab32(data);	// swap data before writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	// READ - step 2 : clear the message buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	data = 0x00000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	wpg_data = swab32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	// READ - step 3 : issue start operation, I2C master control bit 30:ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	//                 2020 : [20] OR operation at [20] offset 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	data = WPG_I2CMCNTL_STARTOP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	wpg_data = swab32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	// READ - step 4 : wait until start operation bit clears
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	i = CMD_COMPLETE_TOUT_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	while (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		wpg_data = readl(wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 		data = swab32(wpg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		debug("%s - Error : WPG timeout\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 		return HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	// READ - step 5 : read I2C status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	i = CMD_COMPLETE_TOUT_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	while (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 		wpg_data = readl(wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		data = swab32(wpg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 		if (HPC_I2CSTATUS_CHECK(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 		i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		debug("ctrl_read - Exit Error:I2C timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		return HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	// READ - step 6 : get DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	wpg_data = readl(wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	data = swab32(wpg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	status = (u8) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	debug_polling("%s - Exit index[%x] status[%x]\n", __func__, index, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) * Name:    i2c_ctrl_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) * Action:  write to HPC over I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) * Return   0 or error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) static u8 i2c_ctrl_write(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	u8 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	void __iomem *wpg_addr;	// base addr + offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	unsigned long wpg_data;	// data to/from WPG LOHI format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	unsigned long ultemp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	unsigned long data;	// actual data HILO format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	debug_polling("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __func__, WPGBbar, index, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	// WRITE - step 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	// write at address, byte length, I2C address (shifted), index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	// or write direct, byte length, index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	data = 0x00000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	if (ctlr_ptr->ctlr_type == 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 		data = WPG_WRITEATADDR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		// fill in I2C address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 		ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 		ultemp = ultemp >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 		data |= (ultemp << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		// fill in index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		data |= (unsigned long)index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	} else if (ctlr_ptr->ctlr_type == 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		data = WPG_WRITEDIRECT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 		// fill in index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		ultemp = (unsigned long)index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 		ultemp = ultemp << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		data |= ultemp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 		err("this controller type is not supported \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 		return HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	wpg_data = swab32(data);	// swap data before writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	// WRITE - step 2 : clear the message buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	data = 0x00000000 | (unsigned long)cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	wpg_data = swab32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	// WRITE - step 3 : issue start operation,I2C master control bit 30:ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	//                 2020 : [20] OR operation at [20] offset 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	data = WPG_I2CMCNTL_STARTOP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	wpg_data = swab32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	writel(wpg_data, wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	// WRITE - step 4 : wait until start operation bit clears
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	i = CMD_COMPLETE_TOUT_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	while (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		wpg_data = readl(wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		data = swab32(wpg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		debug("%s - Exit Error:WPG timeout\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 		rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	// WRITE - step 5 : read I2C status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	i = CMD_COMPLETE_TOUT_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	while (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		wpg_data = readl(wpg_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 		data = swab32(wpg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 		if (HPC_I2CSTATUS_CHECK(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		debug("ctrl_read - Error : I2C timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	debug_polling("%s Exit rc[%x]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	return (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) //------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) //  Read from ISA type HPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) //------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) static u8 isa_ctrl_read(struct controller *ctlr_ptr, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	u16 start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	u16 end_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	start_address = ctlr_ptr->u.isa_ctlr.io_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	end_address = ctlr_ptr->u.isa_ctlr.io_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	data = inb(start_address + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) //--------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) // Write to ISA type HPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) //--------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) static void isa_ctrl_write(struct controller *ctlr_ptr, u8 offset, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	u16 start_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	u16 port_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	start_address = ctlr_ptr->u.isa_ctlr.io_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	port_address = start_address + (u16) offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	outb(data, port_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) static u8 pci_ctrl_read(struct controller *ctrl, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	u8 data = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	debug("inside pci_ctrl_read\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	if (ctrl->ctrl_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 		pci_read_config_byte(ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) static u8 pci_ctrl_write(struct controller *ctrl, u8 offset, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	u8 rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	debug("inside pci_ctrl_write\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	if (ctrl->ctrl_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		pci_write_config_byte(ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) static u8 ctrl_read(struct controller *ctlr, void __iomem *base, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	u8 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	switch (ctlr->ctlr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		rc = isa_ctrl_read(ctlr, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		rc = pci_ctrl_read(ctlr, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		rc = i2c_ctrl_read(ctlr, base, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) static u8 ctrl_write(struct controller *ctlr, void __iomem *base, u8 offset, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	u8 rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	switch (ctlr->ctlr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		isa_ctrl_write(ctlr, offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		rc = pci_ctrl_write(ctlr, offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		rc = i2c_ctrl_write(ctlr, base, offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) * Name:    hpc_writecmdtoindex()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) * Action:  convert a write command to proper index within a controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) * Return   index, HPC_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) static u8 hpc_writecmdtoindex(u8 cmd, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	u8 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	case HPC_CTLR_ENABLEIRQ:	// 0x00.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	case HPC_CTLR_CLEARIRQ:	// 0x06.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	case HPC_CTLR_RESET:	// 0x07.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	case HPC_CTLR_IRQSTEER:	// 0x08.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	case HPC_CTLR_DISABLEIRQ:	// 0x01.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	case HPC_ALLSLOT_ON:	// 0x11.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	case HPC_ALLSLOT_OFF:	// 0x12.N.15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		rc = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	case HPC_SLOT_OFF:	// 0x02.Y.0-14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	case HPC_SLOT_ON:	// 0x03.Y.0-14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	case HPC_SLOT_ATTNOFF:	// 0x04.N.0-14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	case HPC_SLOT_ATTNON:	// 0x05.N.0-14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	case HPC_SLOT_BLINKLED:	// 0x13.N.0-14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		rc = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	case HPC_BUS_33CONVMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	case HPC_BUS_66CONVMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	case HPC_BUS_66PCIXMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	case HPC_BUS_100PCIXMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	case HPC_BUS_133PCIXMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		rc = index + WPG_1ST_BUS_INDEX - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		err("hpc_writecmdtoindex - Error invalid cmd[%x]\n", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) * Name:    hpc_readcmdtoindex()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) * Action:  convert a read command to proper index within a controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) * Return   index, HPC_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) static u8 hpc_readcmdtoindex(u8 cmd, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	u8 rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	case READ_CTLRSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		rc = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	case READ_SLOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	case READ_ALLSTAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		rc = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	case READ_EXTSLOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		rc = index + WPG_1ST_EXTSLOT_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	case READ_BUSSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		rc = index + WPG_1ST_BUS_INDEX - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	case READ_SLOTLATCHLOWREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		rc = 0x28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	case READ_REVLEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		rc = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	case READ_HPCOPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		rc = 0x27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) * Name:    HPCreadslot()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) * Action:  issue a READ command to HPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) * Input:   pslot   - cannot be NULL for READ_ALLSTAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) *          pstatus - can be NULL for READ_ALLSTAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) * Return   0 or error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) int ibmphp_hpc_readslot(struct slot *pslot, u8 cmd, u8 *pstatus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	void __iomem *wpg_bbar = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	struct controller *ctlr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	u8 index, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	int busindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	debug_polling("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __func__, pslot, cmd, pstatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	if ((pslot == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	    || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		err("%s - Error invalid pointer, rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	if (cmd == READ_BUSSTATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		busindex = ibmphp_get_bus_index(pslot->bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		if (busindex < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 			err("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 			index = (u8) busindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		index = pslot->ctlr_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	index = hpc_readcmdtoindex(cmd, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	if (index == HPC_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		err("%s - Exit Error:invalid index, rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	ctlr_ptr = pslot->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	get_hpc_access();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	// map physical address to logical address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		wpg_bbar = ioremap(ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	// check controller status before reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		case READ_ALLSTAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 			// update the slot structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 			pslot->ctrl->status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 			pslot->status = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 			rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 						       &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 			if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 				pslot->ext_status = ctrl_read(ctlr_ptr, wpg_bbar, index + WPG_1ST_EXTSLOT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		case READ_SLOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 			// DO NOT update the slot structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 			*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		case READ_EXTSLOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 			// DO NOT update the slot structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		case READ_CTLRSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			// DO NOT update the slot structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			*pstatus = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		case READ_BUSSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 			pslot->busstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		case READ_REVLEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		case READ_HPCOPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		case READ_SLOTLATCHLOWREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 			// DO NOT update the slot structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 			*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 			// Not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		case READ_ALLSLOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 			list_for_each_entry(pslot, &ibmphp_slot_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 					    ibm_slot_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 				index = pslot->ctlr_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 				rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 								wpg_bbar, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 				if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 					pslot->status = ctrl_read(ctlr_ptr, wpg_bbar, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 					rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 									ctlr_ptr, wpg_bbar, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 					if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 						pslot->ext_status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 						    ctrl_read(ctlr_ptr, wpg_bbar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 								index + WPG_1ST_EXTSLOT_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 					err("%s - Error ctrl_read failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 					rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 			rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	// cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	// remove physical to logical address mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		iounmap(wpg_bbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	free_hpc_access();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	debug_polling("%s - Exit rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) * Name:    ibmphp_hpc_writeslot()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) * Action: issue a WRITE command to HPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) int ibmphp_hpc_writeslot(struct slot *pslot, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	void __iomem *wpg_bbar = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	struct controller *ctlr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	u8 index, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	int busindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	u8 done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	debug_polling("%s - Entry pslot[%p] cmd[%x]\n", __func__, pslot, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	if (pslot == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		err("%s - Error Exit rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	if ((cmd == HPC_BUS_33CONVMODE) || (cmd == HPC_BUS_66CONVMODE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		(cmd == HPC_BUS_66PCIXMODE) || (cmd == HPC_BUS_100PCIXMODE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		(cmd == HPC_BUS_133PCIXMODE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		busindex = ibmphp_get_bus_index(pslot->bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		if (busindex < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 			rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 			err("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			index = (u8) busindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		index = pslot->ctlr_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	index = hpc_writecmdtoindex(cmd, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	if (index == HPC_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		err("%s - Error Exit rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	ctlr_ptr = pslot->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	get_hpc_access();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	// map physical address to logical address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		wpg_bbar = ioremap(ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		debug("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		ctlr_ptr->u.wpeg_ctlr.i2c_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	// check controller status before writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		ctrl_write(ctlr_ptr, wpg_bbar, index, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		// check controller is still not working on the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		//--------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		timeout = CMD_COMPLETE_TOUT_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		while (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 			rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 							&status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 			if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 				if (NEEDTOCHECK_CMDSTATUS(cmd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 					if (CTLR_FINISHED(status) == HPC_CTLR_FINISHED_YES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 						done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 				} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 					done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			if (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 				msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 				if (timeout < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 					done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 					err("%s - Error command complete timeout\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 					rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 				} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 					timeout--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		ctlr_ptr->status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	// cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	// remove physical to logical address mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		iounmap(wpg_bbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	free_hpc_access();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	debug_polling("%s - Exit rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) * Name:    get_hpc_access()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) * Action: make sure only one process can access HPC at one time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) static void get_hpc_access(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	mutex_lock(&sem_hpcaccess);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) * Name:    free_hpc_access()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) void free_hpc_access(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	mutex_unlock(&sem_hpcaccess);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) * Name:    ibmphp_lock_operations()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) * Action: make sure only one process can change the data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) void ibmphp_lock_operations(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	mutex_lock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	to_debug = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) * Name:    ibmphp_unlock_operations()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) void ibmphp_unlock_operations(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	debug("%s - Entry\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	mutex_unlock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	to_debug = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	debug("%s - Exit\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) * Name:    poll_hpc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) #define POLL_LATCH_REGISTER	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) #define POLL_SLOTS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) #define POLL_SLEEP		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) static int poll_hpc(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	struct slot myslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	struct slot *pslot = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	int poll_state = POLL_LATCH_REGISTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	u8 oldlatchlow = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	u8 curlatchlow = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	int poll_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	u8 ctrl_count = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	debug("%s - Entry\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	while (!kthread_should_stop()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 		/* try to get the lock to do some kind of hardware access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		mutex_lock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		switch (poll_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		case POLL_LATCH_REGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			oldlatchlow = curlatchlow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 			ctrl_count = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			list_for_each_entry(pslot, &ibmphp_slot_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 					    ibm_slot_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 				if (ctrl_count >= ibmphp_get_total_controllers())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 					ctrl_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 					if (READ_SLOT_LATCH(pslot->ctrl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 						rc = ibmphp_hpc_readslot(pslot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 									  READ_SLOTLATCHLOWREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 									  &curlatchlow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 						if (oldlatchlow != curlatchlow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 							process_changeinlatch(oldlatchlow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 									       curlatchlow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 									       pslot->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 			++poll_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			poll_state = POLL_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		case POLL_SLOTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 			list_for_each_entry(pslot, &ibmphp_slot_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 					    ibm_slot_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 				// make a copy of the old status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 				memcpy((void *) &myslot, (void *) pslot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 					sizeof(struct slot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 				rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 				if ((myslot.status != pslot->status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 				    || (myslot.ext_status != pslot->ext_status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 					process_changeinstatus(pslot, &myslot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 			ctrl_count = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 			list_for_each_entry(pslot, &ibmphp_slot_head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 					    ibm_slot_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				if (ctrl_count >= ibmphp_get_total_controllers())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 				if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 					ctrl_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 					if (READ_SLOT_LATCH(pslot->ctrl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 						rc = ibmphp_hpc_readslot(pslot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 									  READ_SLOTLATCHLOWREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 									  &curlatchlow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 			++poll_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 			poll_state = POLL_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		case POLL_SLEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			/* don't sleep with a lock on the hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 			mutex_unlock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			msleep(POLL_INTERVAL_SEC * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 			if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 				goto out_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 			mutex_lock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 			if (poll_count >= POLL_LATCH_CNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 				poll_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 				poll_state = POLL_SLOTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 				poll_state = POLL_LATCH_REGISTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		/* give up the hardware semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		mutex_unlock(&operations_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		/* sleep for a short time just for good measure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) out_sleep:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	complete(&exit_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	debug("%s - Exit\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) * Name:    process_changeinstatus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) * Action:  compare old and new slot status, process the change in status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) * Input:   pointer to slot struct, old slot struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) * Return   0 or error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) * Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) * Side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) * Effects: None.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) * Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) static int process_changeinstatus(struct slot *pslot, struct slot *poldslot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	u8 disable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	u8 update = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	debug("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	// bit 0 - HPC_SLOT_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if ((pslot->status & 0x01) != (poldslot->status & 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	// bit 1 - HPC_SLOT_CONNECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	// ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	// bit 2 - HPC_SLOT_ATTN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	if ((pslot->status & 0x04) != (poldslot->status & 0x04))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	// bit 3 - HPC_SLOT_PRSNT2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	// bit 4 - HPC_SLOT_PRSNT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	if (((pslot->status & 0x08) != (poldslot->status & 0x08))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		|| ((pslot->status & 0x10) != (poldslot->status & 0x10)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	// bit 5 - HPC_SLOT_PWRGD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	if ((pslot->status & 0x20) != (poldslot->status & 0x20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		// OFF -> ON: ignore, ON -> OFF: disable slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		if ((poldslot->status & 0x20) && (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 			disable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	// bit 6 - HPC_SLOT_BUS_SPEED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	// ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	// bit 7 - HPC_SLOT_LATCH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	if ((pslot->status & 0x80) != (poldslot->status & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		// OPEN -> CLOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		if (pslot->status & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 			if (SLOT_PWRGD(pslot->status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 				// power goes on and off after closing latch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 				// check again to make sure power is still ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 				msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 				rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 				if (SLOT_PWRGD(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 					update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 				else	// overwrite power in pslot to OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 					pslot->status &= ~HPC_SLOT_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		// CLOSE -> OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		else if ((SLOT_PWRGD(poldslot->status) == HPC_SLOT_PWRGD_GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 			&& (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 			disable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		// else - ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	// bit 4 - HPC_SLOT_BLINK_ATTN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	if (disable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		debug("process_changeinstatus - disable slot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		pslot->flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		rc = ibmphp_do_disable_slot(pslot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	if (update || disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		ibmphp_update_slot_info(pslot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	debug("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) * Name:    process_changeinlatch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) * Action:  compare old and new latch reg status, process the change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) * Input:   old and current latch register status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) * Return   0 or error codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) * Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) static int process_changeinlatch(u8 old, u8 new, struct controller *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	struct slot myslot, *pslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	u8 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	debug("%s - Entry old[%x], new[%x]\n", __func__, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	// bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		mask = 0x01 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		if ((mask & old) != (mask & new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 			pslot = ibmphp_get_slot_from_physical_num(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 			if (pslot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 				memcpy((void *) &myslot, (void *) pslot, sizeof(struct slot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 				rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 				debug("%s - call process_changeinstatus for slot[%d]\n", __func__, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 				process_changeinstatus(pslot, &myslot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 				rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 				err("%s - Error bad pointer for slot[%d]\n", __func__, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	debug("%s - Exit rc[%d]\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * Name:    ibmphp_hpc_start_poll_thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * Action:  start polling thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int __init ibmphp_hpc_start_poll_thread(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	debug("%s - Entry\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	if (IS_ERR(ibmphp_poll_thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		err("%s - Error, thread not started\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		return PTR_ERR(ibmphp_poll_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * Name:    ibmphp_hpc_stop_poll_thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * Action:  stop polling thread and cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) void __exit ibmphp_hpc_stop_poll_thread(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	debug("%s - Entry\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	kthread_stop(ibmphp_poll_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	debug("before locking operations\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	ibmphp_lock_operations();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	debug("after locking operations\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	// wait for poll thread to exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	debug("before exit_complete down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	wait_for_completion(&exit_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	debug("after exit_completion down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	// cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	debug("before free_hpc_access\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	free_hpc_access();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	debug("after free_hpc_access\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	ibmphp_unlock_operations();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	debug("after unlock operations\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	debug("%s - Exit\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /*----------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * Name:    hpc_wait_ctlr_notworking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * Action:  wait until the controller is in a not working state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * Return   0, HPC_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) *---------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static int hpc_wait_ctlr_notworking(int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 				    u8 *pstatus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	u8 done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	debug_polling("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	while (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		if (*pstatus == HPC_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 			rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 			done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		if (CTLR_WORKING(*pstatus) == HPC_CTLR_WORKING_NO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 			done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		if (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 			msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 			if (timeout < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 				done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				err("HPCreadslot - Error ctlr timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 				rc = HPC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 				timeout--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	debug_polling("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }