18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Aic94xx SAS/SATA driver hardware registers definitions.
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
98c2ecf20Sopenharmony_ci#ifndef _AIC94XX_REG_H_
108c2ecf20Sopenharmony_ci#define _AIC94XX_REG_H_
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm/io.h>
138c2ecf20Sopenharmony_ci#include "aic94xx_hwi.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* Values */
168c2ecf20Sopenharmony_ci#define AIC9410_DEV_REV_B0            0x8
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* MBAR0, SWA, SWB, SWC, internal memory space addresses */
198c2ecf20Sopenharmony_ci#define REG_BASE_ADDR                 0xB8000000
208c2ecf20Sopenharmony_ci#define REG_BASE_ADDR_CSEQCIO         0xB8002000
218c2ecf20Sopenharmony_ci#define REG_BASE_ADDR_EXSI            0xB8042800
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define MBAR0_SWA_SIZE                0x58
248c2ecf20Sopenharmony_ciextern  u32    MBAR0_SWB_SIZE;
258c2ecf20Sopenharmony_ci#define MBAR0_SWC_SIZE                0x8
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* MBAR1, points to On Chip Memory */
288c2ecf20Sopenharmony_ci#define OCM_BASE_ADDR                 0xA0000000
298c2ecf20Sopenharmony_ci#define OCM_MAX_SIZE                  0x20000
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Smallest address possible to reference */
328c2ecf20Sopenharmony_ci#define ALL_BASE_ADDR                 OCM_BASE_ADDR
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* PCI configuration space registers */
358c2ecf20Sopenharmony_ci#define PCI_IOBAR_OFFSET              4
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define PCI_CONF_MBAR1                0x6C
388c2ecf20Sopenharmony_ci#define PCI_CONF_MBAR0_SWA            0x70
398c2ecf20Sopenharmony_ci#define PCI_CONF_MBAR0_SWB            0x74
408c2ecf20Sopenharmony_ci#define PCI_CONF_MBAR0_SWC            0x78
418c2ecf20Sopenharmony_ci#define PCI_CONF_MBAR_KEY             0x7C
428c2ecf20Sopenharmony_ci#define PCI_CONF_FLSH_BAR             0xB8
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#include "aic94xx_reg_def.h"
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ciu8  asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg);
478c2ecf20Sopenharmony_ciu16 asd_read_reg_word(struct asd_ha_struct *asd_ha, u32 reg);
488c2ecf20Sopenharmony_ciu32 asd_read_reg_dword(struct asd_ha_struct *asd_ha, u32 reg);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_civoid asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val);
518c2ecf20Sopenharmony_civoid asd_write_reg_word(struct asd_ha_struct *asd_ha, u32 reg, u16 val);
528c2ecf20Sopenharmony_civoid asd_write_reg_dword(struct asd_ha_struct *asd_ha, u32 reg, u32 val);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_civoid asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
558c2ecf20Sopenharmony_ci			 u32 offs, int count);
568c2ecf20Sopenharmony_civoid asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
578c2ecf20Sopenharmony_ci			  u32 offs, int count);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define ASD_READ_OCM(type, ord, S)                                    \
608c2ecf20Sopenharmony_cistatic inline type asd_read_ocm_##ord (struct asd_ha_struct *asd_ha,  \
618c2ecf20Sopenharmony_ci					 u32 offs)                    \
628c2ecf20Sopenharmony_ci{                                                                     \
638c2ecf20Sopenharmony_ci	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
648c2ecf20Sopenharmony_ci	type val = read##S (io_handle->addr + (unsigned long) offs);  \
658c2ecf20Sopenharmony_ci	rmb();                                                        \
668c2ecf20Sopenharmony_ci	return val;                                                   \
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ciASD_READ_OCM(u8, byte, b);
708c2ecf20Sopenharmony_ciASD_READ_OCM(u16,word, w);
718c2ecf20Sopenharmony_ciASD_READ_OCM(u32,dword,l);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define ASD_WRITE_OCM(type, ord, S)                                    \
748c2ecf20Sopenharmony_cistatic inline void asd_write_ocm_##ord (struct asd_ha_struct *asd_ha,  \
758c2ecf20Sopenharmony_ci					 u32 offs, type val)          \
768c2ecf20Sopenharmony_ci{                                                                     \
778c2ecf20Sopenharmony_ci	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
788c2ecf20Sopenharmony_ci	write##S (val, io_handle->addr + (unsigned long) offs);       \
798c2ecf20Sopenharmony_ci	return;                                                       \
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciASD_WRITE_OCM(u8, byte, b);
838c2ecf20Sopenharmony_ciASD_WRITE_OCM(u16,word, w);
848c2ecf20Sopenharmony_ciASD_WRITE_OCM(u32,dword,l);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#define ASD_DDBSITE_READ(type, ord)                                        \
878c2ecf20Sopenharmony_cistatic inline type asd_ddbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
888c2ecf20Sopenharmony_ci					   u16 ddb_site_no,                \
898c2ecf20Sopenharmony_ci					   u16 offs)                       \
908c2ecf20Sopenharmony_ci{                                                                          \
918c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
928c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
938c2ecf20Sopenharmony_ci	return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ciASD_DDBSITE_READ(u32, dword);
978c2ecf20Sopenharmony_ciASD_DDBSITE_READ(u16, word);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic inline u8 asd_ddbsite_read_byte(struct asd_ha_struct *asd_ha,
1008c2ecf20Sopenharmony_ci				       u16 ddb_site_no,
1018c2ecf20Sopenharmony_ci				       u16 offs)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	if (offs & 1)
1048c2ecf20Sopenharmony_ci		return asd_ddbsite_read_word(asd_ha, ddb_site_no,
1058c2ecf20Sopenharmony_ci					     offs & ~1) >> 8;
1068c2ecf20Sopenharmony_ci	else
1078c2ecf20Sopenharmony_ci		return asd_ddbsite_read_word(asd_ha, ddb_site_no,
1088c2ecf20Sopenharmony_ci					     offs) & 0xFF;
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci#define ASD_DDBSITE_WRITE(type, ord)                                       \
1138c2ecf20Sopenharmony_cistatic inline void asd_ddbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
1148c2ecf20Sopenharmony_ci					u16 ddb_site_no,                   \
1158c2ecf20Sopenharmony_ci					u16 offs, type val)                \
1168c2ecf20Sopenharmony_ci{                                                                          \
1178c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
1188c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
1198c2ecf20Sopenharmony_ci	asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ciASD_DDBSITE_WRITE(u32, dword);
1238c2ecf20Sopenharmony_ciASD_DDBSITE_WRITE(u16, word);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic inline void asd_ddbsite_write_byte(struct asd_ha_struct *asd_ha,
1268c2ecf20Sopenharmony_ci					  u16 ddb_site_no,
1278c2ecf20Sopenharmony_ci					  u16 offs, u8 val)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	u16 base = offs & ~1;
1308c2ecf20Sopenharmony_ci	u16 rval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
1318c2ecf20Sopenharmony_ci	if (offs & 1)
1328c2ecf20Sopenharmony_ci		rval = (val << 8) | (rval & 0xFF);
1338c2ecf20Sopenharmony_ci	else
1348c2ecf20Sopenharmony_ci		rval = (rval & 0xFF00) | val;
1358c2ecf20Sopenharmony_ci	asd_ddbsite_write_word(asd_ha, ddb_site_no, base, rval);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#define ASD_SCBSITE_READ(type, ord)                                        \
1408c2ecf20Sopenharmony_cistatic inline type asd_scbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
1418c2ecf20Sopenharmony_ci					   u16 scb_site_no,                \
1428c2ecf20Sopenharmony_ci					   u16 offs)                       \
1438c2ecf20Sopenharmony_ci{                                                                          \
1448c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
1458c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
1468c2ecf20Sopenharmony_ci	return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ciASD_SCBSITE_READ(u32, dword);
1508c2ecf20Sopenharmony_ciASD_SCBSITE_READ(u16, word);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic inline u8 asd_scbsite_read_byte(struct asd_ha_struct *asd_ha,
1538c2ecf20Sopenharmony_ci				       u16 scb_site_no,
1548c2ecf20Sopenharmony_ci				       u16 offs)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	if (offs & 1)
1578c2ecf20Sopenharmony_ci		return asd_scbsite_read_word(asd_ha, scb_site_no,
1588c2ecf20Sopenharmony_ci					     offs & ~1) >> 8;
1598c2ecf20Sopenharmony_ci	else
1608c2ecf20Sopenharmony_ci		return asd_scbsite_read_word(asd_ha, scb_site_no,
1618c2ecf20Sopenharmony_ci					     offs) & 0xFF;
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci#define ASD_SCBSITE_WRITE(type, ord)                                       \
1668c2ecf20Sopenharmony_cistatic inline void asd_scbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
1678c2ecf20Sopenharmony_ci					u16 scb_site_no,                   \
1688c2ecf20Sopenharmony_ci					u16 offs, type val)                \
1698c2ecf20Sopenharmony_ci{                                                                          \
1708c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
1718c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
1728c2ecf20Sopenharmony_ci	asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ciASD_SCBSITE_WRITE(u32, dword);
1768c2ecf20Sopenharmony_ciASD_SCBSITE_WRITE(u16, word);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic inline void asd_scbsite_write_byte(struct asd_ha_struct *asd_ha,
1798c2ecf20Sopenharmony_ci					  u16 scb_site_no,
1808c2ecf20Sopenharmony_ci					  u16 offs, u8 val)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	u16 base = offs & ~1;
1838c2ecf20Sopenharmony_ci	u16 rval = asd_scbsite_read_word(asd_ha, scb_site_no, base);
1848c2ecf20Sopenharmony_ci	if (offs & 1)
1858c2ecf20Sopenharmony_ci		rval = (val << 8) | (rval & 0xFF);
1868c2ecf20Sopenharmony_ci	else
1878c2ecf20Sopenharmony_ci		rval = (rval & 0xFF00) | val;
1888c2ecf20Sopenharmony_ci	asd_scbsite_write_word(asd_ha, scb_site_no, base, rval);
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/**
1928c2ecf20Sopenharmony_ci * asd_ddbsite_update_word -- atomically update a word in a ddb site
1938c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure
1948c2ecf20Sopenharmony_ci * @ddb_site_no: the DDB site number
1958c2ecf20Sopenharmony_ci * @offs: the offset into the DDB
1968c2ecf20Sopenharmony_ci * @oldval: old value found in that offset
1978c2ecf20Sopenharmony_ci * @newval: the new value to replace it
1988c2ecf20Sopenharmony_ci *
1998c2ecf20Sopenharmony_ci * This function is used when the sequencers are running and we need to
2008c2ecf20Sopenharmony_ci * update a DDB site atomically without expensive pausing and upausing
2018c2ecf20Sopenharmony_ci * of the sequencers and accessing the DDB site through the CIO bus.
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * Return 0 on success; -EFAULT on parity error; -EAGAIN if the old value
2048c2ecf20Sopenharmony_ci * is different than the current value at that offset.
2058c2ecf20Sopenharmony_ci */
2068c2ecf20Sopenharmony_cistatic inline int asd_ddbsite_update_word(struct asd_ha_struct *asd_ha,
2078c2ecf20Sopenharmony_ci					  u16 ddb_site_no, u16 offs,
2088c2ecf20Sopenharmony_ci					  u16 oldval, u16 newval)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	u8  done;
2118c2ecf20Sopenharmony_ci	u16 oval = asd_ddbsite_read_word(asd_ha, ddb_site_no, offs);
2128c2ecf20Sopenharmony_ci	if (oval != oldval)
2138c2ecf20Sopenharmony_ci		return -EAGAIN;
2148c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, AOLDDATA, oldval);
2158c2ecf20Sopenharmony_ci	asd_write_reg_word(asd_ha, ANEWDATA, newval);
2168c2ecf20Sopenharmony_ci	do {
2178c2ecf20Sopenharmony_ci		done = asd_read_reg_byte(asd_ha, ATOMICSTATCTL);
2188c2ecf20Sopenharmony_ci	} while (!(done & ATOMICDONE));
2198c2ecf20Sopenharmony_ci	if (done & ATOMICERR)
2208c2ecf20Sopenharmony_ci		return -EFAULT;	  /* parity error */
2218c2ecf20Sopenharmony_ci	else if (done & ATOMICWIN)
2228c2ecf20Sopenharmony_ci		return 0;	  /* success */
2238c2ecf20Sopenharmony_ci	else
2248c2ecf20Sopenharmony_ci		return -EAGAIN;	  /* oldval different than current value */
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic inline int asd_ddbsite_update_byte(struct asd_ha_struct *asd_ha,
2288c2ecf20Sopenharmony_ci					  u16 ddb_site_no, u16 offs,
2298c2ecf20Sopenharmony_ci					  u8 _oldval, u8 _newval)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	u16 base = offs & ~1;
2328c2ecf20Sopenharmony_ci	u16 oval;
2338c2ecf20Sopenharmony_ci	u16 nval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
2348c2ecf20Sopenharmony_ci	if (offs & 1) {
2358c2ecf20Sopenharmony_ci		if ((nval >> 8) != _oldval)
2368c2ecf20Sopenharmony_ci			return -EAGAIN;
2378c2ecf20Sopenharmony_ci		nval = (_newval << 8) | (nval & 0xFF);
2388c2ecf20Sopenharmony_ci		oval = (_oldval << 8) | (nval & 0xFF);
2398c2ecf20Sopenharmony_ci	} else {
2408c2ecf20Sopenharmony_ci		if ((nval & 0xFF) != _oldval)
2418c2ecf20Sopenharmony_ci			return -EAGAIN;
2428c2ecf20Sopenharmony_ci		nval = (nval & 0xFF00) | _newval;
2438c2ecf20Sopenharmony_ci		oval = (nval & 0xFF00) | _oldval;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci	return asd_ddbsite_update_word(asd_ha, ddb_site_no, base, oval, nval);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic inline void asd_write_reg_addr(struct asd_ha_struct *asd_ha, u32 reg,
2498c2ecf20Sopenharmony_ci				      dma_addr_t dma_handle)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, reg,   ASD_BUSADDR_LO(dma_handle));
2528c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, reg+4, ASD_BUSADDR_HI(dma_handle));
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic inline u32 asd_get_cmdctx_size(struct asd_ha_struct *asd_ha)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	/* DCHREVISION returns 0, possibly broken */
2588c2ecf20Sopenharmony_ci	u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
2598c2ecf20Sopenharmony_ci	return ctxmemsize ? 65536 : 32768;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic inline u32 asd_get_devctx_size(struct asd_ha_struct *asd_ha)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
2658c2ecf20Sopenharmony_ci	return ctxmemsize ? 8192 : 4096;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic inline void asd_disable_ints(struct asd_ha_struct *asd_ha)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN);
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic inline void asd_enable_ints(struct asd_ha_struct *asd_ha)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	/* Enable COM SAS interrupt on errors, COMSTAT */
2768c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, COMSTATEN,
2778c2ecf20Sopenharmony_ci			    EN_CSBUFPERR | EN_CSERR | EN_OVLYERR);
2788c2ecf20Sopenharmony_ci	/* Enable DCH SAS CFIFTOERR */
2798c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, DCHSTATUS, EN_CFIFTOERR);
2808c2ecf20Sopenharmony_ci	/* Enable Host Device interrupts */
2818c2ecf20Sopenharmony_ci	asd_write_reg_dword(asd_ha, CHIMINTEN, SET_CHIMINTEN);
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci#endif
285