1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-09-26 19:04:54 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

100 lines
2.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
*/
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include "apu.h"
#include "apu_mbox.h"
#define _INBOX(_m) (_m->apu_mbox + 0x0)
#define _OUTBOX(_m) (_m->apu_mbox + 0x20)
#define _DUMMY(_m) (_m->apu_mbox + 0x40)
#define _INBOX_IRQ(_m) (_m->apu_mbox + 0xc0)
#define _OUTBOX_IRQ(_m) (_m->apu_mbox + 0xc4)
#define _INBOX_IRQ_MASK(_m) (_m->apu_mbox + 0xd0)
#define _OUTBOX_IRQ_MASK(_m) (_m->apu_mbox + 0xd8)
#define WAIT_INBOX_TMO_MS 1000
void apu_mbox_ack_outbox(struct mtk_apu *apu)
{
iowrite32(ioread32(_OUTBOX_IRQ(apu)),
_OUTBOX_IRQ(apu));
}
void apu_mbox_read_outbox(struct mtk_apu *apu, struct apu_mbox_hdr *hdr)
{
unsigned int i, val;
for (i = 0; i < APU_MBOX_HDR_SLOTS; i++) {
val = ioread32(_OUTBOX(apu) + i * APU_MBOX_SLOT_SIZE);
((unsigned int *)hdr)[i] = val;
}
}
int apu_mbox_wait_inbox(struct mtk_apu *apu)
{
unsigned long timeout;
unsigned char irq, mask;
timeout = jiffies + msecs_to_jiffies(WAIT_INBOX_TMO_MS);
do {
irq = ioread32(_INBOX_IRQ(apu));
mask = ioread32(_INBOX_IRQ_MASK(apu));
if (!(irq & ~mask))
return 0;
if (time_after(jiffies, timeout))
break;
} while (irq & ~mask);
/* second chance */
irq = ioread32(_INBOX_IRQ(apu));
mask = ioread32(_INBOX_IRQ_MASK(apu));
if (!(irq & ~mask))
return 0;
dev_info(apu->dev, "timeout. irq = 0x%x, mask = 0x%x\n",
irq, mask);
return -EBUSY;
}
void apu_mbox_write_inbox(struct mtk_apu *apu, struct apu_mbox_hdr *hdr)
{
unsigned int i, val;
for (i = 0; i < APU_MBOX_HDR_SLOTS; i++) {
val = ((unsigned int *)hdr)[i];
iowrite32(val, _INBOX(apu) + i * APU_MBOX_SLOT_SIZE);
}
}
void apu_mbox_inbox_init(struct mtk_apu *apu)
{
iowrite32(~(1 << (APU_MBOX_HDR_SLOTS - 1)),
_INBOX_IRQ_MASK(apu));
}
void apu_mbox_hw_init(struct mtk_apu *apu)
{
apu_mbox_inbox_init(apu);
/* clear outbox IRQ */
apu_mbox_ack_outbox(apu);
}
void apu_mbox_hw_exit(struct mtk_apu *apu)
{
/* mask inbox IRQ */
iowrite32(0xff, _INBOX_IRQ_MASK(apu));
}