162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PCI support for the Sega Dreamcast
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2001, 2002  M. R. Brown
662306a36Sopenharmony_ci * Copyright (C) 2002, 2003  Paul Mundt
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This file originally bore the message (with enclosed-$):
962306a36Sopenharmony_ci *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
1062306a36Sopenharmony_ci *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/sched.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/param.h>
1662306a36Sopenharmony_ci#include <linux/interrupt.h>
1762306a36Sopenharmony_ci#include <linux/init.h>
1862306a36Sopenharmony_ci#include <linux/irq.h>
1962306a36Sopenharmony_ci#include <linux/pci.h>
2062306a36Sopenharmony_ci#include <linux/module.h>
2162306a36Sopenharmony_ci#include <asm/io.h>
2262306a36Sopenharmony_ci#include <asm/irq.h>
2362306a36Sopenharmony_ci#include <mach/pci.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic struct resource gapspci_resources[] = {
2662306a36Sopenharmony_ci	{
2762306a36Sopenharmony_ci		.name	= "GAPSPCI IO",
2862306a36Sopenharmony_ci		.start	= GAPSPCI_BBA_CONFIG,
2962306a36Sopenharmony_ci		.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
3062306a36Sopenharmony_ci		.flags	= IORESOURCE_IO,
3162306a36Sopenharmony_ci	},  {
3262306a36Sopenharmony_ci		.name	= "GAPSPCI mem",
3362306a36Sopenharmony_ci		.start	= GAPSPCI_DMA_BASE,
3462306a36Sopenharmony_ci		.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
3562306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
3662306a36Sopenharmony_ci	},
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic struct pci_channel dreamcast_pci_controller = {
4062306a36Sopenharmony_ci	.pci_ops	= &gapspci_pci_ops,
4162306a36Sopenharmony_ci	.resources	= gapspci_resources,
4262306a36Sopenharmony_ci	.nr_resources	= ARRAY_SIZE(gapspci_resources),
4362306a36Sopenharmony_ci	.io_offset	= 0x00000000,
4462306a36Sopenharmony_ci	.mem_offset	= 0x00000000,
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * gapspci init
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int __init gapspci_init(void)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	char idbuf[16];
5462306a36Sopenharmony_ci	int i;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	/*
5762306a36Sopenharmony_ci	 * FIXME: All of this wants documenting to some degree,
5862306a36Sopenharmony_ci	 * even some basic register definitions would be nice.
5962306a36Sopenharmony_ci	 *
6062306a36Sopenharmony_ci	 * I haven't seen anything this ugly since.. maple.
6162306a36Sopenharmony_ci	 */
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	for (i=0; i<16; i++)
6462306a36Sopenharmony_ci		idbuf[i] = inb(GAPSPCI_REGS+i);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
6762306a36Sopenharmony_ci		return -ENODEV;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	outl(0x5a14a501, GAPSPCI_REGS+0x18);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	for (i=0; i<1000000; i++)
7262306a36Sopenharmony_ci		cpu_relax();
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (inl(GAPSPCI_REGS+0x18) != 1)
7562306a36Sopenharmony_ci		return -EINVAL;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	outl(0x01000000, GAPSPCI_REGS+0x20);
7862306a36Sopenharmony_ci	outl(0x01000000, GAPSPCI_REGS+0x24);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
8162306a36Sopenharmony_ci	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	outl(1, GAPSPCI_REGS+0x14);
8462306a36Sopenharmony_ci	outl(1, GAPSPCI_REGS+0x34);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	/* Setting Broadband Adapter */
8762306a36Sopenharmony_ci	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
8862306a36Sopenharmony_ci	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
8962306a36Sopenharmony_ci	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
9062306a36Sopenharmony_ci	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
9162306a36Sopenharmony_ci	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
9262306a36Sopenharmony_ci	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
9362306a36Sopenharmony_ci	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	return register_pci_controller(&dreamcast_pci_controller);
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ciarch_initcall(gapspci_init);
98