xref: /openbmc/linux/drivers/scsi/aacraid/src.c (revision a44199ee)
1e8b12f0fSMahesh Rajashekhara /*
2e8b12f0fSMahesh Rajashekhara  *	Adaptec AAC series RAID controller driver
3e8b12f0fSMahesh Rajashekhara  *	(c) Copyright 2001 Red Hat Inc.
4e8b12f0fSMahesh Rajashekhara  *
5e8b12f0fSMahesh Rajashekhara  * based on the old aacraid driver that is..
6e8b12f0fSMahesh Rajashekhara  * Adaptec aacraid device driver for Linux.
7e8b12f0fSMahesh Rajashekhara  *
8e8b12f0fSMahesh Rajashekhara  * Copyright (c) 2000-2010 Adaptec, Inc.
9e8b12f0fSMahesh Rajashekhara  *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
10e8b12f0fSMahesh Rajashekhara  *
11e8b12f0fSMahesh Rajashekhara  * This program is free software; you can redistribute it and/or modify
12e8b12f0fSMahesh Rajashekhara  * it under the terms of the GNU General Public License as published by
13e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation; either version 2, or (at your option)
14e8b12f0fSMahesh Rajashekhara  * any later version.
15e8b12f0fSMahesh Rajashekhara  *
16e8b12f0fSMahesh Rajashekhara  * This program is distributed in the hope that it will be useful,
17e8b12f0fSMahesh Rajashekhara  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18e8b12f0fSMahesh Rajashekhara  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19e8b12f0fSMahesh Rajashekhara  * GNU General Public License for more details.
20e8b12f0fSMahesh Rajashekhara  *
21e8b12f0fSMahesh Rajashekhara  * You should have received a copy of the GNU General Public License
22e8b12f0fSMahesh Rajashekhara  * along with this program; see the file COPYING.  If not, write to
23e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24e8b12f0fSMahesh Rajashekhara  *
25e8b12f0fSMahesh Rajashekhara  * Module Name:
26e8b12f0fSMahesh Rajashekhara  *  src.c
27e8b12f0fSMahesh Rajashekhara  *
28e8b12f0fSMahesh Rajashekhara  * Abstract: Hardware Device Interface for PMC SRC based controllers
29e8b12f0fSMahesh Rajashekhara  *
30e8b12f0fSMahesh Rajashekhara  */
31e8b12f0fSMahesh Rajashekhara 
32e8b12f0fSMahesh Rajashekhara #include <linux/kernel.h>
33e8b12f0fSMahesh Rajashekhara #include <linux/init.h>
34e8b12f0fSMahesh Rajashekhara #include <linux/types.h>
35e8b12f0fSMahesh Rajashekhara #include <linux/pci.h>
36e8b12f0fSMahesh Rajashekhara #include <linux/spinlock.h>
37e8b12f0fSMahesh Rajashekhara #include <linux/slab.h>
38e8b12f0fSMahesh Rajashekhara #include <linux/blkdev.h>
39e8b12f0fSMahesh Rajashekhara #include <linux/delay.h>
40e8b12f0fSMahesh Rajashekhara #include <linux/completion.h>
41e8b12f0fSMahesh Rajashekhara #include <linux/time.h>
42e8b12f0fSMahesh Rajashekhara #include <linux/interrupt.h>
43e8b12f0fSMahesh Rajashekhara #include <scsi/scsi_host.h>
44e8b12f0fSMahesh Rajashekhara 
45e8b12f0fSMahesh Rajashekhara #include "aacraid.h"
46e8b12f0fSMahesh Rajashekhara 
47495c0217SMahesh Rajashekhara static int aac_src_get_sync_status(struct aac_dev *dev);
48495c0217SMahesh Rajashekhara 
49305974feSkbuild test robot static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
50e8b12f0fSMahesh Rajashekhara {
51495c0217SMahesh Rajashekhara 	struct aac_msix_ctx *ctx;
52495c0217SMahesh Rajashekhara 	struct aac_dev *dev;
53e8b12f0fSMahesh Rajashekhara 	unsigned long bellbits, bellbits_shifted;
54495c0217SMahesh Rajashekhara 	int vector_no;
55495c0217SMahesh Rajashekhara 	int isFastResponse, mode;
56e8b12f0fSMahesh Rajashekhara 	u32 index, handle;
57e8b12f0fSMahesh Rajashekhara 
58495c0217SMahesh Rajashekhara 	ctx = (struct aac_msix_ctx *)dev_id;
59495c0217SMahesh Rajashekhara 	dev = ctx->dev;
60495c0217SMahesh Rajashekhara 	vector_no = ctx->vector_no;
61495c0217SMahesh Rajashekhara 
62495c0217SMahesh Rajashekhara 	if (dev->msi_enabled) {
63495c0217SMahesh Rajashekhara 		mode = AAC_INT_MODE_MSI;
64495c0217SMahesh Rajashekhara 		if (vector_no == 0) {
65495c0217SMahesh Rajashekhara 			bellbits = src_readl(dev, MUnit.ODR_MSI);
66495c0217SMahesh Rajashekhara 			if (bellbits & 0x40000)
67495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_AIF;
68495c0217SMahesh Rajashekhara 			if (bellbits & 0x1000)
69495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_SYNC;
70495c0217SMahesh Rajashekhara 		}
71495c0217SMahesh Rajashekhara 	} else {
72495c0217SMahesh Rajashekhara 		mode = AAC_INT_MODE_INTX;
73e8b12f0fSMahesh Rajashekhara 		bellbits = src_readl(dev, MUnit.ODR_R);
74e8b12f0fSMahesh Rajashekhara 		if (bellbits & PmDoorBellResponseSent) {
75e8b12f0fSMahesh Rajashekhara 			bellbits = PmDoorBellResponseSent;
7685d22bbfSMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
7785d22bbfSMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
78e8b12f0fSMahesh Rajashekhara 		} else {
79e8b12f0fSMahesh Rajashekhara 			bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
8085d22bbfSMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
8185d22bbfSMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
82495c0217SMahesh Rajashekhara 
83495c0217SMahesh Rajashekhara 			if (bellbits_shifted & DoorBellAifPending)
84495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_AIF;
85495c0217SMahesh Rajashekhara 			else if (bellbits_shifted & OUTBOUNDDOORBELL_0)
86495c0217SMahesh Rajashekhara 				mode |= AAC_INT_MODE_SYNC;
87495c0217SMahesh Rajashekhara 		}
88495c0217SMahesh Rajashekhara 	}
89495c0217SMahesh Rajashekhara 
90495c0217SMahesh Rajashekhara 	if (mode & AAC_INT_MODE_SYNC) {
9111604612SMahesh Rajashekhara 		unsigned long sflags;
9211604612SMahesh Rajashekhara 		struct list_head *entry;
9311604612SMahesh Rajashekhara 		int send_it = 0;
9485d22bbfSMahesh Rajashekhara 		extern int aac_sync_mode;
9585d22bbfSMahesh Rajashekhara 
96495c0217SMahesh Rajashekhara 		if (!aac_sync_mode && !dev->msi_enabled) {
97c5bebd82SMahesh Rajashekhara 			src_writel(dev, MUnit.ODR_C, bellbits);
98c5bebd82SMahesh Rajashekhara 			src_readl(dev, MUnit.ODR_C);
9985d22bbfSMahesh Rajashekhara 		}
10011604612SMahesh Rajashekhara 
10111604612SMahesh Rajashekhara 		if (dev->sync_fib) {
10211604612SMahesh Rajashekhara 			if (dev->sync_fib->callback)
10311604612SMahesh Rajashekhara 				dev->sync_fib->callback(dev->sync_fib->callback_data,
10411604612SMahesh Rajashekhara 					dev->sync_fib);
10511604612SMahesh Rajashekhara 			spin_lock_irqsave(&dev->sync_fib->event_lock, sflags);
10611604612SMahesh Rajashekhara 			if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) {
10711604612SMahesh Rajashekhara 				dev->management_fib_count--;
10811604612SMahesh Rajashekhara 				up(&dev->sync_fib->event_wait);
10911604612SMahesh Rajashekhara 			}
110495c0217SMahesh Rajashekhara 			spin_unlock_irqrestore(&dev->sync_fib->event_lock,
111495c0217SMahesh Rajashekhara 						sflags);
11211604612SMahesh Rajashekhara 			spin_lock_irqsave(&dev->sync_lock, sflags);
11311604612SMahesh Rajashekhara 			if (!list_empty(&dev->sync_fib_list)) {
11411604612SMahesh Rajashekhara 				entry = dev->sync_fib_list.next;
115495c0217SMahesh Rajashekhara 				dev->sync_fib = list_entry(entry,
116495c0217SMahesh Rajashekhara 							   struct fib,
117495c0217SMahesh Rajashekhara 							   fiblink);
11811604612SMahesh Rajashekhara 				list_del(entry);
11911604612SMahesh Rajashekhara 				send_it = 1;
12011604612SMahesh Rajashekhara 			} else {
12111604612SMahesh Rajashekhara 				dev->sync_fib = NULL;
12211604612SMahesh Rajashekhara 			}
12311604612SMahesh Rajashekhara 			spin_unlock_irqrestore(&dev->sync_lock, sflags);
12411604612SMahesh Rajashekhara 			if (send_it) {
12511604612SMahesh Rajashekhara 				aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
126495c0217SMahesh Rajashekhara 					(u32)dev->sync_fib->hw_fib_pa,
127495c0217SMahesh Rajashekhara 					0, 0, 0, 0, 0,
12811604612SMahesh Rajashekhara 					NULL, NULL, NULL, NULL, NULL);
12911604612SMahesh Rajashekhara 			}
13011604612SMahesh Rajashekhara 		}
131495c0217SMahesh Rajashekhara 		if (!dev->msi_enabled)
132495c0217SMahesh Rajashekhara 			mode = 0;
133495c0217SMahesh Rajashekhara 
134e8b12f0fSMahesh Rajashekhara 	}
135e8b12f0fSMahesh Rajashekhara 
136495c0217SMahesh Rajashekhara 	if (mode & AAC_INT_MODE_AIF) {
137495c0217SMahesh Rajashekhara 		/* handle AIF */
1389cb62fa2SRaghava Aditya Renukunta 		if (dev->aif_thread && dev->fsa_dev)
139495c0217SMahesh Rajashekhara 			aac_intr_normal(dev, 0, 2, 0, NULL);
140495c0217SMahesh Rajashekhara 		if (dev->msi_enabled)
141495c0217SMahesh Rajashekhara 			aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
142495c0217SMahesh Rajashekhara 		mode = 0;
143e8b12f0fSMahesh Rajashekhara 	}
144495c0217SMahesh Rajashekhara 
145495c0217SMahesh Rajashekhara 	if (mode) {
146495c0217SMahesh Rajashekhara 		index = dev->host_rrq_idx[vector_no];
147495c0217SMahesh Rajashekhara 
148495c0217SMahesh Rajashekhara 		for (;;) {
149495c0217SMahesh Rajashekhara 			isFastResponse = 0;
150495c0217SMahesh Rajashekhara 			/* remove toggle bit (31) */
151495c0217SMahesh Rajashekhara 			handle = (dev->host_rrq[index] & 0x7fffffff);
152495c0217SMahesh Rajashekhara 			/* check fast response bit (30) */
153495c0217SMahesh Rajashekhara 			if (handle & 0x40000000)
154495c0217SMahesh Rajashekhara 				isFastResponse = 1;
155495c0217SMahesh Rajashekhara 			handle &= 0x0000ffff;
156495c0217SMahesh Rajashekhara 			if (handle == 0)
157495c0217SMahesh Rajashekhara 				break;
158495c0217SMahesh Rajashekhara 			if (dev->msi_enabled && dev->max_msix > 1)
159495c0217SMahesh Rajashekhara 				atomic_dec(&dev->rrq_outstanding[vector_no]);
160495c0217SMahesh Rajashekhara 			dev->host_rrq[index++] = 0;
1613f4ce057SRaghava Aditya Renukunta 			aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
162495c0217SMahesh Rajashekhara 			if (index == (vector_no + 1) * dev->vector_cap)
163495c0217SMahesh Rajashekhara 				index = vector_no * dev->vector_cap;
164495c0217SMahesh Rajashekhara 			dev->host_rrq_idx[vector_no] = index;
165495c0217SMahesh Rajashekhara 		}
166495c0217SMahesh Rajashekhara 		mode = 0;
167495c0217SMahesh Rajashekhara 	}
168495c0217SMahesh Rajashekhara 
169495c0217SMahesh Rajashekhara 	return IRQ_HANDLED;
170e8b12f0fSMahesh Rajashekhara }
171e8b12f0fSMahesh Rajashekhara 
172e8b12f0fSMahesh Rajashekhara /**
173e8b12f0fSMahesh Rajashekhara  *	aac_src_disable_interrupt	-	Disable interrupts
174e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
175e8b12f0fSMahesh Rajashekhara  */
176e8b12f0fSMahesh Rajashekhara 
177e8b12f0fSMahesh Rajashekhara static void aac_src_disable_interrupt(struct aac_dev *dev)
178e8b12f0fSMahesh Rajashekhara {
179e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
180e8b12f0fSMahesh Rajashekhara }
181e8b12f0fSMahesh Rajashekhara 
182e8b12f0fSMahesh Rajashekhara /**
183e8b12f0fSMahesh Rajashekhara  *	aac_src_enable_interrupt_message	-	Enable interrupts
184e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
185e8b12f0fSMahesh Rajashekhara  */
186e8b12f0fSMahesh Rajashekhara 
187e8b12f0fSMahesh Rajashekhara static void aac_src_enable_interrupt_message(struct aac_dev *dev)
188e8b12f0fSMahesh Rajashekhara {
189495c0217SMahesh Rajashekhara 	aac_src_access_devreg(dev, AAC_ENABLE_INTERRUPT);
190e8b12f0fSMahesh Rajashekhara }
191e8b12f0fSMahesh Rajashekhara 
192e8b12f0fSMahesh Rajashekhara /**
193e8b12f0fSMahesh Rajashekhara  *	src_sync_cmd	-	send a command and wait
194e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
195e8b12f0fSMahesh Rajashekhara  *	@command: Command to execute
196e8b12f0fSMahesh Rajashekhara  *	@p1: first parameter
197e8b12f0fSMahesh Rajashekhara  *	@ret: adapter status
198e8b12f0fSMahesh Rajashekhara  *
199e8b12f0fSMahesh Rajashekhara  *	This routine will send a synchronous command to the adapter and wait
200e8b12f0fSMahesh Rajashekhara  *	for its	completion.
201e8b12f0fSMahesh Rajashekhara  */
202e8b12f0fSMahesh Rajashekhara 
203e8b12f0fSMahesh Rajashekhara static int src_sync_cmd(struct aac_dev *dev, u32 command,
204e8b12f0fSMahesh Rajashekhara 	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
205e8b12f0fSMahesh Rajashekhara 	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
206e8b12f0fSMahesh Rajashekhara {
207e8b12f0fSMahesh Rajashekhara 	unsigned long start;
208dafde947SMahesh Rajashekhara 	unsigned long delay;
209e8b12f0fSMahesh Rajashekhara 	int ok;
210e8b12f0fSMahesh Rajashekhara 
211e8b12f0fSMahesh Rajashekhara 	/*
212e8b12f0fSMahesh Rajashekhara 	 *	Write the command into Mailbox 0
213e8b12f0fSMahesh Rajashekhara 	 */
214e8b12f0fSMahesh Rajashekhara 	writel(command, &dev->IndexRegs->Mailbox[0]);
215e8b12f0fSMahesh Rajashekhara 	/*
216e8b12f0fSMahesh Rajashekhara 	 *	Write the parameters into Mailboxes 1 - 6
217e8b12f0fSMahesh Rajashekhara 	 */
218e8b12f0fSMahesh Rajashekhara 	writel(p1, &dev->IndexRegs->Mailbox[1]);
219e8b12f0fSMahesh Rajashekhara 	writel(p2, &dev->IndexRegs->Mailbox[2]);
220e8b12f0fSMahesh Rajashekhara 	writel(p3, &dev->IndexRegs->Mailbox[3]);
221e8b12f0fSMahesh Rajashekhara 	writel(p4, &dev->IndexRegs->Mailbox[4]);
222e8b12f0fSMahesh Rajashekhara 
223e8b12f0fSMahesh Rajashekhara 	/*
224e8b12f0fSMahesh Rajashekhara 	 *	Clear the synch command doorbell to start on a clean slate.
225e8b12f0fSMahesh Rajashekhara 	 */
226495c0217SMahesh Rajashekhara 	if (!dev->msi_enabled)
227495c0217SMahesh Rajashekhara 		src_writel(dev,
228495c0217SMahesh Rajashekhara 			   MUnit.ODR_C,
229495c0217SMahesh Rajashekhara 			   OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
230e8b12f0fSMahesh Rajashekhara 
231e8b12f0fSMahesh Rajashekhara 	/*
232e8b12f0fSMahesh Rajashekhara 	 *	Disable doorbell interrupts
233e8b12f0fSMahesh Rajashekhara 	 */
234e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
235e8b12f0fSMahesh Rajashekhara 
236e8b12f0fSMahesh Rajashekhara 	/*
237e8b12f0fSMahesh Rajashekhara 	 *	Force the completion of the mask register write before issuing
238e8b12f0fSMahesh Rajashekhara 	 *	the interrupt.
239e8b12f0fSMahesh Rajashekhara 	 */
240e8b12f0fSMahesh Rajashekhara 	src_readl(dev, MUnit.OIMR);
241e8b12f0fSMahesh Rajashekhara 
242e8b12f0fSMahesh Rajashekhara 	/*
243e8b12f0fSMahesh Rajashekhara 	 *	Signal that there is a new synch command
244e8b12f0fSMahesh Rajashekhara 	 */
245e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
246e8b12f0fSMahesh Rajashekhara 
24711604612SMahesh Rajashekhara 	if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) {
248e8b12f0fSMahesh Rajashekhara 		ok = 0;
249e8b12f0fSMahesh Rajashekhara 		start = jiffies;
250e8b12f0fSMahesh Rajashekhara 
251dafde947SMahesh Rajashekhara 		if (command == IOP_RESET_ALWAYS) {
252dafde947SMahesh Rajashekhara 			/* Wait up to 10 sec */
253dafde947SMahesh Rajashekhara 			delay = 10*HZ;
254dafde947SMahesh Rajashekhara 		} else {
255dafde947SMahesh Rajashekhara 			/* Wait up to 5 minutes */
256dafde947SMahesh Rajashekhara 			delay = 300*HZ;
257dafde947SMahesh Rajashekhara 		}
258dafde947SMahesh Rajashekhara 		while (time_before(jiffies, start+delay)) {
25911604612SMahesh Rajashekhara 			udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
26011604612SMahesh Rajashekhara 			/*
26111604612SMahesh Rajashekhara 			 *	Mon960 will set doorbell0 bit when it has completed the command.
262e8b12f0fSMahesh Rajashekhara 			 */
263495c0217SMahesh Rajashekhara 			if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) {
26411604612SMahesh Rajashekhara 				/*
26511604612SMahesh Rajashekhara 				 *	Clear the doorbell.
26611604612SMahesh Rajashekhara 				 */
267495c0217SMahesh Rajashekhara 				if (dev->msi_enabled)
268495c0217SMahesh Rajashekhara 					aac_src_access_devreg(dev,
269495c0217SMahesh Rajashekhara 						AAC_CLEAR_SYNC_BIT);
270495c0217SMahesh Rajashekhara 				else
271495c0217SMahesh Rajashekhara 					src_writel(dev,
272495c0217SMahesh Rajashekhara 						MUnit.ODR_C,
273495c0217SMahesh Rajashekhara 						OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
274e8b12f0fSMahesh Rajashekhara 				ok = 1;
275e8b12f0fSMahesh Rajashekhara 				break;
276e8b12f0fSMahesh Rajashekhara 			}
27711604612SMahesh Rajashekhara 			/*
27811604612SMahesh Rajashekhara 			 *	Yield the processor in case we are slow
27911604612SMahesh Rajashekhara 			 */
280e8b12f0fSMahesh Rajashekhara 			msleep(1);
281e8b12f0fSMahesh Rajashekhara 		}
282e8b12f0fSMahesh Rajashekhara 		if (unlikely(ok != 1)) {
28311604612SMahesh Rajashekhara 			/*
28411604612SMahesh Rajashekhara 			 *	Restore interrupt mask even though we timed out
28511604612SMahesh Rajashekhara 			 */
286e8b12f0fSMahesh Rajashekhara 			aac_adapter_enable_int(dev);
287e8b12f0fSMahesh Rajashekhara 			return -ETIMEDOUT;
288e8b12f0fSMahesh Rajashekhara 		}
28911604612SMahesh Rajashekhara 		/*
29011604612SMahesh Rajashekhara 		 *	Pull the synch status from Mailbox 0.
29111604612SMahesh Rajashekhara 		 */
292e8b12f0fSMahesh Rajashekhara 		if (status)
293e8b12f0fSMahesh Rajashekhara 			*status = readl(&dev->IndexRegs->Mailbox[0]);
294e8b12f0fSMahesh Rajashekhara 		if (r1)
295e8b12f0fSMahesh Rajashekhara 			*r1 = readl(&dev->IndexRegs->Mailbox[1]);
296e8b12f0fSMahesh Rajashekhara 		if (r2)
297e8b12f0fSMahesh Rajashekhara 			*r2 = readl(&dev->IndexRegs->Mailbox[2]);
298e8b12f0fSMahesh Rajashekhara 		if (r3)
299e8b12f0fSMahesh Rajashekhara 			*r3 = readl(&dev->IndexRegs->Mailbox[3]);
300e8b12f0fSMahesh Rajashekhara 		if (r4)
301e8b12f0fSMahesh Rajashekhara 			*r4 = readl(&dev->IndexRegs->Mailbox[4]);
302495c0217SMahesh Rajashekhara 		if (command == GET_COMM_PREFERRED_SETTINGS)
303495c0217SMahesh Rajashekhara 			dev->max_msix =
304495c0217SMahesh Rajashekhara 				readl(&dev->IndexRegs->Mailbox[5]) & 0xFFFF;
30511604612SMahesh Rajashekhara 		/*
30611604612SMahesh Rajashekhara 		 *	Clear the synch command doorbell.
30711604612SMahesh Rajashekhara 		 */
308495c0217SMahesh Rajashekhara 		if (!dev->msi_enabled)
309495c0217SMahesh Rajashekhara 			src_writel(dev,
310495c0217SMahesh Rajashekhara 				MUnit.ODR_C,
311495c0217SMahesh Rajashekhara 				OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
31211604612SMahesh Rajashekhara 	}
313e8b12f0fSMahesh Rajashekhara 
31411604612SMahesh Rajashekhara 	/*
31511604612SMahesh Rajashekhara 	 *	Restore interrupt mask
31611604612SMahesh Rajashekhara 	 */
317e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
318e8b12f0fSMahesh Rajashekhara 	return 0;
319e8b12f0fSMahesh Rajashekhara }
320e8b12f0fSMahesh Rajashekhara 
321e8b12f0fSMahesh Rajashekhara /**
322e8b12f0fSMahesh Rajashekhara  *	aac_src_interrupt_adapter	-	interrupt adapter
323e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
324e8b12f0fSMahesh Rajashekhara  *
325e8b12f0fSMahesh Rajashekhara  *	Send an interrupt to the i960 and breakpoint it.
326e8b12f0fSMahesh Rajashekhara  */
327e8b12f0fSMahesh Rajashekhara 
328e8b12f0fSMahesh Rajashekhara static void aac_src_interrupt_adapter(struct aac_dev *dev)
329e8b12f0fSMahesh Rajashekhara {
330e8b12f0fSMahesh Rajashekhara 	src_sync_cmd(dev, BREAKPOINT_REQUEST,
331e8b12f0fSMahesh Rajashekhara 		0, 0, 0, 0, 0, 0,
332e8b12f0fSMahesh Rajashekhara 		NULL, NULL, NULL, NULL, NULL);
333e8b12f0fSMahesh Rajashekhara }
334e8b12f0fSMahesh Rajashekhara 
335e8b12f0fSMahesh Rajashekhara /**
336e8b12f0fSMahesh Rajashekhara  *	aac_src_notify_adapter		-	send an event to the adapter
337e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
338e8b12f0fSMahesh Rajashekhara  *	@event: Event to send
339e8b12f0fSMahesh Rajashekhara  *
340e8b12f0fSMahesh Rajashekhara  *	Notify the i960 that something it probably cares about has
341e8b12f0fSMahesh Rajashekhara  *	happened.
342e8b12f0fSMahesh Rajashekhara  */
343e8b12f0fSMahesh Rajashekhara 
344e8b12f0fSMahesh Rajashekhara static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
345e8b12f0fSMahesh Rajashekhara {
346e8b12f0fSMahesh Rajashekhara 	switch (event) {
347e8b12f0fSMahesh Rajashekhara 
348e8b12f0fSMahesh Rajashekhara 	case AdapNormCmdQue:
349e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
350e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
351e8b12f0fSMahesh Rajashekhara 		break;
352e8b12f0fSMahesh Rajashekhara 	case HostNormRespNotFull:
353e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
354e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
355e8b12f0fSMahesh Rajashekhara 		break;
356e8b12f0fSMahesh Rajashekhara 	case AdapNormRespQue:
357e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
358e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
359e8b12f0fSMahesh Rajashekhara 		break;
360e8b12f0fSMahesh Rajashekhara 	case HostNormCmdNotFull:
361e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
362e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
363e8b12f0fSMahesh Rajashekhara 		break;
364e8b12f0fSMahesh Rajashekhara 	case FastIo:
365e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
366e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
367e8b12f0fSMahesh Rajashekhara 		break;
368e8b12f0fSMahesh Rajashekhara 	case AdapPrintfDone:
369e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
370e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
371e8b12f0fSMahesh Rajashekhara 		break;
372e8b12f0fSMahesh Rajashekhara 	default:
373e8b12f0fSMahesh Rajashekhara 		BUG();
374e8b12f0fSMahesh Rajashekhara 		break;
375e8b12f0fSMahesh Rajashekhara 	}
376e8b12f0fSMahesh Rajashekhara }
377e8b12f0fSMahesh Rajashekhara 
378e8b12f0fSMahesh Rajashekhara /**
379e8b12f0fSMahesh Rajashekhara  *	aac_src_start_adapter		-	activate adapter
380e8b12f0fSMahesh Rajashekhara  *	@dev:	Adapter
381e8b12f0fSMahesh Rajashekhara  *
382e8b12f0fSMahesh Rajashekhara  *	Start up processing on an i960 based AAC adapter
383e8b12f0fSMahesh Rajashekhara  */
384e8b12f0fSMahesh Rajashekhara 
385e8b12f0fSMahesh Rajashekhara static void aac_src_start_adapter(struct aac_dev *dev)
386e8b12f0fSMahesh Rajashekhara {
387e8b12f0fSMahesh Rajashekhara 	struct aac_init *init;
388495c0217SMahesh Rajashekhara 	int i;
389e8b12f0fSMahesh Rajashekhara 
39085d22bbfSMahesh Rajashekhara 	 /* reset host_rrq_idx first */
391495c0217SMahesh Rajashekhara 	for (i = 0; i < dev->max_msix; i++) {
392495c0217SMahesh Rajashekhara 		dev->host_rrq_idx[i] = i * dev->vector_cap;
393495c0217SMahesh Rajashekhara 		atomic_set(&dev->rrq_outstanding[i], 0);
394495c0217SMahesh Rajashekhara 	}
395495c0217SMahesh Rajashekhara 	dev->fibs_pushed_no = 0;
39685d22bbfSMahesh Rajashekhara 
397e8b12f0fSMahesh Rajashekhara 	init = dev->init;
398e8b12f0fSMahesh Rajashekhara 	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
399e8b12f0fSMahesh Rajashekhara 
400e8b12f0fSMahesh Rajashekhara 	/* We can only use a 32 bit address here */
401e8b12f0fSMahesh Rajashekhara 	src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
402e8b12f0fSMahesh Rajashekhara 	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
403e8b12f0fSMahesh Rajashekhara }
404e8b12f0fSMahesh Rajashekhara 
405e8b12f0fSMahesh Rajashekhara /**
406e8b12f0fSMahesh Rajashekhara  *	aac_src_check_health
407e8b12f0fSMahesh Rajashekhara  *	@dev: device to check if healthy
408e8b12f0fSMahesh Rajashekhara  *
409e8b12f0fSMahesh Rajashekhara  *	Will attempt to determine if the specified adapter is alive and
410e8b12f0fSMahesh Rajashekhara  *	capable of handling requests, returning 0 if alive.
411e8b12f0fSMahesh Rajashekhara  */
412e8b12f0fSMahesh Rajashekhara static int aac_src_check_health(struct aac_dev *dev)
413e8b12f0fSMahesh Rajashekhara {
414e8b12f0fSMahesh Rajashekhara 	u32 status = src_readl(dev, MUnit.OMR);
415e8b12f0fSMahesh Rajashekhara 
416e8b12f0fSMahesh Rajashekhara 	/*
417e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
418e8b12f0fSMahesh Rajashekhara 	 */
419e8b12f0fSMahesh Rajashekhara 	if (unlikely(status & SELF_TEST_FAILED))
420e8b12f0fSMahesh Rajashekhara 		return -1;
421e8b12f0fSMahesh Rajashekhara 
422e8b12f0fSMahesh Rajashekhara 	/*
423e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd.
424e8b12f0fSMahesh Rajashekhara 	 */
425e8b12f0fSMahesh Rajashekhara 	if (unlikely(status & KERNEL_PANIC))
426e8b12f0fSMahesh Rajashekhara 		return (status >> 16) & 0xFF;
427e8b12f0fSMahesh Rajashekhara 	/*
428e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running.
429e8b12f0fSMahesh Rajashekhara 	 */
430e8b12f0fSMahesh Rajashekhara 	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
431e8b12f0fSMahesh Rajashekhara 		return -3;
432e8b12f0fSMahesh Rajashekhara 	/*
433e8b12f0fSMahesh Rajashekhara 	 *	Everything is OK
434e8b12f0fSMahesh Rajashekhara 	 */
435e8b12f0fSMahesh Rajashekhara 	return 0;
436e8b12f0fSMahesh Rajashekhara }
437e8b12f0fSMahesh Rajashekhara 
438e8b12f0fSMahesh Rajashekhara /**
439e8b12f0fSMahesh Rajashekhara  *	aac_src_deliver_message
440e8b12f0fSMahesh Rajashekhara  *	@fib: fib to issue
441e8b12f0fSMahesh Rajashekhara  *
442e8b12f0fSMahesh Rajashekhara  *	Will send a fib, returning 0 if successful.
443e8b12f0fSMahesh Rajashekhara  */
444e8b12f0fSMahesh Rajashekhara static int aac_src_deliver_message(struct fib *fib)
445e8b12f0fSMahesh Rajashekhara {
446e8b12f0fSMahesh Rajashekhara 	struct aac_dev *dev = fib->dev;
447e8b12f0fSMahesh Rajashekhara 	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
448e8b12f0fSMahesh Rajashekhara 	u32 fibsize;
449b5f1758fSBen Collins 	dma_addr_t address;
450e8b12f0fSMahesh Rajashekhara 	struct aac_fib_xporthdr *pFibX;
451c6992781SMahesh Rajashekhara #if !defined(writeq)
452c6992781SMahesh Rajashekhara 	unsigned long flags;
453c6992781SMahesh Rajashekhara #endif
454c6992781SMahesh Rajashekhara 
455b5f1758fSBen Collins 	u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
4563f4ce057SRaghava Aditya Renukunta 	u16 vector_no;
457e8b12f0fSMahesh Rajashekhara 
458ef616233SMahesh Rajashekhara 	atomic_inc(&q->numpending);
459e8b12f0fSMahesh Rajashekhara 
460495c0217SMahesh Rajashekhara 	if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest &&
461495c0217SMahesh Rajashekhara 	    dev->max_msix > 1) {
4623f4ce057SRaghava Aditya Renukunta 		vector_no = fib->vector_no;
463495c0217SMahesh Rajashekhara 		fib->hw_fib_va->header.Handle += (vector_no << 16);
4643f4ce057SRaghava Aditya Renukunta 	} else {
4653f4ce057SRaghava Aditya Renukunta 		vector_no = 0;
466495c0217SMahesh Rajashekhara 	}
467495c0217SMahesh Rajashekhara 
4683f4ce057SRaghava Aditya Renukunta 	atomic_inc(&dev->rrq_outstanding[vector_no]);
4693f4ce057SRaghava Aditya Renukunta 
47085d22bbfSMahesh Rajashekhara 	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
47185d22bbfSMahesh Rajashekhara 		/* Calculate the amount to the fibsize bits */
47285d22bbfSMahesh Rajashekhara 		fibsize = (hdr_size + 127) / 128 - 1;
47385d22bbfSMahesh Rajashekhara 		if (fibsize > (ALIGN32 - 1))
47485d22bbfSMahesh Rajashekhara 			return -EMSGSIZE;
47585d22bbfSMahesh Rajashekhara 		/* New FIB header, 32-bit */
47685d22bbfSMahesh Rajashekhara 		address = fib->hw_fib_pa;
47785d22bbfSMahesh Rajashekhara 		fib->hw_fib_va->header.StructType = FIB_MAGIC2;
47885d22bbfSMahesh Rajashekhara 		fib->hw_fib_va->header.SenderFibAddress = (u32)address;
47985d22bbfSMahesh Rajashekhara 		fib->hw_fib_va->header.u.TimeStamp = 0;
48098f99a8aSPaul Bolle 		BUG_ON(upper_32_bits(address) != 0L);
48185d22bbfSMahesh Rajashekhara 		address |= fibsize;
48285d22bbfSMahesh Rajashekhara 	} else {
483e8b12f0fSMahesh Rajashekhara 		/* Calculate the amount to the fibsize bits */
484b5f1758fSBen Collins 		fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1;
485e8b12f0fSMahesh Rajashekhara 		if (fibsize > (ALIGN32 - 1))
486b5f1758fSBen Collins 			return -EMSGSIZE;
487e8b12f0fSMahesh Rajashekhara 
488e8b12f0fSMahesh Rajashekhara 		/* Fill XPORT header */
489b5f1758fSBen Collins 		pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr);
49085d22bbfSMahesh Rajashekhara 		pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle);
491b5f1758fSBen Collins 		pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa);
492b5f1758fSBen Collins 		pFibX->Size = cpu_to_le32(hdr_size);
493e8b12f0fSMahesh Rajashekhara 
494b5f1758fSBen Collins 		/*
495b5f1758fSBen Collins 		 * The xport header has been 32-byte aligned for us so that fibsize
496b5f1758fSBen Collins 		 * can be masked out of this address by hardware. -- BenC
497b5f1758fSBen Collins 		 */
498b5f1758fSBen Collins 		address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr);
499b5f1758fSBen Collins 		if (address & (ALIGN32 - 1))
500b5f1758fSBen Collins 			return -EINVAL;
501b5f1758fSBen Collins 		address |= fibsize;
50285d22bbfSMahesh Rajashekhara 	}
503c6992781SMahesh Rajashekhara #if defined(writeq)
504c6992781SMahesh Rajashekhara 	src_writeq(dev, MUnit.IQ_L, (u64)address);
505c6992781SMahesh Rajashekhara #else
506c6992781SMahesh Rajashekhara 	spin_lock_irqsave(&fib->dev->iq_lock, flags);
50798f99a8aSPaul Bolle 	src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff);
508b5f1758fSBen Collins 	src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
509c6992781SMahesh Rajashekhara 	spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
510c6992781SMahesh Rajashekhara #endif
511e8b12f0fSMahesh Rajashekhara 	return 0;
512e8b12f0fSMahesh Rajashekhara }
513e8b12f0fSMahesh Rajashekhara 
514e8b12f0fSMahesh Rajashekhara /**
515e8b12f0fSMahesh Rajashekhara  *	aac_src_ioremap
516e8b12f0fSMahesh Rajashekhara  *	@size: mapping resize request
517e8b12f0fSMahesh Rajashekhara  *
518e8b12f0fSMahesh Rajashekhara  */
519e8b12f0fSMahesh Rajashekhara static int aac_src_ioremap(struct aac_dev *dev, u32 size)
520e8b12f0fSMahesh Rajashekhara {
521e8b12f0fSMahesh Rajashekhara 	if (!size) {
52271552505STomas Henzl 		iounmap(dev->regs.src.bar1);
52371552505STomas Henzl 		dev->regs.src.bar1 = NULL;
524e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
52511604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
526e8b12f0fSMahesh Rajashekhara 		return 0;
527e8b12f0fSMahesh Rajashekhara 	}
528e8b12f0fSMahesh Rajashekhara 	dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
529e8b12f0fSMahesh Rajashekhara 		AAC_MIN_SRC_BAR1_SIZE);
530e8b12f0fSMahesh Rajashekhara 	dev->base = NULL;
531e8b12f0fSMahesh Rajashekhara 	if (dev->regs.src.bar1 == NULL)
532e8b12f0fSMahesh Rajashekhara 		return -1;
533ff08784bSBen Collins 	dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
534e8b12f0fSMahesh Rajashekhara 	if (dev->base == NULL) {
535e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar1);
536e8b12f0fSMahesh Rajashekhara 		dev->regs.src.bar1 = NULL;
537e8b12f0fSMahesh Rajashekhara 		return -1;
538e8b12f0fSMahesh Rajashekhara 	}
539e8b12f0fSMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
54011604612SMahesh Rajashekhara 		dev->base)->u.tupelo.IndexRegs;
54111604612SMahesh Rajashekhara 	return 0;
54211604612SMahesh Rajashekhara }
54311604612SMahesh Rajashekhara 
54411604612SMahesh Rajashekhara /**
54511604612SMahesh Rajashekhara  *  aac_srcv_ioremap
54611604612SMahesh Rajashekhara  *	@size: mapping resize request
54711604612SMahesh Rajashekhara  *
54811604612SMahesh Rajashekhara  */
54911604612SMahesh Rajashekhara static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
55011604612SMahesh Rajashekhara {
55111604612SMahesh Rajashekhara 	if (!size) {
55211604612SMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
55311604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
55411604612SMahesh Rajashekhara 		return 0;
55511604612SMahesh Rajashekhara 	}
556ff08784bSBen Collins 	dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
55711604612SMahesh Rajashekhara 	if (dev->base == NULL)
55811604612SMahesh Rajashekhara 		return -1;
55911604612SMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
56011604612SMahesh Rajashekhara 		dev->base)->u.denali.IndexRegs;
561e8b12f0fSMahesh Rajashekhara 	return 0;
562e8b12f0fSMahesh Rajashekhara }
563e8b12f0fSMahesh Rajashekhara 
564e8b12f0fSMahesh Rajashekhara static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
565e8b12f0fSMahesh Rajashekhara {
566e8b12f0fSMahesh Rajashekhara 	u32 var, reset_mask;
567e8b12f0fSMahesh Rajashekhara 
568e8b12f0fSMahesh Rajashekhara 	if (bled >= 0) {
569e8b12f0fSMahesh Rajashekhara 		if (bled)
570e8b12f0fSMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
571e8b12f0fSMahesh Rajashekhara 				dev->name, dev->id, bled);
572dafde947SMahesh Rajashekhara 		dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
573e8b12f0fSMahesh Rajashekhara 		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
574e8b12f0fSMahesh Rajashekhara 			0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
575dafde947SMahesh Rajashekhara 		if ((bled || (var != 0x00000001)) &&
576dafde947SMahesh Rajashekhara 		    !dev->doorbell_mask)
57711604612SMahesh Rajashekhara 			return -EINVAL;
578dafde947SMahesh Rajashekhara 		else if (dev->doorbell_mask) {
579dafde947SMahesh Rajashekhara 			reset_mask = dev->doorbell_mask;
580dafde947SMahesh Rajashekhara 			bled = 0;
581dafde947SMahesh Rajashekhara 			var = 0x00000001;
582dafde947SMahesh Rajashekhara 		}
583495c0217SMahesh Rajashekhara 
584495c0217SMahesh Rajashekhara 		if ((dev->pdev->device == PMC_DEVICE_S7 ||
585495c0217SMahesh Rajashekhara 		    dev->pdev->device == PMC_DEVICE_S8 ||
586495c0217SMahesh Rajashekhara 		    dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) {
587495c0217SMahesh Rajashekhara 			aac_src_access_devreg(dev, AAC_ENABLE_INTX);
588495c0217SMahesh Rajashekhara 			dev->msi_enabled = 0;
589495c0217SMahesh Rajashekhara 			msleep(5000); /* Delay 5 seconds */
590495c0217SMahesh Rajashekhara 		}
591495c0217SMahesh Rajashekhara 
592dafde947SMahesh Rajashekhara 		if (!bled && (dev->supplement_adapter_info.SupportedOptions2 &
593dafde947SMahesh Rajashekhara 		    AAC_OPTION_DOORBELL_RESET)) {
594e8b12f0fSMahesh Rajashekhara 			src_writel(dev, MUnit.IDR, reset_mask);
595495c0217SMahesh Rajashekhara 			ssleep(45);
596dafde947SMahesh Rajashekhara 		} else {
597dafde947SMahesh Rajashekhara 			src_writel(dev, MUnit.IDR, 0x100);
598dafde947SMahesh Rajashekhara 			ssleep(45);
599e8b12f0fSMahesh Rajashekhara 		}
600e8b12f0fSMahesh Rajashekhara 	}
601e8b12f0fSMahesh Rajashekhara 
602e8b12f0fSMahesh Rajashekhara 	if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
603e8b12f0fSMahesh Rajashekhara 		return -ENODEV;
604e8b12f0fSMahesh Rajashekhara 
605e8b12f0fSMahesh Rajashekhara 	if (startup_timeout < 300)
606e8b12f0fSMahesh Rajashekhara 		startup_timeout = 300;
607e8b12f0fSMahesh Rajashekhara 
608e8b12f0fSMahesh Rajashekhara 	return 0;
609e8b12f0fSMahesh Rajashekhara }
610e8b12f0fSMahesh Rajashekhara 
611e8b12f0fSMahesh Rajashekhara /**
612e8b12f0fSMahesh Rajashekhara  *	aac_src_select_comm	-	Select communications method
613e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
614e8b12f0fSMahesh Rajashekhara  *	@comm: communications method
615e8b12f0fSMahesh Rajashekhara  */
616a44199eeSBaoyou Xie static int aac_src_select_comm(struct aac_dev *dev, int comm)
617e8b12f0fSMahesh Rajashekhara {
618e8b12f0fSMahesh Rajashekhara 	switch (comm) {
619e8b12f0fSMahesh Rajashekhara 	case AAC_COMM_MESSAGE:
620e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_intr = aac_src_intr_message;
621e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_deliver = aac_src_deliver_message;
622e8b12f0fSMahesh Rajashekhara 		break;
623e8b12f0fSMahesh Rajashekhara 	default:
624e8b12f0fSMahesh Rajashekhara 		return 1;
625e8b12f0fSMahesh Rajashekhara 	}
626e8b12f0fSMahesh Rajashekhara 	return 0;
627e8b12f0fSMahesh Rajashekhara }
628e8b12f0fSMahesh Rajashekhara 
629e8b12f0fSMahesh Rajashekhara /**
630e8b12f0fSMahesh Rajashekhara  *  aac_src_init	-	initialize an Cardinal Frey Bar card
631e8b12f0fSMahesh Rajashekhara  *  @dev: device to configure
632e8b12f0fSMahesh Rajashekhara  *
633e8b12f0fSMahesh Rajashekhara  */
634e8b12f0fSMahesh Rajashekhara 
635e8b12f0fSMahesh Rajashekhara int aac_src_init(struct aac_dev *dev)
636e8b12f0fSMahesh Rajashekhara {
637e8b12f0fSMahesh Rajashekhara 	unsigned long start;
638e8b12f0fSMahesh Rajashekhara 	unsigned long status;
639e8b12f0fSMahesh Rajashekhara 	int restart = 0;
640e8b12f0fSMahesh Rajashekhara 	int instance = dev->id;
641e8b12f0fSMahesh Rajashekhara 	const char *name = dev->name;
642e8b12f0fSMahesh Rajashekhara 
643e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_src_ioremap;
644e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
645e8b12f0fSMahesh Rajashekhara 
646e8b12f0fSMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
647e8b12f0fSMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
648e8b12f0fSMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
649e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
650e8b12f0fSMahesh Rajashekhara 	}
651e8b12f0fSMahesh Rajashekhara 
652e8b12f0fSMahesh Rajashekhara 	/* Failure to reset here is an option ... */
653e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
654e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
655e8b12f0fSMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
656e8b12f0fSMahesh Rajashekhara 		!aac_src_restart_adapter(dev, 0))
657e8b12f0fSMahesh Rajashekhara 		++restart;
658e8b12f0fSMahesh Rajashekhara 	/*
659e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
660e8b12f0fSMahesh Rajashekhara 	 */
661e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
662e8b12f0fSMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
663e8b12f0fSMahesh Rajashekhara 		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
664e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
665e8b12f0fSMahesh Rajashekhara 		++restart;
666e8b12f0fSMahesh Rajashekhara 	}
667e8b12f0fSMahesh Rajashekhara 	/*
668e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
669e8b12f0fSMahesh Rajashekhara 	 */
670e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
671e8b12f0fSMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
672e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
673e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
674e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
675e8b12f0fSMahesh Rajashekhara 	}
676e8b12f0fSMahesh Rajashekhara 	/*
677e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
678e8b12f0fSMahesh Rajashekhara 	 */
679e8b12f0fSMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
680e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n",
681e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
682e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
683e8b12f0fSMahesh Rajashekhara 	}
684e8b12f0fSMahesh Rajashekhara 	start = jiffies;
685e8b12f0fSMahesh Rajashekhara 	/*
686e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
687e8b12f0fSMahesh Rajashekhara 	 */
688e8b12f0fSMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) &
689e8b12f0fSMahesh Rajashekhara 		KERNEL_UP_AND_RUNNING)) {
690e8b12f0fSMahesh Rajashekhara 		if ((restart &&
691e8b12f0fSMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
692e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
693e8b12f0fSMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
694e8b12f0fSMahesh Rajashekhara 					dev->name, instance, status);
695e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
696e8b12f0fSMahesh Rajashekhara 		}
697e8b12f0fSMahesh Rajashekhara 		if (!restart &&
698e8b12f0fSMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
699e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
700e8b12f0fSMahesh Rajashekhara 		  ((startup_timeout > 60)
701e8b12f0fSMahesh Rajashekhara 		    ? (startup_timeout - 60)
702e8b12f0fSMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
703e8b12f0fSMahesh Rajashekhara 			if (likely(!aac_src_restart_adapter(dev,
704e8b12f0fSMahesh Rajashekhara 			    aac_src_check_health(dev))))
705e8b12f0fSMahesh Rajashekhara 				start = jiffies;
706e8b12f0fSMahesh Rajashekhara 			++restart;
707e8b12f0fSMahesh Rajashekhara 		}
708e8b12f0fSMahesh Rajashekhara 		msleep(1);
709e8b12f0fSMahesh Rajashekhara 	}
710e8b12f0fSMahesh Rajashekhara 	if (restart && aac_commit)
711e8b12f0fSMahesh Rajashekhara 		aac_commit = 1;
712e8b12f0fSMahesh Rajashekhara 	/*
713e8b12f0fSMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
714e8b12f0fSMahesh Rajashekhara 	 */
715e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
716e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
717dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
718e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
719e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
720e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
721e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
722de665f28SMahesh Rajashekhara 	dev->a_ops.adapter_start = aac_src_start_adapter;
723e8b12f0fSMahesh Rajashekhara 
724e8b12f0fSMahesh Rajashekhara 	/*
725e8b12f0fSMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
726e8b12f0fSMahesh Rajashekhara 	 *	can handle.
727e8b12f0fSMahesh Rajashekhara 	 */
728e8b12f0fSMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
729e8b12f0fSMahesh Rajashekhara 	aac_adapter_disable_int(dev);
730e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
731e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
732e8b12f0fSMahesh Rajashekhara 
733e8b12f0fSMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
734e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
735e8b12f0fSMahesh Rajashekhara 	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
736e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
737e8b12f0fSMahesh Rajashekhara 
7389022d375SMahesh Rajashekhara 	dev->msi = !pci_enable_msi(dev->pdev);
739e8b12f0fSMahesh Rajashekhara 
740495c0217SMahesh Rajashekhara 	dev->aac_msix[0].vector_no = 0;
741495c0217SMahesh Rajashekhara 	dev->aac_msix[0].dev = dev;
742495c0217SMahesh Rajashekhara 
743e8b12f0fSMahesh Rajashekhara 	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
744495c0217SMahesh Rajashekhara 			IRQF_SHARED, "aacraid", &(dev->aac_msix[0]))  < 0) {
745e8b12f0fSMahesh Rajashekhara 
746e8b12f0fSMahesh Rajashekhara 		if (dev->msi)
747e8b12f0fSMahesh Rajashekhara 			pci_disable_msi(dev->pdev);
748e8b12f0fSMahesh Rajashekhara 
749e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
750e8b12f0fSMahesh Rajashekhara 			name, instance);
751e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
752e8b12f0fSMahesh Rajashekhara 	}
753e8b12f0fSMahesh Rajashekhara 	dev->dbg_base = pci_resource_start(dev->pdev, 2);
754e8b12f0fSMahesh Rajashekhara 	dev->dbg_base_mapped = dev->regs.src.bar1;
755e8b12f0fSMahesh Rajashekhara 	dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
756dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
757e8b12f0fSMahesh Rajashekhara 
758e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
75911604612SMahesh Rajashekhara 
76011604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
761e8b12f0fSMahesh Rajashekhara 		/*
762e8b12f0fSMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
763e8b12f0fSMahesh Rajashekhara 		 * start accepting requests
764e8b12f0fSMahesh Rajashekhara 		 */
765e8b12f0fSMahesh Rajashekhara 		aac_src_start_adapter(dev);
76611604612SMahesh Rajashekhara 	}
767e8b12f0fSMahesh Rajashekhara 	return 0;
768e8b12f0fSMahesh Rajashekhara 
769e8b12f0fSMahesh Rajashekhara error_iounmap:
770e8b12f0fSMahesh Rajashekhara 
771e8b12f0fSMahesh Rajashekhara 	return -1;
772e8b12f0fSMahesh Rajashekhara }
77311604612SMahesh Rajashekhara 
77411604612SMahesh Rajashekhara /**
77511604612SMahesh Rajashekhara  *  aac_srcv_init	-	initialize an SRCv card
77611604612SMahesh Rajashekhara  *  @dev: device to configure
77711604612SMahesh Rajashekhara  *
77811604612SMahesh Rajashekhara  */
77911604612SMahesh Rajashekhara 
78011604612SMahesh Rajashekhara int aac_srcv_init(struct aac_dev *dev)
78111604612SMahesh Rajashekhara {
78211604612SMahesh Rajashekhara 	unsigned long start;
78311604612SMahesh Rajashekhara 	unsigned long status;
78411604612SMahesh Rajashekhara 	int restart = 0;
78511604612SMahesh Rajashekhara 	int instance = dev->id;
78611604612SMahesh Rajashekhara 	const char *name = dev->name;
78711604612SMahesh Rajashekhara 
78811604612SMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
78911604612SMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
79011604612SMahesh Rajashekhara 
79111604612SMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRCV_BAR0_SIZE;
79211604612SMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
79311604612SMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
79411604612SMahesh Rajashekhara 		goto error_iounmap;
79511604612SMahesh Rajashekhara 	}
79611604612SMahesh Rajashekhara 
79711604612SMahesh Rajashekhara 	/* Failure to reset here is an option ... */
79811604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
79911604612SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
80011604612SMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
80111604612SMahesh Rajashekhara 		!aac_src_restart_adapter(dev, 0))
80211604612SMahesh Rajashekhara 		++restart;
80311604612SMahesh Rajashekhara 	/*
8042c10cd43SMahesh Rajashekhara 	 *	Check to see if flash update is running.
8052c10cd43SMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 5 minutes
8062c10cd43SMahesh Rajashekhara 	 */
8072c10cd43SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
8082c10cd43SMahesh Rajashekhara 	if (status & FLASH_UPD_PENDING) {
8092c10cd43SMahesh Rajashekhara 		start = jiffies;
8102c10cd43SMahesh Rajashekhara 		do {
8112c10cd43SMahesh Rajashekhara 			status = src_readl(dev, MUnit.OMR);
8122c10cd43SMahesh Rajashekhara 			if (time_after(jiffies, start+HZ*FWUPD_TIMEOUT)) {
8132c10cd43SMahesh Rajashekhara 				printk(KERN_ERR "%s%d: adapter flash update failed.\n",
8142c10cd43SMahesh Rajashekhara 					dev->name, instance);
8152c10cd43SMahesh Rajashekhara 				goto error_iounmap;
8162c10cd43SMahesh Rajashekhara 			}
8172c10cd43SMahesh Rajashekhara 		} while (!(status & FLASH_UPD_SUCCESS) &&
8182c10cd43SMahesh Rajashekhara 			 !(status & FLASH_UPD_FAILED));
8192c10cd43SMahesh Rajashekhara 		/* Delay 10 seconds.
8202c10cd43SMahesh Rajashekhara 		 * Because right now FW is doing a soft reset,
8212c10cd43SMahesh Rajashekhara 		 * do not read scratch pad register at this time
8222c10cd43SMahesh Rajashekhara 		 */
8232c10cd43SMahesh Rajashekhara 		ssleep(10);
8242c10cd43SMahesh Rajashekhara 	}
8252c10cd43SMahesh Rajashekhara 	/*
82611604612SMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
82711604612SMahesh Rajashekhara 	 */
82811604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
82911604612SMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
83011604612SMahesh Rajashekhara 		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
83111604612SMahesh Rajashekhara 			goto error_iounmap;
83211604612SMahesh Rajashekhara 		++restart;
83311604612SMahesh Rajashekhara 	}
83411604612SMahesh Rajashekhara 	/*
83511604612SMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
83611604612SMahesh Rajashekhara 	 */
83711604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
83811604612SMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
83911604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
84011604612SMahesh Rajashekhara 		goto error_iounmap;
84111604612SMahesh Rajashekhara 	}
84211604612SMahesh Rajashekhara 	/*
84311604612SMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
84411604612SMahesh Rajashekhara 	 */
84511604612SMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
84611604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
84711604612SMahesh Rajashekhara 		goto error_iounmap;
84811604612SMahesh Rajashekhara 	}
84911604612SMahesh Rajashekhara 	start = jiffies;
85011604612SMahesh Rajashekhara 	/*
85111604612SMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
85211604612SMahesh Rajashekhara 	 */
8532c10cd43SMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) &
8542c10cd43SMahesh Rajashekhara 		KERNEL_UP_AND_RUNNING) ||
8552c10cd43SMahesh Rajashekhara 		status == 0xffffffff) {
85611604612SMahesh Rajashekhara 		if ((restart &&
85711604612SMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
85811604612SMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
85911604612SMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
86011604612SMahesh Rajashekhara 					dev->name, instance, status);
86111604612SMahesh Rajashekhara 			goto error_iounmap;
86211604612SMahesh Rajashekhara 		}
86311604612SMahesh Rajashekhara 		if (!restart &&
86411604612SMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
86511604612SMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
86611604612SMahesh Rajashekhara 		  ((startup_timeout > 60)
86711604612SMahesh Rajashekhara 		    ? (startup_timeout - 60)
86811604612SMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
86911604612SMahesh Rajashekhara 			if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev))))
87011604612SMahesh Rajashekhara 				start = jiffies;
87111604612SMahesh Rajashekhara 			++restart;
87211604612SMahesh Rajashekhara 		}
87311604612SMahesh Rajashekhara 		msleep(1);
87411604612SMahesh Rajashekhara 	}
87511604612SMahesh Rajashekhara 	if (restart && aac_commit)
87611604612SMahesh Rajashekhara 		aac_commit = 1;
87711604612SMahesh Rajashekhara 	/*
87811604612SMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
87911604612SMahesh Rajashekhara 	 */
88011604612SMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
88111604612SMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
882dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
88311604612SMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
88411604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
88511604612SMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
88611604612SMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
887de665f28SMahesh Rajashekhara 	dev->a_ops.adapter_start = aac_src_start_adapter;
88811604612SMahesh Rajashekhara 
88911604612SMahesh Rajashekhara 	/*
89011604612SMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
89111604612SMahesh Rajashekhara 	 *	can handle.
89211604612SMahesh Rajashekhara 	 */
89311604612SMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
89411604612SMahesh Rajashekhara 	aac_adapter_disable_int(dev);
89511604612SMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
89611604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
89711604612SMahesh Rajashekhara 
89811604612SMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
89911604612SMahesh Rajashekhara 		goto error_iounmap;
90085d22bbfSMahesh Rajashekhara 	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2)
90111604612SMahesh Rajashekhara 		goto error_iounmap;
902495c0217SMahesh Rajashekhara 	if (dev->msi_enabled)
903495c0217SMahesh Rajashekhara 		aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
904495c0217SMahesh Rajashekhara 
9058b1462e0SMahesh Rajashekhara 	if (aac_acquire_irq(dev))
906495c0217SMahesh Rajashekhara 		goto error_iounmap;
907495c0217SMahesh Rajashekhara 
908ff08784bSBen Collins 	dev->dbg_base = dev->base_start;
90911604612SMahesh Rajashekhara 	dev->dbg_base_mapped = dev->base;
91011604612SMahesh Rajashekhara 	dev->dbg_size = dev->base_size;
911dafde947SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
91211604612SMahesh Rajashekhara 
91311604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
91411604612SMahesh Rajashekhara 
91511604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
91611604612SMahesh Rajashekhara 		/*
91711604612SMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
91811604612SMahesh Rajashekhara 		 * start accepting requests
91911604612SMahesh Rajashekhara 		 */
92011604612SMahesh Rajashekhara 		aac_src_start_adapter(dev);
92111604612SMahesh Rajashekhara 	}
92211604612SMahesh Rajashekhara 	return 0;
92311604612SMahesh Rajashekhara 
92411604612SMahesh Rajashekhara error_iounmap:
92511604612SMahesh Rajashekhara 
92611604612SMahesh Rajashekhara 	return -1;
92711604612SMahesh Rajashekhara }
92811604612SMahesh Rajashekhara 
929495c0217SMahesh Rajashekhara void aac_src_access_devreg(struct aac_dev *dev, int mode)
930495c0217SMahesh Rajashekhara {
931495c0217SMahesh Rajashekhara 	u_int32_t val;
932495c0217SMahesh Rajashekhara 
933495c0217SMahesh Rajashekhara 	switch (mode) {
934495c0217SMahesh Rajashekhara 	case AAC_ENABLE_INTERRUPT:
935495c0217SMahesh Rajashekhara 		src_writel(dev,
936495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
937495c0217SMahesh Rajashekhara 			   dev->OIMR = (dev->msi_enabled ?
938495c0217SMahesh Rajashekhara 					AAC_INT_ENABLE_TYPE1_MSIX :
939495c0217SMahesh Rajashekhara 					AAC_INT_ENABLE_TYPE1_INTX));
940495c0217SMahesh Rajashekhara 		break;
941495c0217SMahesh Rajashekhara 
942495c0217SMahesh Rajashekhara 	case AAC_DISABLE_INTERRUPT:
943495c0217SMahesh Rajashekhara 		src_writel(dev,
944495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
945495c0217SMahesh Rajashekhara 			   dev->OIMR = AAC_INT_DISABLE_ALL);
946495c0217SMahesh Rajashekhara 		break;
947495c0217SMahesh Rajashekhara 
948495c0217SMahesh Rajashekhara 	case AAC_ENABLE_MSIX:
949495c0217SMahesh Rajashekhara 		/* set bit 6 */
950495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
951495c0217SMahesh Rajashekhara 		val |= 0x40;
952495c0217SMahesh Rajashekhara 		src_writel(dev,  MUnit.IDR, val);
953495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
954495c0217SMahesh Rajashekhara 		/* unmask int. */
955495c0217SMahesh Rajashekhara 		val = PMC_ALL_INTERRUPT_BITS;
956495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IOAR, val);
957495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.OIMR);
958495c0217SMahesh Rajashekhara 		src_writel(dev,
959495c0217SMahesh Rajashekhara 			   MUnit.OIMR,
960495c0217SMahesh Rajashekhara 			   val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0)));
961495c0217SMahesh Rajashekhara 		break;
962495c0217SMahesh Rajashekhara 
963495c0217SMahesh Rajashekhara 	case AAC_DISABLE_MSIX:
964495c0217SMahesh Rajashekhara 		/* reset bit 6 */
965495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
966495c0217SMahesh Rajashekhara 		val &= ~0x40;
967495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
968495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
969495c0217SMahesh Rajashekhara 		break;
970495c0217SMahesh Rajashekhara 
971495c0217SMahesh Rajashekhara 	case AAC_CLEAR_AIF_BIT:
972495c0217SMahesh Rajashekhara 		/* set bit 5 */
973495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
974495c0217SMahesh Rajashekhara 		val |= 0x20;
975495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
976495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
977495c0217SMahesh Rajashekhara 		break;
978495c0217SMahesh Rajashekhara 
979495c0217SMahesh Rajashekhara 	case AAC_CLEAR_SYNC_BIT:
980495c0217SMahesh Rajashekhara 		/* set bit 4 */
981495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
982495c0217SMahesh Rajashekhara 		val |= 0x10;
983495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
984495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
985495c0217SMahesh Rajashekhara 		break;
986495c0217SMahesh Rajashekhara 
987495c0217SMahesh Rajashekhara 	case AAC_ENABLE_INTX:
988495c0217SMahesh Rajashekhara 		/* set bit 7 */
989495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.IDR);
990495c0217SMahesh Rajashekhara 		val |= 0x80;
991495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IDR, val);
992495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IDR);
993495c0217SMahesh Rajashekhara 		/* unmask int. */
994495c0217SMahesh Rajashekhara 		val = PMC_ALL_INTERRUPT_BITS;
995495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.IOAR, val);
996495c0217SMahesh Rajashekhara 		src_readl(dev, MUnit.IOAR);
997495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.OIMR);
998495c0217SMahesh Rajashekhara 		src_writel(dev, MUnit.OIMR,
999495c0217SMahesh Rajashekhara 				val & (~(PMC_GLOBAL_INT_BIT2)));
1000495c0217SMahesh Rajashekhara 		break;
1001495c0217SMahesh Rajashekhara 
1002495c0217SMahesh Rajashekhara 	default:
1003495c0217SMahesh Rajashekhara 		break;
1004495c0217SMahesh Rajashekhara 	}
1005495c0217SMahesh Rajashekhara }
1006495c0217SMahesh Rajashekhara 
1007495c0217SMahesh Rajashekhara static int aac_src_get_sync_status(struct aac_dev *dev)
1008495c0217SMahesh Rajashekhara {
1009495c0217SMahesh Rajashekhara 
1010495c0217SMahesh Rajashekhara 	int val;
1011495c0217SMahesh Rajashekhara 
1012495c0217SMahesh Rajashekhara 	if (dev->msi_enabled)
1013495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0;
1014495c0217SMahesh Rajashekhara 	else
1015495c0217SMahesh Rajashekhara 		val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT;
1016495c0217SMahesh Rajashekhara 
1017495c0217SMahesh Rajashekhara 	return val;
1018495c0217SMahesh Rajashekhara }
1019