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

macio-adb.c (6740B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for the ADB controller in the Mac I/O (Hydra) chip.
      4 */
      5#include <linux/types.h>
      6#include <linux/errno.h>
      7#include <linux/kernel.h>
      8#include <linux/delay.h>
      9#include <linux/spinlock.h>
     10#include <linux/interrupt.h>
     11#include <linux/pgtable.h>
     12#include <linux/of.h>
     13#include <linux/of_address.h>
     14#include <linux/of_irq.h>
     15#include <linux/adb.h>
     16
     17#include <asm/io.h>
     18#include <asm/hydra.h>
     19#include <asm/irq.h>
     20#include <linux/init.h>
     21#include <linux/ioport.h>
     22
     23struct preg {
     24	unsigned char r;
     25	char pad[15];
     26};
     27
     28struct adb_regs {
     29	struct preg intr;
     30	struct preg data[9];
     31	struct preg intr_enb;
     32	struct preg dcount;
     33	struct preg error;
     34	struct preg ctrl;
     35	struct preg autopoll;
     36	struct preg active_hi;
     37	struct preg active_lo;
     38	struct preg test;
     39};
     40
     41/* Bits in intr and intr_enb registers */
     42#define DFB	1		/* data from bus */
     43#define TAG	2		/* transfer access grant */
     44
     45/* Bits in dcount register */
     46#define HMB	0x0f		/* how many bytes */
     47#define APD	0x10		/* auto-poll data */
     48
     49/* Bits in error register */
     50#define NRE	1		/* no response error */
     51#define DLE	2		/* data lost error */
     52
     53/* Bits in ctrl register */
     54#define TAR	1		/* transfer access request */
     55#define DTB	2		/* data to bus */
     56#define CRE	4		/* command response expected */
     57#define ADB_RST	8		/* ADB reset */
     58
     59/* Bits in autopoll register */
     60#define APE	1		/* autopoll enable */
     61
     62static volatile struct adb_regs __iomem *adb;
     63static struct adb_request *current_req, *last_req;
     64static DEFINE_SPINLOCK(macio_lock);
     65
     66static int macio_probe(void);
     67static int macio_init(void);
     68static irqreturn_t macio_adb_interrupt(int irq, void *arg);
     69static int macio_send_request(struct adb_request *req, int sync);
     70static int macio_adb_autopoll(int devs);
     71static void macio_adb_poll(void);
     72static int macio_adb_reset_bus(void);
     73
     74struct adb_driver macio_adb_driver = {
     75	.name         = "MACIO",
     76	.probe        = macio_probe,
     77	.init         = macio_init,
     78	.send_request = macio_send_request,
     79	.autopoll     = macio_adb_autopoll,
     80	.poll         = macio_adb_poll,
     81	.reset_bus    = macio_adb_reset_bus,
     82};
     83
     84int macio_probe(void)
     85{
     86	struct device_node *np;
     87
     88	np = of_find_compatible_node(NULL, "adb", "chrp,adb0");
     89	if (np) {
     90		of_node_put(np);
     91		return 0;
     92	}
     93	return -ENODEV;
     94}
     95
     96int macio_init(void)
     97{
     98	struct device_node *adbs;
     99	struct resource r;
    100	unsigned int irq;
    101
    102	adbs = of_find_compatible_node(NULL, "adb", "chrp,adb0");
    103	if (adbs == 0)
    104		return -ENXIO;
    105
    106	if (of_address_to_resource(adbs, 0, &r)) {
    107		of_node_put(adbs);
    108		return -ENXIO;
    109	}
    110	adb = ioremap(r.start, sizeof(struct adb_regs));
    111
    112	out_8(&adb->ctrl.r, 0);
    113	out_8(&adb->intr.r, 0);
    114	out_8(&adb->error.r, 0);
    115	out_8(&adb->active_hi.r, 0xff); /* for now, set all devices active */
    116	out_8(&adb->active_lo.r, 0xff);
    117	out_8(&adb->autopoll.r, APE);
    118
    119	irq = irq_of_parse_and_map(adbs, 0);
    120	of_node_put(adbs);
    121	if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) {
    122		printk(KERN_ERR "ADB: can't get irq %d\n", irq);
    123		return -EAGAIN;
    124	}
    125	out_8(&adb->intr_enb.r, DFB | TAG);
    126
    127	printk("adb: mac-io driver 1.0 for unified ADB\n");
    128
    129	return 0;
    130}
    131
    132static int macio_adb_autopoll(int devs)
    133{
    134	unsigned long flags;
    135	
    136	spin_lock_irqsave(&macio_lock, flags);
    137	out_8(&adb->active_hi.r, devs >> 8);
    138	out_8(&adb->active_lo.r, devs);
    139	out_8(&adb->autopoll.r, devs? APE: 0);
    140	spin_unlock_irqrestore(&macio_lock, flags);
    141	return 0;
    142}
    143
    144static int macio_adb_reset_bus(void)
    145{
    146	unsigned long flags;
    147	int timeout = 1000000;
    148
    149	/* Hrm... we may want to not lock interrupts for so
    150	 * long ... oh well, who uses that chip anyway ? :)
    151	 * That function will be seldom used during boot
    152	 * on rare machines, so...
    153	 */
    154	spin_lock_irqsave(&macio_lock, flags);
    155	out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | ADB_RST);
    156	while ((in_8(&adb->ctrl.r) & ADB_RST) != 0) {
    157		if (--timeout == 0) {
    158			out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) & ~ADB_RST);
    159			spin_unlock_irqrestore(&macio_lock, flags);
    160			return -1;
    161		}
    162	}
    163	spin_unlock_irqrestore(&macio_lock, flags);
    164	return 0;
    165}
    166
    167/* Send an ADB command */
    168static int macio_send_request(struct adb_request *req, int sync)
    169{
    170	unsigned long flags;
    171	int i;
    172	
    173	if (req->data[0] != ADB_PACKET)
    174		return -EINVAL;
    175	
    176	for (i = 0; i < req->nbytes - 1; ++i)
    177		req->data[i] = req->data[i+1];
    178	--req->nbytes;
    179	
    180	req->next = NULL;
    181	req->sent = 0;
    182	req->complete = 0;
    183	req->reply_len = 0;
    184
    185	spin_lock_irqsave(&macio_lock, flags);
    186	if (current_req != 0) {
    187		last_req->next = req;
    188		last_req = req;
    189	} else {
    190		current_req = last_req = req;
    191		out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
    192	}
    193	spin_unlock_irqrestore(&macio_lock, flags);
    194	
    195	if (sync) {
    196		while (!req->complete)
    197			macio_adb_poll();
    198	}
    199
    200	return 0;
    201}
    202
    203static irqreturn_t macio_adb_interrupt(int irq, void *arg)
    204{
    205	int i, n, err;
    206	struct adb_request *req = NULL;
    207	unsigned char ibuf[16];
    208	int ibuf_len = 0;
    209	int complete = 0;
    210	int autopoll = 0;
    211	int handled = 0;
    212
    213	spin_lock(&macio_lock);
    214	if (in_8(&adb->intr.r) & TAG) {
    215		handled = 1;
    216		if ((req = current_req) != 0) {
    217			/* put the current request in */
    218			for (i = 0; i < req->nbytes; ++i)
    219				out_8(&adb->data[i].r, req->data[i]);
    220			out_8(&adb->dcount.r, req->nbytes & HMB);
    221			req->sent = 1;
    222			if (req->reply_expected) {
    223				out_8(&adb->ctrl.r, DTB + CRE);
    224			} else {
    225				out_8(&adb->ctrl.r, DTB);
    226				current_req = req->next;
    227				complete = 1;
    228				if (current_req)
    229					out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
    230			}
    231		}
    232		out_8(&adb->intr.r, 0);
    233	}
    234
    235	if (in_8(&adb->intr.r) & DFB) {
    236		handled = 1;
    237		err = in_8(&adb->error.r);
    238		if (current_req && current_req->sent) {
    239			/* this is the response to a command */
    240			req = current_req;
    241			if (err == 0) {
    242				req->reply_len = in_8(&adb->dcount.r) & HMB;
    243				for (i = 0; i < req->reply_len; ++i)
    244					req->reply[i] = in_8(&adb->data[i].r);
    245			}
    246			current_req = req->next;
    247			complete = 1;
    248			if (current_req)
    249				out_8(&adb->ctrl.r, in_8(&adb->ctrl.r) | TAR);
    250		} else if (err == 0) {
    251			/* autopoll data */
    252			n = in_8(&adb->dcount.r) & HMB;
    253			for (i = 0; i < n; ++i)
    254				ibuf[i] = in_8(&adb->data[i].r);
    255			ibuf_len = n;
    256			autopoll = (in_8(&adb->dcount.r) & APD) != 0;
    257		}
    258		out_8(&adb->error.r, 0);
    259		out_8(&adb->intr.r, 0);
    260	}
    261	spin_unlock(&macio_lock);
    262	if (complete && req) {
    263	    void (*done)(struct adb_request *) = req->done;
    264	    mb();
    265	    req->complete = 1;
    266	    /* Here, we assume that if the request has a done member, the
    267    	     * struct request will survive to setting req->complete to 1
    268	     */
    269	    if (done)
    270		(*done)(req);
    271	}
    272	if (ibuf_len)
    273		adb_input(ibuf, ibuf_len, autopoll);
    274
    275	return IRQ_RETVAL(handled);
    276}
    277
    278static void macio_adb_poll(void)
    279{
    280	unsigned long flags;
    281
    282	local_irq_save(flags);
    283	if (in_8(&adb->intr.r) != 0)
    284		macio_adb_interrupt(0, NULL);
    285	local_irq_restore(flags);
    286}