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