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_QCA9984 12
|
||||||
#define HIF_TYPE_IPQ4019 13
|
#define HIF_TYPE_IPQ4019 13
|
||||||
#define HIF_TYPE_QCA9888 14
|
#define HIF_TYPE_QCA9888 14
|
||||||
|
#define HIF_TYPE_QCA8074 15
|
||||||
|
|
||||||
/* TARGET definition needs to be abstracted in fw common
|
/* TARGET definition needs to be abstracted in fw common
|
||||||
* header files, below is the placeholder till WIN codebase
|
* header files, below is the placeholder till WIN codebase
|
||||||
@@ -95,6 +96,9 @@ typedef void *hif_handle_t;
|
|||||||
/* For Adrastea target */
|
/* For Adrastea target */
|
||||||
#define TARGET_TYPE_ADRASTEA 19
|
#define TARGET_TYPE_ADRASTEA 19
|
||||||
#endif /* CONFIG_WIN */
|
#endif /* CONFIG_WIN */
|
||||||
|
#ifndef TARGET_TYPE_QCA8074
|
||||||
|
#define TARGET_TYPE_QCA8074 20
|
||||||
|
#endif
|
||||||
|
|
||||||
struct CE_state;
|
struct CE_state;
|
||||||
#define CE_COUNT_MAX 12
|
#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);
|
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);
|
qdf_spinlock_create(&hif_state->keep_awake_lock);
|
||||||
return QDF_STATUS_SUCCESS;
|
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)
|
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;
|
bool started;
|
||||||
struct ce_tasklet_entry tasklets[CE_COUNT_MAX];
|
struct ce_tasklet_entry tasklets[CE_COUNT_MAX];
|
||||||
qdf_spinlock_t keep_awake_lock;
|
qdf_spinlock_t keep_awake_lock;
|
||||||
|
qdf_spinlock_t irq_reg_lock;
|
||||||
unsigned int keep_awake_count;
|
unsigned int keep_awake_count;
|
||||||
bool verified_awake;
|
bool verified_awake;
|
||||||
bool fake_sleep;
|
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,
|
int hif_ahb_enable_radio(struct hif_pci_softc *sc,
|
||||||
struct platform_device *pdev,
|
struct platform_device *pdev,
|
||||||
const struct platform_device_id *id);
|
const struct platform_device_id *id);
|
||||||
|
int hif_ahb_configure_irq(struct hif_pci_softc *sc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -680,6 +680,12 @@ int hif_get_device_type(uint32_t device_id,
|
|||||||
HIF_INFO(" *********** IPQ4019 *************");
|
HIF_INFO(" *********** IPQ4019 *************");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QCA8074_DEVICE_ID:
|
||||||
|
*hif_type = HIF_TYPE_QCA8074;
|
||||||
|
*target_type = TARGET_TYPE_QCA8074;
|
||||||
|
HIF_INFO(" *********** QCA8074 *************\n");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
HIF_ERROR("%s: Unsupported device ID!", __func__);
|
HIF_ERROR("%s: Unsupported device ID!", __func__);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
|
@@ -91,6 +91,10 @@
|
|||||||
#define QCA9984_DEVICE_ID (0x0046)
|
#define QCA9984_DEVICE_ID (0x0046)
|
||||||
#define QCA9888_DEVICE_ID (0x0056)
|
#define QCA9888_DEVICE_ID (0x0056)
|
||||||
#define IPQ4019_DEVICE_ID (0x12ef)
|
#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_PCI_SOFTC(scn) ((struct hif_pci_softc *)scn)
|
||||||
#define HIF_GET_CE_STATE(scn) ((struct HIF_CE_state *)scn)
|
#define HIF_GET_CE_STATE(scn) ((struct HIF_CE_state *)scn)
|
||||||
@@ -127,6 +131,7 @@ struct hif_softc {
|
|||||||
|
|
||||||
bool recovery;
|
bool recovery;
|
||||||
bool notice_send;
|
bool notice_send;
|
||||||
|
bool per_ce_irq;
|
||||||
uint32_t ce_irq_summary;
|
uint32_t ce_irq_summary;
|
||||||
/* No of copy engines supported */
|
/* No of copy engines supported */
|
||||||
unsigned int ce_count;
|
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);
|
status = hif_config_ce(hif_sc);
|
||||||
if (status)
|
if (status)
|
||||||
goto disable_wlan;
|
goto disable_wlan;
|
||||||
@@ -3319,6 +3323,9 @@ int hif_configure_irq(struct hif_softc *scn)
|
|||||||
case TARGET_TYPE_IPQ4019:
|
case TARGET_TYPE_IPQ4019:
|
||||||
ret = hif_ahb_configure_legacy_irq(sc);
|
ret = hif_ahb_configure_legacy_irq(sc);
|
||||||
break;
|
break;
|
||||||
|
case TARGET_TYPE_QCA8074:
|
||||||
|
ret = hif_ahb_configure_irq(sc);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = hif_pci_configure_legacy_irq(sc);
|
ret = hif_pci_configure_legacy_irq(sc);
|
||||||
break;
|
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;
|
scn->target_ce_def = IPQ4019_CE_TARGETdef;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(QCA8074_HEADERS_DEF)
|
||||||
|
case TARGET_TYPE_QCA8074:
|
||||||
|
scn->targetdef = QCA8074_TARGETdef;
|
||||||
|
scn->target_ce_def = QCA8074_CE_TARGETdef;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -167,6 +173,11 @@ void hif_register_tbl_attach(struct hif_softc *scn, u32 hif_type)
|
|||||||
scn->hostdef = IPQ4019_HOSTdef;
|
scn->hostdef = IPQ4019_HOSTdef;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(QCA8074_HEADERS_DEF)
|
||||||
|
case HIF_TYPE_QCA8074:
|
||||||
|
scn->hostdef = QCA8074_HOSTdef;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@@ -36,6 +36,69 @@
|
|||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
|
||||||
#define IRQF_DISABLED 0x00000020
|
#define IRQF_DISABLED 0x00000020
|
||||||
#endif
|
#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
|
* hif_disable_isr() - disable isr
|
||||||
*
|
*
|
||||||
@@ -178,6 +241,41 @@ end:
|
|||||||
return ret;
|
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
|
* hif_target_sync() : ensure the target is ready
|
||||||
* @scn: hif control structure
|
* @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)
|
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)
|
void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
|
||||||
{
|
{
|
||||||
hif_pci_irq_enable(scn, 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)
|
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