Skip to content

Commit c6ff944

Browse files
affenull2345Jassi Brar
authored andcommitted
mailbox: sprd: add support for mailbox revision 2
Newer Unisoc SoCs such as UMS9230 include a new revision of the mailbox IP with support for up to 16 channels. Since the new revision has a similar register layout and many parts have remained unchanged, make the driver support both revisions. Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
1 parent c77661d commit c6ff944

1 file changed

Lines changed: 82 additions & 21 deletions

File tree

drivers/mailbox/sprd-mailbox.c

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,27 @@
2424
#define SPRD_MBOX_IRQ_STS 0x18
2525
#define SPRD_MBOX_IRQ_MSK 0x1c
2626
#define SPRD_MBOX_LOCK 0x20
27-
#define SPRD_MBOX_FIFO_DEPTH 0x24
27+
#define SPRD_MBOX_FIFO_DEPTH 0x24 /* outbox only */
28+
#define SPRD_MBOX_IN_FIFO_STS2 0x24 /* inbox only, revision 2 */
2829

2930
/* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */
3031
#define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16)
3132
#define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8)
3233
#define SPRD_INBOX_FIFO_DELIVER_SHIFT 16
3334
#define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0)
3435

36+
/* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_RST register */
37+
#define SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST GENMASK(31, 0)
38+
39+
/* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_STS register */
40+
#define SPRD_INBOX_R2_FIFO_DELIVER_MASK GENMASK(15, 0)
41+
42+
/* Bit and mask definition for SPRD_MBOX_IN_FIFO_STS2 register */
43+
#define SPRD_INBOX_R2_FIFO_OVERFLOW_MASK GENMASK(31, 16)
44+
#define SPRD_INBOX_R2_FIFO_BUSY_MASK GENMASK(15, 0)
45+
3546
/* Bit and mask definition for SPRD_MBOX_IRQ_STS register */
36-
#define SPRD_MBOX_IRQ_CLR BIT(0)
47+
#define SPRD_MBOX_IRQ_CLR GENMASK(31, 0)
3748

3849
/* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */
3950
#define SPRD_OUTBOX_FIFO_FULL BIT(2)
@@ -52,8 +63,18 @@
5263
#define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0)
5364

5465
#define SPRD_OUTBOX_BASE_SPAN 0x1000
55-
#define SPRD_MBOX_CHAN_MAX 8
56-
#define SPRD_SUPP_INBOX_ID_SC9863A 7
66+
#define SPRD_MBOX_R1_CHAN_MAX 8
67+
#define SPRD_MBOX_R2_CHAN_MAX 16
68+
69+
enum sprd_mbox_version {
70+
SPRD_MBOX_R1,
71+
SPRD_MBOX_R2,
72+
};
73+
74+
struct sprd_mbox_info {
75+
enum sprd_mbox_version version;
76+
unsigned long supp_id;
77+
};
5778

5879
struct sprd_mbox_priv {
5980
struct mbox_controller mbox;
@@ -64,9 +85,11 @@ struct sprd_mbox_priv {
6485
void __iomem *supp_base;
6586
u32 outbox_fifo_depth;
6687

88+
const struct sprd_mbox_info *info;
89+
6790
struct mutex lock;
6891
u32 refcnt;
69-
struct mbox_chan chan[SPRD_MBOX_CHAN_MAX];
92+
struct mbox_chan chan[SPRD_MBOX_R2_CHAN_MAX];
7093
};
7194

7295
static struct sprd_mbox_priv *to_sprd_mbox_priv(struct mbox_controller *mbox)
@@ -154,22 +177,34 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
154177
{
155178
struct sprd_mbox_priv *priv = data;
156179
struct mbox_chan *chan;
157-
u32 fifo_sts, send_sts, busy, id;
180+
u32 fifo_sts, fifo_sts2, send_sts, busy, id;
158181

159182
fifo_sts = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS);
160183

184+
if (priv->info->version == SPRD_MBOX_R2)
185+
fifo_sts2 = readl(priv->inbox_base + SPRD_MBOX_IN_FIFO_STS2);
186+
161187
/* Get the inbox data delivery status */
162-
send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
163-
SPRD_INBOX_FIFO_DELIVER_SHIFT;
188+
if (priv->info->version == SPRD_MBOX_R2) {
189+
send_sts = fifo_sts & SPRD_INBOX_R2_FIFO_DELIVER_MASK;
190+
} else {
191+
send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
192+
SPRD_INBOX_FIFO_DELIVER_SHIFT;
193+
}
194+
164195
if (!send_sts) {
165196
dev_warn_ratelimited(priv->dev, "spurious inbox interrupt\n");
166197
return IRQ_NONE;
167198
}
168199

169200
/* Clear FIFO delivery and overflow status first */
170-
writel(fifo_sts &
171-
(SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
172-
priv->inbox_base + SPRD_MBOX_FIFO_RST);
201+
if (priv->info->version == SPRD_MBOX_R2) {
202+
writel(SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST,
203+
priv->inbox_base + SPRD_MBOX_FIFO_RST);
204+
} else {
205+
writel(fifo_sts & (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
206+
priv->inbox_base + SPRD_MBOX_FIFO_RST);
207+
}
173208

174209
while (send_sts) {
175210
id = __ffs(send_sts);
@@ -181,7 +216,11 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
181216
* Check if the message was fetched by remote target, if yes,
182217
* that means the transmission has been completed.
183218
*/
184-
busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
219+
if (priv->info->version == SPRD_MBOX_R2)
220+
busy = fifo_sts2 & SPRD_INBOX_R2_FIFO_BUSY_MASK;
221+
else
222+
busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
223+
185224
if (!(busy & BIT(id)))
186225
mbox_chan_txdone(chan, 0);
187226
}
@@ -295,7 +334,7 @@ static int sprd_mbox_probe(struct platform_device *pdev)
295334
struct device *dev = &pdev->dev;
296335
struct sprd_mbox_priv *priv;
297336
int ret, inbox_irq, outbox_irq, supp_irq;
298-
unsigned long id, supp;
337+
unsigned long id;
299338
struct clk *clk;
300339

301340
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -305,6 +344,10 @@ static int sprd_mbox_probe(struct platform_device *pdev)
305344
priv->dev = dev;
306345
mutex_init(&priv->lock);
307346

347+
priv->info = of_device_get_match_data(dev);
348+
if (!priv->info)
349+
return -EINVAL;
350+
308351
/*
309352
* Unisoc mailbox uses an inbox to send messages to the target
310353
* core, and uses (an) outbox(es) to receive messages from other
@@ -362,24 +405,28 @@ static int sprd_mbox_probe(struct platform_device *pdev)
362405
return ret;
363406
}
364407

365-
supp = (unsigned long) of_device_get_match_data(dev);
366-
if (!supp) {
408+
if (!priv->info->supp_id) {
367409
dev_err(dev, "no supplementary outbox specified\n");
368410
return -ENODEV;
369411
}
370-
priv->supp_base = priv->outbox_base + (SPRD_OUTBOX_BASE_SPAN * supp);
412+
priv->supp_base = priv->outbox_base +
413+
(SPRD_OUTBOX_BASE_SPAN * priv->info->supp_id);
371414
}
372415

373416
/* Get the default outbox FIFO depth */
374417
priv->outbox_fifo_depth =
375418
readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
376419
priv->mbox.dev = dev;
377420
priv->mbox.chans = &priv->chan[0];
378-
priv->mbox.num_chans = SPRD_MBOX_CHAN_MAX;
379421
priv->mbox.ops = &sprd_mbox_ops;
380422
priv->mbox.txdone_irq = true;
381423

382-
for (id = 0; id < SPRD_MBOX_CHAN_MAX; id++)
424+
if (priv->info->version == SPRD_MBOX_R2)
425+
priv->mbox.num_chans = SPRD_MBOX_R2_CHAN_MAX;
426+
else
427+
priv->mbox.num_chans = SPRD_MBOX_R1_CHAN_MAX;
428+
429+
for (id = 0; id < priv->mbox.num_chans; id++)
383430
priv->chan[id].con_priv = (void *)id;
384431

385432
ret = devm_mbox_controller_register(dev, &priv->mbox);
@@ -391,10 +438,24 @@ static int sprd_mbox_probe(struct platform_device *pdev)
391438
return 0;
392439
}
393440

441+
static const struct sprd_mbox_info sc9860_mbox_info = {
442+
.version = SPRD_MBOX_R1,
443+
};
444+
445+
static const struct sprd_mbox_info sc9863a_mbox_info = {
446+
.version = SPRD_MBOX_R1,
447+
.supp_id = 7,
448+
};
449+
450+
static const struct sprd_mbox_info ums9230_mbox_info = {
451+
.version = SPRD_MBOX_R2,
452+
.supp_id = 6,
453+
};
454+
394455
static const struct of_device_id sprd_mbox_of_match[] = {
395-
{ .compatible = "sprd,sc9860-mailbox" },
396-
{ .compatible = "sprd,sc9863a-mailbox",
397-
.data = (void *)SPRD_SUPP_INBOX_ID_SC9863A },
456+
{ .compatible = "sprd,sc9860-mailbox", .data = &sc9860_mbox_info },
457+
{ .compatible = "sprd,sc9863a-mailbox", .data = &sc9863a_mbox_info },
458+
{ .compatible = "sprd,ums9230-mailbox", .data = &ums9230_mbox_info },
398459
{ },
399460
};
400461
MODULE_DEVICE_TABLE(of, sprd_mbox_of_match);

0 commit comments

Comments
 (0)