qcacmn: Interrupt handling support for chipset QCA8074
Changes to handle Interrupts for qca8074 Change-Id: I81d4b0722d56388cc7aca08484bd8957258621d1 Acked-by: Venkateswara Swamy Bandaru <vbandaru@codeaurora.org> CRs-Fixed: 1042915
This commit is contained in:
@@ -62,6 +62,7 @@ typedef void *hif_handle_t;
|
||||
#define HIF_TYPE_QCA9984 12
|
||||
#define HIF_TYPE_IPQ4019 13
|
||||
#define HIF_TYPE_QCA9888 14
|
||||
#define HIF_TYPE_QCA8074 15
|
||||
|
||||
/* TARGET definition needs to be abstracted in fw common
|
||||
* header files, below is the placeholder till WIN codebase
|
||||
@@ -95,6 +96,9 @@ typedef void *hif_handle_t;
|
||||
/* For Adrastea target */
|
||||
#define TARGET_TYPE_ADRASTEA 19
|
||||
#endif /* CONFIG_WIN */
|
||||
#ifndef TARGET_TYPE_QCA8074
|
||||
#define TARGET_TYPE_QCA8074 20
|
||||
#endif
|
||||
|
||||
struct CE_state;
|
||||
#define CE_COUNT_MAX 12
|
||||
|
@@ -2055,6 +2055,7 @@ QDF_STATUS hif_ce_open(struct hif_softc *hif_sc)
|
||||
{
|
||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
|
||||
|
||||
qdf_spinlock_create(&hif_state->irq_reg_lock);
|
||||
qdf_spinlock_create(&hif_state->keep_awake_lock);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2065,6 +2066,9 @@ QDF_STATUS hif_ce_open(struct hif_softc *hif_sc)
|
||||
*/
|
||||
void hif_ce_close(struct hif_softc *hif_sc)
|
||||
{
|
||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
|
||||
|
||||
qdf_spinlock_destroy(&hif_state->irq_reg_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -122,6 +122,7 @@ struct HIF_CE_state {
|
||||
bool started;
|
||||
struct ce_tasklet_entry tasklets[CE_COUNT_MAX];
|
||||
qdf_spinlock_t keep_awake_lock;
|
||||
qdf_spinlock_t irq_reg_lock;
|
||||
unsigned int keep_awake_count;
|
||||
bool verified_awake;
|
||||
bool fake_sleep;
|
||||
|
@@ -43,5 +43,6 @@ void hif_ahb_device_reset(struct hif_softc *scn);
|
||||
int hif_ahb_enable_radio(struct hif_pci_softc *sc,
|
||||
struct platform_device *pdev,
|
||||
const struct platform_device_id *id);
|
||||
int hif_ahb_configure_irq(struct hif_pci_softc *sc);
|
||||
|
||||
#endif
|
||||
|
@@ -680,6 +680,12 @@ int hif_get_device_type(uint32_t device_id,
|
||||
HIF_INFO(" *********** IPQ4019 *************");
|
||||
break;
|
||||
|
||||
case QCA8074_DEVICE_ID:
|
||||
*hif_type = HIF_TYPE_QCA8074;
|
||||
*target_type = TARGET_TYPE_QCA8074;
|
||||
HIF_INFO(" *********** QCA8074 *************\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
HIF_ERROR("%s: Unsupported device ID!", __func__);
|
||||
ret = -ENODEV;
|
||||
|
@@ -91,6 +91,10 @@
|
||||
#define QCA9984_DEVICE_ID (0x0046)
|
||||
#define QCA9888_DEVICE_ID (0x0056)
|
||||
#define IPQ4019_DEVICE_ID (0x12ef)
|
||||
#define QCA8074_DEVICE_ID (0xffff) /* Todo: replace this with
|
||||
actual number once available.
|
||||
currently defining this to 0xffff for
|
||||
emulation purpose */
|
||||
|
||||
#define HIF_GET_PCI_SOFTC(scn) ((struct hif_pci_softc *)scn)
|
||||
#define HIF_GET_CE_STATE(scn) ((struct HIF_CE_state *)scn)
|
||||
@@ -127,6 +131,7 @@ struct hif_softc {
|
||||
|
||||
bool recovery;
|
||||
bool notice_send;
|
||||
bool per_ce_irq;
|
||||
uint32_t ce_irq_summary;
|
||||
/* No of copy engines supported */
|
||||
unsigned int ce_count;
|
||||
|
@@ -1952,6 +1952,10 @@ int hif_pci_bus_configure(struct hif_softc *hif_sc)
|
||||
}
|
||||
}
|
||||
|
||||
if (hif_sc->target_info.target_type == TARGET_TYPE_QCA8074) {
|
||||
hif_sc->per_ce_irq = true;
|
||||
}
|
||||
|
||||
status = hif_config_ce(hif_sc);
|
||||
if (status)
|
||||
goto disable_wlan;
|
||||
@@ -3319,6 +3323,9 @@ int hif_configure_irq(struct hif_softc *scn)
|
||||
case TARGET_TYPE_IPQ4019:
|
||||
ret = hif_ahb_configure_legacy_irq(sc);
|
||||
break;
|
||||
case TARGET_TYPE_QCA8074:
|
||||
ret = hif_ahb_configure_irq(sc);
|
||||
break;
|
||||
default:
|
||||
ret = hif_pci_configure_legacy_irq(sc);
|
||||
break;
|
||||
|
@@ -103,6 +103,12 @@ void hif_target_register_tbl_attach(struct hif_softc *scn, u32 target_type)
|
||||
scn->target_ce_def = IPQ4019_CE_TARGETdef;
|
||||
break;
|
||||
#endif
|
||||
#if defined(QCA8074_HEADERS_DEF)
|
||||
case TARGET_TYPE_QCA8074:
|
||||
scn->targetdef = QCA8074_TARGETdef;
|
||||
scn->target_ce_def = QCA8074_CE_TARGETdef;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
default:
|
||||
@@ -167,6 +173,11 @@ void hif_register_tbl_attach(struct hif_softc *scn, u32 hif_type)
|
||||
scn->hostdef = IPQ4019_HOSTdef;
|
||||
break;
|
||||
#endif
|
||||
#if defined(QCA8074_HEADERS_DEF)
|
||||
case HIF_TYPE_QCA8074:
|
||||
scn->hostdef = QCA8074_HOSTdef;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@@ -36,6 +36,69 @@
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
|
||||
#define IRQF_DISABLED 0x00000020
|
||||
#endif
|
||||
|
||||
#define HIF_IC_CE0_IRQ_OFFSET 4
|
||||
#define HIF_IC_MAX_IRQ 54
|
||||
|
||||
/* integrated chip irq names */
|
||||
const char *ic_irqname[HIF_IC_MAX_IRQ] = {
|
||||
"misc_pulse1",
|
||||
"misc_latch",
|
||||
"sw_exception",
|
||||
"watchdog",
|
||||
"ce0",
|
||||
"ce1",
|
||||
"ce2",
|
||||
"ce3",
|
||||
"ce4",
|
||||
"ce5",
|
||||
"ce6",
|
||||
"ce7",
|
||||
"ce8",
|
||||
"ce9",
|
||||
"ce10",
|
||||
"ce11",
|
||||
"ce12",
|
||||
"ce13",
|
||||
"host2wbm_desc_feed",
|
||||
"host2reo_re_injection",
|
||||
"host2reo_command",
|
||||
"host2rxdma_monitor_ring3",
|
||||
"host2rxdma_monitor_ring2",
|
||||
"host2rxdma_monitor_ring1",
|
||||
"reo2ost_exception",
|
||||
"wbm2host_rx_release",
|
||||
"reo2host_status",
|
||||
"reo2host_destination_ring4",
|
||||
"reo2host_destination_ring3",
|
||||
"reo2host_destination_ring2",
|
||||
"reo2host_destination_ring1",
|
||||
"rxdma2host_monitor_destination_mac3",
|
||||
"rxdma2host_monitor_destination_mac2",
|
||||
"rxdma2host_monitor_destination_mac1",
|
||||
"ppdu_end_interrupts_mac3",
|
||||
"ppdu_end_interrupts_mac2",
|
||||
"ppdu_end_interrupts_mac1",
|
||||
"rxdma2host_monitor_status_ring_mac3",
|
||||
"rxdma2host_monitor_status_ring_mac2",
|
||||
"rxdma2host_monitor_status_ring_mac1",
|
||||
"host2rxdma_host_buf_ring_mac3",
|
||||
"host2rxdma_host_buf_ring_mac2",
|
||||
"host2rxdma_host_buf_ring_mac1",
|
||||
"rxdma2host_destination_ring_mac3",
|
||||
"rxdma2host_destination_ring_mac2",
|
||||
"rxdma2host_destination_ring_mac1",
|
||||
"host2tcl_input_ring4",
|
||||
"host2tcl_input_ring3",
|
||||
"host2tcl_input_ring2",
|
||||
"host2tcl_input_ring1",
|
||||
"wbm2host_tx_completions_ring3",
|
||||
"wbm2host_tx_completions_ring2",
|
||||
"wbm2host_tx_completions_ring1",
|
||||
"tcl2host_status_ring",
|
||||
};
|
||||
|
||||
irqreturn_t hif_ahb_interrupt_handler(int irq, void *context);
|
||||
/**
|
||||
* hif_disable_isr() - disable isr
|
||||
*
|
||||
@@ -178,6 +241,41 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hif_ahb_configure_irq(struct hif_pci_softc *sc)
|
||||
{
|
||||
int ret = 0;
|
||||
struct hif_softc *scn = HIF_GET_SOFTC(sc);
|
||||
struct platform_device *pdev = (struct platform_device *)sc->pdev;
|
||||
struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn);
|
||||
int irq = 0;
|
||||
int i;
|
||||
|
||||
/* configure per CE interrupts */
|
||||
for (i = 0; i < scn->ce_count; i++) {
|
||||
irq = platform_get_irq_byname(pdev, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i]);
|
||||
ret = request_irq(irq ,
|
||||
hif_ahb_interrupt_handler,
|
||||
IRQF_TRIGGER_RISING, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i],
|
||||
&hif_ce_state->tasklets[i]);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "ath_request_irq failed\n");
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
hif_ahb_irq_enable(scn, i);
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
irqreturn_t hif_ahb_interrupt_handler(int irq, void *context)
|
||||
{
|
||||
struct ce_tasklet_entry *tasklet_entry = context;
|
||||
return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hif_target_sync() : ensure the target is ready
|
||||
* @scn: hif control structure
|
||||
@@ -394,7 +492,33 @@ void hif_ahb_reset_soc(struct hif_softc *hif_ctx)
|
||||
*/
|
||||
void hif_ahb_nointrs(struct hif_softc *scn)
|
||||
{
|
||||
hif_pci_nointrs(scn);
|
||||
int i;
|
||||
int irq;
|
||||
struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
|
||||
struct platform_device *pdev = (struct platform_device *)sc->pdev;
|
||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
|
||||
|
||||
if (scn->request_irq_done == false)
|
||||
return;
|
||||
|
||||
if (sc->num_msi_intrs > 0) {
|
||||
/* MSI interrupt(s) */
|
||||
for (i = 0; i < sc->num_msi_intrs; i++) {
|
||||
free_irq(sc->irq + i, sc);
|
||||
}
|
||||
sc->num_msi_intrs = 0;
|
||||
} else {
|
||||
if (!scn->per_ce_irq) {
|
||||
free_irq(sc->irq, sc);
|
||||
} else {
|
||||
for (i = 0; i < scn->ce_count; i++) {
|
||||
irq = platform_get_irq_byname(pdev, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i]);
|
||||
free_irq(irq, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
ce_unregister_irq(hif_state, CE_ALL_BITMAP);
|
||||
scn->request_irq_done = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,7 +532,31 @@ void hif_ahb_nointrs(struct hif_softc *scn)
|
||||
*/
|
||||
void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t reg_offset = 0;
|
||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
|
||||
struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
|
||||
|
||||
if (scn->per_ce_irq) {
|
||||
if (target_ce_conf->pipedir & PIPEDIR_OUT) {
|
||||
reg_offset = HOST_IE_ADDRESS;
|
||||
qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
|
||||
regval = hif_read32_mb(scn->mem + reg_offset);
|
||||
regval |= (1 << ce_id);
|
||||
hif_write32_mb(scn->mem + reg_offset, regval);
|
||||
qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
|
||||
}
|
||||
if (target_ce_conf->pipedir & PIPEDIR_IN) {
|
||||
reg_offset = HOST_IE_ADDRESS_2;
|
||||
qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
|
||||
regval = hif_read32_mb(scn->mem + reg_offset);
|
||||
regval |= (1 << ce_id);
|
||||
hif_write32_mb(scn->mem + reg_offset, regval);
|
||||
qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
|
||||
}
|
||||
} else {
|
||||
hif_pci_irq_enable(scn, ce_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,5 +568,27 @@ void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
|
||||
*/
|
||||
void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t reg_offset = 0;
|
||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
|
||||
struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
|
||||
|
||||
if (scn->per_ce_irq) {
|
||||
if (target_ce_conf->pipedir & PIPEDIR_OUT) {
|
||||
reg_offset = HOST_IE_ADDRESS;
|
||||
qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
|
||||
regval = hif_read32_mb(scn->mem + reg_offset);
|
||||
regval &= ~(1 << ce_id);
|
||||
hif_write32_mb(scn->mem + reg_offset, regval);
|
||||
qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
|
||||
}
|
||||
if (target_ce_conf->pipedir & PIPEDIR_IN) {
|
||||
reg_offset = HOST_IE_ADDRESS_2;
|
||||
qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
|
||||
regval = hif_read32_mb(scn->mem + reg_offset);
|
||||
regval &= ~(1 << ce_id);
|
||||
hif_write32_mb(scn->mem + reg_offset, regval);
|
||||
qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user