18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Aic94xx SAS/SATA driver register access. 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#include <linux/pci.h> 108c2ecf20Sopenharmony_ci#include "aic94xx_reg.h" 118c2ecf20Sopenharmony_ci#include "aic94xx.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* Writing to device address space. 148c2ecf20Sopenharmony_ci * Offset comes before value to remind that the operation of 158c2ecf20Sopenharmony_ci * this function is *offs = val. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistatic void asd_write_byte(struct asd_ha_struct *asd_ha, 188c2ecf20Sopenharmony_ci unsigned long offs, u8 val) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 218c2ecf20Sopenharmony_ci outb(val, 228c2ecf20Sopenharmony_ci (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF)); 238c2ecf20Sopenharmony_ci else 248c2ecf20Sopenharmony_ci writeb(val, asd_ha->io_handle[0].addr + offs); 258c2ecf20Sopenharmony_ci wmb(); 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void asd_write_word(struct asd_ha_struct *asd_ha, 298c2ecf20Sopenharmony_ci unsigned long offs, u16 val) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 328c2ecf20Sopenharmony_ci outw(val, 338c2ecf20Sopenharmony_ci (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF)); 348c2ecf20Sopenharmony_ci else 358c2ecf20Sopenharmony_ci writew(val, asd_ha->io_handle[0].addr + offs); 368c2ecf20Sopenharmony_ci wmb(); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic void asd_write_dword(struct asd_ha_struct *asd_ha, 408c2ecf20Sopenharmony_ci unsigned long offs, u32 val) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 438c2ecf20Sopenharmony_ci outl(val, 448c2ecf20Sopenharmony_ci (unsigned long)asd_ha->io_handle[0].addr + (offs & 0xFF)); 458c2ecf20Sopenharmony_ci else 468c2ecf20Sopenharmony_ci writel(val, asd_ha->io_handle[0].addr + offs); 478c2ecf20Sopenharmony_ci wmb(); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* Reading from device address space. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_cistatic u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci u8 val; 558c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 568c2ecf20Sopenharmony_ci val = inb((unsigned long) asd_ha->io_handle[0].addr 578c2ecf20Sopenharmony_ci + (offs & 0xFF)); 588c2ecf20Sopenharmony_ci else 598c2ecf20Sopenharmony_ci val = readb(asd_ha->io_handle[0].addr + offs); 608c2ecf20Sopenharmony_ci rmb(); 618c2ecf20Sopenharmony_ci return val; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic u16 asd_read_word(struct asd_ha_struct *asd_ha, 658c2ecf20Sopenharmony_ci unsigned long offs) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci u16 val; 688c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 698c2ecf20Sopenharmony_ci val = inw((unsigned long)asd_ha->io_handle[0].addr 708c2ecf20Sopenharmony_ci + (offs & 0xFF)); 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci val = readw(asd_ha->io_handle[0].addr + offs); 738c2ecf20Sopenharmony_ci rmb(); 748c2ecf20Sopenharmony_ci return val; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic u32 asd_read_dword(struct asd_ha_struct *asd_ha, 788c2ecf20Sopenharmony_ci unsigned long offs) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci u32 val; 818c2ecf20Sopenharmony_ci if (unlikely(asd_ha->iospace)) 828c2ecf20Sopenharmony_ci val = inl((unsigned long) asd_ha->io_handle[0].addr 838c2ecf20Sopenharmony_ci + (offs & 0xFF)); 848c2ecf20Sopenharmony_ci else 858c2ecf20Sopenharmony_ci val = readl(asd_ha->io_handle[0].addr + offs); 868c2ecf20Sopenharmony_ci rmb(); 878c2ecf20Sopenharmony_ci return val; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline u32 asd_mem_offs_swa(void) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci return 0; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic inline u32 asd_mem_offs_swc(void) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci return asd_mem_offs_swa() + MBAR0_SWA_SIZE; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline u32 asd_mem_offs_swb(void) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci return asd_mem_offs_swc() + MBAR0_SWC_SIZE + 0x20; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* We know that the register wanted is in the range 1068c2ecf20Sopenharmony_ci * of the sliding window. 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci#define ASD_READ_SW(ww, type, ord) \ 1098c2ecf20Sopenharmony_cistatic type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha, \ 1108c2ecf20Sopenharmony_ci u32 reg) \ 1118c2ecf20Sopenharmony_ci{ \ 1128c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \ 1138c2ecf20Sopenharmony_ci u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\ 1148c2ecf20Sopenharmony_ci return asd_read_##ord(asd_ha, (unsigned long)map_offs); \ 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define ASD_WRITE_SW(ww, type, ord) \ 1188c2ecf20Sopenharmony_cistatic void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha, \ 1198c2ecf20Sopenharmony_ci u32 reg, type val) \ 1208c2ecf20Sopenharmony_ci{ \ 1218c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \ 1228c2ecf20Sopenharmony_ci u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\ 1238c2ecf20Sopenharmony_ci asd_write_##ord(asd_ha, (unsigned long)map_offs, val); \ 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ciASD_READ_SW(swa, u8, byte); 1278c2ecf20Sopenharmony_ciASD_READ_SW(swa, u16, word); 1288c2ecf20Sopenharmony_ciASD_READ_SW(swa, u32, dword); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciASD_READ_SW(swb, u8, byte); 1318c2ecf20Sopenharmony_ciASD_READ_SW(swb, u16, word); 1328c2ecf20Sopenharmony_ciASD_READ_SW(swb, u32, dword); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciASD_READ_SW(swc, u8, byte); 1358c2ecf20Sopenharmony_ciASD_READ_SW(swc, u16, word); 1368c2ecf20Sopenharmony_ciASD_READ_SW(swc, u32, dword); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ciASD_WRITE_SW(swa, u8, byte); 1398c2ecf20Sopenharmony_ciASD_WRITE_SW(swa, u16, word); 1408c2ecf20Sopenharmony_ciASD_WRITE_SW(swa, u32, dword); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ciASD_WRITE_SW(swb, u8, byte); 1438c2ecf20Sopenharmony_ciASD_WRITE_SW(swb, u16, word); 1448c2ecf20Sopenharmony_ciASD_WRITE_SW(swb, u32, dword); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciASD_WRITE_SW(swc, u8, byte); 1478c2ecf20Sopenharmony_ciASD_WRITE_SW(swc, u16, word); 1488c2ecf20Sopenharmony_ciASD_WRITE_SW(swc, u32, dword); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* 1518c2ecf20Sopenharmony_ci * A word about sliding windows: 1528c2ecf20Sopenharmony_ci * MBAR0 is divided into sliding windows A, C and B, in that order. 1538c2ecf20Sopenharmony_ci * SWA starts at offset 0 of MBAR0, up to 0x57, with size 0x58 bytes. 1548c2ecf20Sopenharmony_ci * SWC starts at offset 0x58 of MBAR0, up to 0x60, with size 0x8 bytes. 1558c2ecf20Sopenharmony_ci * From 0x60 to 0x7F, we have a copy of PCI config space 0x60-0x7F. 1568c2ecf20Sopenharmony_ci * SWB starts at offset 0x80 of MBAR0 and extends to the end of MBAR0. 1578c2ecf20Sopenharmony_ci * See asd_init_sw() in aic94xx_hwi.c 1588c2ecf20Sopenharmony_ci * 1598c2ecf20Sopenharmony_ci * We map the most common registers we'd access of the internal 4GB 1608c2ecf20Sopenharmony_ci * host adapter memory space. If a register/internal memory location 1618c2ecf20Sopenharmony_ci * is wanted which is not mapped, we slide SWB, by paging it, 1628c2ecf20Sopenharmony_ci * see asd_move_swb() in aic94xx_reg.c. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/** 1668c2ecf20Sopenharmony_ci * asd_move_swb -- move sliding window B 1678c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 1688c2ecf20Sopenharmony_ci * @reg: register desired to be within range of the new window 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_cistatic void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci u32 base = reg & ~(MBAR0_SWB_SIZE-1); 1738c2ecf20Sopenharmony_ci pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base); 1748c2ecf20Sopenharmony_ci asd_ha->io_handle[0].swb_base = base; 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void __asd_write_reg_byte(struct asd_ha_struct *asd_ha, u32 reg, u8 val) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; 1808c2ecf20Sopenharmony_ci BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); 1818c2ecf20Sopenharmony_ci if (io_handle->swa_base <= reg 1828c2ecf20Sopenharmony_ci && reg < io_handle->swa_base + MBAR0_SWA_SIZE) 1838c2ecf20Sopenharmony_ci asd_write_swa_byte (asd_ha, reg,val); 1848c2ecf20Sopenharmony_ci else if (io_handle->swb_base <= reg 1858c2ecf20Sopenharmony_ci && reg < io_handle->swb_base + MBAR0_SWB_SIZE) 1868c2ecf20Sopenharmony_ci asd_write_swb_byte (asd_ha, reg, val); 1878c2ecf20Sopenharmony_ci else if (io_handle->swc_base <= reg 1888c2ecf20Sopenharmony_ci && reg < io_handle->swc_base + MBAR0_SWC_SIZE) 1898c2ecf20Sopenharmony_ci asd_write_swc_byte (asd_ha, reg, val); 1908c2ecf20Sopenharmony_ci else { 1918c2ecf20Sopenharmony_ci /* Ok, we have to move SWB */ 1928c2ecf20Sopenharmony_ci asd_move_swb(asd_ha, reg); 1938c2ecf20Sopenharmony_ci asd_write_swb_byte (asd_ha, reg, val); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#define ASD_WRITE_REG(type, ord) \ 1988c2ecf20Sopenharmony_civoid asd_write_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg, type val)\ 1998c2ecf20Sopenharmony_ci{ \ 2008c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \ 2018c2ecf20Sopenharmony_ci unsigned long flags; \ 2028c2ecf20Sopenharmony_ci BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); \ 2038c2ecf20Sopenharmony_ci spin_lock_irqsave(&asd_ha->iolock, flags); \ 2048c2ecf20Sopenharmony_ci if (io_handle->swa_base <= reg \ 2058c2ecf20Sopenharmony_ci && reg < io_handle->swa_base + MBAR0_SWA_SIZE) \ 2068c2ecf20Sopenharmony_ci asd_write_swa_##ord (asd_ha, reg,val); \ 2078c2ecf20Sopenharmony_ci else if (io_handle->swb_base <= reg \ 2088c2ecf20Sopenharmony_ci && reg < io_handle->swb_base + MBAR0_SWB_SIZE) \ 2098c2ecf20Sopenharmony_ci asd_write_swb_##ord (asd_ha, reg, val); \ 2108c2ecf20Sopenharmony_ci else if (io_handle->swc_base <= reg \ 2118c2ecf20Sopenharmony_ci && reg < io_handle->swc_base + MBAR0_SWC_SIZE) \ 2128c2ecf20Sopenharmony_ci asd_write_swc_##ord (asd_ha, reg, val); \ 2138c2ecf20Sopenharmony_ci else { \ 2148c2ecf20Sopenharmony_ci /* Ok, we have to move SWB */ \ 2158c2ecf20Sopenharmony_ci asd_move_swb(asd_ha, reg); \ 2168c2ecf20Sopenharmony_ci asd_write_swb_##ord (asd_ha, reg, val); \ 2178c2ecf20Sopenharmony_ci } \ 2188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->iolock, flags); \ 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ciASD_WRITE_REG(u8, byte); 2228c2ecf20Sopenharmony_ciASD_WRITE_REG(u16,word); 2238c2ecf20Sopenharmony_ciASD_WRITE_REG(u32,dword); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic u8 __asd_read_reg_byte(struct asd_ha_struct *asd_ha, u32 reg) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; 2288c2ecf20Sopenharmony_ci u8 val; 2298c2ecf20Sopenharmony_ci BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); 2308c2ecf20Sopenharmony_ci if (io_handle->swa_base <= reg 2318c2ecf20Sopenharmony_ci && reg < io_handle->swa_base + MBAR0_SWA_SIZE) 2328c2ecf20Sopenharmony_ci val = asd_read_swa_byte (asd_ha, reg); 2338c2ecf20Sopenharmony_ci else if (io_handle->swb_base <= reg 2348c2ecf20Sopenharmony_ci && reg < io_handle->swb_base + MBAR0_SWB_SIZE) 2358c2ecf20Sopenharmony_ci val = asd_read_swb_byte (asd_ha, reg); 2368c2ecf20Sopenharmony_ci else if (io_handle->swc_base <= reg 2378c2ecf20Sopenharmony_ci && reg < io_handle->swc_base + MBAR0_SWC_SIZE) 2388c2ecf20Sopenharmony_ci val = asd_read_swc_byte (asd_ha, reg); 2398c2ecf20Sopenharmony_ci else { 2408c2ecf20Sopenharmony_ci /* Ok, we have to move SWB */ 2418c2ecf20Sopenharmony_ci asd_move_swb(asd_ha, reg); 2428c2ecf20Sopenharmony_ci val = asd_read_swb_byte (asd_ha, reg); 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci return val; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci#define ASD_READ_REG(type, ord) \ 2488c2ecf20Sopenharmony_citype asd_read_reg_##ord (struct asd_ha_struct *asd_ha, u32 reg) \ 2498c2ecf20Sopenharmony_ci{ \ 2508c2ecf20Sopenharmony_ci struct asd_ha_addrspace *io_handle=&asd_ha->io_handle[0]; \ 2518c2ecf20Sopenharmony_ci type val; \ 2528c2ecf20Sopenharmony_ci unsigned long flags; \ 2538c2ecf20Sopenharmony_ci BUG_ON(reg >= 0xC0000000 || reg < ALL_BASE_ADDR); \ 2548c2ecf20Sopenharmony_ci spin_lock_irqsave(&asd_ha->iolock, flags); \ 2558c2ecf20Sopenharmony_ci if (io_handle->swa_base <= reg \ 2568c2ecf20Sopenharmony_ci && reg < io_handle->swa_base + MBAR0_SWA_SIZE) \ 2578c2ecf20Sopenharmony_ci val = asd_read_swa_##ord (asd_ha, reg); \ 2588c2ecf20Sopenharmony_ci else if (io_handle->swb_base <= reg \ 2598c2ecf20Sopenharmony_ci && reg < io_handle->swb_base + MBAR0_SWB_SIZE) \ 2608c2ecf20Sopenharmony_ci val = asd_read_swb_##ord (asd_ha, reg); \ 2618c2ecf20Sopenharmony_ci else if (io_handle->swc_base <= reg \ 2628c2ecf20Sopenharmony_ci && reg < io_handle->swc_base + MBAR0_SWC_SIZE) \ 2638c2ecf20Sopenharmony_ci val = asd_read_swc_##ord (asd_ha, reg); \ 2648c2ecf20Sopenharmony_ci else { \ 2658c2ecf20Sopenharmony_ci /* Ok, we have to move SWB */ \ 2668c2ecf20Sopenharmony_ci asd_move_swb(asd_ha, reg); \ 2678c2ecf20Sopenharmony_ci val = asd_read_swb_##ord (asd_ha, reg); \ 2688c2ecf20Sopenharmony_ci } \ 2698c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->iolock, flags); \ 2708c2ecf20Sopenharmony_ci return val; \ 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ciASD_READ_REG(u8, byte); 2748c2ecf20Sopenharmony_ciASD_READ_REG(u16,word); 2758c2ecf20Sopenharmony_ciASD_READ_REG(u32,dword); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci/** 2788c2ecf20Sopenharmony_ci * asd_read_reg_string -- read a string of bytes from io space memory 2798c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 2808c2ecf20Sopenharmony_ci * @dst: pointer to a destination buffer where data will be written to 2818c2ecf20Sopenharmony_ci * @offs: start offset (register) to read from 2828c2ecf20Sopenharmony_ci * @count: number of bytes to read 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_civoid asd_read_reg_string(struct asd_ha_struct *asd_ha, void *dst, 2858c2ecf20Sopenharmony_ci u32 offs, int count) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci u8 *p = dst; 2888c2ecf20Sopenharmony_ci unsigned long flags; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci spin_lock_irqsave(&asd_ha->iolock, flags); 2918c2ecf20Sopenharmony_ci for ( ; count > 0; count--, offs++, p++) 2928c2ecf20Sopenharmony_ci *p = __asd_read_reg_byte(asd_ha, offs); 2938c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->iolock, flags); 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci/** 2978c2ecf20Sopenharmony_ci * asd_write_reg_string -- write a string of bytes to io space memory 2988c2ecf20Sopenharmony_ci * @asd_ha: pointer to host adapter structure 2998c2ecf20Sopenharmony_ci * @src: pointer to source buffer where data will be read from 3008c2ecf20Sopenharmony_ci * @offs: start offset (register) to write to 3018c2ecf20Sopenharmony_ci * @count: number of bytes to write 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_civoid asd_write_reg_string(struct asd_ha_struct *asd_ha, void *src, 3048c2ecf20Sopenharmony_ci u32 offs, int count) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci u8 *p = src; 3078c2ecf20Sopenharmony_ci unsigned long flags; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci spin_lock_irqsave(&asd_ha->iolock, flags); 3108c2ecf20Sopenharmony_ci for ( ; count > 0; count--, offs++, p++) 3118c2ecf20Sopenharmony_ci __asd_write_reg_byte(asd_ha, offs, *p); 3128c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->iolock, flags); 3138c2ecf20Sopenharmony_ci} 314