// SPDX-License-Identifier: GPL-2.0
/*
 * I/O Processor (IOP) ADB Driver
 * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
 * Based on via-cuda.c by Paul Mackerras.
 *
 * 1999-07-01 (jmt) - First implementation for new driver architecture.
 *
 * 1999-07-31 (jmt) - First working version.
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/init.h>

#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_iop.h>
#include <asm/adb_iop.h>

#include <linux/adb.h>

static struct adb_request *current_req;
static struct adb_request *last_req;
static unsigned int autopoll_devs;

static enum adb_iop_state {
	idle,
	sending,
	awaiting_reply
} adb_iop_state;

static void adb_iop_start(void);
static int adb_iop_probe(void);
static int adb_iop_init(void);
static int adb_iop_send_request(struct adb_request *, int);
static int adb_iop_write(struct adb_request *);
static int adb_iop_autopoll(int);
static void adb_iop_poll(void);
static int adb_iop_reset_bus(void);

struct adb_driver adb_iop_driver = {
	.name         = "ISM IOP",
	.probe        = adb_iop_probe,
	.init         = adb_iop_init,
	.send_request = adb_iop_send_request,
	.autopoll     = adb_iop_autopoll,
	.poll         = adb_iop_poll,
	.reset_bus    = adb_iop_reset_bus
};

static void adb_iop_done(void)
{
	struct adb_request *req = current_req;

	adb_iop_state = idle;

	req->complete = 1;
	current_req = req->next;
	if (req->done)
		(*req->done)(req);

	if (adb_iop_state == idle)
		adb_iop_start();
}

/*
 * Completion routine for ADB commands sent to the IOP.
 *
 * This will be called when a packet has been successfully sent.
 */

static void adb_iop_complete(struct iop_msg *msg)
{
	unsigned long flags;

	local_irq_save(flags);

	if (current_req->reply_expected)
		adb_iop_state = awaiting_reply;
	else
		adb_iop_done();

	local_irq_restore(flags);
}

/*
 * Listen for ADB messages from the IOP.
 *
 * This will be called when unsolicited messages (usually replies to TALK
 * commands or autopoll packets) are received.
 */

static void adb_iop_listen(struct iop_msg *msg)
{
	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
	unsigned long flags;
	bool req_done = false;

	local_irq_save(flags);

	/* Handle a timeout. Timeout packets seem to occur even after
	 * we've gotten a valid reply to a TALK, presumably because of
	 * autopolling.
	 */

	if (amsg->flags & ADB_IOP_EXPLICIT) {
		if (adb_iop_state == awaiting_reply) {
			struct adb_request *req = current_req;

			req->reply_len = amsg->count + 1;
			memcpy(req->reply, &amsg->cmd, req->reply_len);

			req_done = true;
		}
	} else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
		adb_input(&amsg->cmd, amsg->count + 1,
			  amsg->flags & ADB_IOP_AUTOPOLL);
	}

	msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0;
	iop_complete_message(msg);

	if (req_done)
		adb_iop_done();

	local_irq_restore(flags);
}

/*
 * Start sending an ADB packet, IOP style
 *
 * There isn't much to do other than hand the packet over to the IOP
 * after encapsulating it in an adb_iopmsg.
 */

static void adb_iop_start(void)
{
	struct adb_request *req;
	struct adb_iopmsg amsg;

	/* get the packet to send */
	req = current_req;
	if (!req)
		return;

	/* The IOP takes MacII-style packets, so strip the initial
	 * ADB_PACKET byte.
	 */
	amsg.flags = ADB_IOP_EXPLICIT;
	amsg.count = req->nbytes - 2;

	/* amsg.data immediately follows amsg.cmd, effectively making
	 * &amsg.cmd a pointer to the beginning of a full ADB packet.
	 */
	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);

	req->sent = 1;
	adb_iop_state = sending;

	/* Now send it. The IOP manager will call adb_iop_complete
	 * when the message has been sent.
	 */
	iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
			 adb_iop_complete);
}

static int adb_iop_probe(void)
{
	if (!iop_ism_present)
		return -ENODEV;
	return 0;
}

static int adb_iop_init(void)
{
	pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
	return 0;
}

static int adb_iop_send_request(struct adb_request *req, int sync)
{
	int err;

	err = adb_iop_write(req);
	if (err)
		return err;

	if (sync) {
		while (!req->complete)
			adb_iop_poll();
	}
	return 0;
}

static int adb_iop_write(struct adb_request *req)
{
	unsigned long flags;

	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
		req->complete = 1;
		return -EINVAL;
	}

	req->next = NULL;
	req->sent = 0;
	req->complete = 0;
	req->reply_len = 0;

	local_irq_save(flags);

	if (current_req) {
		last_req->next = req;
		last_req = req;
	} else {
		current_req = req;
		last_req = req;
	}

	if (adb_iop_state == idle)
		adb_iop_start();

	local_irq_restore(flags);

	return 0;
}

static void adb_iop_set_ap_complete(struct iop_msg *msg)
{
	struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;

	autopoll_devs = (amsg->data[1] << 8) | amsg->data[0];
}

static int adb_iop_autopoll(int devs)
{
	struct adb_iopmsg amsg;
	unsigned long flags;
	unsigned int mask = (unsigned int)devs & 0xFFFE;

	local_irq_save(flags);

	amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0);
	amsg.count = 2;
	amsg.cmd = 0;
	amsg.data[0] = mask & 0xFF;
	amsg.data[1] = (mask >> 8) & 0xFF;

	iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg,
			 adb_iop_set_ap_complete);

	local_irq_restore(flags);

	return 0;
}

static void adb_iop_poll(void)
{
	iop_ism_irq_poll(ADB_IOP);
}

static int adb_iop_reset_bus(void)
{
	struct adb_request req;

	/* Command = 0, Address = ignored */
	adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET);
	adb_iop_send_request(&req, 1);

	/* Don't want any more requests during the Global Reset low time. */
	mdelay(3);

	return 0;
}
