Commit f4cbfd24 authored by Ofir Bitton's avatar Ofir Bitton Committed by Oded Gabbay

habanalabs: PCIe iATU refactoring

Divide iATU initialization into inbound/outbound methods.
We must separate it in order to enable different match mode
per PCIe region.
In addition, added support for PCI address match mode.
Signed-off-by: default avatarOfir Bitton <obitton@habana.ai>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent fcc6a4e6
...@@ -465,6 +465,7 @@ static int gaudi_pci_bars_map(struct hl_device *hdev) ...@@ -465,6 +465,7 @@ static int gaudi_pci_bars_map(struct hl_device *hdev)
static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr) static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr)
{ {
struct gaudi_device *gaudi = hdev->asic_specific; struct gaudi_device *gaudi = hdev->asic_specific;
struct hl_inbound_pci_region pci_region;
u64 old_addr = addr; u64 old_addr = addr;
int rc; int rc;
...@@ -472,7 +473,10 @@ static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr) ...@@ -472,7 +473,10 @@ static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr)
return old_addr; return old_addr;
/* Inbound Region 2 - Bar 4 - Point to HBM */ /* Inbound Region 2 - Bar 4 - Point to HBM */
rc = hl_pci_set_dram_bar_base(hdev, 2, 4, addr); pci_region.mode = PCI_BAR_MATCH_MODE;
pci_region.bar = HBM_BAR_ID;
pci_region.addr = addr;
rc = hl_pci_set_inbound_region(hdev, 2, &pci_region);
if (rc) if (rc)
return U64_MAX; return U64_MAX;
...@@ -486,22 +490,43 @@ static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr) ...@@ -486,22 +490,43 @@ static u64 gaudi_set_hbm_bar_base(struct hl_device *hdev, u64 addr)
static int gaudi_init_iatu(struct hl_device *hdev) static int gaudi_init_iatu(struct hl_device *hdev)
{ {
int rc = 0; struct hl_inbound_pci_region inbound_region;
struct hl_outbound_pci_region outbound_region;
int rc;
/* Inbound Region 0 - Bar 0 - Point to SRAM + CFG */
inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = SRAM_BAR_ID;
inbound_region.addr = SRAM_BASE_ADDR;
rc = hl_pci_set_inbound_region(hdev, 0, &inbound_region);
if (rc)
goto done;
/* Inbound Region 1 - Bar 2 - Point to SPI FLASH */ /* Inbound Region 1 - Bar 2 - Point to SPI FLASH */
rc = hl_pci_iatu_write(hdev, 0x314, inbound_region.mode = PCI_BAR_MATCH_MODE;
lower_32_bits(SPI_FLASH_BASE_ADDR)); inbound_region.bar = CFG_BAR_ID;
rc |= hl_pci_iatu_write(hdev, 0x318, inbound_region.addr = SPI_FLASH_BASE_ADDR;
upper_32_bits(SPI_FLASH_BASE_ADDR)); rc = hl_pci_set_inbound_region(hdev, 1, &inbound_region);
rc |= hl_pci_iatu_write(hdev, 0x300, 0); if (rc)
/* Enable + Bar match + match enable */ goto done;
rc |= hl_pci_iatu_write(hdev, 0x304, 0xC0080200);
/* Inbound Region 2 - Bar 4 - Point to HBM */
inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = HBM_BAR_ID;
inbound_region.addr = DRAM_PHYS_BASE;
rc = hl_pci_set_inbound_region(hdev, 2, &inbound_region);
if (rc) if (rc)
return -EIO; goto done;
hdev->asic_funcs->set_dma_mask_from_fw(hdev);
return hl_pci_init_iatu(hdev, SRAM_BASE_ADDR, DRAM_PHYS_BASE, /* Outbound Region 0 - Point to Host */
HOST_PHYS_BASE, HOST_PHYS_SIZE); outbound_region.addr = HOST_PHYS_BASE;
outbound_region.size = HOST_PHYS_SIZE;
rc = hl_pci_set_outbound_region(hdev, &outbound_region);
done:
return rc;
} }
static int gaudi_early_init(struct hl_device *hdev) static int gaudi_early_init(struct hl_device *hdev)
...@@ -2884,16 +2909,6 @@ static int gaudi_hw_init(struct hl_device *hdev) ...@@ -2884,16 +2909,6 @@ static int gaudi_hw_init(struct hl_device *hdev)
gaudi_init_hbm_dma_qmans(hdev); gaudi_init_hbm_dma_qmans(hdev);
/*
* Before pushing u-boot/linux to device, need to set the hbm bar to
* base address of dram
*/
if (gaudi_set_hbm_bar_base(hdev, DRAM_PHYS_BASE) == U64_MAX) {
dev_err(hdev->dev,
"failed to map HBM bar to DRAM base address\n");
return -EIO;
}
rc = gaudi_init_cpu(hdev); rc = gaudi_init_cpu(hdev);
if (rc) { if (rc) {
dev_err(hdev->dev, "failed to initialize CPU\n"); dev_err(hdev->dev, "failed to initialize CPU\n");
......
...@@ -458,6 +458,7 @@ static int goya_pci_bars_map(struct hl_device *hdev) ...@@ -458,6 +458,7 @@ static int goya_pci_bars_map(struct hl_device *hdev)
static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr) static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr)
{ {
struct goya_device *goya = hdev->asic_specific; struct goya_device *goya = hdev->asic_specific;
struct hl_inbound_pci_region pci_region;
u64 old_addr = addr; u64 old_addr = addr;
int rc; int rc;
...@@ -465,7 +466,10 @@ static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr) ...@@ -465,7 +466,10 @@ static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr)
return old_addr; return old_addr;
/* Inbound Region 1 - Bar 4 - Point to DDR */ /* Inbound Region 1 - Bar 4 - Point to DDR */
rc = hl_pci_set_dram_bar_base(hdev, 1, 4, addr); pci_region.mode = PCI_BAR_MATCH_MODE;
pci_region.bar = DDR_BAR_ID;
pci_region.addr = addr;
rc = hl_pci_set_inbound_region(hdev, 1, &pci_region);
if (rc) if (rc)
return U64_MAX; return U64_MAX;
...@@ -487,8 +491,35 @@ static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr) ...@@ -487,8 +491,35 @@ static u64 goya_set_ddr_bar_base(struct hl_device *hdev, u64 addr)
*/ */
static int goya_init_iatu(struct hl_device *hdev) static int goya_init_iatu(struct hl_device *hdev)
{ {
return hl_pci_init_iatu(hdev, SRAM_BASE_ADDR, DRAM_PHYS_BASE, struct hl_inbound_pci_region inbound_region;
HOST_PHYS_BASE, HOST_PHYS_SIZE); struct hl_outbound_pci_region outbound_region;
int rc;
/* Inbound Region 0 - Bar 0 - Point to SRAM and CFG */
inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = SRAM_CFG_BAR_ID;
inbound_region.addr = SRAM_BASE_ADDR;
rc = hl_pci_set_inbound_region(hdev, 0, &inbound_region);
if (rc)
goto done;
/* Inbound Region 1 - Bar 4 - Point to DDR */
inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = DDR_BAR_ID;
inbound_region.addr = DRAM_PHYS_BASE;
rc = hl_pci_set_inbound_region(hdev, 1, &inbound_region);
if (rc)
goto done;
hdev->asic_funcs->set_dma_mask_from_fw(hdev);
/* Outbound Region 0 - Point to Host */
outbound_region.addr = HOST_PHYS_BASE;
outbound_region.size = HOST_PHYS_SIZE;
rc = hl_pci_set_outbound_region(hdev, &outbound_region);
done:
return rc;
} }
/* /*
......
...@@ -66,6 +66,8 @@ ...@@ -66,6 +66,8 @@
#define IS_POWER_OF_2(n) (n != 0 && ((n & (n - 1)) == 0)) #define IS_POWER_OF_2(n) (n != 0 && ((n & (n - 1)) == 0))
#define IS_MAX_PENDING_CS_VALID(n) (IS_POWER_OF_2(n) && (n > 1)) #define IS_MAX_PENDING_CS_VALID(n) (IS_POWER_OF_2(n) && (n > 1))
#define HL_PCI_NUM_BARS 6
/** /**
* struct pgt_info - MMU hop page info. * struct pgt_info - MMU hop page info.
* @node: hash linked-list node for the pgts shadow hash of pgts. * @node: hash linked-list node for the pgts shadow hash of pgts.
...@@ -90,6 +92,16 @@ struct pgt_info { ...@@ -90,6 +92,16 @@ struct pgt_info {
struct hl_device; struct hl_device;
struct hl_fpriv; struct hl_fpriv;
/**
* enum hl_pci_match_mode - pci match mode per region
* @PCI_ADDRESS_MATCH_MODE: address match mode
* @PCI_BAR_MATCH_MODE: bar match mode
*/
enum hl_pci_match_mode {
PCI_ADDRESS_MATCH_MODE,
PCI_BAR_MATCH_MODE
};
/** /**
* enum hl_fw_component - F/W components to read version through registers. * enum hl_fw_component - F/W components to read version through registers.
* @FW_COMP_UBOOT: u-boot. * @FW_COMP_UBOOT: u-boot.
...@@ -125,6 +137,32 @@ enum hl_cs_type { ...@@ -125,6 +137,32 @@ enum hl_cs_type {
CS_TYPE_WAIT CS_TYPE_WAIT
}; };
/*
* struct hl_inbound_pci_region - inbound region descriptor
* @mode: pci match mode for this region
* @addr: region target address
* @size: region size in bytes
* @offset_in_bar: offset within bar (address match mode)
* @bar: bar id
*/
struct hl_inbound_pci_region {
enum hl_pci_match_mode mode;
u64 addr;
u64 size;
u64 offset_in_bar;
u8 bar;
};
/*
* struct hl_outbound_pci_region - outbound region descriptor
* @addr: region target address
* @size: region size in bytes
*/
struct hl_outbound_pci_region {
u64 addr;
u64 size;
};
/* /*
* struct hl_hw_sob - H/W SOB info. * struct hl_hw_sob - H/W SOB info.
* @hdev: habanalabs device structure. * @hdev: habanalabs device structure.
...@@ -1347,7 +1385,9 @@ struct hl_device_idle_busy_ts { ...@@ -1347,7 +1385,9 @@ struct hl_device_idle_busy_ts {
/** /**
* struct hl_device - habanalabs device structure. * struct hl_device - habanalabs device structure.
* @pdev: pointer to PCI device, can be NULL in case of simulator device. * @pdev: pointer to PCI device, can be NULL in case of simulator device.
* @pcie_bar: array of available PCIe bars. * @pcie_bar_phys: array of available PCIe bars physical addresses.
* (required only for PCI address match mode)
* @pcie_bar: array of available PCIe bars virtual addresses.
* @rmmio: configuration area address on SRAM. * @rmmio: configuration area address on SRAM.
* @cdev: related char device. * @cdev: related char device.
* @cdev_ctrl: char device for control operations only (INFO IOCTL) * @cdev_ctrl: char device for control operations only (INFO IOCTL)
...@@ -1442,7 +1482,8 @@ struct hl_device_idle_busy_ts { ...@@ -1442,7 +1482,8 @@ struct hl_device_idle_busy_ts {
*/ */
struct hl_device { struct hl_device {
struct pci_dev *pdev; struct pci_dev *pdev;
void __iomem *pcie_bar[6]; u64 pcie_bar_phys[HL_PCI_NUM_BARS];
void __iomem *pcie_bar[HL_PCI_NUM_BARS];
void __iomem *rmmio; void __iomem *rmmio;
struct cdev cdev; struct cdev cdev;
struct cdev cdev_ctrl; struct cdev cdev_ctrl;
...@@ -1767,9 +1808,10 @@ int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3], ...@@ -1767,9 +1808,10 @@ int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3],
int hl_pci_iatu_write(struct hl_device *hdev, u32 addr, u32 data); int hl_pci_iatu_write(struct hl_device *hdev, u32 addr, u32 data);
int hl_pci_set_dram_bar_base(struct hl_device *hdev, u8 inbound_region, u8 bar, int hl_pci_set_dram_bar_base(struct hl_device *hdev, u8 inbound_region, u8 bar,
u64 addr); u64 addr);
int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address, int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
u64 dram_base_address, u64 host_phys_base_address, struct hl_inbound_pci_region *pci_region);
u64 host_phys_size); int hl_pci_set_outbound_region(struct hl_device *hdev,
struct hl_outbound_pci_region *pci_region);
int hl_pci_init(struct hl_device *hdev); int hl_pci_init(struct hl_device *hdev);
void hl_pci_fini(struct hl_device *hdev); void hl_pci_fini(struct hl_device *hdev);
......
...@@ -9,9 +9,15 @@ ...@@ -9,9 +9,15 @@
#include "include/hw_ip/pci/pci_general.h" #include "include/hw_ip/pci/pci_general.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/bitfield.h>
#define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 10) #define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 10)
#define IATU_REGION_CTRL_REGION_EN_MASK BIT(31)
#define IATU_REGION_CTRL_MATCH_MODE_MASK BIT(30)
#define IATU_REGION_CTRL_NUM_MATCH_EN_MASK BIT(19)
#define IATU_REGION_CTRL_BAR_NUM_MASK GENMASK(10, 8)
/** /**
* hl_pci_bars_map() - Map PCI BARs. * hl_pci_bars_map() - Map PCI BARs.
* @hdev: Pointer to hl_device structure. * @hdev: Pointer to hl_device structure.
...@@ -187,110 +193,94 @@ static void hl_pci_reset_link_through_bridge(struct hl_device *hdev) ...@@ -187,110 +193,94 @@ static void hl_pci_reset_link_through_bridge(struct hl_device *hdev)
} }
/** /**
* hl_pci_set_dram_bar_base() - Set DDR BAR to map specific device address. * hl_pci_set_inbound_region() - Configure inbound region
* @hdev: Pointer to hl_device structure. * @hdev: Pointer to hl_device structure.
* @inbound_region: Inbound region number. * @region: Inbound region number.
* @bar: PCI BAR number. * @pci_region: Inbound region parameters.
* @addr: Address in DRAM. Must be aligned to DRAM bar size.
* *
* Configure the iATU so that the DRAM bar will start at the specified address. * Configure the iATU inbound region.
* *
* Return: 0 on success, negative value for failure. * Return: 0 on success, negative value for failure.
*/ */
int hl_pci_set_dram_bar_base(struct hl_device *hdev, u8 inbound_region, u8 bar, int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
u64 addr) struct hl_inbound_pci_region *pci_region)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
u32 offset; u64 bar_phys_base, region_base, region_end_address;
int rc; u32 offset, ctrl_reg_val;
int rc = 0;
switch (inbound_region) { /* region offset */
case 0: offset = (0x200 * region) + 0x100;
offset = 0x100;
break; if (pci_region->mode == PCI_ADDRESS_MATCH_MODE) {
case 1: bar_phys_base = hdev->pcie_bar_phys[pci_region->bar];
offset = 0x300; region_base = bar_phys_base + pci_region->offset_in_bar;
break; region_end_address = region_base + pci_region->size - 1;
case 2:
offset = 0x500;
break;
default:
dev_err(hdev->dev, "Invalid inbound region %d\n",
inbound_region);
return -EINVAL;
}
if (bar != 0 && bar != 2 && bar != 4) { rc |= hl_pci_iatu_write(hdev, offset + 0x8,
dev_err(hdev->dev, "Invalid PCI BAR %d\n", bar); lower_32_bits(region_base));
return -EINVAL; rc |= hl_pci_iatu_write(hdev, offset + 0xC,
upper_32_bits(region_base));
rc |= hl_pci_iatu_write(hdev, offset + 0x10,
lower_32_bits(region_end_address));
} }
/* Point to the specified address */ /* Point to the specified address */
rc = hl_pci_iatu_write(hdev, offset + 0x14, lower_32_bits(addr)); rc = hl_pci_iatu_write(hdev, offset + 0x14,
rc |= hl_pci_iatu_write(hdev, offset + 0x18, upper_32_bits(addr)); lower_32_bits(pci_region->addr));
rc |= hl_pci_iatu_write(hdev, offset + 0x18,
upper_32_bits(pci_region->addr));
rc |= hl_pci_iatu_write(hdev, offset + 0x0, 0); rc |= hl_pci_iatu_write(hdev, offset + 0x0, 0);
/* Enable + BAR match + match enable + BAR number */
rc |= hl_pci_iatu_write(hdev, offset + 0x4, 0xC0080000 | (bar << 8)); /* Enable + bar/address match + match enable + bar number */
ctrl_reg_val = FIELD_PREP(IATU_REGION_CTRL_REGION_EN_MASK, 1);
ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_MATCH_MODE_MASK,
pci_region->mode);
ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_NUM_MATCH_EN_MASK, 1);
if (pci_region->mode == PCI_BAR_MATCH_MODE)
ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_BAR_NUM_MASK,
pci_region->bar);
rc |= hl_pci_iatu_write(hdev, offset + 0x4, ctrl_reg_val);
/* Return the DBI window to the default location */ /* Return the DBI window to the default location */
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0); rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0); rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0);
if (rc) if (rc)
dev_err(hdev->dev, "failed to map DRAM bar to 0x%08llx\n", dev_err(hdev->dev, "failed to map bar %u to 0x%08llx\n",
addr); pci_region->bar, pci_region->addr);
return rc; return rc;
} }
/** /**
* hl_pci_init_iatu() - Initialize the iATU unit inside the PCI controller. * hl_pci_set_outbound_region() - Configure outbound region 0
* @hdev: Pointer to hl_device structure. * @hdev: Pointer to hl_device structure.
* @sram_base_address: SRAM base address. * @pci_region: Outbound region parameters.
* @dram_base_address: DRAM base address.
* @host_phys_base_address: Base physical address of host memory for device
* transactions.
* @host_phys_size: Size of host memory for device transactions.
* *
* This is needed in case the firmware doesn't initialize the iATU. * Configure the iATU outbound region 0.
* *
* Return: 0 on success, negative value for failure. * Return: 0 on success, negative value for failure.
*/ */
int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address, int hl_pci_set_outbound_region(struct hl_device *hdev,
u64 dram_base_address, u64 host_phys_base_address, struct hl_outbound_pci_region *pci_region)
u64 host_phys_size)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
u64 host_phys_end_addr; u64 outbound_region_end_address;
int rc = 0; int rc = 0;
/* Inbound Region 0 - Bar 0 - Point to SRAM base address */ /* Outbound Region 0 */
rc = hl_pci_iatu_write(hdev, 0x114, lower_32_bits(sram_base_address)); outbound_region_end_address =
rc |= hl_pci_iatu_write(hdev, 0x118, upper_32_bits(sram_base_address)); pci_region->addr + pci_region->size - 1;
rc |= hl_pci_iatu_write(hdev, 0x100, 0);
/* Enable + Bar match + match enable */
rc |= hl_pci_iatu_write(hdev, 0x104, 0xC0080000);
/* Return the DBI window to the default location */
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0);
hdev->asic_funcs->set_dma_mask_from_fw(hdev);
/* Point to DRAM */
if (!hdev->asic_funcs->set_dram_bar_base)
return -EINVAL;
if (hdev->asic_funcs->set_dram_bar_base(hdev, dram_base_address) ==
U64_MAX)
return -EIO;
/* Outbound Region 0 - Point to Host */
host_phys_end_addr = host_phys_base_address + host_phys_size - 1;
rc |= hl_pci_iatu_write(hdev, 0x008, rc |= hl_pci_iatu_write(hdev, 0x008,
lower_32_bits(host_phys_base_address)); lower_32_bits(pci_region->addr));
rc |= hl_pci_iatu_write(hdev, 0x00C, rc |= hl_pci_iatu_write(hdev, 0x00C,
upper_32_bits(host_phys_base_address)); upper_32_bits(pci_region->addr));
rc |= hl_pci_iatu_write(hdev, 0x010, lower_32_bits(host_phys_end_addr)); rc |= hl_pci_iatu_write(hdev, 0x010,
lower_32_bits(outbound_region_end_address));
rc |= hl_pci_iatu_write(hdev, 0x014, 0); rc |= hl_pci_iatu_write(hdev, 0x014, 0);
if ((hdev->power9_64bit_dma_enable) && (hdev->dma_mask == 64)) if ((hdev->power9_64bit_dma_enable) && (hdev->dma_mask == 64))
...@@ -298,7 +288,8 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address, ...@@ -298,7 +288,8 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
else else
rc |= hl_pci_iatu_write(hdev, 0x018, 0); rc |= hl_pci_iatu_write(hdev, 0x018, 0);
rc |= hl_pci_iatu_write(hdev, 0x020, upper_32_bits(host_phys_end_addr)); rc |= hl_pci_iatu_write(hdev, 0x020,
upper_32_bits(outbound_region_end_address));
/* Increase region size */ /* Increase region size */
rc |= hl_pci_iatu_write(hdev, 0x000, 0x00002000); rc |= hl_pci_iatu_write(hdev, 0x000, 0x00002000);
/* Enable */ /* Enable */
...@@ -308,10 +299,7 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address, ...@@ -308,10 +299,7 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0); rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);
rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0); rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0);
if (rc) return rc;
return -EIO;
return 0;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment