// SPDX-License-Identifier: GPL-2.0-only
/*
 * Driver for Intel I82092AA PCI-PCMCIA bridge.
 *
 * (C) 2001 Red Hat, Inc.
 *
 * Author: Arjan Van De Ven <arjanv@redhat.com>
 * Loosly based on i82365.c from the pcmcia-cs package
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/device.h>

#include <pcmcia/ss.h>

#include <linux/io.h>

#include "i82092aa.h"
#include "i82365.h"

MODULE_DESCRIPTION("Driver for Intel I82092AA PCI-PCMCIA bridge");
MODULE_LICENSE("GPL");

/* PCI core routines */
static const struct pci_device_id i82092aa_pci_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
	{ }
};
MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);

static struct pci_driver i82092aa_pci_driver = {
	.name		= "i82092aa",
	.id_table	= i82092aa_pci_ids,
	.probe		= i82092aa_pci_probe,
	.remove	= i82092aa_pci_remove,
};


/* the pccard structure and its functions */
static struct pccard_operations i82092aa_operations = {
	.init			= i82092aa_init,
	.get_status		= i82092aa_get_status,
	.set_socket		= i82092aa_set_socket,
	.set_io_map		= i82092aa_set_io_map,
	.set_mem_map		= i82092aa_set_mem_map,
};

/* The card can do up to 4 sockets, allocate a structure for each of them */

struct socket_info {
	int	number;
	int	card_state;
		/* 0 = no socket,
		 * 1 = empty socket,
		 * 2 = card but not initialized,
		 * 3 = operational card
		 */
	unsigned int io_base;	/* base io address of the socket */

	struct pcmcia_socket socket;
	struct pci_dev *dev;	/* The PCI device for the socket */
};

#define MAX_SOCKETS 4
static struct socket_info sockets[MAX_SOCKETS];
static int socket_count;	/* shortcut */


static int i82092aa_pci_probe(struct pci_dev *dev,
			      const struct pci_device_id *id)
{
	unsigned char configbyte;
	int i, ret;

	ret = pci_enable_device(dev);
	if (ret)
		return ret;

	/* PCI Configuration Control */
	pci_read_config_byte(dev, 0x40, &configbyte);

	switch (configbyte&6) {
	case 0:
		socket_count = 2;
		break;
	case 2:
		socket_count = 1;
		break;
	case 4:
	case 6:
		socket_count = 4;
		break;

	default:
		dev_err(&dev->dev,
			"Oops, you did something we didn't think of.\n");
		ret = -EIO;
		goto err_out_disable;
	}
	dev_info(&dev->dev, "configured as a %d socket device.\n",
		 socket_count);

	if (!request_region(pci_resource_start(dev, 0), 2, "i82092aa")) {
		ret = -EBUSY;
		goto err_out_disable;
	}

	for (i = 0; i < socket_count; i++) {
		sockets[i].card_state = 1; /* 1 = present but empty */
		sockets[i].io_base = pci_resource_start(dev, 0);
		sockets[i].dev = dev;
		sockets[i].socket.features |= SS_CAP_PCCARD;
		sockets[i].socket.map_size = 0x1000;
		sockets[i].socket.irq_mask = 0;
		sockets[i].socket.pci_irq  = dev->irq;
		sockets[i].socket.cb_dev  = dev;
		sockets[i].socket.owner = THIS_MODULE;

		sockets[i].number = i;

		if (card_present(i)) {
			sockets[i].card_state = 3;
			dev_dbg(&dev->dev, "slot %i is occupied\n", i);
		} else {
			dev_dbg(&dev->dev, "slot %i is vacant\n", i);
		}
	}

	/* Now, specifiy that all interrupts are to be done as PCI interrupts
	 * bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt
	 */
	configbyte = 0xFF;

	/* PCI Interrupt Routing Register */
	pci_write_config_byte(dev, 0x50, configbyte);

	/* Register the interrupt handler */
	dev_dbg(&dev->dev, "Requesting interrupt %i\n", dev->irq);
	ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED,
			  "i82092aa", i82092aa_interrupt);
	if (ret) {
		dev_err(&dev->dev, "Failed to register IRQ %d, aborting\n",
			dev->irq);
		goto err_out_free_res;
	}

	for (i = 0; i < socket_count; i++) {
		sockets[i].socket.dev.parent = &dev->dev;
		sockets[i].socket.ops = &i82092aa_operations;
		sockets[i].socket.resource_ops = &pccard_nonstatic_ops;
		ret = pcmcia_register_socket(&sockets[i].socket);
		if (ret)
			goto err_out_free_sockets;
	}

	return 0;

err_out_free_sockets:
	if (i) {
		for (i--; i >= 0; i--)
			pcmcia_unregister_socket(&sockets[i].socket);
	}
	free_irq(dev->irq, i82092aa_interrupt);
err_out_free_res:
	release_region(pci_resource_start(dev, 0), 2);
err_out_disable:
	pci_disable_device(dev);
	return ret;
}

static void i82092aa_pci_remove(struct pci_dev *dev)
{
	int i;

	free_irq(dev->irq, i82092aa_interrupt);

	for (i = 0; i < socket_count; i++)
		pcmcia_unregister_socket(&sockets[i].socket);
}

static DEFINE_SPINLOCK(port_lock);

/* basic value read/write functions */

static unsigned char indirect_read(int socket, unsigned short reg)
{
	unsigned short int port;
	unsigned char val;
	unsigned long flags;

	spin_lock_irqsave(&port_lock, flags);
	reg += socket * 0x40;
	port = sockets[socket].io_base;
	outb(reg, port);
	val = inb(port+1);
	spin_unlock_irqrestore(&port_lock, flags);
	return val;
}

static void indirect_write(int socket, unsigned short reg, unsigned char value)
{
	unsigned short int port;
	unsigned long flags;

	spin_lock_irqsave(&port_lock, flags);
	reg = reg + socket * 0x40;
	port = sockets[socket].io_base;
	outb(reg, port);
	outb(value, port+1);
	spin_unlock_irqrestore(&port_lock, flags);
}

static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
{
	unsigned short int port;
	unsigned char val;
	unsigned long flags;

	spin_lock_irqsave(&port_lock, flags);
	reg = reg + socket * 0x40;
	port = sockets[socket].io_base;
	outb(reg, port);
	val = inb(port+1);
	val |= mask;
	outb(reg, port);
	outb(val, port+1);
	spin_unlock_irqrestore(&port_lock, flags);
}


static void indirect_resetbit(int socket,
			      unsigned short reg, unsigned char mask)
{
	unsigned short int port;
	unsigned char val;
	unsigned long flags;

	spin_lock_irqsave(&port_lock, flags);
	reg = reg + socket * 0x40;
	port = sockets[socket].io_base;
	outb(reg, port);
	val = inb(port+1);
	val &= ~mask;
	outb(reg, port);
	outb(val, port+1);
	spin_unlock_irqrestore(&port_lock, flags);
}

static void indirect_write16(int socket,
			     unsigned short reg, unsigned short value)
{
	unsigned short int port;
	unsigned char val;
	unsigned long flags;

	spin_lock_irqsave(&port_lock, flags);
	reg = reg + socket * 0x40;
	port = sockets[socket].io_base;

	outb(reg, port);
	val = value & 255;
	outb(val, port+1);

	reg++;

	outb(reg, port);
	val = value>>8;
	outb(val, port+1);
	spin_unlock_irqrestore(&port_lock, flags);
}

/* simple helper functions */
/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
static int cycle_time = 120;

static int to_cycles(int ns)
{
	if (cycle_time != 0)
		return ns/cycle_time;
	else
		return 0;
}


/* Interrupt handler functionality */

static irqreturn_t i82092aa_interrupt(int irq, void *dev)
{
	int i;
	int loopcount = 0;
	int handled = 0;

	unsigned int events, active = 0;

	while (1) {
		loopcount++;
		if (loopcount > 20) {
			pr_err("i82092aa: infinite eventloop in interrupt\n");
			break;
		}

		active = 0;

		for (i = 0; i < socket_count; i++) {
			int csc;

			/* Inactive socket, should not happen */
			if (sockets[i].card_state == 0)
				continue;

			/* card status change register */
			csc = indirect_read(i, I365_CSC);

			if (csc == 0)  /* no events on this socket */
				continue;
			handled = 1;
			events = 0;

			if (csc & I365_CSC_DETECT) {
				events |= SS_DETECT;
				dev_info(&sockets[i].dev->dev,
					 "Card detected in socket %i!\n", i);
			}

			if (indirect_read(i, I365_INTCTL) & I365_PC_IOCARD) {
				/* For IO/CARDS, bit 0 means "read the card" */
				if (csc & I365_CSC_STSCHG)
					events |= SS_STSCHG;
			} else {
				/* Check for battery/ready events */
				if (csc & I365_CSC_BVD1)
					events |= SS_BATDEAD;
				if (csc & I365_CSC_BVD2)
					events |= SS_BATWARN;
				if (csc & I365_CSC_READY)
					events |= SS_READY;
			}

			if (events)
				pcmcia_parse_events(&sockets[i].socket, events);
			active |= events;
		}

		if (active == 0) /* no more events to handle */
			break;
	}
	return IRQ_RETVAL(handled);
}



/* socket functions */

static int card_present(int socketno)
{
	unsigned int val;

	if ((socketno < 0) || (socketno >= MAX_SOCKETS))
		return 0;
	if (sockets[socketno].io_base == 0)
		return 0;


	val = indirect_read(socketno, 1); /* Interface status register */
	if ((val&12) == 12)
		return 1;

	return 0;
}

static void set_bridge_state(int sock)
{
	indirect_write(sock, I365_GBLCTL, 0x00);
	indirect_write(sock, I365_GENCTL, 0x00);

	indirect_setbit(sock, I365_INTCTL, 0x08);
}


static int i82092aa_init(struct pcmcia_socket *sock)
{
	int i;
	struct resource res = { .start = 0, .end = 0x0fff };
	pccard_io_map io = { 0, 0, 0, 0, 1 };
	pccard_mem_map mem = { .res = &res, };

	for (i = 0; i < 2; i++) {
		io.map = i;
		i82092aa_set_io_map(sock, &io);
	}
	for (i = 0; i < 5; i++) {
		mem.map = i;
		i82092aa_set_mem_map(sock, &mem);
	}

	return 0;
}

static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
{
	unsigned int sock = container_of(socket,
				struct socket_info, socket)->number;
	unsigned int status;

	/* Interface Status Register */
	status = indirect_read(sock, I365_STATUS);

	*value = 0;

	if ((status & I365_CS_DETECT) == I365_CS_DETECT)
		*value |= SS_DETECT;

	/* IO cards have a different meaning of bits 0,1 */
	/* Also notice the inverse-logic on the bits */
	if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
		/* IO card */
		if (!(status & I365_CS_STSCHG))
			*value |= SS_STSCHG;
	} else { /* non I/O card */
		if (!(status & I365_CS_BVD1))
			*value |= SS_BATDEAD;
		if (!(status & I365_CS_BVD2))
			*value |= SS_BATWARN;
	}

	if (status & I365_CS_WRPROT)
		(*value) |= SS_WRPROT;	/* card is write protected */

	if (status & I365_CS_READY)
		(*value) |= SS_READY;    /* card is not busy */

	if (status & I365_CS_POWERON)
		(*value) |= SS_POWERON;  /* power is applied to the card */

	return 0;
}


static int i82092aa_set_socket(struct pcmcia_socket *socket,
			       socket_state_t *state)
{
	struct socket_info *sock_info = container_of(socket, struct socket_info,
						     socket);
	unsigned int sock = sock_info->number;
	unsigned char reg;

	/* First, set the global controller options */

	set_bridge_state(sock);

	/* Values for the IGENC register */

	reg = 0;

	/* The reset bit has "inverse" logic */
	if (!(state->flags & SS_RESET))
		reg = reg | I365_PC_RESET;
	if (state->flags & SS_IOCARD)
		reg = reg | I365_PC_IOCARD;

	/* IGENC, Interrupt and General Control Register */
	indirect_write(sock, I365_INTCTL, reg);

	/* Power registers */

	reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */

	if (state->flags & SS_PWR_AUTO) {
		dev_info(&sock_info->dev->dev, "Auto power\n");
		reg |= I365_PWR_AUTO;	/* automatic power mngmnt */
	}
	if (state->flags & SS_OUTPUT_ENA) {
		dev_info(&sock_info->dev->dev, "Power Enabled\n");
		reg |= I365_PWR_OUT;	/* enable power */
	}

	switch (state->Vcc) {
	case 0:
		break;
	case 50:
		dev_info(&sock_info->dev->dev,
			 "setting voltage to Vcc to 5V on socket %i\n",
			 sock);
		reg |= I365_VCC_5V;
		break;
	default:
		dev_err(&sock_info->dev->dev,
			"%s called with invalid VCC power value: %i",
			__func__, state->Vcc);
		return -EINVAL;
	}

	switch (state->Vpp) {
	case 0:
		dev_info(&sock_info->dev->dev,
			 "not setting Vpp on socket %i\n", sock);
		break;
	case 50:
		dev_info(&sock_info->dev->dev,
			 "setting Vpp to 5.0 for socket %i\n", sock);
		reg |= I365_VPP1_5V | I365_VPP2_5V;
		break;
	case 120:
		dev_info(&sock_info->dev->dev, "setting Vpp to 12.0\n");
		reg |= I365_VPP1_12V | I365_VPP2_12V;
		break;
	default:
		dev_err(&sock_info->dev->dev,
			"%s called with invalid VPP power value: %i",
			__func__, state->Vcc);
		return -EINVAL;
	}

	if (reg != indirect_read(sock, I365_POWER)) /* only write if changed */
		indirect_write(sock, I365_POWER, reg);

	/* Enable specific interrupt events */

	reg = 0x00;
	if (state->csc_mask & SS_DETECT)
		reg |= I365_CSC_DETECT;
	if (state->flags & SS_IOCARD) {
		if (state->csc_mask & SS_STSCHG)
			reg |= I365_CSC_STSCHG;
	} else {
		if (state->csc_mask & SS_BATDEAD)
			reg |= I365_CSC_BVD1;
		if (state->csc_mask & SS_BATWARN)
			reg |= I365_CSC_BVD2;
		if (state->csc_mask & SS_READY)
			reg |= I365_CSC_READY;

	}

	/* now write the value and clear the (probably bogus) pending stuff
	 * by doing a dummy read
	 */

	indirect_write(sock, I365_CSCINT, reg);
	(void)indirect_read(sock, I365_CSC);

	return 0;
}

static int i82092aa_set_io_map(struct pcmcia_socket *socket,
			       struct pccard_io_map *io)
{
	struct socket_info *sock_info = container_of(socket, struct socket_info,
						     socket);
	unsigned int sock = sock_info->number;
	unsigned char map, ioctl;

	map = io->map;

	/* Check error conditions */
	if (map > 1)
		return -EINVAL;

	if ((io->start > 0xffff) || (io->stop > 0xffff)
				 || (io->stop < io->start))
		return -EINVAL;

	/* Turn off the window before changing anything */
	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
		indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));

	/* write the new values */
	indirect_write16(sock, I365_IO(map)+I365_W_START, io->start);
	indirect_write16(sock, I365_IO(map)+I365_W_STOP, io->stop);

	ioctl = indirect_read(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);

	if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
		ioctl |= I365_IOCTL_16BIT(map);

	indirect_write(sock, I365_IOCTL, ioctl);

	/* Turn the window back on if needed */
	if (io->flags & MAP_ACTIVE)
		indirect_setbit(sock, I365_ADDRWIN, I365_ENA_IO(map));

	return 0;
}

static int i82092aa_set_mem_map(struct pcmcia_socket *socket,
				struct pccard_mem_map *mem)
{
	struct socket_info *sock_info = container_of(socket, struct socket_info,
						     socket);
	unsigned int sock = sock_info->number;
	struct pci_bus_region region;
	unsigned short base, i;
	unsigned char map;

	pcibios_resource_to_bus(sock_info->dev->bus, &region, mem->res);

	map = mem->map;
	if (map > 4)
		return -EINVAL;

	if ((mem->card_start > 0x3ffffff) || (region.start > region.end) ||
	     (mem->speed > 1000)) {
		dev_err(&sock_info->dev->dev,
			"invalid mem map for socket %i: %llx to %llx with a start of %x\n",
			sock,
			(unsigned long long)region.start,
			(unsigned long long)region.end,
			mem->card_start);
		return -EINVAL;
	}

	/* Turn off the window before changing anything */
	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
		indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));

	/* write the start address */
	base = I365_MEM(map);
	i = (region.start >> 12) & 0x0fff;
	if (mem->flags & MAP_16BIT)
		i |= I365_MEM_16BIT;
	if (mem->flags & MAP_0WS)
		i |= I365_MEM_0WS;
	indirect_write16(sock, base+I365_W_START, i);

	/* write the stop address */

	i = (region.end >> 12) & 0x0fff;
	switch (to_cycles(mem->speed)) {
	case 0:
		break;
	case 1:
		i |= I365_MEM_WS0;
		break;
	case 2:
		i |= I365_MEM_WS1;
		break;
	default:
		i |= I365_MEM_WS1 | I365_MEM_WS0;
		break;
	}

	indirect_write16(sock, base+I365_W_STOP, i);

	/* card start */

	i = ((mem->card_start - region.start) >> 12) & 0x3fff;
	if (mem->flags & MAP_WRPROT)
		i |= I365_MEM_WRPROT;
	if (mem->flags & MAP_ATTRIB)
		i |= I365_MEM_REG;
	indirect_write16(sock, base+I365_W_OFF, i);

	/* Enable the window if necessary */
	if (mem->flags & MAP_ACTIVE)
		indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));

	return 0;
}

static int __init i82092aa_module_init(void)
{
	return pci_register_driver(&i82092aa_pci_driver);
}

static void __exit i82092aa_module_exit(void)
{
	pci_unregister_driver(&i82092aa_pci_driver);
	if (sockets[0].io_base > 0)
		release_region(sockets[0].io_base, 2);
}

module_init(i82092aa_module_init);
module_exit(i82092aa_module_exit);

