162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PCI operations 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
962306a36Sopenharmony_ci#include <linux/sched.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/param.h>
1262306a36Sopenharmony_ci#include <linux/interrupt.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/irq.h>
1562306a36Sopenharmony_ci#include <linux/pci.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/io.h>
1862306a36Sopenharmony_ci#include <mach/pci.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * The !gapspci_config_access case really shouldn't happen, ever, unless
2262306a36Sopenharmony_ci * someone implicitly messes around with the last devfn value.. otherwise we
2362306a36Sopenharmony_ci * only support a single device anyways, and if we didn't have a BBA, we
2462306a36Sopenharmony_ci * wouldn't make it terribly far through the PCI setup anyways.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * Also, we could very easily support both Type 0 and Type 1 configurations
2762306a36Sopenharmony_ci * here, but since it doesn't seem that there is any such implementation in
2862306a36Sopenharmony_ci * existence, we don't bother.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * I suppose if someone actually gets around to ripping the chip out of
3162306a36Sopenharmony_ci * the BBA and hanging some more devices off of it, then this might be
3262306a36Sopenharmony_ci * something to take into consideration. However, due to the cost of the BBA,
3362306a36Sopenharmony_ci * and the general lack of activity by DC hardware hackers, this doesn't seem
3462306a36Sopenharmony_ci * likely to happen anytime soon.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cistatic int gapspci_config_access(unsigned char bus, unsigned int devfn)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	return (bus == 0) && (devfn == 0);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * We can also actually read and write in b/w/l sizes! Thankfully this part
4362306a36Sopenharmony_ci * was at least done right, and we don't have to do the stupid masking and
4462306a36Sopenharmony_ci * shifting that we do on the 7751! Small wonders never cease to amaze.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_cistatic int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	*val = 0xffffffff;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (!gapspci_config_access(bus->number, devfn))
5162306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	switch (size) {
5462306a36Sopenharmony_ci	case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
5562306a36Sopenharmony_ci	case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
5662306a36Sopenharmony_ci	case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci        return PCIBIOS_SUCCESSFUL;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	if (!gapspci_config_access(bus->number, devfn))
6562306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	switch (size) {
6862306a36Sopenharmony_ci	case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
6962306a36Sopenharmony_ci	case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
7062306a36Sopenharmony_ci	case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci        return PCIBIOS_SUCCESSFUL;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct pci_ops gapspci_pci_ops = {
7762306a36Sopenharmony_ci	.read	= gapspci_read,
7862306a36Sopenharmony_ci	.write	= gapspci_write,
7962306a36Sopenharmony_ci};
80