cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i82092.c (15551B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for Intel I82092AA PCI-PCMCIA bridge.
      4 *
      5 * (C) 2001 Red Hat, Inc.
      6 *
      7 * Author: Arjan Van De Ven <arjanv@redhat.com>
      8 * Loosly based on i82365.c from the pcmcia-cs package
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/pci.h>
     14#include <linux/init.h>
     15#include <linux/workqueue.h>
     16#include <linux/interrupt.h>
     17#include <linux/device.h>
     18
     19#include <pcmcia/ss.h>
     20
     21#include <linux/io.h>
     22
     23#include "i82092aa.h"
     24#include "i82365.h"
     25
     26MODULE_LICENSE("GPL");
     27
     28/* PCI core routines */
     29static const struct pci_device_id i82092aa_pci_ids[] = {
     30	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
     31	{ }
     32};
     33MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
     34
     35static struct pci_driver i82092aa_pci_driver = {
     36	.name		= "i82092aa",
     37	.id_table	= i82092aa_pci_ids,
     38	.probe		= i82092aa_pci_probe,
     39	.remove	= i82092aa_pci_remove,
     40};
     41
     42
     43/* the pccard structure and its functions */
     44static struct pccard_operations i82092aa_operations = {
     45	.init			= i82092aa_init,
     46	.get_status		= i82092aa_get_status,
     47	.set_socket		= i82092aa_set_socket,
     48	.set_io_map		= i82092aa_set_io_map,
     49	.set_mem_map		= i82092aa_set_mem_map,
     50};
     51
     52/* The card can do up to 4 sockets, allocate a structure for each of them */
     53
     54struct socket_info {
     55	int	number;
     56	int	card_state;
     57		/* 0 = no socket,
     58		 * 1 = empty socket,
     59		 * 2 = card but not initialized,
     60		 * 3 = operational card
     61		 */
     62	unsigned int io_base;	/* base io address of the socket */
     63
     64	struct pcmcia_socket socket;
     65	struct pci_dev *dev;	/* The PCI device for the socket */
     66};
     67
     68#define MAX_SOCKETS 4
     69static struct socket_info sockets[MAX_SOCKETS];
     70static int socket_count;	/* shortcut */
     71
     72
     73static int i82092aa_pci_probe(struct pci_dev *dev,
     74			      const struct pci_device_id *id)
     75{
     76	unsigned char configbyte;
     77	int i, ret;
     78
     79	ret = pci_enable_device(dev);
     80	if (ret)
     81		return ret;
     82
     83	/* PCI Configuration Control */
     84	pci_read_config_byte(dev, 0x40, &configbyte);
     85
     86	switch (configbyte&6) {
     87	case 0:
     88		socket_count = 2;
     89		break;
     90	case 2:
     91		socket_count = 1;
     92		break;
     93	case 4:
     94	case 6:
     95		socket_count = 4;
     96		break;
     97
     98	default:
     99		dev_err(&dev->dev,
    100			"Oops, you did something we didn't think of.\n");
    101		ret = -EIO;
    102		goto err_out_disable;
    103	}
    104	dev_info(&dev->dev, "configured as a %d socket device.\n",
    105		 socket_count);
    106
    107	if (!request_region(pci_resource_start(dev, 0), 2, "i82092aa")) {
    108		ret = -EBUSY;
    109		goto err_out_disable;
    110	}
    111
    112	for (i = 0; i < socket_count; i++) {
    113		sockets[i].card_state = 1; /* 1 = present but empty */
    114		sockets[i].io_base = pci_resource_start(dev, 0);
    115		sockets[i].dev = dev;
    116		sockets[i].socket.features |= SS_CAP_PCCARD;
    117		sockets[i].socket.map_size = 0x1000;
    118		sockets[i].socket.irq_mask = 0;
    119		sockets[i].socket.pci_irq  = dev->irq;
    120		sockets[i].socket.cb_dev  = dev;
    121		sockets[i].socket.owner = THIS_MODULE;
    122
    123		sockets[i].number = i;
    124
    125		if (card_present(i)) {
    126			sockets[i].card_state = 3;
    127			dev_dbg(&dev->dev, "slot %i is occupied\n", i);
    128		} else {
    129			dev_dbg(&dev->dev, "slot %i is vacant\n", i);
    130		}
    131	}
    132
    133	/* Now, specifiy that all interrupts are to be done as PCI interrupts
    134	 * bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt
    135	 */
    136	configbyte = 0xFF;
    137
    138	/* PCI Interrupt Routing Register */
    139	pci_write_config_byte(dev, 0x50, configbyte);
    140
    141	/* Register the interrupt handler */
    142	dev_dbg(&dev->dev, "Requesting interrupt %i\n", dev->irq);
    143	ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED,
    144			  "i82092aa", i82092aa_interrupt);
    145	if (ret) {
    146		dev_err(&dev->dev, "Failed to register IRQ %d, aborting\n",
    147			dev->irq);
    148		goto err_out_free_res;
    149	}
    150
    151	for (i = 0; i < socket_count; i++) {
    152		sockets[i].socket.dev.parent = &dev->dev;
    153		sockets[i].socket.ops = &i82092aa_operations;
    154		sockets[i].socket.resource_ops = &pccard_nonstatic_ops;
    155		ret = pcmcia_register_socket(&sockets[i].socket);
    156		if (ret)
    157			goto err_out_free_sockets;
    158	}
    159
    160	return 0;
    161
    162err_out_free_sockets:
    163	if (i) {
    164		for (i--; i >= 0; i--)
    165			pcmcia_unregister_socket(&sockets[i].socket);
    166	}
    167	free_irq(dev->irq, i82092aa_interrupt);
    168err_out_free_res:
    169	release_region(pci_resource_start(dev, 0), 2);
    170err_out_disable:
    171	pci_disable_device(dev);
    172	return ret;
    173}
    174
    175static void i82092aa_pci_remove(struct pci_dev *dev)
    176{
    177	int i;
    178
    179	free_irq(dev->irq, i82092aa_interrupt);
    180
    181	for (i = 0; i < socket_count; i++)
    182		pcmcia_unregister_socket(&sockets[i].socket);
    183}
    184
    185static DEFINE_SPINLOCK(port_lock);
    186
    187/* basic value read/write functions */
    188
    189static unsigned char indirect_read(int socket, unsigned short reg)
    190{
    191	unsigned short int port;
    192	unsigned char val;
    193	unsigned long flags;
    194
    195	spin_lock_irqsave(&port_lock, flags);
    196	reg += socket * 0x40;
    197	port = sockets[socket].io_base;
    198	outb(reg, port);
    199	val = inb(port+1);
    200	spin_unlock_irqrestore(&port_lock, flags);
    201	return val;
    202}
    203
    204static void indirect_write(int socket, unsigned short reg, unsigned char value)
    205{
    206	unsigned short int port;
    207	unsigned long flags;
    208
    209	spin_lock_irqsave(&port_lock, flags);
    210	reg = reg + socket * 0x40;
    211	port = sockets[socket].io_base;
    212	outb(reg, port);
    213	outb(value, port+1);
    214	spin_unlock_irqrestore(&port_lock, flags);
    215}
    216
    217static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
    218{
    219	unsigned short int port;
    220	unsigned char val;
    221	unsigned long flags;
    222
    223	spin_lock_irqsave(&port_lock, flags);
    224	reg = reg + socket * 0x40;
    225	port = sockets[socket].io_base;
    226	outb(reg, port);
    227	val = inb(port+1);
    228	val |= mask;
    229	outb(reg, port);
    230	outb(val, port+1);
    231	spin_unlock_irqrestore(&port_lock, flags);
    232}
    233
    234
    235static void indirect_resetbit(int socket,
    236			      unsigned short reg, unsigned char mask)
    237{
    238	unsigned short int port;
    239	unsigned char val;
    240	unsigned long flags;
    241
    242	spin_lock_irqsave(&port_lock, flags);
    243	reg = reg + socket * 0x40;
    244	port = sockets[socket].io_base;
    245	outb(reg, port);
    246	val = inb(port+1);
    247	val &= ~mask;
    248	outb(reg, port);
    249	outb(val, port+1);
    250	spin_unlock_irqrestore(&port_lock, flags);
    251}
    252
    253static void indirect_write16(int socket,
    254			     unsigned short reg, unsigned short value)
    255{
    256	unsigned short int port;
    257	unsigned char val;
    258	unsigned long flags;
    259
    260	spin_lock_irqsave(&port_lock, flags);
    261	reg = reg + socket * 0x40;
    262	port = sockets[socket].io_base;
    263
    264	outb(reg, port);
    265	val = value & 255;
    266	outb(val, port+1);
    267
    268	reg++;
    269
    270	outb(reg, port);
    271	val = value>>8;
    272	outb(val, port+1);
    273	spin_unlock_irqrestore(&port_lock, flags);
    274}
    275
    276/* simple helper functions */
    277/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
    278static int cycle_time = 120;
    279
    280static int to_cycles(int ns)
    281{
    282	if (cycle_time != 0)
    283		return ns/cycle_time;
    284	else
    285		return 0;
    286}
    287
    288
    289/* Interrupt handler functionality */
    290
    291static irqreturn_t i82092aa_interrupt(int irq, void *dev)
    292{
    293	int i;
    294	int loopcount = 0;
    295	int handled = 0;
    296
    297	unsigned int events, active = 0;
    298
    299	while (1) {
    300		loopcount++;
    301		if (loopcount > 20) {
    302			pr_err("i82092aa: infinite eventloop in interrupt\n");
    303			break;
    304		}
    305
    306		active = 0;
    307
    308		for (i = 0; i < socket_count; i++) {
    309			int csc;
    310
    311			/* Inactive socket, should not happen */
    312			if (sockets[i].card_state == 0)
    313				continue;
    314
    315			/* card status change register */
    316			csc = indirect_read(i, I365_CSC);
    317
    318			if (csc == 0)  /* no events on this socket */
    319				continue;
    320			handled = 1;
    321			events = 0;
    322
    323			if (csc & I365_CSC_DETECT) {
    324				events |= SS_DETECT;
    325				dev_info(&sockets[i].dev->dev,
    326					 "Card detected in socket %i!\n", i);
    327			}
    328
    329			if (indirect_read(i, I365_INTCTL) & I365_PC_IOCARD) {
    330				/* For IO/CARDS, bit 0 means "read the card" */
    331				if (csc & I365_CSC_STSCHG)
    332					events |= SS_STSCHG;
    333			} else {
    334				/* Check for battery/ready events */
    335				if (csc & I365_CSC_BVD1)
    336					events |= SS_BATDEAD;
    337				if (csc & I365_CSC_BVD2)
    338					events |= SS_BATWARN;
    339				if (csc & I365_CSC_READY)
    340					events |= SS_READY;
    341			}
    342
    343			if (events)
    344				pcmcia_parse_events(&sockets[i].socket, events);
    345			active |= events;
    346		}
    347
    348		if (active == 0) /* no more events to handle */
    349			break;
    350	}
    351	return IRQ_RETVAL(handled);
    352}
    353
    354
    355
    356/* socket functions */
    357
    358static int card_present(int socketno)
    359{
    360	unsigned int val;
    361
    362	if ((socketno < 0) || (socketno >= MAX_SOCKETS))
    363		return 0;
    364	if (sockets[socketno].io_base == 0)
    365		return 0;
    366
    367
    368	val = indirect_read(socketno, 1); /* Interface status register */
    369	if ((val&12) == 12)
    370		return 1;
    371
    372	return 0;
    373}
    374
    375static void set_bridge_state(int sock)
    376{
    377	indirect_write(sock, I365_GBLCTL, 0x00);
    378	indirect_write(sock, I365_GENCTL, 0x00);
    379
    380	indirect_setbit(sock, I365_INTCTL, 0x08);
    381}
    382
    383
    384static int i82092aa_init(struct pcmcia_socket *sock)
    385{
    386	int i;
    387	struct resource res = { .start = 0, .end = 0x0fff };
    388	pccard_io_map io = { 0, 0, 0, 0, 1 };
    389	pccard_mem_map mem = { .res = &res, };
    390
    391	for (i = 0; i < 2; i++) {
    392		io.map = i;
    393		i82092aa_set_io_map(sock, &io);
    394	}
    395	for (i = 0; i < 5; i++) {
    396		mem.map = i;
    397		i82092aa_set_mem_map(sock, &mem);
    398	}
    399
    400	return 0;
    401}
    402
    403static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
    404{
    405	unsigned int sock = container_of(socket,
    406				struct socket_info, socket)->number;
    407	unsigned int status;
    408
    409	/* Interface Status Register */
    410	status = indirect_read(sock, I365_STATUS);
    411
    412	*value = 0;
    413
    414	if ((status & I365_CS_DETECT) == I365_CS_DETECT)
    415		*value |= SS_DETECT;
    416
    417	/* IO cards have a different meaning of bits 0,1 */
    418	/* Also notice the inverse-logic on the bits */
    419	if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
    420		/* IO card */
    421		if (!(status & I365_CS_STSCHG))
    422			*value |= SS_STSCHG;
    423	} else { /* non I/O card */
    424		if (!(status & I365_CS_BVD1))
    425			*value |= SS_BATDEAD;
    426		if (!(status & I365_CS_BVD2))
    427			*value |= SS_BATWARN;
    428	}
    429
    430	if (status & I365_CS_WRPROT)
    431		(*value) |= SS_WRPROT;	/* card is write protected */
    432
    433	if (status & I365_CS_READY)
    434		(*value) |= SS_READY;    /* card is not busy */
    435
    436	if (status & I365_CS_POWERON)
    437		(*value) |= SS_POWERON;  /* power is applied to the card */
    438
    439	return 0;
    440}
    441
    442
    443static int i82092aa_set_socket(struct pcmcia_socket *socket,
    444			       socket_state_t *state)
    445{
    446	struct socket_info *sock_info = container_of(socket, struct socket_info,
    447						     socket);
    448	unsigned int sock = sock_info->number;
    449	unsigned char reg;
    450
    451	/* First, set the global controller options */
    452
    453	set_bridge_state(sock);
    454
    455	/* Values for the IGENC register */
    456
    457	reg = 0;
    458
    459	/* The reset bit has "inverse" logic */
    460	if (!(state->flags & SS_RESET))
    461		reg = reg | I365_PC_RESET;
    462	if (state->flags & SS_IOCARD)
    463		reg = reg | I365_PC_IOCARD;
    464
    465	/* IGENC, Interrupt and General Control Register */
    466	indirect_write(sock, I365_INTCTL, reg);
    467
    468	/* Power registers */
    469
    470	reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
    471
    472	if (state->flags & SS_PWR_AUTO) {
    473		dev_info(&sock_info->dev->dev, "Auto power\n");
    474		reg |= I365_PWR_AUTO;	/* automatic power mngmnt */
    475	}
    476	if (state->flags & SS_OUTPUT_ENA) {
    477		dev_info(&sock_info->dev->dev, "Power Enabled\n");
    478		reg |= I365_PWR_OUT;	/* enable power */
    479	}
    480
    481	switch (state->Vcc) {
    482	case 0:
    483		break;
    484	case 50:
    485		dev_info(&sock_info->dev->dev,
    486			 "setting voltage to Vcc to 5V on socket %i\n",
    487			 sock);
    488		reg |= I365_VCC_5V;
    489		break;
    490	default:
    491		dev_err(&sock_info->dev->dev,
    492			"%s called with invalid VCC power value: %i",
    493			__func__, state->Vcc);
    494		return -EINVAL;
    495	}
    496
    497	switch (state->Vpp) {
    498	case 0:
    499		dev_info(&sock_info->dev->dev,
    500			 "not setting Vpp on socket %i\n", sock);
    501		break;
    502	case 50:
    503		dev_info(&sock_info->dev->dev,
    504			 "setting Vpp to 5.0 for socket %i\n", sock);
    505		reg |= I365_VPP1_5V | I365_VPP2_5V;
    506		break;
    507	case 120:
    508		dev_info(&sock_info->dev->dev, "setting Vpp to 12.0\n");
    509		reg |= I365_VPP1_12V | I365_VPP2_12V;
    510		break;
    511	default:
    512		dev_err(&sock_info->dev->dev,
    513			"%s called with invalid VPP power value: %i",
    514			__func__, state->Vcc);
    515		return -EINVAL;
    516	}
    517
    518	if (reg != indirect_read(sock, I365_POWER)) /* only write if changed */
    519		indirect_write(sock, I365_POWER, reg);
    520
    521	/* Enable specific interrupt events */
    522
    523	reg = 0x00;
    524	if (state->csc_mask & SS_DETECT)
    525		reg |= I365_CSC_DETECT;
    526	if (state->flags & SS_IOCARD) {
    527		if (state->csc_mask & SS_STSCHG)
    528			reg |= I365_CSC_STSCHG;
    529	} else {
    530		if (state->csc_mask & SS_BATDEAD)
    531			reg |= I365_CSC_BVD1;
    532		if (state->csc_mask & SS_BATWARN)
    533			reg |= I365_CSC_BVD2;
    534		if (state->csc_mask & SS_READY)
    535			reg |= I365_CSC_READY;
    536
    537	}
    538
    539	/* now write the value and clear the (probably bogus) pending stuff
    540	 * by doing a dummy read
    541	 */
    542
    543	indirect_write(sock, I365_CSCINT, reg);
    544	(void)indirect_read(sock, I365_CSC);
    545
    546	return 0;
    547}
    548
    549static int i82092aa_set_io_map(struct pcmcia_socket *socket,
    550			       struct pccard_io_map *io)
    551{
    552	struct socket_info *sock_info = container_of(socket, struct socket_info,
    553						     socket);
    554	unsigned int sock = sock_info->number;
    555	unsigned char map, ioctl;
    556
    557	map = io->map;
    558
    559	/* Check error conditions */
    560	if (map > 1)
    561		return -EINVAL;
    562
    563	if ((io->start > 0xffff) || (io->stop > 0xffff)
    564				 || (io->stop < io->start))
    565		return -EINVAL;
    566
    567	/* Turn off the window before changing anything */
    568	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
    569		indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
    570
    571	/* write the new values */
    572	indirect_write16(sock, I365_IO(map)+I365_W_START, io->start);
    573	indirect_write16(sock, I365_IO(map)+I365_W_STOP, io->stop);
    574
    575	ioctl = indirect_read(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
    576
    577	if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
    578		ioctl |= I365_IOCTL_16BIT(map);
    579
    580	indirect_write(sock, I365_IOCTL, ioctl);
    581
    582	/* Turn the window back on if needed */
    583	if (io->flags & MAP_ACTIVE)
    584		indirect_setbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
    585
    586	return 0;
    587}
    588
    589static int i82092aa_set_mem_map(struct pcmcia_socket *socket,
    590				struct pccard_mem_map *mem)
    591{
    592	struct socket_info *sock_info = container_of(socket, struct socket_info,
    593						     socket);
    594	unsigned int sock = sock_info->number;
    595	struct pci_bus_region region;
    596	unsigned short base, i;
    597	unsigned char map;
    598
    599	pcibios_resource_to_bus(sock_info->dev->bus, &region, mem->res);
    600
    601	map = mem->map;
    602	if (map > 4)
    603		return -EINVAL;
    604
    605	if ((mem->card_start > 0x3ffffff) || (region.start > region.end) ||
    606	     (mem->speed > 1000)) {
    607		dev_err(&sock_info->dev->dev,
    608			"invalid mem map for socket %i: %llx to %llx with a start of %x\n",
    609			sock,
    610			(unsigned long long)region.start,
    611			(unsigned long long)region.end,
    612			mem->card_start);
    613		return -EINVAL;
    614	}
    615
    616	/* Turn off the window before changing anything */
    617	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
    618		indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
    619
    620	/* write the start address */
    621	base = I365_MEM(map);
    622	i = (region.start >> 12) & 0x0fff;
    623	if (mem->flags & MAP_16BIT)
    624		i |= I365_MEM_16BIT;
    625	if (mem->flags & MAP_0WS)
    626		i |= I365_MEM_0WS;
    627	indirect_write16(sock, base+I365_W_START, i);
    628
    629	/* write the stop address */
    630
    631	i = (region.end >> 12) & 0x0fff;
    632	switch (to_cycles(mem->speed)) {
    633	case 0:
    634		break;
    635	case 1:
    636		i |= I365_MEM_WS0;
    637		break;
    638	case 2:
    639		i |= I365_MEM_WS1;
    640		break;
    641	default:
    642		i |= I365_MEM_WS1 | I365_MEM_WS0;
    643		break;
    644	}
    645
    646	indirect_write16(sock, base+I365_W_STOP, i);
    647
    648	/* card start */
    649
    650	i = ((mem->card_start - region.start) >> 12) & 0x3fff;
    651	if (mem->flags & MAP_WRPROT)
    652		i |= I365_MEM_WRPROT;
    653	if (mem->flags & MAP_ATTRIB)
    654		i |= I365_MEM_REG;
    655	indirect_write16(sock, base+I365_W_OFF, i);
    656
    657	/* Enable the window if necessary */
    658	if (mem->flags & MAP_ACTIVE)
    659		indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
    660
    661	return 0;
    662}
    663
    664static int i82092aa_module_init(void)
    665{
    666	return pci_register_driver(&i82092aa_pci_driver);
    667}
    668
    669static void i82092aa_module_exit(void)
    670{
    671	pci_unregister_driver(&i82092aa_pci_driver);
    672	if (sockets[0].io_base > 0)
    673		release_region(sockets[0].io_base, 2);
    674}
    675
    676module_init(i82092aa_module_init);
    677module_exit(i82092aa_module_exit);
    678