// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
 * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
 * Copyright (C) 2004 Christoph Hellwig.
 *
 * Generic XTALK initialization code
 */

#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/platform_device.h>
#include <linux/platform_data/sgi-w1.h>
#include <linux/platform_data/xtalk-bridge.h>
#include <asm/sn/addrs.h>
#include <asm/sn/types.h>
#include <asm/sn/klconfig.h>
#include <asm/pci/bridge.h>
#include <asm/xtalk/xtalk.h>


#define XBOW_WIDGET_PART_NUM	0x0
#define XXBOW_WIDGET_PART_NUM	0xd000	/* Xbow in Xbridge */
#define BASE_XBOW_PORT		8     /* Lowest external port */

static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
{
	struct xtalk_bridge_platform_data *bd;
	struct sgi_w1_platform_data *wd;
	struct platform_device *pdev;
	struct resource w1_res;
	unsigned long offset;

	offset = NODE_OFFSET(nasid);

	wd = kzalloc(sizeof(*wd), GFP_KERNEL);
	if (!wd)
		goto no_mem;

	snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
		 offset + (widget << SWIN_SIZE_BITS));

	memset(&w1_res, 0, sizeof(w1_res));
	w1_res.start = offset + (widget << SWIN_SIZE_BITS) +
				offsetof(struct bridge_regs, b_nic);
	w1_res.end = w1_res.start + 3;
	w1_res.flags = IORESOURCE_MEM;

	pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
	if (!pdev) {
		kfree(wd);
		goto no_mem;
	}
	platform_device_add_resources(pdev, &w1_res, 1);
	platform_device_add_data(pdev, wd, sizeof(*wd));
	platform_device_add(pdev);

	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
	if (!bd)
		goto no_mem;
	pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
	if (!pdev) {
		kfree(bd);
		goto no_mem;
	}


	bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget);
	bd->intr_addr	= BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD;
	bd->nasid	= nasid;
	bd->masterwid	= masterwid;

	bd->mem.name	= "Bridge PCI MEM";
	bd->mem.start	= offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
	bd->mem.end	= offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
	bd->mem.flags	= IORESOURCE_MEM;
	bd->mem_offset	= offset;

	bd->io.name	= "Bridge PCI IO";
	bd->io.start	= offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
	bd->io.end	= offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
	bd->io.flags	= IORESOURCE_IO;
	bd->io_offset	= offset;

	platform_device_add_data(pdev, bd, sizeof(*bd));
	platform_device_add(pdev);
	pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget);
	return;

no_mem:
	pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
}

static int probe_one_port(nasid_t nasid, int widget, int masterwid)
{
	widgetreg_t		widget_id;
	xwidget_part_num_t	partnum;

	widget_id = *(volatile widgetreg_t *)
		(RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
	partnum = XWIDGET_PART_NUM(widget_id);

	switch (partnum) {
	case BRIDGE_WIDGET_PART_NUM:
	case XBRIDGE_WIDGET_PART_NUM:
		bridge_platform_create(nasid, widget, masterwid);
		break;
	default:
		pr_info("xtalk:n%d/%d unknown widget (0x%x)\n",
			nasid, widget, partnum);
		break;
	}

	return 0;
}

static int xbow_probe(nasid_t nasid)
{
	lboard_t *brd;
	klxbow_t *xbow_p;
	unsigned masterwid, i;

	/*
	 * found xbow, so may have multiple bridges
	 * need to probe xbow
	 */
	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
	if (!brd)
		return -ENODEV;

	xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
	if (!xbow_p)
		return -ENODEV;

	/*
	 * Okay, here's a xbow. Let's arbitrate and find
	 * out if we should initialize it. Set enabled
	 * hub connected at highest or lowest widget as
	 * master.
	 */
#ifdef WIDGET_A
	i = HUB_WIDGET_ID_MAX + 1;
	do {
		i--;
	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
#else
	i = HUB_WIDGET_ID_MIN - 1;
	do {
		i++;
	} while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
		 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
#endif

	masterwid = i;
	if (nasid != XBOW_PORT_NASID(xbow_p, i))
		return 1;

	for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
		if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
		    XBOW_PORT_TYPE_IO(xbow_p, i))
			probe_one_port(nasid, i, masterwid);
	}

	return 0;
}

static void xtalk_probe_node(nasid_t nasid)
{
	volatile u64		hubreg;
	xwidget_part_num_t	partnum;
	widgetreg_t		widget_id;

	hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);

	/* check whether the link is up */
	if (!(hubreg & IIO_LLP_CSR_IS_UP))
		return;

	widget_id = *(volatile widgetreg_t *)
		       (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
	partnum = XWIDGET_PART_NUM(widget_id);

	switch (partnum) {
	case BRIDGE_WIDGET_PART_NUM:
		bridge_platform_create(nasid, 0x8, 0xa);
		break;
	case XBOW_WIDGET_PART_NUM:
	case XXBOW_WIDGET_PART_NUM:
		pr_info("xtalk:n%d/0 xbow widget\n", nasid);
		xbow_probe(nasid);
		break;
	default:
		pr_info("xtalk:n%d/0 unknown widget (0x%x)\n", nasid, partnum);
		break;
	}
}

static int __init xtalk_init(void)
{
	nasid_t nasid;

	for_each_online_node(nasid)
		xtalk_probe_node(nasid);

	return 0;
}
arch_initcall(xtalk_init);
