18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PCI support for the Sega Dreamcast
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2001, 2002  M. R. Brown
68c2ecf20Sopenharmony_ci * Copyright (C) 2002, 2003  Paul Mundt
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This file originally bore the message (with enclosed-$):
98c2ecf20Sopenharmony_ci *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
108c2ecf20Sopenharmony_ci *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/sched.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/param.h>
168c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/irq.h>
198c2ecf20Sopenharmony_ci#include <linux/pci.h>
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <asm/io.h>
228c2ecf20Sopenharmony_ci#include <asm/irq.h>
238c2ecf20Sopenharmony_ci#include <mach/pci.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct resource gapspci_resources[] = {
268c2ecf20Sopenharmony_ci	{
278c2ecf20Sopenharmony_ci		.name	= "GAPSPCI IO",
288c2ecf20Sopenharmony_ci		.start	= GAPSPCI_BBA_CONFIG,
298c2ecf20Sopenharmony_ci		.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
308c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IO,
318c2ecf20Sopenharmony_ci	},  {
328c2ecf20Sopenharmony_ci		.name	= "GAPSPCI mem",
338c2ecf20Sopenharmony_ci		.start	= GAPSPCI_DMA_BASE,
348c2ecf20Sopenharmony_ci		.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
358c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_MEM,
368c2ecf20Sopenharmony_ci	},
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic struct pci_channel dreamcast_pci_controller = {
408c2ecf20Sopenharmony_ci	.pci_ops	= &gapspci_pci_ops,
418c2ecf20Sopenharmony_ci	.resources	= gapspci_resources,
428c2ecf20Sopenharmony_ci	.nr_resources	= ARRAY_SIZE(gapspci_resources),
438c2ecf20Sopenharmony_ci	.io_offset	= 0x00000000,
448c2ecf20Sopenharmony_ci	.mem_offset	= 0x00000000,
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/*
488c2ecf20Sopenharmony_ci * gapspci init
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic int __init gapspci_init(void)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	char idbuf[16];
548c2ecf20Sopenharmony_ci	int i;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	/*
578c2ecf20Sopenharmony_ci	 * FIXME: All of this wants documenting to some degree,
588c2ecf20Sopenharmony_ci	 * even some basic register definitions would be nice.
598c2ecf20Sopenharmony_ci	 *
608c2ecf20Sopenharmony_ci	 * I haven't seen anything this ugly since.. maple.
618c2ecf20Sopenharmony_ci	 */
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	for (i=0; i<16; i++)
648c2ecf20Sopenharmony_ci		idbuf[i] = inb(GAPSPCI_REGS+i);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
678c2ecf20Sopenharmony_ci		return -ENODEV;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	outl(0x5a14a501, GAPSPCI_REGS+0x18);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	for (i=0; i<1000000; i++)
728c2ecf20Sopenharmony_ci		cpu_relax();
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	if (inl(GAPSPCI_REGS+0x18) != 1)
758c2ecf20Sopenharmony_ci		return -EINVAL;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	outl(0x01000000, GAPSPCI_REGS+0x20);
788c2ecf20Sopenharmony_ci	outl(0x01000000, GAPSPCI_REGS+0x24);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
818c2ecf20Sopenharmony_ci	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	outl(1, GAPSPCI_REGS+0x14);
848c2ecf20Sopenharmony_ci	outl(1, GAPSPCI_REGS+0x34);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* Setting Broadband Adapter */
878c2ecf20Sopenharmony_ci	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
888c2ecf20Sopenharmony_ci	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
898c2ecf20Sopenharmony_ci	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
908c2ecf20Sopenharmony_ci	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
918c2ecf20Sopenharmony_ci	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
928c2ecf20Sopenharmony_ci	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
938c2ecf20Sopenharmony_ci	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return register_pci_controller(&dreamcast_pci_controller);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ciarch_initcall(gapspci_init);
98