1*65c85c83SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
22908d778SJames Bottomley /*
32908d778SJames Bottomley * Aic94xx SAS/SATA driver hardware registers definitions.
42908d778SJames Bottomley *
52908d778SJames Bottomley * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
62908d778SJames Bottomley * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
72908d778SJames Bottomley */
82908d778SJames Bottomley
92908d778SJames Bottomley #ifndef _AIC94XX_REG_H_
102908d778SJames Bottomley #define _AIC94XX_REG_H_
112908d778SJames Bottomley
122908d778SJames Bottomley #include <asm/io.h>
132908d778SJames Bottomley #include "aic94xx_hwi.h"
142908d778SJames Bottomley
152908d778SJames Bottomley /* Values */
162908d778SJames Bottomley #define AIC9410_DEV_REV_B0 0x8
172908d778SJames Bottomley
182908d778SJames Bottomley /* MBAR0, SWA, SWB, SWC, internal memory space addresses */
192908d778SJames Bottomley #define REG_BASE_ADDR 0xB8000000
202908d778SJames Bottomley #define REG_BASE_ADDR_CSEQCIO 0xB8002000
212908d778SJames Bottomley #define REG_BASE_ADDR_EXSI 0xB8042800
222908d778SJames Bottomley
232908d778SJames Bottomley #define MBAR0_SWA_SIZE 0x58
242908d778SJames Bottomley extern u32 MBAR0_SWB_SIZE;
252908d778SJames Bottomley #define MBAR0_SWC_SIZE 0x8
262908d778SJames Bottomley
272908d778SJames Bottomley /* MBAR1, points to On Chip Memory */
282908d778SJames Bottomley #define OCM_BASE_ADDR 0xA0000000
292908d778SJames Bottomley #define OCM_MAX_SIZE 0x20000
302908d778SJames Bottomley
312908d778SJames Bottomley /* Smallest address possible to reference */
322908d778SJames Bottomley #define ALL_BASE_ADDR OCM_BASE_ADDR
332908d778SJames Bottomley
342908d778SJames Bottomley /* PCI configuration space registers */
352908d778SJames Bottomley #define PCI_IOBAR_OFFSET 4
362908d778SJames Bottomley
372908d778SJames Bottomley #define PCI_CONF_MBAR1 0x6C
382908d778SJames Bottomley #define PCI_CONF_MBAR0_SWA 0x70
392908d778SJames Bottomley #define PCI_CONF_MBAR0_SWB 0x74
402908d778SJames Bottomley #define PCI_CONF_MBAR0_SWC 0x78
412908d778SJames Bottomley #define PCI_CONF_MBAR_KEY 0x7C
422908d778SJames Bottomley #define PCI_CONF_FLSH_BAR 0xB8
432908d778SJames Bottomley
442908d778SJames Bottomley #include "aic94xx_reg_def.h"
452908d778SJames Bottomley
462908d778SJames Bottomley u8 asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg);
472908d778SJames Bottomley u16 asd_read_reg_word(struct asd_ha_struct *asd_ha, u32 reg);
482908d778SJames Bottomley u32 asd_read_reg_dword(struct asd_ha_struct *asd_ha, u32 reg);
492908d778SJames Bottomley
502908d778SJames Bottomley void asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val);
512908d778SJames Bottomley void asd_write_reg_word(struct asd_ha_struct *asd_ha, u32 reg, u16 val);
522908d778SJames Bottomley void asd_write_reg_dword(struct asd_ha_struct *asd_ha, u32 reg, u32 val);
532908d778SJames Bottomley
542908d778SJames Bottomley void asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
552908d778SJames Bottomley u32 offs, int count);
562908d778SJames Bottomley void asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
572908d778SJames Bottomley u32 offs, int count);
582908d778SJames Bottomley
592908d778SJames Bottomley #define ASD_READ_OCM(type, ord, S) \
602908d778SJames Bottomley static inline type asd_read_ocm_##ord (struct asd_ha_struct *asd_ha, \
612908d778SJames Bottomley u32 offs) \
622908d778SJames Bottomley { \
632908d778SJames Bottomley struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1]; \
642908d778SJames Bottomley type val = read##S (io_handle->addr + (unsigned long) offs); \
652908d778SJames Bottomley rmb(); \
662908d778SJames Bottomley return val; \
672908d778SJames Bottomley }
682908d778SJames Bottomley
692908d778SJames Bottomley ASD_READ_OCM(u8, byte, b);
702908d778SJames Bottomley ASD_READ_OCM(u16,word, w);
712908d778SJames Bottomley ASD_READ_OCM(u32,dword,l);
722908d778SJames Bottomley
732908d778SJames Bottomley #define ASD_WRITE_OCM(type, ord, S) \
742908d778SJames Bottomley static inline void asd_write_ocm_##ord (struct asd_ha_struct *asd_ha, \
752908d778SJames Bottomley u32 offs, type val) \
762908d778SJames Bottomley { \
772908d778SJames Bottomley struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1]; \
782908d778SJames Bottomley write##S (val, io_handle->addr + (unsigned long) offs); \
792908d778SJames Bottomley return; \
802908d778SJames Bottomley }
812908d778SJames Bottomley
822908d778SJames Bottomley ASD_WRITE_OCM(u8, byte, b);
832908d778SJames Bottomley ASD_WRITE_OCM(u16,word, w);
842908d778SJames Bottomley ASD_WRITE_OCM(u32,dword,l);
852908d778SJames Bottomley
862908d778SJames Bottomley #define ASD_DDBSITE_READ(type, ord) \
872908d778SJames Bottomley static inline type asd_ddbsite_read_##ord (struct asd_ha_struct *asd_ha, \
882908d778SJames Bottomley u16 ddb_site_no, \
892908d778SJames Bottomley u16 offs) \
902908d778SJames Bottomley { \
912908d778SJames Bottomley asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs); \
922908d778SJames Bottomley asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no); \
932908d778SJames Bottomley return asd_read_reg_##ord (asd_ha, CTXACCESS); \
942908d778SJames Bottomley }
952908d778SJames Bottomley
962908d778SJames Bottomley ASD_DDBSITE_READ(u32, dword);
972908d778SJames Bottomley ASD_DDBSITE_READ(u16, word);
982908d778SJames Bottomley
asd_ddbsite_read_byte(struct asd_ha_struct * asd_ha,u16 ddb_site_no,u16 offs)992908d778SJames Bottomley static inline u8 asd_ddbsite_read_byte(struct asd_ha_struct *asd_ha,
1002908d778SJames Bottomley u16 ddb_site_no,
1012908d778SJames Bottomley u16 offs)
1022908d778SJames Bottomley {
1032908d778SJames Bottomley if (offs & 1)
1042908d778SJames Bottomley return asd_ddbsite_read_word(asd_ha, ddb_site_no,
1052908d778SJames Bottomley offs & ~1) >> 8;
1062908d778SJames Bottomley else
1072908d778SJames Bottomley return asd_ddbsite_read_word(asd_ha, ddb_site_no,
1082908d778SJames Bottomley offs) & 0xFF;
1092908d778SJames Bottomley }
1102908d778SJames Bottomley
1112908d778SJames Bottomley
1122908d778SJames Bottomley #define ASD_DDBSITE_WRITE(type, ord) \
1132908d778SJames Bottomley static inline void asd_ddbsite_write_##ord (struct asd_ha_struct *asd_ha, \
1142908d778SJames Bottomley u16 ddb_site_no, \
1152908d778SJames Bottomley u16 offs, type val) \
1162908d778SJames Bottomley { \
1172908d778SJames Bottomley asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs); \
1182908d778SJames Bottomley asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no); \
1192908d778SJames Bottomley asd_write_reg_##ord (asd_ha, CTXACCESS, val); \
1202908d778SJames Bottomley }
1212908d778SJames Bottomley
1222908d778SJames Bottomley ASD_DDBSITE_WRITE(u32, dword);
1232908d778SJames Bottomley ASD_DDBSITE_WRITE(u16, word);
1242908d778SJames Bottomley
asd_ddbsite_write_byte(struct asd_ha_struct * asd_ha,u16 ddb_site_no,u16 offs,u8 val)1252908d778SJames Bottomley static inline void asd_ddbsite_write_byte(struct asd_ha_struct *asd_ha,
1262908d778SJames Bottomley u16 ddb_site_no,
1272908d778SJames Bottomley u16 offs, u8 val)
1282908d778SJames Bottomley {
1292908d778SJames Bottomley u16 base = offs & ~1;
1302908d778SJames Bottomley u16 rval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
1312908d778SJames Bottomley if (offs & 1)
1322908d778SJames Bottomley rval = (val << 8) | (rval & 0xFF);
1332908d778SJames Bottomley else
1342908d778SJames Bottomley rval = (rval & 0xFF00) | val;
1352908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb_site_no, base, rval);
1362908d778SJames Bottomley }
1372908d778SJames Bottomley
1382908d778SJames Bottomley
1392908d778SJames Bottomley #define ASD_SCBSITE_READ(type, ord) \
1402908d778SJames Bottomley static inline type asd_scbsite_read_##ord (struct asd_ha_struct *asd_ha, \
1412908d778SJames Bottomley u16 scb_site_no, \
1422908d778SJames Bottomley u16 offs) \
1432908d778SJames Bottomley { \
1442908d778SJames Bottomley asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs); \
1452908d778SJames Bottomley asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no); \
1462908d778SJames Bottomley return asd_read_reg_##ord (asd_ha, CTXACCESS); \
1472908d778SJames Bottomley }
1482908d778SJames Bottomley
1492908d778SJames Bottomley ASD_SCBSITE_READ(u32, dword);
1502908d778SJames Bottomley ASD_SCBSITE_READ(u16, word);
1512908d778SJames Bottomley
asd_scbsite_read_byte(struct asd_ha_struct * asd_ha,u16 scb_site_no,u16 offs)1522908d778SJames Bottomley static inline u8 asd_scbsite_read_byte(struct asd_ha_struct *asd_ha,
1532908d778SJames Bottomley u16 scb_site_no,
1542908d778SJames Bottomley u16 offs)
1552908d778SJames Bottomley {
1562908d778SJames Bottomley if (offs & 1)
1572908d778SJames Bottomley return asd_scbsite_read_word(asd_ha, scb_site_no,
1582908d778SJames Bottomley offs & ~1) >> 8;
1592908d778SJames Bottomley else
1602908d778SJames Bottomley return asd_scbsite_read_word(asd_ha, scb_site_no,
1612908d778SJames Bottomley offs) & 0xFF;
1622908d778SJames Bottomley }
1632908d778SJames Bottomley
1642908d778SJames Bottomley
1652908d778SJames Bottomley #define ASD_SCBSITE_WRITE(type, ord) \
1662908d778SJames Bottomley static inline void asd_scbsite_write_##ord (struct asd_ha_struct *asd_ha, \
1672908d778SJames Bottomley u16 scb_site_no, \
1682908d778SJames Bottomley u16 offs, type val) \
1692908d778SJames Bottomley { \
1702908d778SJames Bottomley asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs); \
1712908d778SJames Bottomley asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no); \
1722908d778SJames Bottomley asd_write_reg_##ord (asd_ha, CTXACCESS, val); \
1732908d778SJames Bottomley }
1742908d778SJames Bottomley
1752908d778SJames Bottomley ASD_SCBSITE_WRITE(u32, dword);
1762908d778SJames Bottomley ASD_SCBSITE_WRITE(u16, word);
1772908d778SJames Bottomley
asd_scbsite_write_byte(struct asd_ha_struct * asd_ha,u16 scb_site_no,u16 offs,u8 val)1782908d778SJames Bottomley static inline void asd_scbsite_write_byte(struct asd_ha_struct *asd_ha,
1792908d778SJames Bottomley u16 scb_site_no,
1802908d778SJames Bottomley u16 offs, u8 val)
1812908d778SJames Bottomley {
1822908d778SJames Bottomley u16 base = offs & ~1;
1832908d778SJames Bottomley u16 rval = asd_scbsite_read_word(asd_ha, scb_site_no, base);
1842908d778SJames Bottomley if (offs & 1)
1852908d778SJames Bottomley rval = (val << 8) | (rval & 0xFF);
1862908d778SJames Bottomley else
1872908d778SJames Bottomley rval = (rval & 0xFF00) | val;
1882908d778SJames Bottomley asd_scbsite_write_word(asd_ha, scb_site_no, base, rval);
1892908d778SJames Bottomley }
1902908d778SJames Bottomley
1912908d778SJames Bottomley /**
1922908d778SJames Bottomley * asd_ddbsite_update_word -- atomically update a word in a ddb site
1932908d778SJames Bottomley * @asd_ha: pointer to host adapter structure
1942908d778SJames Bottomley * @ddb_site_no: the DDB site number
1952908d778SJames Bottomley * @offs: the offset into the DDB
1962908d778SJames Bottomley * @oldval: old value found in that offset
1972908d778SJames Bottomley * @newval: the new value to replace it
1982908d778SJames Bottomley *
1992908d778SJames Bottomley * This function is used when the sequencers are running and we need to
2002908d778SJames Bottomley * update a DDB site atomically without expensive pausing and upausing
2012908d778SJames Bottomley * of the sequencers and accessing the DDB site through the CIO bus.
2022908d778SJames Bottomley *
2032908d778SJames Bottomley * Return 0 on success; -EFAULT on parity error; -EAGAIN if the old value
2042908d778SJames Bottomley * is different than the current value at that offset.
2052908d778SJames Bottomley */
asd_ddbsite_update_word(struct asd_ha_struct * asd_ha,u16 ddb_site_no,u16 offs,u16 oldval,u16 newval)2062908d778SJames Bottomley static inline int asd_ddbsite_update_word(struct asd_ha_struct *asd_ha,
2072908d778SJames Bottomley u16 ddb_site_no, u16 offs,
2082908d778SJames Bottomley u16 oldval, u16 newval)
2092908d778SJames Bottomley {
2102908d778SJames Bottomley u8 done;
2112908d778SJames Bottomley u16 oval = asd_ddbsite_read_word(asd_ha, ddb_site_no, offs);
2122908d778SJames Bottomley if (oval != oldval)
2132908d778SJames Bottomley return -EAGAIN;
2142908d778SJames Bottomley asd_write_reg_word(asd_ha, AOLDDATA, oldval);
2152908d778SJames Bottomley asd_write_reg_word(asd_ha, ANEWDATA, newval);
2162908d778SJames Bottomley do {
2172908d778SJames Bottomley done = asd_read_reg_byte(asd_ha, ATOMICSTATCTL);
2182908d778SJames Bottomley } while (!(done & ATOMICDONE));
2192908d778SJames Bottomley if (done & ATOMICERR)
2202908d778SJames Bottomley return -EFAULT; /* parity error */
2212908d778SJames Bottomley else if (done & ATOMICWIN)
2222908d778SJames Bottomley return 0; /* success */
2232908d778SJames Bottomley else
2242908d778SJames Bottomley return -EAGAIN; /* oldval different than current value */
2252908d778SJames Bottomley }
2262908d778SJames Bottomley
asd_ddbsite_update_byte(struct asd_ha_struct * asd_ha,u16 ddb_site_no,u16 offs,u8 _oldval,u8 _newval)2272908d778SJames Bottomley static inline int asd_ddbsite_update_byte(struct asd_ha_struct *asd_ha,
2282908d778SJames Bottomley u16 ddb_site_no, u16 offs,
2292908d778SJames Bottomley u8 _oldval, u8 _newval)
2302908d778SJames Bottomley {
2312908d778SJames Bottomley u16 base = offs & ~1;
2322908d778SJames Bottomley u16 oval;
2332908d778SJames Bottomley u16 nval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
2342908d778SJames Bottomley if (offs & 1) {
2352908d778SJames Bottomley if ((nval >> 8) != _oldval)
2362908d778SJames Bottomley return -EAGAIN;
2372908d778SJames Bottomley nval = (_newval << 8) | (nval & 0xFF);
2382908d778SJames Bottomley oval = (_oldval << 8) | (nval & 0xFF);
2392908d778SJames Bottomley } else {
2402908d778SJames Bottomley if ((nval & 0xFF) != _oldval)
2412908d778SJames Bottomley return -EAGAIN;
2422908d778SJames Bottomley nval = (nval & 0xFF00) | _newval;
2432908d778SJames Bottomley oval = (nval & 0xFF00) | _oldval;
2442908d778SJames Bottomley }
2452908d778SJames Bottomley return asd_ddbsite_update_word(asd_ha, ddb_site_no, base, oval, nval);
2462908d778SJames Bottomley }
2472908d778SJames Bottomley
asd_write_reg_addr(struct asd_ha_struct * asd_ha,u32 reg,dma_addr_t dma_handle)2482908d778SJames Bottomley static inline void asd_write_reg_addr(struct asd_ha_struct *asd_ha, u32 reg,
2492908d778SJames Bottomley dma_addr_t dma_handle)
2502908d778SJames Bottomley {
2512908d778SJames Bottomley asd_write_reg_dword(asd_ha, reg, ASD_BUSADDR_LO(dma_handle));
2522908d778SJames Bottomley asd_write_reg_dword(asd_ha, reg+4, ASD_BUSADDR_HI(dma_handle));
2532908d778SJames Bottomley }
2542908d778SJames Bottomley
asd_get_cmdctx_size(struct asd_ha_struct * asd_ha)2552908d778SJames Bottomley static inline u32 asd_get_cmdctx_size(struct asd_ha_struct *asd_ha)
2562908d778SJames Bottomley {
2572908d778SJames Bottomley /* DCHREVISION returns 0, possibly broken */
2582908d778SJames Bottomley u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
2592908d778SJames Bottomley return ctxmemsize ? 65536 : 32768;
2602908d778SJames Bottomley }
2612908d778SJames Bottomley
asd_get_devctx_size(struct asd_ha_struct * asd_ha)2622908d778SJames Bottomley static inline u32 asd_get_devctx_size(struct asd_ha_struct *asd_ha)
2632908d778SJames Bottomley {
2642908d778SJames Bottomley u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
2652908d778SJames Bottomley return ctxmemsize ? 8192 : 4096;
2662908d778SJames Bottomley }
2672908d778SJames Bottomley
asd_disable_ints(struct asd_ha_struct * asd_ha)2682908d778SJames Bottomley static inline void asd_disable_ints(struct asd_ha_struct *asd_ha)
2692908d778SJames Bottomley {
2702908d778SJames Bottomley asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN);
2712908d778SJames Bottomley }
2722908d778SJames Bottomley
asd_enable_ints(struct asd_ha_struct * asd_ha)2732908d778SJames Bottomley static inline void asd_enable_ints(struct asd_ha_struct *asd_ha)
2742908d778SJames Bottomley {
2752908d778SJames Bottomley /* Enable COM SAS interrupt on errors, COMSTAT */
2762908d778SJames Bottomley asd_write_reg_dword(asd_ha, COMSTATEN,
2772908d778SJames Bottomley EN_CSBUFPERR | EN_CSERR | EN_OVLYERR);
2782908d778SJames Bottomley /* Enable DCH SAS CFIFTOERR */
2792908d778SJames Bottomley asd_write_reg_dword(asd_ha, DCHSTATUS, EN_CFIFTOERR);
2802908d778SJames Bottomley /* Enable Host Device interrupts */
2812908d778SJames Bottomley asd_write_reg_dword(asd_ha, CHIMINTEN, SET_CHIMINTEN);
2822908d778SJames Bottomley }
2832908d778SJames Bottomley
2842908d778SJames Bottomley #endif
285