You've already forked apple-bce-drv
mirror of
https://github.com/t2linux/apple-bce-drv.git
synced 2026-04-30 13:31:39 -07:00
c4c7356dba
del_timer_sync was renamed to timer_delete_sync in 6.1, and starting from 6.15, the older name was completely removed.
156 lines
4.1 KiB
C
156 lines
4.1 KiB
C
#include "mailbox.h"
|
|
#include <linux/atomic.h>
|
|
#include "apple_bce.h"
|
|
#include <linux/version.h>
|
|
|
|
#define REG_MBOX_OUT_BASE 0x820
|
|
#define REG_MBOX_REPLY_COUNTER 0x108
|
|
#define REG_MBOX_REPLY_BASE 0x810
|
|
#define REG_TIMESTAMP_BASE 0xC000
|
|
|
|
#define BCE_MBOX_TIMEOUT_MS 200
|
|
|
|
void bce_mailbox_init(struct bce_mailbox *mb, void __iomem *reg_mb)
|
|
{
|
|
mb->reg_mb = reg_mb;
|
|
init_completion(&mb->mb_completion);
|
|
}
|
|
|
|
int bce_mailbox_send(struct bce_mailbox *mb, u64 msg, u64* recv)
|
|
{
|
|
u32 __iomem *regb;
|
|
|
|
if (atomic_cmpxchg(&mb->mb_status, 0, 1) != 0) {
|
|
return -EEXIST; // We don't support two messages at once
|
|
}
|
|
reinit_completion(&mb->mb_completion);
|
|
|
|
pr_debug("bce_mailbox_send: %llx\n", msg);
|
|
regb = (u32*) ((u8*) mb->reg_mb + REG_MBOX_OUT_BASE);
|
|
iowrite32((u32) msg, regb);
|
|
iowrite32((u32) (msg >> 32), regb + 1);
|
|
iowrite32(0, regb + 2);
|
|
iowrite32(0, regb + 3);
|
|
|
|
wait_for_completion_timeout(&mb->mb_completion, msecs_to_jiffies(BCE_MBOX_TIMEOUT_MS));
|
|
if (atomic_read(&mb->mb_status) != 2) { // Didn't get the reply
|
|
atomic_set(&mb->mb_status, 0);
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
*recv = mb->mb_result;
|
|
pr_debug("bce_mailbox_send: reply %llx\n", *recv);
|
|
|
|
atomic_set(&mb->mb_status, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int bce_mailbox_retrive_response(struct bce_mailbox *mb)
|
|
{
|
|
u32 __iomem *regb;
|
|
u32 lo, hi;
|
|
int count, counter;
|
|
u32 res = ioread32((u8*) mb->reg_mb + REG_MBOX_REPLY_COUNTER);
|
|
count = (res >> 20) & 0xf;
|
|
counter = count;
|
|
pr_debug("bce_mailbox_retrive_response count=%i\n", count);
|
|
while (counter--) {
|
|
regb = (u32*) ((u8*) mb->reg_mb + REG_MBOX_REPLY_BASE);
|
|
lo = ioread32(regb);
|
|
hi = ioread32(regb + 1);
|
|
ioread32(regb + 2);
|
|
ioread32(regb + 3);
|
|
pr_debug("bce_mailbox_retrive_response %llx\n", ((u64) hi << 32) | lo);
|
|
mb->mb_result = ((u64) hi << 32) | lo;
|
|
}
|
|
return count > 0 ? 0 : -ENODATA;
|
|
}
|
|
|
|
int bce_mailbox_handle_interrupt(struct bce_mailbox *mb)
|
|
{
|
|
int status = bce_mailbox_retrive_response(mb);
|
|
if (!status) {
|
|
atomic_set(&mb->mb_status, 2);
|
|
complete(&mb->mb_completion);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
static void bc_send_timestamp(struct timer_list *tl);
|
|
|
|
void bce_timestamp_init(struct bce_timestamp *ts, void __iomem *reg)
|
|
{
|
|
u32 __iomem *regb;
|
|
|
|
spin_lock_init(&ts->stop_sl);
|
|
ts->stopped = false;
|
|
|
|
ts->reg = reg;
|
|
|
|
regb = (u32*) ((u8*) ts->reg + REG_TIMESTAMP_BASE);
|
|
|
|
ioread32(regb);
|
|
mb();
|
|
|
|
timer_setup(&ts->timer, bc_send_timestamp, 0);
|
|
}
|
|
|
|
void bce_timestamp_start(struct bce_timestamp *ts, bool is_initial)
|
|
{
|
|
unsigned long flags;
|
|
u32 __iomem *regb = (u32*) ((u8*) ts->reg + REG_TIMESTAMP_BASE);
|
|
|
|
if (is_initial) {
|
|
iowrite32((u32) -4, regb + 2);
|
|
iowrite32((u32) -1, regb);
|
|
} else {
|
|
iowrite32((u32) -3, regb + 2);
|
|
iowrite32((u32) -1, regb);
|
|
}
|
|
|
|
spin_lock_irqsave(&ts->stop_sl, flags);
|
|
ts->stopped = false;
|
|
spin_unlock_irqrestore(&ts->stop_sl, flags);
|
|
mod_timer(&ts->timer, jiffies + msecs_to_jiffies(150));
|
|
}
|
|
|
|
void bce_timestamp_stop(struct bce_timestamp *ts)
|
|
{
|
|
unsigned long flags;
|
|
u32 __iomem *regb = (u32*) ((u8*) ts->reg + REG_TIMESTAMP_BASE);
|
|
|
|
spin_lock_irqsave(&ts->stop_sl, flags);
|
|
ts->stopped = true;
|
|
spin_unlock_irqrestore(&ts->stop_sl, flags);
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,15,0)
|
|
del_timer_sync(&ts->timer);
|
|
#else
|
|
timer_delete_sync(&ts->timer);
|
|
#endif
|
|
iowrite32((u32) -2, regb + 2);
|
|
iowrite32((u32) -1, regb);
|
|
}
|
|
|
|
static void bc_send_timestamp(struct timer_list *tl)
|
|
{
|
|
struct bce_timestamp *ts;
|
|
unsigned long flags;
|
|
u32 __iomem *regb;
|
|
ktime_t bt;
|
|
|
|
ts = container_of(tl, struct bce_timestamp, timer);
|
|
regb = (u32*) ((u8*) ts->reg + REG_TIMESTAMP_BASE);
|
|
local_irq_save(flags);
|
|
ioread32(regb + 2);
|
|
mb();
|
|
bt = ktime_get_boottime();
|
|
iowrite32((u32) bt, regb + 2);
|
|
iowrite32((u32) (bt >> 32), regb);
|
|
|
|
spin_lock(&ts->stop_sl);
|
|
if (!ts->stopped)
|
|
mod_timer(&ts->timer, jiffies + msecs_to_jiffies(150));
|
|
spin_unlock(&ts->stop_sl);
|
|
local_irq_restore(flags);
|
|
}
|