// SPDX-License-Identifier: GPL-2.0
/* Code to support devices on the DIO and DIO-II bus
 * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
 * Copyright (C) 2004 Jochen Friedrich <jochen@scram.de>
 *
 * This code has basically these routines at the moment:
 * int dio_find(u_int deviceid)
 *    Search the list of DIO devices and return the select code
 *    of the next unconfigured device found that matches the given device ID.
 *    Note that the deviceid parameter should be the encoded ID.
 *    This means that framebuffers should pass it as
 *    DIO_ENCODE_ID(DIO_ID_FBUFFER,DIO_ID2_TOPCAT)
 *    (or whatever); everybody else just uses DIO_ID_FOOBAR.
 * unsigned long dio_scodetophysaddr(int scode)
 *    Return the physical address corresponding to the given select code.
 * int dio_scodetoipl(int scode)
 *    Every DIO card has a fixed interrupt priority level. This function
 *    returns it, whatever it is.
 * const char *dio_scodetoname(int scode)
 *    Return a character string describing this board [might be "" if
 *    not CONFIG_DIO_CONSTANTS]
 * void dio_config_board(int scode)     mark board as configured in the list
 * void dio_unconfig_board(int scode)   mark board as no longer configured
 *
 * This file is based on the way the Amiga port handles Zorro II cards,
 * although we aren't so complicated...
 */
#include <linux/module.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/dio.h>
#include <linux/slab.h>                         /* kmalloc() */
#include <linux/uaccess.h>
#include <linux/io.h>                           /* readb() */

struct dio_bus dio_bus = {
	.resources = {
		/* DIO range */
		{ .name = "DIO mem", .start = 0x00600000, .end = 0x007fffff },
		/* DIO-II range */
		{ .name = "DIO-II mem", .start = 0x01000000, .end = 0x1fffffff }
	},
	.name = "DIO bus"
};

/* not a real config option yet! */
#define CONFIG_DIO_CONSTANTS

#ifdef CONFIG_DIO_CONSTANTS
/* We associate each numeric ID with an appropriate descriptive string
 * using a constant array of these structs.
 * FIXME: we should be able to arrange to throw away most of the strings
 * using the initdata stuff. Then we wouldn't need to worry about
 * carrying them around...
 * I think we do this by copying them into newly kmalloc()ed memory and
 * marking the names[] array as .initdata ?
 */
struct dioname {
	int id;
	const char *name;
};

/* useful macro */
#define DIONAME(x) { DIO_ID_##x, DIO_DESC_##x }
#define DIOFBNAME(x) { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_##x), DIO_DESC2_##x }

static struct dioname names[] = {
	DIONAME(DCA0), DIONAME(DCA0REM), DIONAME(DCA1), DIONAME(DCA1REM),
	DIONAME(DCM), DIONAME(DCMREM),
	DIONAME(LAN),
	DIONAME(FHPIB), DIONAME(NHPIB),
	DIONAME(SCSI0), DIONAME(SCSI1), DIONAME(SCSI2), DIONAME(SCSI3),
	DIONAME(FBUFFER),
	DIONAME(PARALLEL), DIONAME(VME), DIONAME(DCL), DIONAME(DCLREM),
	DIONAME(MISC0), DIONAME(MISC1), DIONAME(MISC2), DIONAME(MISC3),
	DIONAME(MISC4), DIONAME(MISC5), DIONAME(MISC6), DIONAME(MISC7),
	DIONAME(MISC8), DIONAME(MISC9), DIONAME(MISC10), DIONAME(MISC11),
	DIONAME(MISC12), DIONAME(MISC13),
	DIOFBNAME(GATORBOX), DIOFBNAME(TOPCAT), DIOFBNAME(RENAISSANCE),
	DIOFBNAME(LRCATSEYE), DIOFBNAME(HRCCATSEYE), DIOFBNAME(HRMCATSEYE),
	DIOFBNAME(DAVINCI), DIOFBNAME(XXXCATSEYE), DIOFBNAME(HYPERION),
	DIOFBNAME(XGENESIS), DIOFBNAME(TIGER), DIOFBNAME(YGENESIS)
};

#undef DIONAME
#undef DIOFBNAME

static const char unknowndioname[]
	= "unknown DIO board, please email linux-m68k@lists.linux-m68k.org";

static const char *dio_getname(int id)
{
	/* return pointer to a constant string describing the board with given ID */
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(names); i++)
		if (names[i].id == id)
			return names[i].name;

	return unknowndioname;
}

#else

static char dio_no_name[] = { 0 };
#define dio_getname(_id)	(dio_no_name)

#endif /* CONFIG_DIO_CONSTANTS */

int __init dio_find(int deviceid)
{
	/* Called to find a DIO device before the full bus scan has run.
	 * Only used by the console driver.
	 */
	int scode, id;
	u_char prid, secid, i;

	for (scode = 0; scode < DIO_SCMAX; scode++) {
		void *va;
		unsigned long pa;

		if (DIO_SCINHOLE(scode))
			continue;

		pa = dio_scodetophysaddr(scode);

		if (!pa)
			continue;

		if (scode < DIOII_SCBASE)
			va = (void *)(pa + DIO_VIRADDRBASE);
		else
			va = ioremap(pa, PAGE_SIZE);

		if (copy_from_kernel_nofault(&i,
				(unsigned char *)va + DIO_IDOFF, 1)) {
			if (scode >= DIOII_SCBASE)
				iounmap(va);
			continue;	     /* no board present at that select code */
		}

		prid = DIO_ID(va);

		if (DIO_NEEDSSECID(prid)) {
			secid = DIO_SECID(va);
			id = DIO_ENCODE_ID(prid, secid);
		} else
			id = prid;

		if (id == deviceid) {
			if (scode >= DIOII_SCBASE)
				iounmap(va);
			return scode;
		}
	}

	return -1;
}

/* This is the function that scans the DIO space and works out what
 * hardware is actually present.
 */
static int __init dio_init(void)
{
	int scode;
	int i;
	struct dio_dev *dev;
	int error;

	if (!MACH_IS_HP300)
		return 0;

        printk(KERN_INFO "Scanning for DIO devices...\n");

	/* Initialize the DIO bus */
	INIT_LIST_HEAD(&dio_bus.devices);
	dev_set_name(&dio_bus.dev, "dio");
	error = device_register(&dio_bus.dev);
	if (error) {
		pr_err("DIO: Error registering dio_bus\n");
		return error;
	}

	/* Request all resources */
	dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
	for (i = 0; i < dio_bus.num_resources; i++)
		request_resource(&iomem_resource, &dio_bus.resources[i]);

	/* Register all devices */
	for (scode = 0; scode < DIO_SCMAX; ++scode) {
		u_char prid, secid = 0;	/* primary, secondary ID bytes */
		u_char *va;
		unsigned long pa;

		if (DIO_SCINHOLE(scode))
			continue;

		pa = dio_scodetophysaddr(scode);

		if (!pa)
			continue;

		if (scode < DIOII_SCBASE)
			va = (void *)(pa + DIO_VIRADDRBASE);
		else
			va = ioremap(pa, PAGE_SIZE);

		if (copy_from_kernel_nofault(&i,
				(unsigned char *)va + DIO_IDOFF, 1)) {
			if (scode >= DIOII_SCBASE)
				iounmap(va);
			continue;	      /* no board present at that select code */
		}

		/* Found a board, allocate it an entry in the list */
		dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL);
		if (!dev)
			return -ENOMEM;

		dev->bus = &dio_bus;
		dev->dev.parent = &dio_bus.dev;
		dev->dev.bus = &dio_bus_type;
		dev->scode = scode;
		dev->resource.start = pa;
		dev->resource.end = pa + DIO_SIZE(scode, va);
		dev_set_name(&dev->dev, "%02x", scode);

		/* read the ID byte(s) and encode if necessary. */
		prid = DIO_ID(va);

		if (DIO_NEEDSSECID(prid)) {
			secid = DIO_SECID(va);
			dev->id = DIO_ENCODE_ID(prid, secid);
		} else
			dev->id = prid;

		dev->ipl = DIO_IPL(va);
		strcpy(dev->name, dio_getname(dev->id));
                printk(KERN_INFO "select code %3d: ipl %d: ID %02X", dev->scode, dev->ipl, prid);
		if (DIO_NEEDSSECID(prid))
                        printk(":%02X", secid);
                printk(": %s\n", dev->name);

		if (scode >= DIOII_SCBASE)
			iounmap(va);
		error = device_register(&dev->dev);
		if (error) {
			pr_err("DIO: Error registering device %s\n",
			       dev->name);
			continue;
		}
		error = dio_create_sysfs_dev_files(dev);
		if (error)
			dev_err(&dev->dev, "Error creating sysfs files\n");
	}
	return 0;
}

subsys_initcall(dio_init);

/* Bear in mind that this is called in the very early stages of initialisation
 * in order to get the address of the serial port for the console...
 */
unsigned long dio_scodetophysaddr(int scode)
{
	if (scode >= DIOII_SCBASE)
		return (DIOII_BASE + (scode - 132) * DIOII_DEVSIZE);
	else if (scode > DIO_SCMAX || scode < 0)
		return 0;
	else if (DIO_SCINHOLE(scode))
		return 0;

	return (DIO_BASE + scode * DIO_DEVSIZE);
}
