mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	mailbox: imx: support RST channel
i.MX generic MU supports MU-A/B reset feature. When stop/start remotecore, MU is not reset. So when Linux stop remotecore, the MU-B side BCR may contain valid configuration, because MU-B is not reset. So when linux start Mcore again and notify Mcore, Mcore is not ready to handle MU interrupt and cause issues. So need reset MU when stop Mcore. Signed-off-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
This commit is contained in:
		
							parent
							
								
									095730dd4c
								
							
						
					
					
						commit
						82ab513bae
					
				
					 1 changed files with 23 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#include <linux/suspend.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
#define IMX_MU_CHANS		16
 | 
			
		||||
#define IMX_MU_CHANS		17
 | 
			
		||||
/* TX0/RX0/RXDB[0-3] */
 | 
			
		||||
#define IMX_MU_SCU_CHANS	6
 | 
			
		||||
/* TX0/RX0 */
 | 
			
		||||
| 
						 | 
				
			
			@ -35,9 +35,11 @@ enum imx_mu_chan_type {
 | 
			
		|||
	IMX_MU_TYPE_RX		= 1, /* Rx */
 | 
			
		||||
	IMX_MU_TYPE_TXDB	= 2, /* Tx doorbell */
 | 
			
		||||
	IMX_MU_TYPE_RXDB	= 3, /* Rx doorbell */
 | 
			
		||||
	IMX_MU_TYPE_RST		= 4, /* Reset */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum imx_mu_xcr {
 | 
			
		||||
	IMX_MU_CR,
 | 
			
		||||
	IMX_MU_GIER,
 | 
			
		||||
	IMX_MU_GCR,
 | 
			
		||||
	IMX_MU_TCR,
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +52,7 @@ enum imx_mu_xsr {
 | 
			
		|||
	IMX_MU_GSR,
 | 
			
		||||
	IMX_MU_TSR,
 | 
			
		||||
	IMX_MU_RSR,
 | 
			
		||||
	IMX_MU_xSR_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct imx_sc_rpc_msg_max {
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +88,7 @@ struct imx_mu_priv {
 | 
			
		|||
	int			irq[IMX_MU_CHANS];
 | 
			
		||||
	bool			suspend;
 | 
			
		||||
 | 
			
		||||
	u32 xcr[4];
 | 
			
		||||
	u32 xcr[IMX_MU_xCR_MAX];
 | 
			
		||||
 | 
			
		||||
	bool			side_b;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -105,8 +108,8 @@ struct imx_mu_dcfg {
 | 
			
		|||
	enum imx_mu_type type;
 | 
			
		||||
	u32	xTR;		/* Transmit Register0 */
 | 
			
		||||
	u32	xRR;		/* Receive Register0 */
 | 
			
		||||
	u32	xSR[4];		/* Status Registers */
 | 
			
		||||
	u32	xCR[4];		/* Control Registers */
 | 
			
		||||
	u32	xSR[IMX_MU_xSR_MAX];	/* Status Registers */
 | 
			
		||||
	u32	xCR[IMX_MU_xCR_MAX];	/* Control Registers */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +124,9 @@ struct imx_mu_dcfg {
 | 
			
		|||
#define IMX_MU_xCR_TIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))
 | 
			
		||||
/* General Purpose Interrupt Request */
 | 
			
		||||
#define IMX_MU_xCR_GIRn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x))))
 | 
			
		||||
/* MU reset */
 | 
			
		||||
#define IMX_MU_xCR_RST(type)	(type & IMX_MU_V2 ? BIT(0) : BIT(5))
 | 
			
		||||
#define IMX_MU_xSR_RST(type)	(type & IMX_MU_V2 ? BIT(0) : BIT(7))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
 | 
			
		||||
| 
						 | 
				
			
			@ -497,6 +503,8 @@ static irqreturn_t imx_mu_isr(int irq, void *p)
 | 
			
		|||
		val &= IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx) &
 | 
			
		||||
			(ctrl & IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));
 | 
			
		||||
		break;
 | 
			
		||||
	case IMX_MU_TYPE_RST:
 | 
			
		||||
		return IRQ_NONE;
 | 
			
		||||
	default:
 | 
			
		||||
		dev_warn_ratelimited(priv->dev, "Unhandled channel type %d\n",
 | 
			
		||||
				     cp->type);
 | 
			
		||||
| 
						 | 
				
			
			@ -581,6 +589,8 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
 | 
			
		|||
{
 | 
			
		||||
	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
 | 
			
		||||
	struct imx_mu_con_priv *cp = chan->con_priv;
 | 
			
		||||
	int ret;
 | 
			
		||||
	u32 sr;
 | 
			
		||||
 | 
			
		||||
	if (cp->type == IMX_MU_TYPE_TXDB) {
 | 
			
		||||
		tasklet_kill(&cp->txdb_tasklet);
 | 
			
		||||
| 
						 | 
				
			
			@ -598,6 +608,13 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
 | 
			
		|||
	case IMX_MU_TYPE_RXDB:
 | 
			
		||||
		imx_mu_xcr_rmw(priv, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));
 | 
			
		||||
		break;
 | 
			
		||||
	case IMX_MU_TYPE_RST:
 | 
			
		||||
		imx_mu_xcr_rmw(priv, IMX_MU_CR, IMX_MU_xCR_RST(priv->dcfg->type), 0);
 | 
			
		||||
		ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_SR], sr,
 | 
			
		||||
					 !(sr & IMX_MU_xSR_RST(priv->dcfg->type)), 1, 5);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			dev_warn(priv->dev, "RST channel timeout\n");
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -865,7 +882,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = {
 | 
			
		|||
	.xTR	= 0x0,
 | 
			
		||||
	.xRR	= 0x10,
 | 
			
		||||
	.xSR	= {0x20, 0x20, 0x20, 0x20},
 | 
			
		||||
	.xCR	= {0x24, 0x24, 0x24, 0x24},
 | 
			
		||||
	.xCR	= {0x24, 0x24, 0x24, 0x24, 0x24},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {
 | 
			
		||||
| 
						 | 
				
			
			@ -888,7 +905,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
 | 
			
		|||
	.xTR	= 0x200,
 | 
			
		||||
	.xRR	= 0x280,
 | 
			
		||||
	.xSR	= {0xC, 0x118, 0x124, 0x12C},
 | 
			
		||||
	.xCR	= {0x110, 0x114, 0x120, 0x128},
 | 
			
		||||
	.xCR	= {0x8, 0x110, 0x114, 0x120, 0x128},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp_s4 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue