18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Aic94xx SAS/SATA driver sequencer interface. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Parts of this code adapted from David Chaw's adp94xx_seq.c. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/gfp.h> 138c2ecf20Sopenharmony_ci#include <linux/pci.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/firmware.h> 168c2ecf20Sopenharmony_ci#include "aic94xx_reg.h" 178c2ecf20Sopenharmony_ci#include "aic94xx_hwi.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "aic94xx_seq.h" 208c2ecf20Sopenharmony_ci#include "aic94xx_dump.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* It takes no more than 0.05 us for an instruction 238c2ecf20Sopenharmony_ci * to complete. So waiting for 1 us should be more than 248c2ecf20Sopenharmony_ci * plenty. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci#define PAUSE_DELAY 1 278c2ecf20Sopenharmony_ci#define PAUSE_TRIES 1000 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const struct firmware *sequencer_fw; 308c2ecf20Sopenharmony_cistatic u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, 318c2ecf20Sopenharmony_ci cseq_idle_loop, lseq_idle_loop; 328c2ecf20Sopenharmony_cistatic const u8 *cseq_code, *lseq_code; 338c2ecf20Sopenharmony_cistatic u32 cseq_code_size, lseq_code_size; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic u16 first_scb_site_no = 0xFFFF; 368c2ecf20Sopenharmony_cistatic u16 last_scb_site_no; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* ---------- Pause/Unpause CSEQ/LSEQ ---------- */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/** 418c2ecf20Sopenharmony_ci * asd_pause_cseq - pause the central sequencer 428c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_cistatic int asd_pause_cseq(struct asd_ha_struct *asd_ha) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci int count = PAUSE_TRIES; 498c2ecf20Sopenharmony_ci u32 arp2ctl; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); 528c2ecf20Sopenharmony_ci if (arp2ctl & PAUSED) 538c2ecf20Sopenharmony_ci return 0; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl | EPAUSE); 568c2ecf20Sopenharmony_ci do { 578c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); 588c2ecf20Sopenharmony_ci if (arp2ctl & PAUSED) 598c2ecf20Sopenharmony_ci return 0; 608c2ecf20Sopenharmony_ci udelay(PAUSE_DELAY); 618c2ecf20Sopenharmony_ci } while (--count > 0); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci ASD_DPRINTK("couldn't pause CSEQ\n"); 648c2ecf20Sopenharmony_ci return -1; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/** 688c2ecf20Sopenharmony_ci * asd_unpause_cseq - unpause the central sequencer. 698c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure. 708c2ecf20Sopenharmony_ci * 718c2ecf20Sopenharmony_ci * Return 0 on success, negative on error. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_cistatic int asd_unpause_cseq(struct asd_ha_struct *asd_ha) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci u32 arp2ctl; 768c2ecf20Sopenharmony_ci int count = PAUSE_TRIES; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); 798c2ecf20Sopenharmony_ci if (!(arp2ctl & PAUSED)) 808c2ecf20Sopenharmony_ci return 0; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl & ~EPAUSE); 838c2ecf20Sopenharmony_ci do { 848c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); 858c2ecf20Sopenharmony_ci if (!(arp2ctl & PAUSED)) 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci udelay(PAUSE_DELAY); 888c2ecf20Sopenharmony_ci } while (--count > 0); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci ASD_DPRINTK("couldn't unpause the CSEQ\n"); 918c2ecf20Sopenharmony_ci return -1; 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/** 958c2ecf20Sopenharmony_ci * asd_seq_pause_lseq - pause a link sequencer 968c2ecf20Sopenharmony_ci * @asd_ha: pointer to a host adapter structure 978c2ecf20Sopenharmony_ci * @lseq: link sequencer of interest 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * Return 0 on success, negative on error. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_cistatic int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci u32 arp2ctl; 1048c2ecf20Sopenharmony_ci int count = PAUSE_TRIES; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); 1078c2ecf20Sopenharmony_ci if (arp2ctl & PAUSED) 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl | EPAUSE); 1118c2ecf20Sopenharmony_ci do { 1128c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); 1138c2ecf20Sopenharmony_ci if (arp2ctl & PAUSED) 1148c2ecf20Sopenharmony_ci return 0; 1158c2ecf20Sopenharmony_ci udelay(PAUSE_DELAY); 1168c2ecf20Sopenharmony_ci } while (--count > 0); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci ASD_DPRINTK("couldn't pause LSEQ %d\n", lseq); 1198c2ecf20Sopenharmony_ci return -1; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/** 1238c2ecf20Sopenharmony_ci * asd_pause_lseq - pause the link sequencer(s) 1248c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 1258c2ecf20Sopenharmony_ci * @lseq_mask: mask of link sequencers of interest 1268c2ecf20Sopenharmony_ci * 1278c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_cistatic int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci int lseq; 1328c2ecf20Sopenharmony_ci int err = 0; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) { 1358c2ecf20Sopenharmony_ci err = asd_seq_pause_lseq(asd_ha, lseq); 1368c2ecf20Sopenharmony_ci if (err) 1378c2ecf20Sopenharmony_ci return err; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci return err; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/** 1448c2ecf20Sopenharmony_ci * asd_seq_unpause_lseq - unpause a link sequencer 1458c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 1468c2ecf20Sopenharmony_ci * @lseq: link sequencer of interest 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Return 0 on success, negative on error. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci u32 arp2ctl; 1538c2ecf20Sopenharmony_ci int count = PAUSE_TRIES; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); 1568c2ecf20Sopenharmony_ci if (!(arp2ctl & PAUSED)) 1578c2ecf20Sopenharmony_ci return 0; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl & ~EPAUSE); 1608c2ecf20Sopenharmony_ci do { 1618c2ecf20Sopenharmony_ci arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); 1628c2ecf20Sopenharmony_ci if (!(arp2ctl & PAUSED)) 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci udelay(PAUSE_DELAY); 1658c2ecf20Sopenharmony_ci } while (--count > 0); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci ASD_DPRINTK("couldn't unpause LSEQ %d\n", lseq); 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* ---------- Downloading CSEQ/LSEQ microcode ---------- */ 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog, 1758c2ecf20Sopenharmony_ci u32 size) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci u32 addr = CSEQ_RAM_REG_BASE_ADR; 1788c2ecf20Sopenharmony_ci const u32 *prog = (u32 *) _prog; 1798c2ecf20Sopenharmony_ci u32 i; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci for (i = 0; i < size; i += 4, prog++, addr += 4) { 1828c2ecf20Sopenharmony_ci u32 val = asd_read_reg_dword(asd_ha, addr); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (le32_to_cpu(*prog) != val) { 1858c2ecf20Sopenharmony_ci asd_printk("%s: cseq verify failed at %u " 1868c2ecf20Sopenharmony_ci "read:0x%x, wanted:0x%x\n", 1878c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev), 1888c2ecf20Sopenharmony_ci i, val, le32_to_cpu(*prog)); 1898c2ecf20Sopenharmony_ci return -1; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci ASD_DPRINTK("verified %d bytes, passed\n", size); 1938c2ecf20Sopenharmony_ci return 0; 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/** 1978c2ecf20Sopenharmony_ci * asd_verify_lseq - verify the microcode of a link sequencer 1988c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 1998c2ecf20Sopenharmony_ci * @_prog: pointer to the microcode 2008c2ecf20Sopenharmony_ci * @size: size of the microcode in bytes 2018c2ecf20Sopenharmony_ci * @lseq: link sequencer of interest 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * The link sequencer code is accessed in 4 KB pages, which are selected 2048c2ecf20Sopenharmony_ci * by setting LmRAMPAGE (bits 8 and 9) of the LmBISTCTL1 register. 2058c2ecf20Sopenharmony_ci * The 10 KB LSEQm instruction code is mapped, page at a time, at 2068c2ecf20Sopenharmony_ci * LmSEQRAM address. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_cistatic int asd_verify_lseq(struct asd_ha_struct *asd_ha, const u8 *_prog, 2098c2ecf20Sopenharmony_ci u32 size, int lseq) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci#define LSEQ_CODEPAGE_SIZE 4096 2128c2ecf20Sopenharmony_ci int pages = (size + LSEQ_CODEPAGE_SIZE - 1) / LSEQ_CODEPAGE_SIZE; 2138c2ecf20Sopenharmony_ci u32 page; 2148c2ecf20Sopenharmony_ci const u32 *prog = (u32 *) _prog; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci for (page = 0; page < pages; page++) { 2178c2ecf20Sopenharmony_ci u32 i; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmBISTCTL1(lseq), 2208c2ecf20Sopenharmony_ci page << LmRAMPAGE_LSHIFT); 2218c2ecf20Sopenharmony_ci for (i = 0; size > 0 && i < LSEQ_CODEPAGE_SIZE; 2228c2ecf20Sopenharmony_ci i += 4, prog++, size-=4) { 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci u32 val = asd_read_reg_dword(asd_ha, LmSEQRAM(lseq)+i); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (le32_to_cpu(*prog) != val) { 2278c2ecf20Sopenharmony_ci asd_printk("%s: LSEQ%d verify failed " 2288c2ecf20Sopenharmony_ci "page:%d, offs:%d\n", 2298c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev), 2308c2ecf20Sopenharmony_ci lseq, page, i); 2318c2ecf20Sopenharmony_ci return -1; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci ASD_DPRINTK("LSEQ%d verified %d bytes, passed\n", lseq, 2368c2ecf20Sopenharmony_ci (int)((u8 *)prog-_prog)); 2378c2ecf20Sopenharmony_ci return 0; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/** 2418c2ecf20Sopenharmony_ci * asd_verify_seq -- verify CSEQ/LSEQ microcode 2428c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 2438c2ecf20Sopenharmony_ci * @prog: pointer to microcode 2448c2ecf20Sopenharmony_ci * @size: size of the microcode 2458c2ecf20Sopenharmony_ci * @lseq_mask: if 0, verify CSEQ microcode, else mask of LSEQs of interest 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * Return 0 if microcode is correct, negative on mismatch. 2488c2ecf20Sopenharmony_ci */ 2498c2ecf20Sopenharmony_cistatic int asd_verify_seq(struct asd_ha_struct *asd_ha, const u8 *prog, 2508c2ecf20Sopenharmony_ci u32 size, u8 lseq_mask) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci if (lseq_mask == 0) 2538c2ecf20Sopenharmony_ci return asd_verify_cseq(asd_ha, prog, size); 2548c2ecf20Sopenharmony_ci else { 2558c2ecf20Sopenharmony_ci int lseq, err; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) { 2588c2ecf20Sopenharmony_ci err = asd_verify_lseq(asd_ha, prog, size, lseq); 2598c2ecf20Sopenharmony_ci if (err) 2608c2ecf20Sopenharmony_ci return err; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci return 0; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci#define ASD_DMA_MODE_DOWNLOAD 2678c2ecf20Sopenharmony_ci#ifdef ASD_DMA_MODE_DOWNLOAD 2688c2ecf20Sopenharmony_ci/* This is the size of the CSEQ Mapped instruction page */ 2698c2ecf20Sopenharmony_ci#define MAX_DMA_OVLY_COUNT ((1U << 14)-1) 2708c2ecf20Sopenharmony_cistatic int asd_download_seq(struct asd_ha_struct *asd_ha, 2718c2ecf20Sopenharmony_ci const u8 * const prog, u32 size, u8 lseq_mask) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci u32 comstaten; 2748c2ecf20Sopenharmony_ci u32 reg; 2758c2ecf20Sopenharmony_ci int page; 2768c2ecf20Sopenharmony_ci const int pages = (size + MAX_DMA_OVLY_COUNT - 1) / MAX_DMA_OVLY_COUNT; 2778c2ecf20Sopenharmony_ci struct asd_dma_tok *token; 2788c2ecf20Sopenharmony_ci int err = 0; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (size % 4) { 2818c2ecf20Sopenharmony_ci asd_printk("sequencer program not multiple of 4\n"); 2828c2ecf20Sopenharmony_ci return -1; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci asd_pause_cseq(asd_ha); 2868c2ecf20Sopenharmony_ci asd_pause_lseq(asd_ha, 0xFF); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci /* save, disable and clear interrupts */ 2898c2ecf20Sopenharmony_ci comstaten = asd_read_reg_dword(asd_ha, COMSTATEN); 2908c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, COMSTATEN, 0); 2918c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, COMSTAT, COMSTAT_MASK); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN); 2948c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CHIMINT, CHIMINT_MASK); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci token = asd_alloc_coherent(asd_ha, MAX_DMA_OVLY_COUNT, GFP_KERNEL); 2978c2ecf20Sopenharmony_ci if (!token) { 2988c2ecf20Sopenharmony_ci asd_printk("out of memory for dma SEQ download\n"); 2998c2ecf20Sopenharmony_ci err = -ENOMEM; 3008c2ecf20Sopenharmony_ci goto out; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci ASD_DPRINTK("dma-ing %d bytes\n", size); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci for (page = 0; page < pages; page++) { 3058c2ecf20Sopenharmony_ci int i; 3068c2ecf20Sopenharmony_ci u32 left = min(size-page*MAX_DMA_OVLY_COUNT, 3078c2ecf20Sopenharmony_ci (u32)MAX_DMA_OVLY_COUNT); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci memcpy(token->vaddr, prog + page*MAX_DMA_OVLY_COUNT, left); 3108c2ecf20Sopenharmony_ci asd_write_reg_addr(asd_ha, OVLYDMAADR, token->dma_handle); 3118c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, OVLYDMACNT, left); 3128c2ecf20Sopenharmony_ci reg = !page ? RESETOVLYDMA : 0; 3138c2ecf20Sopenharmony_ci reg |= (STARTOVLYDMA | OVLYHALTERR); 3148c2ecf20Sopenharmony_ci reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); 3158c2ecf20Sopenharmony_ci /* Start DMA. */ 3168c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci for (i = PAUSE_TRIES*100; i > 0; i--) { 3198c2ecf20Sopenharmony_ci u32 dmadone = asd_read_reg_dword(asd_ha, OVLYDMACTL); 3208c2ecf20Sopenharmony_ci if (!(dmadone & OVLYDMAACT)) 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci udelay(PAUSE_DELAY); 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci reg = asd_read_reg_dword(asd_ha, COMSTAT); 3278c2ecf20Sopenharmony_ci if (!(reg & OVLYDMADONE) || (reg & OVLYERR) 3288c2ecf20Sopenharmony_ci || (asd_read_reg_dword(asd_ha, CHIMINT) & DEVEXCEPT_MASK)){ 3298c2ecf20Sopenharmony_ci asd_printk("%s: error DMA-ing sequencer code\n", 3308c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev)); 3318c2ecf20Sopenharmony_ci err = -ENODEV; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci asd_free_coherent(asd_ha, token); 3358c2ecf20Sopenharmony_ci out: 3368c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, COMSTATEN, comstaten); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci return err ? : asd_verify_seq(asd_ha, prog, size, lseq_mask); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci#else /* ASD_DMA_MODE_DOWNLOAD */ 3418c2ecf20Sopenharmony_cistatic int asd_download_seq(struct asd_ha_struct *asd_ha, const u8 *_prog, 3428c2ecf20Sopenharmony_ci u32 size, u8 lseq_mask) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci int i; 3458c2ecf20Sopenharmony_ci u32 reg = 0; 3468c2ecf20Sopenharmony_ci const u32 *prog = (u32 *) _prog; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci if (size % 4) { 3498c2ecf20Sopenharmony_ci asd_printk("sequencer program not multiple of 4\n"); 3508c2ecf20Sopenharmony_ci return -1; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci asd_pause_cseq(asd_ha); 3548c2ecf20Sopenharmony_ci asd_pause_lseq(asd_ha, 0xFF); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); 3578c2ecf20Sopenharmony_ci reg |= PIOCMODE; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, OVLYDMACNT, size); 3608c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci ASD_DPRINTK("downloading %s sequencer%s in PIO mode...\n", 3638c2ecf20Sopenharmony_ci lseq_mask ? "LSEQ" : "CSEQ", lseq_mask ? "s" : ""); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci for (i = 0; i < size; i += 4, prog++) 3668c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, SPIODATA, *prog); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci reg = (reg & ~PIOCMODE) | OVLYHALTERR; 3698c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci return asd_verify_seq(asd_ha, _prog, size, lseq_mask); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci#endif /* ASD_DMA_MODE_DOWNLOAD */ 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci/** 3768c2ecf20Sopenharmony_ci * asd_seq_download_seqs - download the sequencer microcode 3778c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Download the central and link sequencer microcode. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_cistatic int asd_seq_download_seqs(struct asd_ha_struct *asd_ha) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci int err; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (!asd_ha->hw_prof.enabled_phys) { 3868c2ecf20Sopenharmony_ci asd_printk("%s: no enabled phys!\n", pci_name(asd_ha->pcidev)); 3878c2ecf20Sopenharmony_ci return -ENODEV; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* Download the CSEQ */ 3918c2ecf20Sopenharmony_ci ASD_DPRINTK("downloading CSEQ...\n"); 3928c2ecf20Sopenharmony_ci err = asd_download_seq(asd_ha, cseq_code, cseq_code_size, 0); 3938c2ecf20Sopenharmony_ci if (err) { 3948c2ecf20Sopenharmony_ci asd_printk("CSEQ download failed:%d\n", err); 3958c2ecf20Sopenharmony_ci return err; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* Download the Link Sequencers code. All of the Link Sequencers 3998c2ecf20Sopenharmony_ci * microcode can be downloaded at the same time. 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci ASD_DPRINTK("downloading LSEQs...\n"); 4028c2ecf20Sopenharmony_ci err = asd_download_seq(asd_ha, lseq_code, lseq_code_size, 4038c2ecf20Sopenharmony_ci asd_ha->hw_prof.enabled_phys); 4048c2ecf20Sopenharmony_ci if (err) { 4058c2ecf20Sopenharmony_ci /* Try it one at a time */ 4068c2ecf20Sopenharmony_ci u8 lseq; 4078c2ecf20Sopenharmony_ci u8 lseq_mask = asd_ha->hw_prof.enabled_phys; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) { 4108c2ecf20Sopenharmony_ci err = asd_download_seq(asd_ha, lseq_code, 4118c2ecf20Sopenharmony_ci lseq_code_size, 1<<lseq); 4128c2ecf20Sopenharmony_ci if (err) 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci if (err) 4178c2ecf20Sopenharmony_ci asd_printk("LSEQs download failed:%d\n", err); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return err; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* ---------- Initializing the chip, chip memory, etc. ---------- */ 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/** 4258c2ecf20Sopenharmony_ci * asd_init_cseq_mip - initialize CSEQ mode independent pages 4-7 4268c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_cistatic void asd_init_cseq_mip(struct asd_ha_struct *asd_ha) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci /* CSEQ Mode Independent, page 4 setup. */ 4318c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EXE_HEAD, 0xFFFF); 4328c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EXE_TAIL, 0xFFFF); 4338c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_DONE_HEAD, 0xFFFF); 4348c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_DONE_TAIL, 0xFFFF); 4358c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_SEND_HEAD, 0xFFFF); 4368c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_SEND_TAIL, 0xFFFF); 4378c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_HEAD, 0xFFFF); 4388c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_TAIL, 0xFFFF); 4398c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_COPY_HEAD, 0xFFFF); 4408c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_COPY_TAIL, 0xFFFF); 4418c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_REG0, 0); 4428c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_REG1, 0); 4438c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_REG2, 0); 4448c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_LINK_CTL_Q_MAP, 0); 4458c2ecf20Sopenharmony_ci { 4468c2ecf20Sopenharmony_ci u8 con = asd_read_reg_byte(asd_ha, CCONEXIST); 4478c2ecf20Sopenharmony_ci u8 val = hweight8(con); 4488c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_MAX_CSEQ_MODE, (val<<4)|val); 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_FREE_LIST_HACK_COUNT, 0); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* CSEQ Mode independent, page 5 setup. */ 4538c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE, 0); 4548c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE+4, 0); 4558c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT, 0); 4568c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT+4, 0); 4578c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_HEAD, 0xFFFF); 4588c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_TAIL, 0xFFFF); 4598c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_NEED_EST_NEXUS_SCB, 0); 4608c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_HEAD, 0); 4618c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_TAIL, 0); 4628c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_SCB_OFFSET, 0); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* CSEQ Mode independent, page 6 setup. */ 4658c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR0, 0); 4668c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR1, 0); 4678c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_SCBPTR, 0); 4688c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_INT_ROUT_MODE, 0); 4698c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_ISR_SCRATCH_FLAGS, 0); 4708c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_SINDEX, 0); 4718c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_DINDEX, 0); 4728c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_HEAD, 0xFFFF); 4738c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_TAIL, 0xFFFF); 4748c2ecf20Sopenharmony_ci /* Calculate the free scb mask. */ 4758c2ecf20Sopenharmony_ci { 4768c2ecf20Sopenharmony_ci u16 cmdctx = asd_get_cmdctx_size(asd_ha); 4778c2ecf20Sopenharmony_ci cmdctx = (~((cmdctx/128)-1)) >> 8; 4788c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_FREE_SCB_MASK, (u8)cmdctx); 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_HEAD, 4818c2ecf20Sopenharmony_ci first_scb_site_no); 4828c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_TAIL, 4838c2ecf20Sopenharmony_ci last_scb_site_no); 4848c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_HEAD, 0xFFFF); 4858c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_TAIL, 0xFFFF); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci /* CSEQ Mode independent, page 7 setup. */ 4888c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE, 0); 4898c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE+4, 0); 4908c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT, 0); 4918c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT+4, 0); 4928c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_HEAD, 0xFFFF); 4938c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_TAIL, 0xFFFF); 4948c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_NEED_EMPTY_SCB, 0); 4958c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_HEAD, 0); 4968c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_TAIL, 0); 4978c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_EMPTY_SCB_OFFSET, 0); 4988c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_PRIMITIVE_DATA, 0); 4998c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_TIMEOUT_CONST, 0); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci/** 5038c2ecf20Sopenharmony_ci * asd_init_cseq_mdp - initialize CSEQ Mode dependent pages 5048c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 5058c2ecf20Sopenharmony_ci */ 5068c2ecf20Sopenharmony_cistatic void asd_init_cseq_mdp(struct asd_ha_struct *asd_ha) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci int i; 5098c2ecf20Sopenharmony_ci int moffs; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci moffs = CSEQ_PAGE_SIZE * 2; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, modes 0-7, page 0 setup. */ 5148c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 5158c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SINDEX, 0); 5168c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCBPTR, 0); 5178c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_HEAD, 0xFFFF); 5188c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_TAIL, 0xFFFF); 5198c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCRPAGE, 0); 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, mode 0-7, page 1 and 2 shall be ignored. */ 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, mode 8, page 0 setup. */ 5258c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_RET_ADDR, 0xFFFF); 5268c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_RET_SCBPTR, 0); 5278c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_SAVE_SCBPTR, 0); 5288c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_EMPTY_TRANS_CTX, 0); 5298c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_RESP_LEN, 0); 5308c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_TMF_SCBPTR, 0); 5318c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_GLOBAL_PREV_SCB, 0); 5328c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_GLOBAL_HEAD, 0); 5338c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_CLEAR_LU_HEAD, 0); 5348c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_TMF_OPCODE, 0); 5358c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_SCRATCH_FLAGS, 0); 5368c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_HSB_SITE, 0); 5378c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_SCB_SITE, 5388c2ecf20Sopenharmony_ci (u16)last_scb_site_no+1); 5398c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_DDB_SITE, 5408c2ecf20Sopenharmony_ci (u16)asd_ha->hw_prof.max_ddbs); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, mode 8, page 1 setup. */ 5438c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR, 0); 5448c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR + 4, 0); 5458c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK, 0); 5468c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK + 4, 0); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, mode 8, page 2 setup. */ 5498c2ecf20Sopenharmony_ci /* Tell the sequencer the bus address of the first SCB. */ 5508c2ecf20Sopenharmony_ci asd_write_reg_addr(asd_ha, CSEQ_HQ_NEW_POINTER, 5518c2ecf20Sopenharmony_ci asd_ha->seq.next_scb.dma_handle); 5528c2ecf20Sopenharmony_ci ASD_DPRINTK("First SCB dma_handle: 0x%llx\n", 5538c2ecf20Sopenharmony_ci (unsigned long long)asd_ha->seq.next_scb.dma_handle); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Tell the sequencer the first Done List entry address. */ 5568c2ecf20Sopenharmony_ci asd_write_reg_addr(asd_ha, CSEQ_HQ_DONE_BASE, 5578c2ecf20Sopenharmony_ci asd_ha->seq.actual_dl->dma_handle); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci /* Initialize the Q_DONE_POINTER with the least significant 5608c2ecf20Sopenharmony_ci * 4 bytes of the first Done List address. */ 5618c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQ_HQ_DONE_POINTER, 5628c2ecf20Sopenharmony_ci ASD_BUSADDR_LO(asd_ha->seq.actual_dl->dma_handle)); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQ_HQ_DONE_PASS, ASD_DEF_DL_TOGGLE); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* CSEQ Mode dependent, mode 8, page 3 shall be ignored. */ 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci/** 5708c2ecf20Sopenharmony_ci * asd_init_cseq_scratch -- setup and init CSEQ 5718c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 5728c2ecf20Sopenharmony_ci * 5738c2ecf20Sopenharmony_ci * Setup and initialize Central sequencers. Initialize the mode 5748c2ecf20Sopenharmony_ci * independent and dependent scratch page to the default settings. 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_cistatic void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci asd_init_cseq_mip(asd_ha); 5798c2ecf20Sopenharmony_ci asd_init_cseq_mdp(asd_ha); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci/** 5838c2ecf20Sopenharmony_ci * asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3 5848c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 5858c2ecf20Sopenharmony_ci * @lseq: link sequencer 5868c2ecf20Sopenharmony_ci */ 5878c2ecf20Sopenharmony_cistatic void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci int i; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* LSEQ Mode independent page 0 setup. */ 5928c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_HEAD(lseq), 0xFFFF); 5938c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_TAIL(lseq), 0xFFFF); 5948c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LINK_NUMBER(lseq), lseq); 5958c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SCRATCH_FLAGS(lseq), 5968c2ecf20Sopenharmony_ci ASD_NOTIFY_ENABLE_SPINUP); 5978c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_CONNECTION_STATE(lseq),0x08000000); 5988c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_CONCTL(lseq), 0); 5998c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_CONSTAT(lseq), 0); 6008c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_CONNECTION_MODES(lseq), 0); 6018c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_REG1_ISR(lseq), 0); 6028c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_REG2_ISR(lseq), 0); 6038c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_REG3_ISR(lseq), 0); 6048c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq), 0); 6058c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq)+4, 0); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* LSEQ Mode independent page 1 setup. */ 6088c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR0(lseq), 0xFFFF); 6098c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR1(lseq), 0xFFFF); 6108c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR2(lseq), 0xFFFF); 6118c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR3(lseq), 0xFFFF); 6128c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE0(lseq), 0); 6138c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE1(lseq), 0); 6148c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE2(lseq), 0); 6158c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE3(lseq), 0); 6168c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_HEAD(lseq), 0); 6178c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_TAIL(lseq), 0); 6188c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_BUF_AVAIL(lseq), 0); 6198c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_TIMEOUT_CONST(lseq), 0); 6208c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_SINDEX(lseq), 0); 6218c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_DINDEX(lseq), 0); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* LSEQ Mode Independent page 2 setup. */ 6248c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR0(lseq), 0xFFFF); 6258c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR1(lseq), 0xFFFF); 6268c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR2(lseq), 0xFFFF); 6278c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR3(lseq), 0xFFFF); 6288c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD0(lseq), 0); 6298c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD1(lseq), 0); 6308c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD2(lseq), 0); 6318c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD3(lseq), 0); 6328c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_HEAD(lseq), 0); 6338c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_TAIL(lseq), 0); 6348c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_BUFS_AVAIL(lseq), 0); 6358c2ecf20Sopenharmony_ci for (i = 0; i < 12; i += 4) 6368c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_ATA_SCR_REGS(lseq) + i, 0); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* LSEQ Mode Independent page 3 setup. */ 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci /* Device present timer timeout */ 6418c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TMR_TOUT_CONST(lseq), 6428c2ecf20Sopenharmony_ci ASD_DEV_PRESENT_TIMEOUT); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* SATA interlock timer disabled */ 6458c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_SATA_INTERLOCK_TIMEOUT(lseq), 6468c2ecf20Sopenharmony_ci ASD_SATA_INTERLOCK_TIMEOUT); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* STP shutdown timer timeout constant, IGNORED by the sequencer, 6498c2ecf20Sopenharmony_ci * always 0. */ 6508c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMEOUT(lseq), 6518c2ecf20Sopenharmony_ci ASD_STP_SHUTDOWN_TIMEOUT); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_SRST_ASSERT_TIMEOUT(lseq), 6548c2ecf20Sopenharmony_ci ASD_SRST_ASSERT_TIMEOUT); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMEOUT(lseq), 6578c2ecf20Sopenharmony_ci ASD_RCV_FIS_TIMEOUT); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_ONE_MILLISEC_TIMEOUT(lseq), 6608c2ecf20Sopenharmony_ci ASD_ONE_MILLISEC_TIMEOUT); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci /* COM_INIT timer */ 6638c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_TEN_MS_COMINIT_TIMEOUT(lseq), 6648c2ecf20Sopenharmony_ci ASD_TEN_MILLISEC_TIMEOUT); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMEOUT(lseq), 6678c2ecf20Sopenharmony_ci ASD_SMP_RCV_TIMEOUT); 6688c2ecf20Sopenharmony_ci} 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci/** 6718c2ecf20Sopenharmony_ci * asd_init_lseq_mdp -- initialize LSEQ mode dependent pages. 6728c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 6738c2ecf20Sopenharmony_ci * @lseq: link sequencer 6748c2ecf20Sopenharmony_ci */ 6758c2ecf20Sopenharmony_cistatic void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci int i; 6788c2ecf20Sopenharmony_ci u32 moffs; 6798c2ecf20Sopenharmony_ci u16 ret_addr[] = { 6808c2ecf20Sopenharmony_ci 0xFFFF, /* mode 0 */ 6818c2ecf20Sopenharmony_ci 0xFFFF, /* mode 1 */ 6828c2ecf20Sopenharmony_ci mode2_task, /* mode 2 */ 6838c2ecf20Sopenharmony_ci 0, 6848c2ecf20Sopenharmony_ci 0xFFFF, /* mode 4/5 */ 6858c2ecf20Sopenharmony_ci 0xFFFF, /* mode 4/5 */ 6868c2ecf20Sopenharmony_ci }; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* 6898c2ecf20Sopenharmony_ci * Mode 0,1,2 and 4/5 have common field on page 0 for the first 6908c2ecf20Sopenharmony_ci * 14 bytes. 6918c2ecf20Sopenharmony_ci */ 6928c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 6938c2ecf20Sopenharmony_ci moffs = i * LSEQ_MODE_SCRATCH_SIZE; 6948c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR(lseq)+moffs, 6958c2ecf20Sopenharmony_ci ret_addr[i]); 6968c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_REG0_MODE(lseq)+moffs, 0); 6978c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_MODE_FLAGS(lseq)+moffs, 0); 6988c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR2(lseq)+moffs,0xFFFF); 6998c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR1(lseq)+moffs,0xFFFF); 7008c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_OPCODE_TO_CSEQ(lseq)+moffs,0); 7018c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_DATA_TO_CSEQ(lseq)+moffs,0); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci /* 7048c2ecf20Sopenharmony_ci * Mode 5 page 0 overlaps the same scratch page with Mode 0 page 3. 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7078c2ecf20Sopenharmony_ci LmSEQ_RET_ADDR(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 7088c2ecf20Sopenharmony_ci ret_addr[5]); 7098c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7108c2ecf20Sopenharmony_ci LmSEQ_REG0_MODE(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); 7118c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7128c2ecf20Sopenharmony_ci LmSEQ_MODE_FLAGS(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); 7138c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7148c2ecf20Sopenharmony_ci LmSEQ_RET_ADDR2(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); 7158c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7168c2ecf20Sopenharmony_ci LmSEQ_RET_ADDR1(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); 7178c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, 7188c2ecf20Sopenharmony_ci LmSEQ_OPCODE_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); 7198c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, 7208c2ecf20Sopenharmony_ci LmSEQ_DATA_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* LSEQ Mode dependent 0, page 0 setup. */ 7238c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_DDB_SITE(lseq), 7248c2ecf20Sopenharmony_ci (u16)asd_ha->hw_prof.max_ddbs); 7258c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_EMPTY_TRANS_CTX(lseq), 0); 7268c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_RESP_LEN(lseq), 0); 7278c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_SCB_SITE(lseq), 7288c2ecf20Sopenharmony_ci (u16)last_scb_site_no+1); 7298c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq), 7308c2ecf20Sopenharmony_ci (u16) ((LmM0INTEN_MASK & 0xFFFF0000) >> 16)); 7318c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq) + 2, 7328c2ecf20Sopenharmony_ci (u16) LmM0INTEN_MASK & 0xFFFF); 7338c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_FRM_LEN(lseq), 0); 7348c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_PROTOCOL(lseq), 0); 7358c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_RESP_STATUS(lseq), 0); 7368c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LAST_LOADED_SGE(lseq), 0); 7378c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_SAVE_SCBPTR(lseq), 0); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* LSEQ mode dependent, mode 1, page 0 setup. */ 7408c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_Q_XMIT_HEAD(lseq), 0xFFFF); 7418c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_M1_EMPTY_TRANS_CTX(lseq), 0); 7428c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_INI_CONN_TAG(lseq), 0); 7438c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_FAILED_OPEN_STATUS(lseq), 0); 7448c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_XMIT_REQUEST_TYPE(lseq), 0); 7458c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_M1_RESP_STATUS(lseq), 0); 7468c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_M1_LAST_LOADED_SGE(lseq), 0); 7478c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_M1_SAVE_SCBPTR(lseq), 0); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* LSEQ Mode dependent mode 2, page 0 setup */ 7508c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_PORT_COUNTER(lseq), 0); 7518c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_PM_TABLE_PTR(lseq), 0); 7528c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_SATA_INTERLOCK_TMR_SAVE(lseq), 0); 7538c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_IP_BITL(lseq), 0); 7548c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_COPY_SMP_CONN_TAG(lseq), 0); 7558c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_P0M2_OFFS1AH(lseq), 0); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci /* LSEQ Mode dependent, mode 4/5, page 0 setup. */ 7588c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_STATUS(lseq), 0); 7598c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_MODE(lseq), 0); 7608c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_Q_LINK_HEAD(lseq), 0xFFFF); 7618c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_ERR(lseq), 0); 7628c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_SIGNALS(lseq), 0); 7638c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SAS_RESET_MODE(lseq), 0); 7648c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_LINK_RESET_RETRY_COUNT(lseq), 0); 7658c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_NUM_LINK_RESET_RETRIES(lseq), 0); 7668c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_OOB_INT_ENABLES(lseq), 0); 7678c2ecf20Sopenharmony_ci /* 7688c2ecf20Sopenharmony_ci * Set the desired interval between transmissions of the NOTIFY 7698c2ecf20Sopenharmony_ci * (ENABLE SPINUP) primitive. Must be initialized to val - 1. 7708c2ecf20Sopenharmony_ci */ 7718c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_TIMEOUT(lseq), 7728c2ecf20Sopenharmony_ci ASD_NOTIFY_TIMEOUT - 1); 7738c2ecf20Sopenharmony_ci /* No delay for the first NOTIFY to be sent to the attached target. */ 7748c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq), 7758c2ecf20Sopenharmony_ci ASD_NOTIFY_DOWN_COUNT); 7768c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq), 7778c2ecf20Sopenharmony_ci ASD_NOTIFY_DOWN_COUNT); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci /* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */ 7808c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 7818c2ecf20Sopenharmony_ci int j; 7828c2ecf20Sopenharmony_ci /* Start from Page 1 of Mode 0 and 1. */ 7838c2ecf20Sopenharmony_ci moffs = LSEQ_PAGE_SIZE + i*LSEQ_MODE_SCRATCH_SIZE; 7848c2ecf20Sopenharmony_ci /* All the fields of page 1 can be initialized to 0. */ 7858c2ecf20Sopenharmony_ci for (j = 0; j < LSEQ_PAGE_SIZE; j += 4) 7868c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSCRATCH(lseq)+moffs+j,0); 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* LSEQ Mode dependent, mode 2, page 1 setup. */ 7908c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_INVALID_DWORD_COUNT(lseq), 0); 7918c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_DISPARITY_ERROR_COUNT(lseq), 0); 7928c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_LOSS_OF_SYNC_COUNT(lseq), 0); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci /* LSEQ Mode dependent, mode 4/5, page 1. */ 7958c2ecf20Sopenharmony_ci for (i = 0; i < LSEQ_PAGE_SIZE; i+=4) 7968c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq)+i, 0); 7978c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq), 0xFF); 7988c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq), 0xFF); 7998c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+1,0xFF); 8008c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+2,0xFF); 8018c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq), 0xFF); 8028c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+1, 0xFF); 8038c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+2, 0xFF); 8048c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_DATA_OFFSET(lseq), 0xFFFFFFFF); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* LSEQ Mode dependent, mode 0, page 2 setup. */ 8078c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMER_TERM_TS(lseq), 0); 8088c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_DEVICE_BITS(lseq), 0); 8098c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmSEQ_SDB_DDB(lseq), 0); 8108c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SDB_NUM_TAGS(lseq), 0); 8118c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSEQ_SDB_CURR_TAG(lseq), 0); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci /* LSEQ Mode Dependent 1, page 2 setup. */ 8148c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq), 0); 8158c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq)+4, 0); 8168c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_OPEN_TIMER_TERM_TS(lseq), 0); 8178c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_SRST_AS_TIMER_TERM_TS(lseq), 0); 8188c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_LAST_LOADED_SG_EL(lseq), 0); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci /* LSEQ Mode Dependent 2, page 2 setup. */ 8218c2ecf20Sopenharmony_ci /* The LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS is IGNORED by the sequencer, 8228c2ecf20Sopenharmony_ci * i.e. always 0. */ 8238c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS(lseq),0); 8248c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_CLOSE_TIMER_TERM_TS(lseq), 0); 8258c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_BREAK_TIMER_TERM_TS(lseq), 0); 8268c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_DWS_RESET_TIMER_TERM_TS(lseq), 0); 8278c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha,LmSEQ_SATA_INTERLOCK_TIMER_TERM_TS(lseq),0); 8288c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_MCTL_TIMER_TERM_TS(lseq), 0); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* LSEQ Mode Dependent 4/5, page 2 setup. */ 8318c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_COMINIT_TIMER_TERM_TS(lseq), 0); 8328c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_RCV_ID_TIMER_TERM_TS(lseq), 0); 8338c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMER_TERM_TS(lseq), 0); 8348c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TIMER_TERM_TS(lseq), 0); 8358c2ecf20Sopenharmony_ci} 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci/** 8388c2ecf20Sopenharmony_ci * asd_init_lseq_scratch -- setup and init link sequencers 8398c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter struct 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_cistatic void asd_init_lseq_scratch(struct asd_ha_struct *asd_ha) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci u8 lseq; 8448c2ecf20Sopenharmony_ci u8 lseq_mask; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci lseq_mask = asd_ha->hw_prof.enabled_phys; 8478c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) { 8488c2ecf20Sopenharmony_ci asd_init_lseq_mip(asd_ha, lseq); 8498c2ecf20Sopenharmony_ci asd_init_lseq_mdp(asd_ha, lseq); 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci/** 8548c2ecf20Sopenharmony_ci * asd_init_scb_sites -- initialize sequencer SCB sites (memory). 8558c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 8568c2ecf20Sopenharmony_ci * 8578c2ecf20Sopenharmony_ci * This should be done before initializing common CSEQ and LSEQ 8588c2ecf20Sopenharmony_ci * scratch since those areas depend on some computed values here, 8598c2ecf20Sopenharmony_ci * last_scb_site_no, etc. 8608c2ecf20Sopenharmony_ci */ 8618c2ecf20Sopenharmony_cistatic void asd_init_scb_sites(struct asd_ha_struct *asd_ha) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci u16 site_no; 8648c2ecf20Sopenharmony_ci u16 max_scbs = 0; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci for (site_no = asd_ha->hw_prof.max_scbs-1; 8678c2ecf20Sopenharmony_ci site_no != (u16) -1; 8688c2ecf20Sopenharmony_ci site_no--) { 8698c2ecf20Sopenharmony_ci u16 i; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci /* Initialize all fields in the SCB site to 0. */ 8728c2ecf20Sopenharmony_ci for (i = 0; i < ASD_SCB_SIZE; i += 4) 8738c2ecf20Sopenharmony_ci asd_scbsite_write_dword(asd_ha, site_no, i, 0); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* Initialize SCB Site Opcode field to invalid. */ 8768c2ecf20Sopenharmony_ci asd_scbsite_write_byte(asd_ha, site_no, 8778c2ecf20Sopenharmony_ci offsetof(struct scb_header, opcode), 8788c2ecf20Sopenharmony_ci 0xFF); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci /* Initialize SCB Site Flags field to mean a response 8818c2ecf20Sopenharmony_ci * frame has been received. This means inadvertent 8828c2ecf20Sopenharmony_ci * frames received to be dropped. */ 8838c2ecf20Sopenharmony_ci asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* Workaround needed by SEQ to fix a SATA issue is to exclude 8868c2ecf20Sopenharmony_ci * certain SCB sites from the free list. */ 8878c2ecf20Sopenharmony_ci if (!SCB_SITE_VALID(site_no)) 8888c2ecf20Sopenharmony_ci continue; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (last_scb_site_no == 0) 8918c2ecf20Sopenharmony_ci last_scb_site_no = site_no; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* For every SCB site, we need to initialize the 8948c2ecf20Sopenharmony_ci * following fields: Q_NEXT, SCB_OPCODE, SCB_FLAGS, 8958c2ecf20Sopenharmony_ci * and SG Element Flag. */ 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* Q_NEXT field of the last SCB is invalidated. */ 8988c2ecf20Sopenharmony_ci asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci first_scb_site_no = site_no; 9018c2ecf20Sopenharmony_ci max_scbs++; 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci asd_ha->hw_prof.max_scbs = max_scbs; 9048c2ecf20Sopenharmony_ci ASD_DPRINTK("max_scbs:%d\n", asd_ha->hw_prof.max_scbs); 9058c2ecf20Sopenharmony_ci ASD_DPRINTK("first_scb_site_no:0x%x\n", first_scb_site_no); 9068c2ecf20Sopenharmony_ci ASD_DPRINTK("last_scb_site_no:0x%x\n", last_scb_site_no); 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci/** 9108c2ecf20Sopenharmony_ci * asd_init_cseq_cio - initialize CSEQ CIO registers 9118c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 9128c2ecf20Sopenharmony_ci */ 9138c2ecf20Sopenharmony_cistatic void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci int i; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQCOMINTEN, 0); 9188c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQDLCTL, ASD_DL_SIZE_BITS); 9198c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQDLOFFS, 0); 9208c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSEQDLOFFS+1, 0); 9218c2ecf20Sopenharmony_ci asd_ha->seq.scbpro = 0; 9228c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, SCBPRO, 0); 9238c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CSEQCON, 0); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci /* Initialize CSEQ Mode 11 Interrupt Vectors. 9268c2ecf20Sopenharmony_ci * The addresses are 16 bit wide and in dword units. 9278c2ecf20Sopenharmony_ci * The values of their macros are in byte units. 9288c2ecf20Sopenharmony_ci * Thus we have to divide by 4. */ 9298c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CM11INTVEC0, cseq_vecs[0]); 9308c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CM11INTVEC1, cseq_vecs[1]); 9318c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CM11INTVEC2, cseq_vecs[2]); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ 9348c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CARP2INTEN, EN_ARP2HALTC); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* Initialize CSEQ Scratch Page to 0x04. */ 9378c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CSCRATCHPAGE, 0x04); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* Initialize CSEQ Mode[0-8] Dependent registers. */ 9408c2ecf20Sopenharmony_ci /* Initialize Scratch Page to 0. */ 9418c2ecf20Sopenharmony_ci for (i = 0; i < 9; i++) 9428c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CMnSCRATCHPAGE(i), 0); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci /* Reset the ARP2 Program Count. */ 9458c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 9488c2ecf20Sopenharmony_ci /* Initialize Mode n Link m Interrupt Enable. */ 9498c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CMnINTEN(i), EN_CMnRSPMBXF); 9508c2ecf20Sopenharmony_ci /* Initialize Mode n Request Mailbox. */ 9518c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CMnREQMBX(i), 0); 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci/** 9568c2ecf20Sopenharmony_ci * asd_init_lseq_cio -- initialize LmSEQ CIO registers 9578c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 9588c2ecf20Sopenharmony_ci * @lseq: link sequencer 9598c2ecf20Sopenharmony_ci */ 9608c2ecf20Sopenharmony_cistatic void asd_init_lseq_cio(struct asd_ha_struct *asd_ha, int lseq) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci u8 *sas_addr; 9638c2ecf20Sopenharmony_ci int i; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ 9668c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmARP2INTEN(lseq), EN_ARP2HALTC); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmSCRATCHPAGE(lseq), 0); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* Initialize Mode 0,1, and 2 SCRATCHPAGE to 0. */ 9718c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 9728c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, i), 0); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci /* Initialize Mode 5 SCRATCHPAGE to 0. */ 9758c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, 5), 0); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmRSPMBX(lseq), 0); 9788c2ecf20Sopenharmony_ci /* Initialize Mode 0,1,2 and 5 Interrupt Enable and 9798c2ecf20Sopenharmony_ci * Interrupt registers. */ 9808c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 0), LmM0INTEN_MASK); 9818c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINT(lseq, 0), 0xFFFFFFFF); 9828c2ecf20Sopenharmony_ci /* Mode 1 */ 9838c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 1), LmM1INTEN_MASK); 9848c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINT(lseq, 1), 0xFFFFFFFF); 9858c2ecf20Sopenharmony_ci /* Mode 2 */ 9868c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 2), LmM2INTEN_MASK); 9878c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINT(lseq, 2), 0xFFFFFFFF); 9888c2ecf20Sopenharmony_ci /* Mode 5 */ 9898c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 5), LmM5INTEN_MASK); 9908c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnINT(lseq, 5), 0xFFFFFFFF); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /* Enable HW Timer status. */ 9938c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmHWTSTATEN(lseq), LmHWTSTATEN_MASK); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci /* Enable Primitive Status 0 and 1. */ 9968c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmPRIMSTAT0EN(lseq), LmPRIMSTAT0EN_MASK); 9978c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmPRIMSTAT1EN(lseq), LmPRIMSTAT1EN_MASK); 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci /* Enable Frame Error. */ 10008c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmFRMERREN(lseq), LmFRMERREN_MASK); 10018c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnHOLDLVL(lseq, 0), 0x50); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci /* Initialize Mode 0 Transfer Level to 512. */ 10048c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 0), LmMnXFRLVL_512); 10058c2ecf20Sopenharmony_ci /* Initialize Mode 1 Transfer Level to 256. */ 10068c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 1), LmMnXFRLVL_256); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci /* Initialize Program Count. */ 10098c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci /* Enable Blind SG Move. */ 10128c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMODECTL(lseq), LmBLIND48); 10138c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3SATATIMER(lseq), 10148c2ecf20Sopenharmony_ci ASD_SATA_INTERLOCK_TIMEOUT); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci (void) asd_read_reg_dword(asd_ha, LmREQMBX(lseq)); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci /* Clear Primitive Status 0 and 1. */ 10198c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmPRMSTAT0(lseq), 0xFFFFFFFF); 10208c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmPRMSTAT1(lseq), 0xFFFFFFFF); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci /* Clear HW Timer status. */ 10238c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmHWTSTAT(lseq), 0xFF); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* Clear DMA Errors for Mode 0 and 1. */ 10268c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 0), 0xFF); 10278c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 1), 0xFF); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci /* Clear SG DMA Errors for Mode 0 and 1. */ 10308c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 0), 0xFF); 10318c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 1), 0xFF); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* Clear Mode 0 Buffer Parity Error. */ 10348c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnBUFSTAT(lseq, 0), LmMnBUFPERR); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci /* Clear Mode 0 Frame Error register. */ 10378c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmMnFRMERR(lseq, 0), 0xFFFFFFFF); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* Reset LSEQ external interrupt arbiter. */ 10408c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmARP2INTCTL(lseq), RSTINTCTL); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci /* Set the Phy SAS for the LmSEQ WWN. */ 10438c2ecf20Sopenharmony_ci sas_addr = asd_ha->phys[lseq].phy_desc->sas_addr; 10448c2ecf20Sopenharmony_ci for (i = 0; i < SAS_ADDR_SIZE; i++) 10458c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmWWN(lseq) + i, sas_addr[i]); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* Set the Transmit Size to 1024 bytes, 0 = 256 Dwords. */ 10488c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnXMTSIZE(lseq, 1), 0); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* Set the Bus Inactivity Time Limit Timer. */ 10518c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmBITL_TIMER(lseq), 9); 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci /* Enable SATA Port Multiplier. */ 10548c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmMnSATAFS(lseq, 1), 0x80); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* Initialize Interrupt Vector[0-10] address in Mode 3. 10578c2ecf20Sopenharmony_ci * See the comment on CSEQ_INT_* */ 10588c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC0(lseq), lseq_vecs[0]); 10598c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC1(lseq), lseq_vecs[1]); 10608c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC2(lseq), lseq_vecs[2]); 10618c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC3(lseq), lseq_vecs[3]); 10628c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC4(lseq), lseq_vecs[4]); 10638c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC5(lseq), lseq_vecs[5]); 10648c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC6(lseq), lseq_vecs[6]); 10658c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC7(lseq), lseq_vecs[7]); 10668c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC8(lseq), lseq_vecs[8]); 10678c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC9(lseq), lseq_vecs[9]); 10688c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmM3INTVEC10(lseq), lseq_vecs[10]); 10698c2ecf20Sopenharmony_ci /* 10708c2ecf20Sopenharmony_ci * Program the Link LED control, applicable only for 10718c2ecf20Sopenharmony_ci * Chip Rev. B or later. 10728c2ecf20Sopenharmony_ci */ 10738c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, LmCONTROL(lseq), 10748c2ecf20Sopenharmony_ci (LEDTIMER | LEDMODE_TXRX | LEDTIMERS_100ms)); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci /* Set the Align Rate for SAS and STP mode. */ 10778c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmM1SASALIGN(lseq), SAS_ALIGN_DEFAULT); 10788c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, LmM1STPALIGN(lseq), STP_ALIGN_DEFAULT); 10798c2ecf20Sopenharmony_ci} 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci/** 10838c2ecf20Sopenharmony_ci * asd_post_init_cseq -- clear CSEQ Mode n Int. status and Response mailbox 10848c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter struct 10858c2ecf20Sopenharmony_ci */ 10868c2ecf20Sopenharmony_cistatic void asd_post_init_cseq(struct asd_ha_struct *asd_ha) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci int i; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 10918c2ecf20Sopenharmony_ci asd_write_reg_dword(asd_ha, CMnINT(i), 0xFFFFFFFF); 10928c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 10938c2ecf20Sopenharmony_ci asd_read_reg_dword(asd_ha, CMnRSPMBX(i)); 10948c2ecf20Sopenharmony_ci /* Reset the external interrupt arbiter. */ 10958c2ecf20Sopenharmony_ci asd_write_reg_byte(asd_ha, CARP2INTCTL, RSTINTCTL); 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci/** 10998c2ecf20Sopenharmony_ci * asd_init_ddb_0 -- initialize DDB 0 11008c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 11018c2ecf20Sopenharmony_ci * 11028c2ecf20Sopenharmony_ci * Initialize DDB site 0 which is used internally by the sequencer. 11038c2ecf20Sopenharmony_ci */ 11048c2ecf20Sopenharmony_cistatic void asd_init_ddb_0(struct asd_ha_struct *asd_ha) 11058c2ecf20Sopenharmony_ci{ 11068c2ecf20Sopenharmony_ci int i; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* Zero out the DDB explicitly */ 11098c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(struct asd_ddb_seq_shared); i+=4) 11108c2ecf20Sopenharmony_ci asd_ddbsite_write_dword(asd_ha, 0, i, 0); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11138c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, q_free_ddb_head), 0); 11148c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11158c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, q_free_ddb_tail), 11168c2ecf20Sopenharmony_ci asd_ha->hw_prof.max_ddbs-1); 11178c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11188c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, q_free_ddb_cnt), 0); 11198c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11208c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, q_used_ddb_head), 0xFFFF); 11218c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11228c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, q_used_ddb_tail), 0xFFFF); 11238c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11248c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, shared_mem_lock), 0); 11258c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11268c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, smp_conn_tag), 0); 11278c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11288c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, est_nexus_buf_cnt), 0); 11298c2ecf20Sopenharmony_ci asd_ddbsite_write_word(asd_ha, 0, 11308c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, est_nexus_buf_thresh), 11318c2ecf20Sopenharmony_ci asd_ha->hw_prof.num_phys * 2); 11328c2ecf20Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, 0, 11338c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, settable_max_contexts),0); 11348c2ecf20Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, 0, 11358c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, conn_not_active), 0xFF); 11368c2ecf20Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, 0, 11378c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, phy_is_up), 0x00); 11388c2ecf20Sopenharmony_ci /* DDB 0 is reserved */ 11398c2ecf20Sopenharmony_ci set_bit(0, asd_ha->hw_prof.ddb_bitmap); 11408c2ecf20Sopenharmony_ci} 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci unsigned int i; 11458c2ecf20Sopenharmony_ci unsigned int ddb_site; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++) 11488c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) 11498c2ecf20Sopenharmony_ci asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0); 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci/** 11538c2ecf20Sopenharmony_ci * asd_seq_setup_seqs -- setup and initialize central and link sequencers 11548c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_cistatic void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha) 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci int lseq; 11598c2ecf20Sopenharmony_ci u8 lseq_mask; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci /* Initialize DDB sites */ 11628c2ecf20Sopenharmony_ci asd_seq_init_ddb_sites(asd_ha); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci /* Initialize SCB sites. Done first to compute some values which 11658c2ecf20Sopenharmony_ci * the rest of the init code depends on. */ 11668c2ecf20Sopenharmony_ci asd_init_scb_sites(asd_ha); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci /* Initialize CSEQ Scratch RAM registers. */ 11698c2ecf20Sopenharmony_ci asd_init_cseq_scratch(asd_ha); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci /* Initialize LmSEQ Scratch RAM registers. */ 11728c2ecf20Sopenharmony_ci asd_init_lseq_scratch(asd_ha); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci /* Initialize CSEQ CIO registers. */ 11758c2ecf20Sopenharmony_ci asd_init_cseq_cio(asd_ha); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci asd_init_ddb_0(asd_ha); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci /* Initialize LmSEQ CIO registers. */ 11808c2ecf20Sopenharmony_ci lseq_mask = asd_ha->hw_prof.enabled_phys; 11818c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) 11828c2ecf20Sopenharmony_ci asd_init_lseq_cio(asd_ha, lseq); 11838c2ecf20Sopenharmony_ci asd_post_init_cseq(asd_ha); 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci/** 11888c2ecf20Sopenharmony_ci * asd_seq_start_cseq -- start the central sequencer, CSEQ 11898c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 11908c2ecf20Sopenharmony_ci */ 11918c2ecf20Sopenharmony_cistatic int asd_seq_start_cseq(struct asd_ha_struct *asd_ha) 11928c2ecf20Sopenharmony_ci{ 11938c2ecf20Sopenharmony_ci /* Reset the ARP2 instruction to location zero. */ 11948c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci /* Unpause the CSEQ */ 11978c2ecf20Sopenharmony_ci return asd_unpause_cseq(asd_ha); 11988c2ecf20Sopenharmony_ci} 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci/** 12018c2ecf20Sopenharmony_ci * asd_seq_start_lseq -- start a link sequencer 12028c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 12038c2ecf20Sopenharmony_ci * @lseq: the link sequencer of interest 12048c2ecf20Sopenharmony_ci */ 12058c2ecf20Sopenharmony_cistatic int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq) 12068c2ecf20Sopenharmony_ci{ 12078c2ecf20Sopenharmony_ci /* Reset the ARP2 instruction to location zero. */ 12088c2ecf20Sopenharmony_ci asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci /* Unpause the LmSEQ */ 12118c2ecf20Sopenharmony_ci return asd_seq_unpause_lseq(asd_ha, lseq); 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ciint asd_release_firmware(void) 12158c2ecf20Sopenharmony_ci{ 12168c2ecf20Sopenharmony_ci release_firmware(sequencer_fw); 12178c2ecf20Sopenharmony_ci return 0; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic int asd_request_firmware(struct asd_ha_struct *asd_ha) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci int err, i; 12238c2ecf20Sopenharmony_ci struct sequencer_file_header header; 12248c2ecf20Sopenharmony_ci const struct sequencer_file_header *hdr_ptr; 12258c2ecf20Sopenharmony_ci u32 csum = 0; 12268c2ecf20Sopenharmony_ci u16 *ptr_cseq_vecs, *ptr_lseq_vecs; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (sequencer_fw) 12298c2ecf20Sopenharmony_ci /* already loaded */ 12308c2ecf20Sopenharmony_ci return 0; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci err = request_firmware(&sequencer_fw, 12338c2ecf20Sopenharmony_ci SAS_RAZOR_SEQUENCER_FW_FILE, 12348c2ecf20Sopenharmony_ci &asd_ha->pcidev->dev); 12358c2ecf20Sopenharmony_ci if (err) 12368c2ecf20Sopenharmony_ci return err; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci hdr_ptr = (const struct sequencer_file_header *)sequencer_fw->data; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci header.csum = le32_to_cpu(hdr_ptr->csum); 12418c2ecf20Sopenharmony_ci header.major = le32_to_cpu(hdr_ptr->major); 12428c2ecf20Sopenharmony_ci header.minor = le32_to_cpu(hdr_ptr->minor); 12438c2ecf20Sopenharmony_ci header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset); 12448c2ecf20Sopenharmony_ci header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size); 12458c2ecf20Sopenharmony_ci header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset); 12468c2ecf20Sopenharmony_ci header.lseq_table_size = le32_to_cpu(hdr_ptr->lseq_table_size); 12478c2ecf20Sopenharmony_ci header.cseq_code_offset = le32_to_cpu(hdr_ptr->cseq_code_offset); 12488c2ecf20Sopenharmony_ci header.cseq_code_size = le32_to_cpu(hdr_ptr->cseq_code_size); 12498c2ecf20Sopenharmony_ci header.lseq_code_offset = le32_to_cpu(hdr_ptr->lseq_code_offset); 12508c2ecf20Sopenharmony_ci header.lseq_code_size = le32_to_cpu(hdr_ptr->lseq_code_size); 12518c2ecf20Sopenharmony_ci header.mode2_task = le16_to_cpu(hdr_ptr->mode2_task); 12528c2ecf20Sopenharmony_ci header.cseq_idle_loop = le16_to_cpu(hdr_ptr->cseq_idle_loop); 12538c2ecf20Sopenharmony_ci header.lseq_idle_loop = le16_to_cpu(hdr_ptr->lseq_idle_loop); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci for (i = sizeof(header.csum); i < sequencer_fw->size; i++) 12568c2ecf20Sopenharmony_ci csum += sequencer_fw->data[i]; 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if (csum != header.csum) { 12598c2ecf20Sopenharmony_ci asd_printk("Firmware file checksum mismatch\n"); 12608c2ecf20Sopenharmony_ci return -EINVAL; 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci if (header.cseq_table_size != CSEQ_NUM_VECS || 12648c2ecf20Sopenharmony_ci header.lseq_table_size != LSEQ_NUM_VECS) { 12658c2ecf20Sopenharmony_ci asd_printk("Firmware file table size mismatch\n"); 12668c2ecf20Sopenharmony_ci return -EINVAL; 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci asd_printk("Found sequencer Firmware version %d.%d (%s)\n", 12708c2ecf20Sopenharmony_ci header.major, header.minor, hdr_ptr->version); 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) { 12738c2ecf20Sopenharmony_ci asd_printk("Firmware Major Version Mismatch;" 12748c2ecf20Sopenharmony_ci "driver requires version %d.X", 12758c2ecf20Sopenharmony_ci SAS_RAZOR_SEQUENCER_FW_MAJOR); 12768c2ecf20Sopenharmony_ci return -EINVAL; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset]; 12808c2ecf20Sopenharmony_ci ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset]; 12818c2ecf20Sopenharmony_ci mode2_task = header.mode2_task; 12828c2ecf20Sopenharmony_ci cseq_idle_loop = header.cseq_idle_loop; 12838c2ecf20Sopenharmony_ci lseq_idle_loop = header.lseq_idle_loop; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci for (i = 0; i < CSEQ_NUM_VECS; i++) 12868c2ecf20Sopenharmony_ci cseq_vecs[i] = le16_to_cpu(ptr_cseq_vecs[i]); 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci for (i = 0; i < LSEQ_NUM_VECS; i++) 12898c2ecf20Sopenharmony_ci lseq_vecs[i] = le16_to_cpu(ptr_lseq_vecs[i]); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci cseq_code = &sequencer_fw->data[header.cseq_code_offset]; 12928c2ecf20Sopenharmony_ci cseq_code_size = header.cseq_code_size; 12938c2ecf20Sopenharmony_ci lseq_code = &sequencer_fw->data[header.lseq_code_offset]; 12948c2ecf20Sopenharmony_ci lseq_code_size = header.lseq_code_size; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci return 0; 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ciint asd_init_seqs(struct asd_ha_struct *asd_ha) 13008c2ecf20Sopenharmony_ci{ 13018c2ecf20Sopenharmony_ci int err; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci err = asd_request_firmware(asd_ha); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci if (err) { 13068c2ecf20Sopenharmony_ci asd_printk("Failed to load sequencer firmware file %s, error %d\n", 13078c2ecf20Sopenharmony_ci SAS_RAZOR_SEQUENCER_FW_FILE, err); 13088c2ecf20Sopenharmony_ci return err; 13098c2ecf20Sopenharmony_ci } 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci err = asd_seq_download_seqs(asd_ha); 13128c2ecf20Sopenharmony_ci if (err) { 13138c2ecf20Sopenharmony_ci asd_printk("couldn't download sequencers for %s\n", 13148c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev)); 13158c2ecf20Sopenharmony_ci return err; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci asd_seq_setup_seqs(asd_ha); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci return 0; 13218c2ecf20Sopenharmony_ci} 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ciint asd_start_seqs(struct asd_ha_struct *asd_ha) 13248c2ecf20Sopenharmony_ci{ 13258c2ecf20Sopenharmony_ci int err; 13268c2ecf20Sopenharmony_ci u8 lseq_mask; 13278c2ecf20Sopenharmony_ci int lseq; 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci err = asd_seq_start_cseq(asd_ha); 13308c2ecf20Sopenharmony_ci if (err) { 13318c2ecf20Sopenharmony_ci asd_printk("couldn't start CSEQ for %s\n", 13328c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev)); 13338c2ecf20Sopenharmony_ci return err; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci lseq_mask = asd_ha->hw_prof.enabled_phys; 13378c2ecf20Sopenharmony_ci for_each_sequencer(lseq_mask, lseq_mask, lseq) { 13388c2ecf20Sopenharmony_ci err = asd_seq_start_lseq(asd_ha, lseq); 13398c2ecf20Sopenharmony_ci if (err) { 13408c2ecf20Sopenharmony_ci asd_printk("couldn't start LSEQ %d for %s\n", lseq, 13418c2ecf20Sopenharmony_ci pci_name(asd_ha->pcidev)); 13428c2ecf20Sopenharmony_ci return err; 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci return 0; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci/** 13508c2ecf20Sopenharmony_ci * asd_update_port_links -- update port_map_by_links and phy_is_up 13518c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 13528c2ecf20Sopenharmony_ci * @phy: pointer to the phy which has been added to a port 13538c2ecf20Sopenharmony_ci * 13548c2ecf20Sopenharmony_ci * 1) When a link reset has completed and we got BYTES DMAED with a 13558c2ecf20Sopenharmony_ci * valid frame we call this function for that phy, to indicate that 13568c2ecf20Sopenharmony_ci * the phy is up, i.e. we update the phy_is_up in DDB 0. The 13578c2ecf20Sopenharmony_ci * sequencer checks phy_is_up when pending SCBs are to be sent, and 13588c2ecf20Sopenharmony_ci * when an open address frame has been received. 13598c2ecf20Sopenharmony_ci * 13608c2ecf20Sopenharmony_ci * 2) When we know of ports, we call this function to update the map 13618c2ecf20Sopenharmony_ci * of phys participaing in that port, i.e. we update the 13628c2ecf20Sopenharmony_ci * port_map_by_links in DDB 0. When a HARD_RESET primitive has been 13638c2ecf20Sopenharmony_ci * received, the sequencer disables all phys in that port. 13648c2ecf20Sopenharmony_ci * port_map_by_links is also used as the conn_mask byte in the 13658c2ecf20Sopenharmony_ci * initiator/target port DDB. 13668c2ecf20Sopenharmony_ci */ 13678c2ecf20Sopenharmony_civoid asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci const u8 phy_mask = (u8) phy->asd_port->phy_mask; 13708c2ecf20Sopenharmony_ci u8 phy_is_up; 13718c2ecf20Sopenharmony_ci u8 mask; 13728c2ecf20Sopenharmony_ci int i, err; 13738c2ecf20Sopenharmony_ci unsigned long flags; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 13768c2ecf20Sopenharmony_ci for_each_phy(phy_mask, mask, i) 13778c2ecf20Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, 0, 13788c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, 13798c2ecf20Sopenharmony_ci port_map_by_links)+i,phy_mask); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci for (i = 0; i < 12; i++) { 13828c2ecf20Sopenharmony_ci phy_is_up = asd_ddbsite_read_byte(asd_ha, 0, 13838c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, phy_is_up)); 13848c2ecf20Sopenharmony_ci err = asd_ddbsite_update_byte(asd_ha, 0, 13858c2ecf20Sopenharmony_ci offsetof(struct asd_ddb_seq_shared, phy_is_up), 13868c2ecf20Sopenharmony_ci phy_is_up, 13878c2ecf20Sopenharmony_ci phy_is_up | phy_mask); 13888c2ecf20Sopenharmony_ci if (!err) 13898c2ecf20Sopenharmony_ci break; 13908c2ecf20Sopenharmony_ci else if (err == -EFAULT) { 13918c2ecf20Sopenharmony_ci asd_printk("phy_is_up: parity error in DDB 0\n"); 13928c2ecf20Sopenharmony_ci break; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci if (err) 13988c2ecf20Sopenharmony_ci asd_printk("couldn't update DDB 0:error:%d\n", err); 13998c2ecf20Sopenharmony_ci} 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ciMODULE_FIRMWARE(SAS_RAZOR_SEQUENCER_FW_FILE); 1402