^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Aic94xx SAS/SATA driver register access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "aic94xx_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "aic94xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* Writing to device address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Offset comes before value to remind that the operation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * this function is *offs = val.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void asd_write_byte(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned long offs, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) outb(val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) writeb(val, asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void asd_write_word(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long offs, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) outw(val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) writew(val, asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void asd_write_dword(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned long offs, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) outl(val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) writel(val, asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Reading from device address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) val = inb((unsigned long) asd_ha->io_handle[0].addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) val = readb(asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static u16 asd_read_word(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) val = inw((unsigned long)asd_ha->io_handle[0].addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) val = readw(asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static u32 asd_read_dword(struct asd_ha_struct *asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (unlikely(asd_ha->iospace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) val = inl((unsigned long) asd_ha->io_handle[0].addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) + (offs & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) val = readl(asd_ha->io_handle[0].addr + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static inline u32 asd_mem_offs_swa(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static inline u32 asd_mem_offs_swc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return asd_mem_offs_swa() + MBAR0_SWA_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static inline u32 asd_mem_offs_swb(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return asd_mem_offs_swc() + MBAR0_SWC_SIZE + 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* We know that the register wanted is in the range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * of the sliding window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define ASD_READ_SW(ww, type, ord) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return asd_read_##ord(asd_ha, (unsigned long)map_offs); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define ASD_WRITE_SW(ww, type, ord) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u32 reg, type val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) asd_write_##ord(asd_ha, (unsigned long)map_offs, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ASD_READ_SW(swa, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ASD_READ_SW(swa, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ASD_READ_SW(swa, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ASD_READ_SW(swb, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ASD_READ_SW(swb, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ASD_READ_SW(swb, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ASD_READ_SW(swc, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ASD_READ_SW(swc, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ASD_READ_SW(swc, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ASD_WRITE_SW(swa, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ASD_WRITE_SW(swa, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ASD_WRITE_SW(swa, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ASD_WRITE_SW(swb, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ASD_WRITE_SW(swb, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ASD_WRITE_SW(swb, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ASD_WRITE_SW(swc, u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ASD_WRITE_SW(swc, u16, word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ASD_WRITE_SW(swc, u32, dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * A word about sliding windows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * MBAR0 is divided into sliding windows A, C and B, in that order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * SWA starts at offset 0 of MBAR0, up to 0x57, with size 0x58 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * SWC starts at offset 0x58 of MBAR0, up to 0x60, with size 0x8 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * From 0x60 to 0x7F, we have a copy of PCI config space 0x60-0x7F.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * SWB starts at offset 0x80 of MBAR0 and extends to the end of MBAR0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * See asd_init_sw() in aic94xx_hwi.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * We map the most common registers we'd access of the internal 4GB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * host adapter memory space. If a register/internal memory location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * is wanted which is not mapped, we slide SWB, by paging it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * see asd_move_swb() in aic94xx_reg.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * asd_move_swb -- move sliding window B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @reg: register desired to be within range of the new window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u32 base = reg & ~(MBAR0_SWB_SIZE-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) asd_ha->io_handle[0].swb_base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void __asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (io_handle->swa_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) asd_write_swa_byte (asd_ha, reg,val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) else if (io_handle->swb_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) asd_write_swb_byte (asd_ha, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else if (io_handle->swc_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) asd_write_swc_byte (asd_ha, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* Ok, we have to move SWB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) asd_move_swb(asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) asd_write_swb_byte (asd_ha, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define ASD_WRITE_REG(type, ord) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void asd_write_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg, type val)\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned long flags; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) spin_lock_irqsave(&asd_ha->iolock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (io_handle->swa_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) && reg < io_handle->swa_base + MBAR0_SWA_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) asd_write_swa_##ord (asd_ha, reg,val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else if (io_handle->swb_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) && reg < io_handle->swb_base + MBAR0_SWB_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) asd_write_swb_##ord (asd_ha, reg, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) else if (io_handle->swc_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) && reg < io_handle->swc_base + MBAR0_SWC_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) asd_write_swc_##ord (asd_ha, reg, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Ok, we have to move SWB */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) asd_move_swb(asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) asd_write_swb_##ord (asd_ha, reg, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) spin_unlock_irqrestore(&asd_ha->iolock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ASD_WRITE_REG(u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ASD_WRITE_REG(u16,word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ASD_WRITE_REG(u32,dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static u8 __asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (io_handle->swa_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) && reg < io_handle->swa_base + MBAR0_SWA_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) val = asd_read_swa_byte (asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) else if (io_handle->swb_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) && reg < io_handle->swb_base + MBAR0_SWB_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) val = asd_read_swb_byte (asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else if (io_handle->swc_base <= reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) && reg < io_handle->swc_base + MBAR0_SWC_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) val = asd_read_swc_byte (asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Ok, we have to move SWB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) asd_move_swb(asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) val = asd_read_swb_byte (asd_ha, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define ASD_READ_REG(type, ord) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) type asd_read_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) type val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) unsigned long flags; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) spin_lock_irqsave(&asd_ha->iolock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (io_handle->swa_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) && reg < io_handle->swa_base + MBAR0_SWA_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) val = asd_read_swa_##ord (asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) else if (io_handle->swb_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) && reg < io_handle->swb_base + MBAR0_SWB_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) val = asd_read_swb_##ord (asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) else if (io_handle->swc_base <= reg \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) && reg < io_handle->swc_base + MBAR0_SWC_SIZE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) val = asd_read_swc_##ord (asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Ok, we have to move SWB */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) asd_move_swb(asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) val = asd_read_swb_##ord (asd_ha, reg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) spin_unlock_irqrestore(&asd_ha->iolock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ASD_READ_REG(u8, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ASD_READ_REG(u16,word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ASD_READ_REG(u32,dword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * asd_read_reg_string -- read a string of bytes from io space memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * @dst: pointer to a destination buffer where data will be written to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @offs: start offset (register) to read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @count: number of bytes to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) void asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u32 offs, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) u8 *p = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) spin_lock_irqsave(&asd_ha->iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) for ( ; count > 0; count--, offs++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *p = __asd_read_reg_byte(asd_ha, offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) spin_unlock_irqrestore(&asd_ha->iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * asd_write_reg_string -- write a string of bytes to io space memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * @asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * @src: pointer to source buffer where data will be read from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @offs: start offset (register) to write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @count: number of bytes to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) void asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u32 offs, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u8 *p = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) spin_lock_irqsave(&asd_ha->iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) for ( ; count > 0; count--, offs++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) __asd_write_reg_byte(asd_ha, offs, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) spin_unlock_irqrestore(&asd_ha->iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }