Merge tag 'xfs-5.13-merge-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-2.6-microblaze.git] / drivers / scsi / aacraid / sa.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *      Adaptec AAC series RAID controller driver
4  *      (c) Copyright 2001 Red Hat Inc.
5  *
6  * based on the old aacraid driver that is..
7  * Adaptec aacraid device driver for Linux.
8  *
9  * Copyright (c) 2000-2010 Adaptec, Inc.
10  *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
11  *               2016-2017 Microsemi Corp. (aacraid@microsemi.com)
12  *
13  * Module Name:
14  *  sa.c
15  *
16  * Abstract: Drawbridge specific support functions
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/types.h>
22 #include <linux/pci.h>
23 #include <linux/spinlock.h>
24 #include <linux/blkdev.h>
25 #include <linux/delay.h>
26 #include <linux/completion.h>
27 #include <linux/time.h>
28 #include <linux/interrupt.h>
29
30 #include <scsi/scsi_host.h>
31
32 #include "aacraid.h"
33
34 static irqreturn_t aac_sa_intr(int irq, void *dev_id)
35 {
36         struct aac_dev *dev = dev_id;
37         unsigned short intstat, mask;
38
39         intstat = sa_readw(dev, DoorbellReg_p);
40         /*
41          *      Read mask and invert because drawbridge is reversed.
42          *      This allows us to only service interrupts that have been enabled.
43          */
44         mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
45
46         /* Check to see if this is our interrupt.  If it isn't just return */
47
48         if (intstat & mask) {
49                 if (intstat & PrintfReady) {
50                         aac_printf(dev, sa_readl(dev, Mailbox5));
51                         sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
52                         sa_writew(dev, DoorbellReg_s, PrintfDone);
53                 } else if (intstat & DOORBELL_1) {      // dev -> Host Normal Command Ready
54                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
55                         aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
56                 } else if (intstat & DOORBELL_2) {      // dev -> Host Normal Response Ready
57                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
58                         aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
59                 } else if (intstat & DOORBELL_3) {      // dev -> Host Normal Command Not Full
60                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
61                 } else if (intstat & DOORBELL_4) {      // dev -> Host Normal Response Not Full
62                         sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
63                 }
64                 return IRQ_HANDLED;
65         }
66         return IRQ_NONE;
67 }
68
69 /**
70  *      aac_sa_disable_interrupt        -       disable interrupt
71  *      @dev: Which adapter to enable.
72  */
73
74 static void aac_sa_disable_interrupt (struct aac_dev *dev)
75 {
76         sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
77 }
78
79 /**
80  *      aac_sa_enable_interrupt -       enable interrupt
81  *      @dev: Which adapter to enable.
82  */
83
84 static void aac_sa_enable_interrupt (struct aac_dev *dev)
85 {
86         sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
87                                 DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
88 }
89
90 /**
91  *      aac_sa_notify_adapter           -       handle adapter notification
92  *      @dev:   Adapter that notification is for
93  *      @event: Event to notidy
94  *
95  *      Notify the adapter of an event
96  */
97  
98 static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
99 {
100         switch (event) {
101
102         case AdapNormCmdQue:
103                 sa_writew(dev, DoorbellReg_s,DOORBELL_1);
104                 break;
105         case HostNormRespNotFull:
106                 sa_writew(dev, DoorbellReg_s,DOORBELL_4);
107                 break;
108         case AdapNormRespQue:
109                 sa_writew(dev, DoorbellReg_s,DOORBELL_2);
110                 break;
111         case HostNormCmdNotFull:
112                 sa_writew(dev, DoorbellReg_s,DOORBELL_3);
113                 break;
114         case HostShutdown:
115                 /*
116                 sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
117                 NULL, NULL, NULL, NULL, NULL);
118                 */
119                 break;
120         case FastIo:
121                 sa_writew(dev, DoorbellReg_s,DOORBELL_6);
122                 break;
123         case AdapPrintfDone:
124                 sa_writew(dev, DoorbellReg_s,DOORBELL_5);
125                 break;
126         default:
127                 BUG();
128                 break;
129         }
130 }
131
132
133 /**
134  *      sa_sync_cmd     -       send a command and wait
135  *      @dev: Adapter
136  *      @command: Command to execute
137  *      @p1: first parameter
138  *      @p2: second parameter
139  *      @p3: third parameter
140  *      @p4: forth parameter
141  *      @p5: fifth parameter
142  *      @p6: sixth parameter
143  *      @ret: adapter status
144  *      @r1: first return value
145  *      @r2: second return value
146  *      @r3: third return value
147  *      @r4: forth return value
148  *
149  *      This routine will send a synchronous command to the adapter and wait
150  *      for its completion.
151  */
152 static int sa_sync_cmd(struct aac_dev *dev, u32 command,
153                 u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
154                 u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
155 {
156         unsigned long start;
157         int ok;
158         /*
159          *      Write the Command into Mailbox 0
160          */
161         sa_writel(dev, Mailbox0, command);
162         /*
163          *      Write the parameters into Mailboxes 1 - 4
164          */
165         sa_writel(dev, Mailbox1, p1);
166         sa_writel(dev, Mailbox2, p2);
167         sa_writel(dev, Mailbox3, p3);
168         sa_writel(dev, Mailbox4, p4);
169
170         /*
171          *      Clear the synch command doorbell to start on a clean slate.
172          */
173         sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
174         /*
175          *      Signal that there is a new synch command
176          */
177         sa_writew(dev, DoorbellReg_s, DOORBELL_0);
178
179         ok = 0;
180         start = jiffies;
181
182         while(time_before(jiffies, start+30*HZ))
183         {
184                 /*
185                  *      Delay 5uS so that the monitor gets access
186                  */
187                 udelay(5);
188                 /*
189                  *      Mon110 will set doorbell0 bit when it has 
190                  *      completed the command.
191                  */
192                 if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0)  {
193                         ok = 1;
194                         break;
195                 }
196                 msleep(1);
197         }
198
199         if (ok != 1)
200                 return -ETIMEDOUT;
201         /*
202          *      Clear the synch command doorbell.
203          */
204         sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
205         /*
206          *      Pull the synch status from Mailbox 0.
207          */
208         if (ret)
209                 *ret = sa_readl(dev, Mailbox0);
210         if (r1)
211                 *r1 = sa_readl(dev, Mailbox1);
212         if (r2)
213                 *r2 = sa_readl(dev, Mailbox2);
214         if (r3)
215                 *r3 = sa_readl(dev, Mailbox3);
216         if (r4)
217                 *r4 = sa_readl(dev, Mailbox4);
218         return 0;
219 }
220
221 /**
222  *      aac_sa_interrupt_adapter        -       interrupt an adapter
223  *      @dev: Which adapter to enable.
224  *
225  *      Breakpoint an adapter.
226  */
227  
228 static void aac_sa_interrupt_adapter (struct aac_dev *dev)
229 {
230         sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
231                         NULL, NULL, NULL, NULL, NULL);
232 }
233
234 /**
235  *      aac_sa_start_adapter            -       activate adapter
236  *      @dev:   Adapter
237  *
238  *      Start up processing on an ARM based AAC adapter
239  */
240
241 static void aac_sa_start_adapter(struct aac_dev *dev)
242 {
243         union aac_init *init;
244         /*
245          * Fill in the remaining pieces of the init.
246          */
247         init = dev->init;
248         init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds());
249         /* We can only use a 32 bit address here */
250         sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 
251                         (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
252                         NULL, NULL, NULL, NULL, NULL);
253 }
254
255 static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
256 {
257         return -EINVAL;
258 }
259
260 /**
261  *      aac_sa_check_health
262  *      @dev: device to check if healthy
263  *
264  *      Will attempt to determine if the specified adapter is alive and
265  *      capable of handling requests, returning 0 if alive.
266  */
267 static int aac_sa_check_health(struct aac_dev *dev)
268 {
269         long status = sa_readl(dev, Mailbox7);
270
271         /*
272          *      Check to see if the board failed any self tests.
273          */
274         if (status & SELF_TEST_FAILED)
275                 return -1;
276         /*
277          *      Check to see if the board panic'd while booting.
278          */
279         if (status & KERNEL_PANIC)
280                 return -2;
281         /*
282          *      Wait for the adapter to be up and running. Wait up to 3 minutes
283          */
284         if (!(status & KERNEL_UP_AND_RUNNING))
285                 return -3;
286         /*
287          *      Everything is OK
288          */
289         return 0;
290 }
291
292 /**
293  *      aac_sa_ioremap
294  *      @dev: device to ioremap
295  *      @size: mapping resize request
296  *
297  */
298 static int aac_sa_ioremap(struct aac_dev * dev, u32 size)
299 {
300         if (!size) {
301                 iounmap(dev->regs.sa);
302                 return 0;
303         }
304         dev->base = dev->regs.sa = ioremap(dev->base_start, size);
305         return (dev->base == NULL) ? -1 : 0;
306 }
307
308 /**
309  *      aac_sa_init     -       initialize an ARM based AAC card
310  *      @dev: device to configure
311  *
312  *      Allocate and set up resources for the ARM based AAC variants. The
313  *      device_interface in the commregion will be allocated and linked
314  *      to the comm region.
315  */
316
317 int aac_sa_init(struct aac_dev *dev)
318 {
319         unsigned long start;
320         unsigned long status;
321         int instance;
322         const char *name;
323
324         instance = dev->id;
325         name     = dev->name;
326
327         /*
328          *      Fill in the function dispatch table.
329          */
330
331         dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
332         dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
333         dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
334         dev->a_ops.adapter_notify = aac_sa_notify_adapter;
335         dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
336         dev->a_ops.adapter_check_health = aac_sa_check_health;
337         dev->a_ops.adapter_restart = aac_sa_restart_adapter;
338         dev->a_ops.adapter_start = aac_sa_start_adapter;
339         dev->a_ops.adapter_intr = aac_sa_intr;
340         dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
341         dev->a_ops.adapter_ioremap = aac_sa_ioremap;
342
343         if (aac_sa_ioremap(dev, dev->base_size)) {
344                 printk(KERN_WARNING "%s: unable to map adapter.\n", name);
345                 goto error_iounmap;
346         }
347
348         /*
349          *      Check to see if the board failed any self tests.
350          */
351         if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) {
352                 printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance);
353                 goto error_iounmap;
354         }
355         /*
356          *      Check to see if the board panic'd while booting.
357          */
358         if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) {
359                 printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance);
360                 goto error_iounmap;
361         }
362         start = jiffies;
363         /*
364          *      Wait for the adapter to be up and running. Wait up to 3 minutes.
365          */
366         while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
367                 if (time_after(jiffies, start+startup_timeout*HZ)) {
368                         status = sa_readl(dev, Mailbox7);
369                         printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", 
370                                         name, instance, status);
371                         goto error_iounmap;
372                 }
373                 msleep(1);
374         }
375
376         /*
377          *      First clear out all interrupts.  Then enable the one's that 
378          *      we can handle.
379          */
380         aac_adapter_disable_int(dev);
381         aac_adapter_enable_int(dev);
382
383         if(aac_init_adapter(dev) == NULL)
384                 goto error_irq;
385         dev->sync_mode = 0;     /* sync. mode not supported */
386         if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
387                         IRQF_SHARED, "aacraid", (void *)dev) < 0) {
388                 printk(KERN_WARNING "%s%d: Interrupt unavailable.\n",
389                         name, instance);
390                 goto error_iounmap;
391         }
392         dev->dbg_base = dev->base_start;
393         dev->dbg_base_mapped = dev->base;
394         dev->dbg_size = dev->base_size;
395
396         aac_adapter_enable_int(dev);
397
398         /*
399          *      Tell the adapter that all is configure, and it can start 
400          *      accepting requests
401          */
402         aac_sa_start_adapter(dev);
403         return 0;
404
405 error_irq:
406         aac_sa_disable_interrupt(dev);
407         free_irq(dev->pdev->irq, (void *)dev);
408
409 error_iounmap:
410
411         return -1;
412 }
413