#define avs_platattr_test(adev, attr) \
        ((adev)->spec->attributes & AVS_PLATATTR_##attr)
 
+struct avs_sram_spec {
+       const u32 base_offset;
+       const u32 window_size;
+       const u32 rom_status_offset;
+};
+
+struct avs_hipc_spec {
+       const u32 req_offset;
+       const u32 req_ext_offset;
+       const u32 req_busy_mask;
+       const u32 ack_offset;
+       const u32 ack_done_mask;
+       const u32 rsp_offset;
+       const u32 rsp_busy_mask;
+       const u32 ctl_offset;
+};
+
 /* Platform specific descriptor */
 struct avs_spec {
        const char *name;
 
        const u32 core_init_mask;       /* used during DSP boot */
        const u64 attributes;           /* bitmask of AVS_PLATATTR_* */
-       const u32 sram_base_offset;
-       const u32 sram_window_size;
-       const u32 rom_status;
+       const struct avs_sram_spec *sram;
+       const struct avs_hipc_spec *hipc;
 };
 
 struct avs_fw_entry {
 
        SET_RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL)
 };
 
+static const struct avs_sram_spec skl_sram_spec = {
+       .base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
+       .window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
+       .rom_status_offset = SKL_ADSP_SRAM_BASE_OFFSET,
+};
+
+static const struct avs_sram_spec apl_sram_spec = {
+       .base_offset = APL_ADSP_SRAM_BASE_OFFSET,
+       .window_size = APL_ADSP_SRAM_WINDOW_SIZE,
+       .rom_status_offset = APL_ADSP_SRAM_BASE_OFFSET,
+};
+
+static const struct avs_hipc_spec skl_hipc_spec = {
+       .req_offset = SKL_ADSP_REG_HIPCI,
+       .req_ext_offset = SKL_ADSP_REG_HIPCIE,
+       .req_busy_mask = SKL_ADSP_HIPCI_BUSY,
+       .ack_offset = SKL_ADSP_REG_HIPCIE,
+       .ack_done_mask = SKL_ADSP_HIPCIE_DONE,
+       .rsp_offset = SKL_ADSP_REG_HIPCT,
+       .rsp_busy_mask = SKL_ADSP_HIPCT_BUSY,
+       .ctl_offset = SKL_ADSP_REG_HIPCCTL,
+};
+
 static const struct avs_spec skl_desc = {
        .name = "skl",
-       .min_fw_version = {
-               .major = 9,
-               .minor = 21,
-               .hotfix = 0,
-               .build = 4732,
-       },
+       .min_fw_version = { 9, 21, 0, 4732 },
        .dsp_ops = &avs_skl_dsp_ops,
        .core_init_mask = 1,
        .attributes = AVS_PLATATTR_CLDMA,
-       .sram_base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
-       .sram_window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
-       .rom_status = SKL_ADSP_SRAM_BASE_OFFSET,
+       .sram = &skl_sram_spec,
+       .hipc = &skl_hipc_spec,
 };
 
 static const struct avs_spec apl_desc = {
        .name = "apl",
-       .min_fw_version = {
-               .major = 9,
-               .minor = 22,
-               .hotfix = 1,
-               .build = 4323,
-       },
+       .min_fw_version = { 9, 22, 1, 4323 },
        .dsp_ops = &avs_apl_dsp_ops,
        .core_init_mask = 3,
        .attributes = AVS_PLATATTR_IMR,
-       .sram_base_offset = APL_ADSP_SRAM_BASE_OFFSET,
-       .sram_window_size = APL_ADSP_SRAM_WINDOW_SIZE,
-       .rom_status = APL_ADSP_SRAM_BASE_OFFSET,
+       .sram = &apl_sram_spec,
+       .hipc = &skl_hipc_spec,
 };
 
 static const struct pci_device_id avs_ids[] = {
 
 {
        struct avs_dev *adev = dev_id;
        struct avs_ipc *ipc = adev->ipc;
+       const struct avs_spec *const spec = adev->spec;
        u32 adspis, hipc_rsp, hipc_ack;
        irqreturn_t ret = IRQ_NONE;
 
        if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC))
                return ret;
 
-       hipc_ack = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCIE);
-       hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
+       hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset);
+       hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
 
        /* DSP acked host's request */
-       if (hipc_ack & SKL_ADSP_HIPCIE_DONE) {
+       if (hipc_ack & spec->hipc->ack_done_mask) {
                /*
                 * As an extra precaution, mask done interrupt. Code executed
                 * due to complete() found below does not assume any masking.
                 */
-               snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+               snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
                                      AVS_ADSP_HIPCCTL_DONE, 0);
 
                complete(&ipc->done_completion);
 
                /* tell DSP it has our attention */
-               snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCIE,
-                                     SKL_ADSP_HIPCIE_DONE,
-                                     SKL_ADSP_HIPCIE_DONE);
+               snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset,
+                                     spec->hipc->ack_done_mask,
+                                     spec->hipc->ack_done_mask);
                /* unmask done interrupt */
-               snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+               snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
                                      AVS_ADSP_HIPCCTL_DONE,
                                      AVS_ADSP_HIPCCTL_DONE);
                ret = IRQ_HANDLED;
        }
 
        /* DSP sent new response to process */
-       if (hipc_rsp & SKL_ADSP_HIPCT_BUSY) {
+       if (hipc_rsp & spec->hipc->rsp_busy_mask) {
                /* mask busy interrupt */
-               snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+               snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
                                      AVS_ADSP_HIPCCTL_BUSY, 0);
 
                ret = IRQ_WAKE_THREAD;
 static bool avs_ipc_is_busy(struct avs_ipc *ipc)
 {
        struct avs_dev *adev = to_avs_dev(ipc->dev);
+       const struct avs_spec *const spec = adev->spec;
        u32 hipc_rsp;
 
-       hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
-       return hipc_rsp & SKL_ADSP_HIPCT_BUSY;
+       hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
+       return hipc_rsp & spec->hipc->rsp_busy_mask;
 }
 
 static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout)
 
 static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool read_fwregs)
 {
+       const struct avs_spec *const spec = adev->spec;
        u64 reg = ULONG_MAX;
 
-       tx->header |= SKL_ADSP_HIPCI_BUSY;
+       tx->header |= spec->hipc->req_busy_mask;
        if (read_fwregs)
                reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
 
 
        if (tx->size)
                memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size);
-       snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCIE, tx->header >> 32);
-       snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCI, tx->header & UINT_MAX);
+       snd_hdac_adsp_writel(adev, spec->hipc->req_ext_offset, tx->header >> 32);
+       snd_hdac_adsp_writel(adev, spec->hipc->req_offset, tx->header & UINT_MAX);
 }
 
 static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
 
 void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)
 {
+       const struct avs_spec *const spec = adev->spec;
        u32 value, mask;
 
        /*
 
        mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY;
        value = enable ? mask : 0;
-       snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, mask, value);
+       snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, mask, value);
 }
 
 int avs_ipc_init(struct avs_ipc *ipc, struct device *dev)
 
        }
 
        /* await ROM init */
-       ret = snd_hdac_adsp_readq_poll(adev, spec->rom_status, reg,
+       ret = snd_hdac_adsp_readq_poll(adev, spec->sram->rom_status_offset, reg,
                                       (reg & 0xF) == AVS_ROM_INIT_DONE ||
                                       (reg & 0xF) == APL_ROM_FW_ENTERED,
                                       AVS_ROM_INIT_POLLING_US, APL_ROM_INIT_TIMEOUT_US);
 
 #define APL_ADSP_SRAM_WINDOW_SIZE      0x20000
 
 /* Constants used when accessing SRAM, space shared with firmware */
-#define AVS_FW_REG_BASE(adev)          ((adev)->spec->sram_base_offset)
+#define AVS_FW_REG_BASE(adev)          ((adev)->spec->sram->base_offset)
 #define AVS_FW_REG_STATUS(adev)                (AVS_FW_REG_BASE(adev) + 0x0)
 #define AVS_FW_REG_ERROR_CODE(adev)    (AVS_FW_REG_BASE(adev) + 0x4)
 
 
 /* registry I/O helpers */
 #define avs_sram_offset(adev, window_idx) \
-       ((adev)->spec->sram_base_offset + \
-        (adev)->spec->sram_window_size * (window_idx))
+       ((adev)->spec->sram->base_offset + \
+        (adev)->spec->sram->window_size * (window_idx))
 
 #define avs_sram_addr(adev, window_idx) \
        ((adev)->dsp_ba + avs_sram_offset(adev, window_idx))