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