162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Aic94xx SAS/SATA driver hardware registers definitions.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
662306a36Sopenharmony_ci * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef _AIC94XX_REG_H_
1062306a36Sopenharmony_ci#define _AIC94XX_REG_H_
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <asm/io.h>
1362306a36Sopenharmony_ci#include "aic94xx_hwi.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* Values */
1662306a36Sopenharmony_ci#define AIC9410_DEV_REV_B0            0x8
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* MBAR0, SWA, SWB, SWC, internal memory space addresses */
1962306a36Sopenharmony_ci#define REG_BASE_ADDR                 0xB8000000
2062306a36Sopenharmony_ci#define REG_BASE_ADDR_CSEQCIO         0xB8002000
2162306a36Sopenharmony_ci#define REG_BASE_ADDR_EXSI            0xB8042800
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define MBAR0_SWA_SIZE                0x58
2462306a36Sopenharmony_ciextern  u32    MBAR0_SWB_SIZE;
2562306a36Sopenharmony_ci#define MBAR0_SWC_SIZE                0x8
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* MBAR1, points to On Chip Memory */
2862306a36Sopenharmony_ci#define OCM_BASE_ADDR                 0xA0000000
2962306a36Sopenharmony_ci#define OCM_MAX_SIZE                  0x20000
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/* Smallest address possible to reference */
3262306a36Sopenharmony_ci#define ALL_BASE_ADDR                 OCM_BASE_ADDR
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* PCI configuration space registers */
3562306a36Sopenharmony_ci#define PCI_IOBAR_OFFSET              4
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define PCI_CONF_MBAR1                0x6C
3862306a36Sopenharmony_ci#define PCI_CONF_MBAR0_SWA            0x70
3962306a36Sopenharmony_ci#define PCI_CONF_MBAR0_SWB            0x74
4062306a36Sopenharmony_ci#define PCI_CONF_MBAR0_SWC            0x78
4162306a36Sopenharmony_ci#define PCI_CONF_MBAR_KEY             0x7C
4262306a36Sopenharmony_ci#define PCI_CONF_FLSH_BAR             0xB8
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#include "aic94xx_reg_def.h"
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciu8  asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg);
4762306a36Sopenharmony_ciu16 asd_read_reg_word(struct asd_ha_struct *asd_ha, u32 reg);
4862306a36Sopenharmony_ciu32 asd_read_reg_dword(struct asd_ha_struct *asd_ha, u32 reg);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_civoid asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val);
5162306a36Sopenharmony_civoid asd_write_reg_word(struct asd_ha_struct *asd_ha, u32 reg, u16 val);
5262306a36Sopenharmony_civoid asd_write_reg_dword(struct asd_ha_struct *asd_ha, u32 reg, u32 val);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_civoid asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
5562306a36Sopenharmony_ci			 u32 offs, int count);
5662306a36Sopenharmony_civoid asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
5762306a36Sopenharmony_ci			  u32 offs, int count);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define ASD_READ_OCM(type, ord, S)                                    \
6062306a36Sopenharmony_cistatic inline type asd_read_ocm_##ord (struct asd_ha_struct *asd_ha,  \
6162306a36Sopenharmony_ci					 u32 offs)                    \
6262306a36Sopenharmony_ci{                                                                     \
6362306a36Sopenharmony_ci	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
6462306a36Sopenharmony_ci	type val = read##S (io_handle->addr + (unsigned long) offs);  \
6562306a36Sopenharmony_ci	rmb();                                                        \
6662306a36Sopenharmony_ci	return val;                                                   \
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciASD_READ_OCM(u8, byte, b);
7062306a36Sopenharmony_ciASD_READ_OCM(u16,word, w);
7162306a36Sopenharmony_ciASD_READ_OCM(u32,dword,l);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define ASD_WRITE_OCM(type, ord, S)                                    \
7462306a36Sopenharmony_cistatic inline void asd_write_ocm_##ord (struct asd_ha_struct *asd_ha,  \
7562306a36Sopenharmony_ci					 u32 offs, type val)          \
7662306a36Sopenharmony_ci{                                                                     \
7762306a36Sopenharmony_ci	struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
7862306a36Sopenharmony_ci	write##S (val, io_handle->addr + (unsigned long) offs);       \
7962306a36Sopenharmony_ci	return;                                                       \
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciASD_WRITE_OCM(u8, byte, b);
8362306a36Sopenharmony_ciASD_WRITE_OCM(u16,word, w);
8462306a36Sopenharmony_ciASD_WRITE_OCM(u32,dword,l);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define ASD_DDBSITE_READ(type, ord)                                        \
8762306a36Sopenharmony_cistatic inline type asd_ddbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
8862306a36Sopenharmony_ci					   u16 ddb_site_no,                \
8962306a36Sopenharmony_ci					   u16 offs)                       \
9062306a36Sopenharmony_ci{                                                                          \
9162306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
9262306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
9362306a36Sopenharmony_ci	return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciASD_DDBSITE_READ(u32, dword);
9762306a36Sopenharmony_ciASD_DDBSITE_READ(u16, word);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline u8 asd_ddbsite_read_byte(struct asd_ha_struct *asd_ha,
10062306a36Sopenharmony_ci				       u16 ddb_site_no,
10162306a36Sopenharmony_ci				       u16 offs)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	if (offs & 1)
10462306a36Sopenharmony_ci		return asd_ddbsite_read_word(asd_ha, ddb_site_no,
10562306a36Sopenharmony_ci					     offs & ~1) >> 8;
10662306a36Sopenharmony_ci	else
10762306a36Sopenharmony_ci		return asd_ddbsite_read_word(asd_ha, ddb_site_no,
10862306a36Sopenharmony_ci					     offs) & 0xFF;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define ASD_DDBSITE_WRITE(type, ord)                                       \
11362306a36Sopenharmony_cistatic inline void asd_ddbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
11462306a36Sopenharmony_ci					u16 ddb_site_no,                   \
11562306a36Sopenharmony_ci					u16 offs, type val)                \
11662306a36Sopenharmony_ci{                                                                          \
11762306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
11862306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
11962306a36Sopenharmony_ci	asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciASD_DDBSITE_WRITE(u32, dword);
12362306a36Sopenharmony_ciASD_DDBSITE_WRITE(u16, word);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline void asd_ddbsite_write_byte(struct asd_ha_struct *asd_ha,
12662306a36Sopenharmony_ci					  u16 ddb_site_no,
12762306a36Sopenharmony_ci					  u16 offs, u8 val)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	u16 base = offs & ~1;
13062306a36Sopenharmony_ci	u16 rval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
13162306a36Sopenharmony_ci	if (offs & 1)
13262306a36Sopenharmony_ci		rval = (val << 8) | (rval & 0xFF);
13362306a36Sopenharmony_ci	else
13462306a36Sopenharmony_ci		rval = (rval & 0xFF00) | val;
13562306a36Sopenharmony_ci	asd_ddbsite_write_word(asd_ha, ddb_site_no, base, rval);
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci#define ASD_SCBSITE_READ(type, ord)                                        \
14062306a36Sopenharmony_cistatic inline type asd_scbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
14162306a36Sopenharmony_ci					   u16 scb_site_no,                \
14262306a36Sopenharmony_ci					   u16 offs)                       \
14362306a36Sopenharmony_ci{                                                                          \
14462306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
14562306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
14662306a36Sopenharmony_ci	return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ciASD_SCBSITE_READ(u32, dword);
15062306a36Sopenharmony_ciASD_SCBSITE_READ(u16, word);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic inline u8 asd_scbsite_read_byte(struct asd_ha_struct *asd_ha,
15362306a36Sopenharmony_ci				       u16 scb_site_no,
15462306a36Sopenharmony_ci				       u16 offs)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	if (offs & 1)
15762306a36Sopenharmony_ci		return asd_scbsite_read_word(asd_ha, scb_site_no,
15862306a36Sopenharmony_ci					     offs & ~1) >> 8;
15962306a36Sopenharmony_ci	else
16062306a36Sopenharmony_ci		return asd_scbsite_read_word(asd_ha, scb_site_no,
16162306a36Sopenharmony_ci					     offs) & 0xFF;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci#define ASD_SCBSITE_WRITE(type, ord)                                       \
16662306a36Sopenharmony_cistatic inline void asd_scbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
16762306a36Sopenharmony_ci					u16 scb_site_no,                   \
16862306a36Sopenharmony_ci					u16 offs, type val)                \
16962306a36Sopenharmony_ci{                                                                          \
17062306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
17162306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
17262306a36Sopenharmony_ci	asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciASD_SCBSITE_WRITE(u32, dword);
17662306a36Sopenharmony_ciASD_SCBSITE_WRITE(u16, word);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic inline void asd_scbsite_write_byte(struct asd_ha_struct *asd_ha,
17962306a36Sopenharmony_ci					  u16 scb_site_no,
18062306a36Sopenharmony_ci					  u16 offs, u8 val)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	u16 base = offs & ~1;
18362306a36Sopenharmony_ci	u16 rval = asd_scbsite_read_word(asd_ha, scb_site_no, base);
18462306a36Sopenharmony_ci	if (offs & 1)
18562306a36Sopenharmony_ci		rval = (val << 8) | (rval & 0xFF);
18662306a36Sopenharmony_ci	else
18762306a36Sopenharmony_ci		rval = (rval & 0xFF00) | val;
18862306a36Sopenharmony_ci	asd_scbsite_write_word(asd_ha, scb_site_no, base, rval);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/**
19262306a36Sopenharmony_ci * asd_ddbsite_update_word -- atomically update a word in a ddb site
19362306a36Sopenharmony_ci * @asd_ha: pointer to host adapter structure
19462306a36Sopenharmony_ci * @ddb_site_no: the DDB site number
19562306a36Sopenharmony_ci * @offs: the offset into the DDB
19662306a36Sopenharmony_ci * @oldval: old value found in that offset
19762306a36Sopenharmony_ci * @newval: the new value to replace it
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci * This function is used when the sequencers are running and we need to
20062306a36Sopenharmony_ci * update a DDB site atomically without expensive pausing and upausing
20162306a36Sopenharmony_ci * of the sequencers and accessing the DDB site through the CIO bus.
20262306a36Sopenharmony_ci *
20362306a36Sopenharmony_ci * Return 0 on success; -EFAULT on parity error; -EAGAIN if the old value
20462306a36Sopenharmony_ci * is different than the current value at that offset.
20562306a36Sopenharmony_ci */
20662306a36Sopenharmony_cistatic inline int asd_ddbsite_update_word(struct asd_ha_struct *asd_ha,
20762306a36Sopenharmony_ci					  u16 ddb_site_no, u16 offs,
20862306a36Sopenharmony_ci					  u16 oldval, u16 newval)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	u8  done;
21162306a36Sopenharmony_ci	u16 oval = asd_ddbsite_read_word(asd_ha, ddb_site_no, offs);
21262306a36Sopenharmony_ci	if (oval != oldval)
21362306a36Sopenharmony_ci		return -EAGAIN;
21462306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, AOLDDATA, oldval);
21562306a36Sopenharmony_ci	asd_write_reg_word(asd_ha, ANEWDATA, newval);
21662306a36Sopenharmony_ci	do {
21762306a36Sopenharmony_ci		done = asd_read_reg_byte(asd_ha, ATOMICSTATCTL);
21862306a36Sopenharmony_ci	} while (!(done & ATOMICDONE));
21962306a36Sopenharmony_ci	if (done & ATOMICERR)
22062306a36Sopenharmony_ci		return -EFAULT;	  /* parity error */
22162306a36Sopenharmony_ci	else if (done & ATOMICWIN)
22262306a36Sopenharmony_ci		return 0;	  /* success */
22362306a36Sopenharmony_ci	else
22462306a36Sopenharmony_ci		return -EAGAIN;	  /* oldval different than current value */
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic inline int asd_ddbsite_update_byte(struct asd_ha_struct *asd_ha,
22862306a36Sopenharmony_ci					  u16 ddb_site_no, u16 offs,
22962306a36Sopenharmony_ci					  u8 _oldval, u8 _newval)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	u16 base = offs & ~1;
23262306a36Sopenharmony_ci	u16 oval;
23362306a36Sopenharmony_ci	u16 nval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
23462306a36Sopenharmony_ci	if (offs & 1) {
23562306a36Sopenharmony_ci		if ((nval >> 8) != _oldval)
23662306a36Sopenharmony_ci			return -EAGAIN;
23762306a36Sopenharmony_ci		nval = (_newval << 8) | (nval & 0xFF);
23862306a36Sopenharmony_ci		oval = (_oldval << 8) | (nval & 0xFF);
23962306a36Sopenharmony_ci	} else {
24062306a36Sopenharmony_ci		if ((nval & 0xFF) != _oldval)
24162306a36Sopenharmony_ci			return -EAGAIN;
24262306a36Sopenharmony_ci		nval = (nval & 0xFF00) | _newval;
24362306a36Sopenharmony_ci		oval = (nval & 0xFF00) | _oldval;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci	return asd_ddbsite_update_word(asd_ha, ddb_site_no, base, oval, nval);
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic inline void asd_write_reg_addr(struct asd_ha_struct *asd_ha, u32 reg,
24962306a36Sopenharmony_ci				      dma_addr_t dma_handle)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, reg,   ASD_BUSADDR_LO(dma_handle));
25262306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, reg+4, ASD_BUSADDR_HI(dma_handle));
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic inline u32 asd_get_cmdctx_size(struct asd_ha_struct *asd_ha)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	/* DCHREVISION returns 0, possibly broken */
25862306a36Sopenharmony_ci	u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
25962306a36Sopenharmony_ci	return ctxmemsize ? 65536 : 32768;
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic inline u32 asd_get_devctx_size(struct asd_ha_struct *asd_ha)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
26562306a36Sopenharmony_ci	return ctxmemsize ? 8192 : 4096;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic inline void asd_disable_ints(struct asd_ha_struct *asd_ha)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN);
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic inline void asd_enable_ints(struct asd_ha_struct *asd_ha)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	/* Enable COM SAS interrupt on errors, COMSTAT */
27662306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, COMSTATEN,
27762306a36Sopenharmony_ci			    EN_CSBUFPERR | EN_CSERR | EN_OVLYERR);
27862306a36Sopenharmony_ci	/* Enable DCH SAS CFIFTOERR */
27962306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, DCHSTATUS, EN_CFIFTOERR);
28062306a36Sopenharmony_ci	/* Enable Host Device interrupts */
28162306a36Sopenharmony_ci	asd_write_reg_dword(asd_ha, CHIMINTEN, SET_CHIMINTEN);
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci#endif
285