@@ -57,7 +57,7 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
struct platform_device *pdev = to_platform_device(drm->dev);
/*struct resource *res;*/
/*u32 version;*/
- /*int irq_lcd, irq_mipi; */
+ int irq_lcd, irq_mipi;
int ret;
/* TBD - not sure if clock_get needs to be called here */
@@ -108,11 +108,29 @@ static int kmb_load(struct drm_device *drm, unsigned long flags)
dev_p->msscam_mmio = ioremap_cache(MSS_CAM_BASE_ADDR,
MSS_CAM_MMIO_SIZE);
- /*TODO - register irqs here - section 17.3 in databook
- * lists LCD at 79 under MSS CPU - firmware has to redirect it to A53
- * May be 33 for LCD and 34 for MIPI? Will wait till firmware
- * finalizes the IRQ numbers for redirection
+ /* register irqs here - section 17.3 in databook
+ * lists LCD at 79 and 82 for MIPI under MSS CPU -
+ * firmware has to redirect it to A53
*/
+ irq_lcd = platform_get_irq_byname(pdev, "irq_lcd");
+ if (irq_lcd < 0) {
+ DRM_ERROR("irq_lcd not found");
+ return irq_lcd;
+ }
+ pr_info("irq_lcd platform_get_irq = %d\n", irq_lcd);
+ ret = request_irq(irq_lcd, kmb_isr, IRQF_SHARED, "irq_lcd", dev_p);
+ dev_p->irq_lcd = irq_lcd;
+
+ irq_mipi = platform_get_irq_byname(pdev, "irq_mipi");
+ if (irq_mipi < 0) {
+ DRM_ERROR("irq_mipi not found");
+ return irq_mipi;
+ }
+ pr_info("irq_mipi platform_get_irq = %d\n", irq_mipi);
+ ret = request_irq(irq_mipi, kmb_isr, IRQF_SHARED, "irq_mipi", dev_p);
+ dev_p->irq_mipi = irq_mipi;
+
+
/*TBD read and check for correct product version here */
@@ -161,9 +179,9 @@ static void kmb_setup_mode_config(struct drm_device *drm)
drm->mode_config.funcs = &kmb_mode_config_funcs;
}
-static irqreturn_t kmb_isr(int irq, void *arg)
+
+static irqreturn_t handle_lcd_irq(struct drm_device *dev)
{
- struct drm_device *dev = (struct drm_device *)arg;
unsigned long status, val;
status = kmb_read_lcd(dev->dev_private, LCD_INT_STATUS);
@@ -192,10 +210,29 @@ static irqreturn_t kmb_isr(int irq, void *arg)
break;
}
}
+ return IRQ_HANDLED;
+}
+static irqreturn_t handle_mipi_irq(struct drm_device *dev)
+{
+ mipi_tx_handle_irqs(dev->dev_private);
return IRQ_HANDLED;
}
+static irqreturn_t kmb_isr(int irq, void *arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ struct kmb_drm_private *dev_p = dev->dev_private;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (irq == dev_p->irq_lcd)
+ ret = handle_lcd_irq(dev);
+ else if (irq == dev_p->irq_mipi)
+ ret = handle_mipi_irq(dev);
+
+ return ret;
+}
+
static void kmb_irq_reset(struct drm_device *drm)
{
kmb_write_lcd(drm->dev_private, LCD_INT_CLEAR, 0xFFFF);
@@ -43,6 +43,8 @@ struct kmb_drm_private {
struct kmb_plane *plane;
struct drm_atomic_state *state;
spinlock_t irq_lock;
+ int irq_lcd;
+ int irq_mipi;
};
static inline struct kmb_drm_private *to_kmb(const struct drm_device *dev)
@@ -1234,7 +1234,7 @@ static void mipi_tx_init_irqs(struct kmb_drm_private *dev_p,
SET_MIPI_TX_HS_IRQ_CLEAR(dev_p, MIPI_CTRL6, MIPI_TX_HS_IRQ_ALL);
/*global interrupts */
SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_HS_IRQ);
- SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_DHY_ERR_IRQ);
+ SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_DPHY_ERR_IRQ);
SET_MIPI_CTRL_IRQ_CLEAR1(dev_p, MIPI_CTRL6, MIPI_HS_RX_EVENT_IRQ);
/*enable interrupts */
@@ -1250,7 +1250,7 @@ static void mipi_tx_init_irqs(struct kmb_drm_private *dev_p,
/*enable user enabled interrupts */
if (cfg->irq_cfg.dphy_error)
- SET_MIPI_CTRL_IRQ_ENABLE0(dev_p, MIPI_CTRL6, MIPI_DHY_ERR_IRQ);
+ SET_MIPI_CTRL_IRQ_ENABLE0(dev_p, MIPI_CTRL6, MIPI_DPHY_ERR_IRQ);
if (cfg->irq_cfg.line_compare)
SET_HS_IRQ_ENABLE(dev_p, MIPI_CTRL6,
MIPI_TX_HS_IRQ_LINE_COMPARE);
@@ -1260,6 +1260,39 @@ static void mipi_tx_init_irqs(struct kmb_drm_private *dev_p,
spin_unlock_irqrestore(&dev_p->irq_lock, irqflags);
}
+
+void mipi_tx_handle_irqs(struct kmb_drm_private *dev_p)
+{
+ uint32_t irq_ctrl_stat_0, hs_stat, hs_enable;
+ uint32_t irq_ctrl_enabled_0;
+
+ irq_ctrl_stat_0 = MIPI_GET_IRQ_STAT0(dev_p);
+ irq_ctrl_enabled_0 = MIPI_GET_IRQ_ENABLED0(dev_p);
+ /*only service enabled interrupts */
+ irq_ctrl_stat_0 &= irq_ctrl_enabled_0;
+
+ if (irq_ctrl_stat_0 & MIPI_DPHY_ERR_MASK) {
+ if (irq_ctrl_stat_0 & ((1 << (MIPI_DPHY6 + 1))))
+ SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6,
+ MIPI_DPHY_ERR_IRQ);
+ } else if (irq_ctrl_stat_0 & MIPI_HS_IRQ_MASK) {
+ hs_stat = GET_MIPI_TX_HS_IRQ_STATUS(dev_p, MIPI_CTRL6);
+ hs_enable = GET_HS_IRQ_ENABLE(dev_p, MIPI_CTRL6);
+ hs_stat &= hs_enable;
+ /*look for errors */
+ if (hs_stat & MIPI_TX_HS_IRQ_ERROR) {
+ CLR_HS_IRQ_ENABLE(dev_p, MIPI_CTRL6,
+ (hs_stat & MIPI_TX_HS_IRQ_ERROR) |
+ MIPI_TX_HS_IRQ_DMA_DONE |
+ MIPI_TX_HS_IRQ_DMA_IDLE);
+ }
+ /* clear local, then global */
+ SET_MIPI_TX_HS_IRQ_CLEAR(dev_p, MIPI_CTRL6, hs_stat);
+ SET_MIPI_CTRL_IRQ_CLEAR0(dev_p, MIPI_CTRL6, MIPI_HS_IRQ);
+ }
+
+}
+
void kmb_dsi_init(struct drm_device *dev)
{
struct kmb_dsi *kmb_dsi;
@@ -330,6 +330,7 @@ union mipi_irq_cfg {
void kmb_dsi_init(struct drm_device *dev);
void kmb_plane_destroy(struct drm_plane *plane);
+void mipi_tx_handle_irqs(struct kmb_drm_private *dev_p);
#define to_kmb_connector(x) container_of(x, struct kmb_connector, base)
#define to_kmb_host(x) container_of(x, struct kmb_dsi_host, base)
@@ -527,15 +527,25 @@
/* MIPI IRQ */
#define MIPI_CTRL_IRQ_STATUS0 (0x00)
-#define MIPI_DHY_ERR_IRQ 1
+#define MIPI_DPHY_ERR_IRQ 1
+#define MIPI_DPHY_ERR_MASK 0x7FE /*bits 1-10 */
#define MIPI_HS_IRQ 13
+#define MIPI_HS_IRQ_MASK 0x7FE000 /*bits 13-22 */
#define MIPI_LP_EVENT_IRQ 25
+#define MIPI_GET_IRQ_STAT0(dev) kmb_read_mipi(dev, \
+ MIPI_CTRL_IRQ_STATUS0)
#define MIPI_CTRL_IRQ_STATUS1 (0x04)
#define MIPI_HS_RX_EVENT_IRQ 0
+#define MIPI_GET_IRQ_STAT1(dev) kmb_read_mipi(dev, \
+ MIPI_CTRL_IRQ_STATUS1)
#define MIPI_CTRL_IRQ_ENABLE0 (0x08)
-#define SET_MIPI_CTRL_IRQ_ENABLE0(dev, M, N) \
- kmb_set_bit_mipi(dev, MIPI_CTRL_IRQ_ENABLE0, M+N)
+#define SET_MIPI_CTRL_IRQ_ENABLE0(dev, M, N) kmb_set_bit_mipi(dev, \
+ MIPI_CTRL_IRQ_ENABLE0, M+N)
+#define MIPI_GET_IRQ_ENABLED0(dev) kmb_read_mipi(dev, \
+ MIPI_CTRL_IRQ_ENABLE0)
#define MIPI_CTRL_IRQ_ENABLE1 (0x0c)
+#define MIPI_GET_IRQ_ENABLED1(dev) kmb_read_mipi(dev, \
+ MIPI_CTRL_IRQ_ENABLE1)
#define MIPI_CTRL_IRQ_CLEAR0 (0x010)
#define SET_MIPI_CTRL_IRQ_CLEAR0(dev, M, N) \
kmb_set_bit_mipi(dev, MIPI_CTRL_IRQ_CLEAR0, M+N)
@@ -543,8 +553,10 @@
#define SET_MIPI_CTRL_IRQ_CLEAR1(dev, M, N) \
kmb_set_bit_mipi(dev, MIPI_CTRL_IRQ_CLEAR1, M+N)
#define MIPI_TX_HS_IRQ_STATUS (0x01c)
-#define MIPI_TX_HS_IRQ_STATUSm(M) \
- (MIPI_TX_HS_IRQ_STATUS + HS_OFFSET(M))
+#define MIPI_TX_HS_IRQ_STATUSm(M) (MIPI_TX_HS_IRQ_STATUS + \
+ HS_OFFSET(M))
+#define GET_MIPI_TX_HS_IRQ_STATUS(dev, M) kmb_read_mipi(dev, \
+ MIPI_TX_HS_IRQ_STATUSm(M))
#define MIPI_TX_HS_IRQ_LINE_COMPARE (1<<1)
#define MIPI_TX_HS_IRQ_FRAME_DONE_0 (1<<2)
#define MIPI_TX_HS_IRQ_FRAME_DONE_1 (1<<3)
@@ -598,10 +610,15 @@
MIPI_TX_HS_IRQ_ERROR)
#define MIPI_TX_HS_IRQ_ENABLE (0x020)
-#define SET_HS_IRQ_ENABLE(dev, M, val) \
- kmb_set_bitmask_mipi(dev, \
- MIPI_TX_HS_IRQ_ENABLE \
- + HS_OFFSET(M), val)
+#define SET_HS_IRQ_ENABLE(dev, M, val) kmb_set_bitmask_mipi(dev, \
+ MIPI_TX_HS_IRQ_ENABLE \
+ + HS_OFFSET(M), val)
+#define CLR_HS_IRQ_ENABLE(dev, M, val) kmb_clr_bitmask_mipi(dev, \
+ MIPI_TX_HS_IRQ_ENABLE \
+ + HS_OFFSET(M), val)
+#define GET_HS_IRQ_ENABLE(dev, M) kmb_read_mipi(dev, \
+ MIPI_TX_HS_IRQ_ENABLE \
+ + HS_OFFSET(M))
#define MIPI_TX_HS_IRQ_CLEAR (0x024)
#define SET_MIPI_TX_HS_IRQ_CLEAR(dev, M, val) \
kmb_set_bitmask_mipi(dev, \