drivers: pcie: ep: iproc: Add reset callback support

Add support to register callback function for each PCIe reset.
These callback functions are executed from corresponding
PCIe reset interrupt handler if registered.

Signed-off-by: Shivaraj Shetty <shivaraj.shetty@broadcom.com>
Signed-off-by: Abhishek Shah <abhishek.shah@broadcom.com>
This commit is contained in:
Abhishek Shah 2020-05-23 04:18:23 +05:30 committed by Carles Cufí
commit 11972a48c2
2 changed files with 42 additions and 0 deletions

View file

@ -240,10 +240,28 @@ static int iproc_pcie_raise_irq(struct device *dev,
return ret; return ret;
} }
static int iproc_pcie_register_reset_cb(struct device *dev,
enum pcie_reset reset,
pcie_ep_reset_callback_t cb, void *arg)
{
struct iproc_pcie_ep_ctx *ctx = dev->driver_data;
if (reset < PCIE_PERST || reset >= PCIE_RESET_MAX)
return -EINVAL;
LOG_DBG("Registering the callback for reset %d", reset);
ctx->reset_cb[reset] = cb;
ctx->reset_data[reset] = arg;
return 0;
}
#if DT_INST_IRQ_HAS_NAME(0, perst) #if DT_INST_IRQ_HAS_NAME(0, perst)
static void iproc_pcie_perst(void *arg) static void iproc_pcie_perst(void *arg)
{ {
struct device *dev = arg; struct device *dev = arg;
struct iproc_pcie_ep_ctx *ctx = dev->driver_data;
void *reset_data;
uint32_t data; uint32_t data;
data = sys_read32(CRMU_MCU_EXTRA_EVENT_STATUS); data = sys_read32(CRMU_MCU_EXTRA_EVENT_STATUS);
@ -251,6 +269,11 @@ static void iproc_pcie_perst(void *arg)
if (data & PCIE0_PERST_INTR) { if (data & PCIE0_PERST_INTR) {
LOG_DBG("PERST interrupt [0x%x]", data); LOG_DBG("PERST interrupt [0x%x]", data);
sys_write32(PCIE0_PERST_INTR, CRMU_MCU_EXTRA_EVENT_CLEAR); sys_write32(PCIE0_PERST_INTR, CRMU_MCU_EXTRA_EVENT_CLEAR);
if (ctx->reset_cb[PCIE_PERST] != NULL) {
reset_data = ctx->reset_data[PCIE_PERST];
ctx->reset_cb[PCIE_PERST](reset_data);
}
} }
} }
#endif #endif
@ -259,6 +282,8 @@ static void iproc_pcie_perst(void *arg)
static void iproc_pcie_hot_reset(void *arg) static void iproc_pcie_hot_reset(void *arg)
{ {
struct device *dev = arg; struct device *dev = arg;
struct iproc_pcie_ep_ctx *ctx = dev->driver_data;
void *reset_data;
uint32_t data; uint32_t data;
data = sys_read32(CRMU_MCU_EXTRA_EVENT_STATUS); data = sys_read32(CRMU_MCU_EXTRA_EVENT_STATUS);
@ -266,6 +291,11 @@ static void iproc_pcie_hot_reset(void *arg)
if (data & PCIE0_PERST_INB_INTR) { if (data & PCIE0_PERST_INB_INTR) {
LOG_DBG("INBAND PERST interrupt [0x%x]", data); LOG_DBG("INBAND PERST interrupt [0x%x]", data);
sys_write32(PCIE0_PERST_INB_INTR, CRMU_MCU_EXTRA_EVENT_CLEAR); sys_write32(PCIE0_PERST_INB_INTR, CRMU_MCU_EXTRA_EVENT_CLEAR);
if (ctx->reset_cb[PCIE_PERST_INB] != NULL) {
reset_data = ctx->reset_data[PCIE_PERST_INB];
ctx->reset_cb[PCIE_PERST_INB](reset_data);
}
} }
} }
#endif #endif
@ -275,6 +305,8 @@ static void iproc_pcie_flr(void *arg)
{ {
struct device *dev = arg; struct device *dev = arg;
const struct iproc_pcie_ep_config *cfg = dev->config_info; const struct iproc_pcie_ep_config *cfg = dev->config_info;
struct iproc_pcie_ep_ctx *ctx = dev->driver_data;
void *reset_data;
uint32_t data; uint32_t data;
data = pcie_read32(&cfg->base->paxb_paxb_intr_status); data = pcie_read32(&cfg->base->paxb_paxb_intr_status);
@ -282,6 +314,11 @@ static void iproc_pcie_flr(void *arg)
if (data & PCIE0_FLR_INTR) { if (data & PCIE0_FLR_INTR) {
LOG_DBG("FLR interrupt[0x%x]", data); LOG_DBG("FLR interrupt[0x%x]", data);
pcie_write32(PCIE0_FLR_INTR, &cfg->base->paxb_paxb_intr_clear); pcie_write32(PCIE0_FLR_INTR, &cfg->base->paxb_paxb_intr_clear);
if (ctx->reset_cb[PCIE_FLR] != NULL) {
reset_data = ctx->reset_data[PCIE_FLR];
ctx->reset_cb[PCIE_FLR](reset_data);
}
} else { } else {
/* /*
* Other interrupts like PAXB ECC Error interrupt * Other interrupts like PAXB ECC Error interrupt
@ -442,6 +479,7 @@ static struct pcie_ep_driver_api iproc_pcie_ep_api = {
.map_addr = iproc_pcie_map_addr, .map_addr = iproc_pcie_map_addr,
.unmap_addr = iproc_pcie_unmap_addr, .unmap_addr = iproc_pcie_unmap_addr,
.raise_irq = iproc_pcie_raise_irq, .raise_irq = iproc_pcie_raise_irq,
.register_reset_cb = iproc_pcie_register_reset_cb,
}; };
DEVICE_AND_API_INIT(iproc_pcie_ep_0, DT_INST_LABEL(0), DEVICE_AND_API_INIT(iproc_pcie_ep_0, DT_INST_LABEL(0),

View file

@ -72,6 +72,10 @@ struct iproc_pcie_ep_ctx {
struct k_spinlock raise_irq_lock; struct k_spinlock raise_irq_lock;
bool highmem_in_use; bool highmem_in_use;
bool lowmem_in_use; bool lowmem_in_use;
/* Callback function for reset interrupt */
pcie_ep_reset_callback_t reset_cb[PCIE_RESET_MAX];
/* Callback data for reset interrupt */
void *reset_data[PCIE_RESET_MAX];
}; };
#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_BCM_IPROC_H_ */ #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_BCM_IPROC_H_ */