linux/drivers/scsi/aic94xx/aic94xx_reg.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Aic94xx SAS/SATA driver hardware registers definitions.
   4 *
   5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
   6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
   7 */
   8
   9#ifndef _AIC94XX_REG_H_
  10#define _AIC94XX_REG_H_
  11
  12#include <asm/io.h>
  13#include "aic94xx_hwi.h"
  14
  15/* Values */
  16#define AIC9410_DEV_REV_B0            0x8
  17
  18/* MBAR0, SWA, SWB, SWC, internal memory space addresses */
  19#define REG_BASE_ADDR                 0xB8000000
  20#define REG_BASE_ADDR_CSEQCIO         0xB8002000
  21#define REG_BASE_ADDR_EXSI            0xB8042800
  22
  23#define MBAR0_SWA_SIZE                0x58
  24extern  u32    MBAR0_SWB_SIZE;
  25#define MBAR0_SWC_SIZE                0x8
  26
  27/* MBAR1, points to On Chip Memory */
  28#define OCM_BASE_ADDR                 0xA0000000
  29#define OCM_MAX_SIZE                  0x20000
  30
  31/* Smallest address possible to reference */
  32#define ALL_BASE_ADDR                 OCM_BASE_ADDR
  33
  34/* PCI configuration space registers */
  35#define PCI_IOBAR_OFFSET              4
  36
  37#define PCI_CONF_MBAR1                0x6C
  38#define PCI_CONF_MBAR0_SWA            0x70
  39#define PCI_CONF_MBAR0_SWB            0x74
  40#define PCI_CONF_MBAR0_SWC            0x78
  41#define PCI_CONF_MBAR_KEY             0x7C
  42#define PCI_CONF_FLSH_BAR             0xB8
  43
  44#include "aic94xx_reg_def.h"
  45
  46u8  asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg);
  47u16 asd_read_reg_word(struct asd_ha_struct *asd_ha, u32 reg);
  48u32 asd_read_reg_dword(struct asd_ha_struct *asd_ha, u32 reg);
  49
  50void asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val);
  51void asd_write_reg_word(struct asd_ha_struct *asd_ha, u32 reg, u16 val);
  52void asd_write_reg_dword(struct asd_ha_struct *asd_ha, u32 reg, u32 val);
  53
  54void asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
  55                         u32 offs, int count);
  56void asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
  57                          u32 offs, int count);
  58
  59#define ASD_READ_OCM(type, ord, S)                                    \
  60static inline type asd_read_ocm_##ord (struct asd_ha_struct *asd_ha,  \
  61                                         u32 offs)                    \
  62{                                                                     \
  63        struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
  64        type val = read##S (io_handle->addr + (unsigned long) offs);  \
  65        rmb();                                                        \
  66        return val;                                                   \
  67}
  68
  69ASD_READ_OCM(u8, byte, b);
  70ASD_READ_OCM(u16,word, w);
  71ASD_READ_OCM(u32,dword,l);
  72
  73#define ASD_WRITE_OCM(type, ord, S)                                    \
  74static inline void asd_write_ocm_##ord (struct asd_ha_struct *asd_ha,  \
  75                                         u32 offs, type val)          \
  76{                                                                     \
  77        struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[1];   \
  78        write##S (val, io_handle->addr + (unsigned long) offs);       \
  79        return;                                                       \
  80}
  81
  82ASD_WRITE_OCM(u8, byte, b);
  83ASD_WRITE_OCM(u16,word, w);
  84ASD_WRITE_OCM(u32,dword,l);
  85
  86#define ASD_DDBSITE_READ(type, ord)                                        \
  87static inline type asd_ddbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
  88                                           u16 ddb_site_no,                \
  89                                           u16 offs)                       \
  90{                                                                          \
  91        asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
  92        asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
  93        return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
  94}
  95
  96ASD_DDBSITE_READ(u32, dword);
  97ASD_DDBSITE_READ(u16, word);
  98
  99static inline u8 asd_ddbsite_read_byte(struct asd_ha_struct *asd_ha,
 100                                       u16 ddb_site_no,
 101                                       u16 offs)
 102{
 103        if (offs & 1)
 104                return asd_ddbsite_read_word(asd_ha, ddb_site_no,
 105                                             offs & ~1) >> 8;
 106        else
 107                return asd_ddbsite_read_word(asd_ha, ddb_site_no,
 108                                             offs) & 0xFF;
 109}
 110
 111
 112#define ASD_DDBSITE_WRITE(type, ord)                                       \
 113static inline void asd_ddbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
 114                                        u16 ddb_site_no,                   \
 115                                        u16 offs, type val)                \
 116{                                                                          \
 117        asd_write_reg_word(asd_ha, ALTCIOADR, MnDDB_SITE + offs);          \
 118        asd_write_reg_word(asd_ha, ADDBPTR, ddb_site_no);                  \
 119        asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
 120}
 121
 122ASD_DDBSITE_WRITE(u32, dword);
 123ASD_DDBSITE_WRITE(u16, word);
 124
 125static inline void asd_ddbsite_write_byte(struct asd_ha_struct *asd_ha,
 126                                          u16 ddb_site_no,
 127                                          u16 offs, u8 val)
 128{
 129        u16 base = offs & ~1;
 130        u16 rval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
 131        if (offs & 1)
 132                rval = (val << 8) | (rval & 0xFF);
 133        else
 134                rval = (rval & 0xFF00) | val;
 135        asd_ddbsite_write_word(asd_ha, ddb_site_no, base, rval);
 136}
 137
 138
 139#define ASD_SCBSITE_READ(type, ord)                                        \
 140static inline type asd_scbsite_read_##ord (struct asd_ha_struct *asd_ha,   \
 141                                           u16 scb_site_no,                \
 142                                           u16 offs)                       \
 143{                                                                          \
 144        asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
 145        asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
 146        return asd_read_reg_##ord (asd_ha, CTXACCESS);                     \
 147}
 148
 149ASD_SCBSITE_READ(u32, dword);
 150ASD_SCBSITE_READ(u16, word);
 151
 152static inline u8 asd_scbsite_read_byte(struct asd_ha_struct *asd_ha,
 153                                       u16 scb_site_no,
 154                                       u16 offs)
 155{
 156        if (offs & 1)
 157                return asd_scbsite_read_word(asd_ha, scb_site_no,
 158                                             offs & ~1) >> 8;
 159        else
 160                return asd_scbsite_read_word(asd_ha, scb_site_no,
 161                                             offs) & 0xFF;
 162}
 163
 164
 165#define ASD_SCBSITE_WRITE(type, ord)                                       \
 166static inline void asd_scbsite_write_##ord (struct asd_ha_struct *asd_ha,  \
 167                                        u16 scb_site_no,                   \
 168                                        u16 offs, type val)                \
 169{                                                                          \
 170        asd_write_reg_word(asd_ha, ALTCIOADR, MnSCB_SITE + offs);          \
 171        asd_write_reg_word(asd_ha, ASCBPTR, scb_site_no);                  \
 172        asd_write_reg_##ord (asd_ha, CTXACCESS, val);                      \
 173}
 174
 175ASD_SCBSITE_WRITE(u32, dword);
 176ASD_SCBSITE_WRITE(u16, word);
 177
 178static inline void asd_scbsite_write_byte(struct asd_ha_struct *asd_ha,
 179                                          u16 scb_site_no,
 180                                          u16 offs, u8 val)
 181{
 182        u16 base = offs & ~1;
 183        u16 rval = asd_scbsite_read_word(asd_ha, scb_site_no, base);
 184        if (offs & 1)
 185                rval = (val << 8) | (rval & 0xFF);
 186        else
 187                rval = (rval & 0xFF00) | val;
 188        asd_scbsite_write_word(asd_ha, scb_site_no, base, rval);
 189}
 190
 191/**
 192 * asd_ddbsite_update_word -- atomically update a word in a ddb site
 193 * @asd_ha: pointer to host adapter structure
 194 * @ddb_site_no: the DDB site number
 195 * @offs: the offset into the DDB
 196 * @oldval: old value found in that offset
 197 * @newval: the new value to replace it
 198 *
 199 * This function is used when the sequencers are running and we need to
 200 * update a DDB site atomically without expensive pausing and upausing
 201 * of the sequencers and accessing the DDB site through the CIO bus.
 202 *
 203 * Return 0 on success; -EFAULT on parity error; -EAGAIN if the old value
 204 * is different than the current value at that offset.
 205 */
 206static inline int asd_ddbsite_update_word(struct asd_ha_struct *asd_ha,
 207                                          u16 ddb_site_no, u16 offs,
 208                                          u16 oldval, u16 newval)
 209{
 210        u8  done;
 211        u16 oval = asd_ddbsite_read_word(asd_ha, ddb_site_no, offs);
 212        if (oval != oldval)
 213                return -EAGAIN;
 214        asd_write_reg_word(asd_ha, AOLDDATA, oldval);
 215        asd_write_reg_word(asd_ha, ANEWDATA, newval);
 216        do {
 217                done = asd_read_reg_byte(asd_ha, ATOMICSTATCTL);
 218        } while (!(done & ATOMICDONE));
 219        if (done & ATOMICERR)
 220                return -EFAULT;   /* parity error */
 221        else if (done & ATOMICWIN)
 222                return 0;         /* success */
 223        else
 224                return -EAGAIN;   /* oldval different than current value */
 225}
 226
 227static inline int asd_ddbsite_update_byte(struct asd_ha_struct *asd_ha,
 228                                          u16 ddb_site_no, u16 offs,
 229                                          u8 _oldval, u8 _newval)
 230{
 231        u16 base = offs & ~1;
 232        u16 oval;
 233        u16 nval = asd_ddbsite_read_word(asd_ha, ddb_site_no, base);
 234        if (offs & 1) {
 235                if ((nval >> 8) != _oldval)
 236                        return -EAGAIN;
 237                nval = (_newval << 8) | (nval & 0xFF);
 238                oval = (_oldval << 8) | (nval & 0xFF);
 239        } else {
 240                if ((nval & 0xFF) != _oldval)
 241                        return -EAGAIN;
 242                nval = (nval & 0xFF00) | _newval;
 243                oval = (nval & 0xFF00) | _oldval;
 244        }
 245        return asd_ddbsite_update_word(asd_ha, ddb_site_no, base, oval, nval);
 246}
 247
 248static inline void asd_write_reg_addr(struct asd_ha_struct *asd_ha, u32 reg,
 249                                      dma_addr_t dma_handle)
 250{
 251        asd_write_reg_dword(asd_ha, reg,   ASD_BUSADDR_LO(dma_handle));
 252        asd_write_reg_dword(asd_ha, reg+4, ASD_BUSADDR_HI(dma_handle));
 253}
 254
 255static inline u32 asd_get_cmdctx_size(struct asd_ha_struct *asd_ha)
 256{
 257        /* DCHREVISION returns 0, possibly broken */
 258        u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
 259        return ctxmemsize ? 65536 : 32768;
 260}
 261
 262static inline u32 asd_get_devctx_size(struct asd_ha_struct *asd_ha)
 263{
 264        u32 ctxmemsize = asd_read_reg_dword(asd_ha, LmMnINT(0,0)) & CTXMEMSIZE;
 265        return ctxmemsize ? 8192 : 4096;
 266}
 267
 268static inline void asd_disable_ints(struct asd_ha_struct *asd_ha)
 269{
 270        asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN);
 271}
 272
 273static inline void asd_enable_ints(struct asd_ha_struct *asd_ha)
 274{
 275        /* Enable COM SAS interrupt on errors, COMSTAT */
 276        asd_write_reg_dword(asd_ha, COMSTATEN,
 277                            EN_CSBUFPERR | EN_CSERR | EN_OVLYERR);
 278        /* Enable DCH SAS CFIFTOERR */
 279        asd_write_reg_dword(asd_ha, DCHSTATUS, EN_CFIFTOERR);
 280        /* Enable Host Device interrupts */
 281        asd_write_reg_dword(asd_ha, CHIMINTEN, SET_CHIMINTEN);
 282}
 283
 284#endif
 285