File Index
Files and directories
Sign in
FILE

hp_sdc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/input/serio/hp_sdc.c C
   1/*
   2 * HP i8042-based System Device Controller driver.
   3 *
   4 * Copyright (c) 2001 Brian S. Julin
   5 * All rights reserved.
   6 *
   7 * Redistribution and use in source and binary forms, with or without
   8 * modification, are permitted provided that the following conditions
   9 * are met:
  10 * 1. Redistributions of source code must retain the above copyright
  11 *    notice, this list of conditions, and the following disclaimer,
  12 *    without modification.
  13 * 2. The name of the author may not be used to endorse or promote products
  14 *    derived from this software without specific prior written permission.
  15 *
  16 * Alternatively, this software may be distributed under the terms of the
  17 * GNU General Public License ("GPL").
  18 *
  19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28 *
  29 * References:
  30 * System Device Controller Microprocessor Firmware Theory of Operation
  31 *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
  32 * Helge Deller's original hilkbd.c port for PA-RISC.
  33 *
  34 *
  35 * Driver theory of operation:
  36 *
  37 * hp_sdc_put does all writing to the SDC.  ISR can run on a different
  38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
  39 * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
  40 *
  41 * All data coming back from the SDC is sent via interrupt and can be read
  42 * fully in the ISR, so there are no latency/throughput problems there.
  43 * The problem is with output, due to the slow clock speed of the SDC
  44 * compared to the CPU.  This should not be too horrible most of the time,
  45 * but if used with HIL devices that support the multibyte transfer command,
  46 * keeping outbound throughput flowing at the 6500KBps that the HIL is
  47 * capable of is more than can be done at HZ=100.
  48 *
  49 * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf
  50 * is set to 0 when the IBF flag in the status register has cleared.  ISR
  51 * may do this, and may also access the parts of queued transactions related
  52 * to reading data back from the SDC, but otherwise will not touch the
  53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
  54 *
  55 * The i8042 write index and the values in the 4-byte input buffer
  56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
  57 * to minimize the amount of IO needed to the SDC.  However these values
  58 * do not need to be locked since they are only ever accessed by hp_sdc_put.
  59 *
  60 * A timer task schedules the tasklet once per second just to make
  61 * sure it doesn't freeze up and to allow for bad reads to time out.
  62 */
  63
  64#include <linux/hp_sdc.h>
  65#include <linux/errno.h>
  66#include <linux/export.h>
  67#include <linux/init.h>
  68#include <linux/module.h>
  69#include <linux/ioport.h>
  70#include <linux/time.h>
  71#include <linux/semaphore.h>
  72#include <linux/slab.h>
  73#include <linux/hil.h>
  74#include <asm/io.h>
  75
  76/* Machine-specific abstraction */
  77
  78#if defined(__hppa__)
  79# include <asm/parisc-device.h>
  80# define sdc_readb(p)		gsc_readb(p)
  81# define sdc_writeb(v,p)	gsc_writeb((v),(p))
  82#elif defined(__mc68000__)
  83#include <linux/uaccess.h>
  84# define sdc_readb(p)		in_8(p)
  85# define sdc_writeb(v,p)	out_8((p),(v))
  86#else
  87# error "HIL is not supported on this platform"
  88#endif
  89
  90#define PREFIX "HP SDC: "
  91
  92MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
  93MODULE_DESCRIPTION("HP i8042-based SDC Driver");
  94MODULE_LICENSE("Dual BSD/GPL");
  95
  96EXPORT_SYMBOL(hp_sdc_request_timer_irq);
  97EXPORT_SYMBOL(hp_sdc_request_hil_irq);
  98EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
  99
 100EXPORT_SYMBOL(hp_sdc_release_timer_irq);
 101EXPORT_SYMBOL(hp_sdc_release_hil_irq);
 102EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
 103
 104EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
 105EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 106EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 107
 108static bool hp_sdc_disabled;
 109module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
 110MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
 111
 112static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
 113
 114/*************** primitives for use in any context *********************/
 115static inline uint8_t hp_sdc_status_in8(void)
 116{
 117	uint8_t status;
 118	unsigned long flags;
 119
 120	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 121	status = sdc_readb(hp_sdc.status_io);
 122	if (!(status & HP_SDC_STATUS_IBF))
 123		hp_sdc.ibf = 0;
 124	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 125
 126	return status;
 127}
 128
 129static inline uint8_t hp_sdc_data_in8(void)
 130{
 131	return sdc_readb(hp_sdc.data_io);
 132}
 133
 134static inline void hp_sdc_status_out8(uint8_t val)
 135{
 136	unsigned long flags;
 137
 138	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 139	hp_sdc.ibf = 1;
 140	if ((val & 0xf0) == 0xe0)
 141		hp_sdc.wi = 0xff;
 142	sdc_writeb(val, hp_sdc.status_io);
 143	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 144}
 145
 146static inline void hp_sdc_data_out8(uint8_t val)
 147{
 148	unsigned long flags;
 149
 150	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
 151	hp_sdc.ibf = 1;
 152	sdc_writeb(val, hp_sdc.data_io);
 153	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 154}
 155
 156/*	Care must be taken to only invoke hp_sdc_spin_ibf when
 157 *	absolutely needed, or in rarely invoked subroutines.
 158 *	Not only does it waste CPU cycles, it also wastes bus cycles.
 159 */
 160static inline void hp_sdc_spin_ibf(void)
 161{
 162	unsigned long flags;
 163	rwlock_t *lock;
 164
 165	lock = &hp_sdc.ibf_lock;
 166
 167	read_lock_irqsave(lock, flags);
 168	if (!hp_sdc.ibf) {
 169		read_unlock_irqrestore(lock, flags);
 170		return;
 171	}
 172	read_unlock(lock);
 173	write_lock(lock);
 174	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
 175		{ }
 176	hp_sdc.ibf = 0;
 177	write_unlock_irqrestore(lock, flags);
 178}
 179
 180
 181/************************ Interrupt context functions ************************/
 182static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
 183{
 184	hp_sdc_transaction *curr;
 185
 186	read_lock(&hp_sdc.rtq_lock);
 187	if (hp_sdc.rcurr < 0) {
 188		read_unlock(&hp_sdc.rtq_lock);
 189		return;
 190	}
 191	curr = hp_sdc.tq[hp_sdc.rcurr];
 192	read_unlock(&hp_sdc.rtq_lock);
 193
 194	curr->seq[curr->idx++] = status;
 195	curr->seq[curr->idx++] = data;
 196	hp_sdc.rqty -= 2;
 197	hp_sdc.rtime = ktime_get();
 198
 199	if (hp_sdc.rqty <= 0) {
 200		/* All data has been gathered. */
 201		if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
 202			if (curr->act.semaphore)
 203				up(curr->act.semaphore);
 204
 205		if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
 206			if (curr->act.irqhook)
 207				curr->act.irqhook(irq, dev_id, status, data);
 208
 209		curr->actidx = curr->idx;
 210		curr->idx++;
 211		/* Return control of this transaction */
 212		write_lock(&hp_sdc.rtq_lock);
 213		hp_sdc.rcurr = -1;
 214		hp_sdc.rqty = 0;
 215		write_unlock(&hp_sdc.rtq_lock);
 216		tasklet_schedule(&hp_sdc.task);
 217	}
 218}
 219
 220static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
 221{
 222	uint8_t status, data;
 223
 224	status = hp_sdc_status_in8();
 225	/* Read data unconditionally to advance i8042. */
 226	data =   hp_sdc_data_in8();
 227
 228	/* For now we are ignoring these until we get the SDC to behave. */
 229	if (((status & 0xf1) == 0x51) && data == 0x82)
 230		return IRQ_HANDLED;
 231
 232	switch (status & HP_SDC_STATUS_IRQMASK) {
 233	case 0: /* This case is not documented. */
 234		break;
 235
 236	case HP_SDC_STATUS_USERTIMER:
 237	case HP_SDC_STATUS_PERIODIC:
 238	case HP_SDC_STATUS_TIMER:
 239		read_lock(&hp_sdc.hook_lock);
 240		if (hp_sdc.timer != NULL)
 241			hp_sdc.timer(irq, dev_id, status, data);
 242		read_unlock(&hp_sdc.hook_lock);
 243		break;
 244
 245	case HP_SDC_STATUS_REG:
 246		hp_sdc_take(irq, dev_id, status, data);
 247		break;
 248
 249	case HP_SDC_STATUS_HILCMD:
 250	case HP_SDC_STATUS_HILDATA:
 251		read_lock(&hp_sdc.hook_lock);
 252		if (hp_sdc.hil != NULL)
 253			hp_sdc.hil(irq, dev_id, status, data);
 254		read_unlock(&hp_sdc.hook_lock);
 255		break;
 256
 257	case HP_SDC_STATUS_PUP:
 258		read_lock(&hp_sdc.hook_lock);
 259		if (hp_sdc.pup != NULL)
 260			hp_sdc.pup(irq, dev_id, status, data);
 261		else
 262			printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
 263		read_unlock(&hp_sdc.hook_lock);
 264		break;
 265
 266	default:
 267		read_lock(&hp_sdc.hook_lock);
 268		if (hp_sdc.cooked != NULL)
 269			hp_sdc.cooked(irq, dev_id, status, data);
 270		read_unlock(&hp_sdc.hook_lock);
 271		break;
 272	}
 273
 274	return IRQ_HANDLED;
 275}
 276
 277
 278static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
 279{
 280	int status;
 281
 282	status = hp_sdc_status_in8();
 283	printk(KERN_WARNING PREFIX "NMI !\n");
 284
 285#if 0
 286	if (status & HP_SDC_NMISTATUS_FHS) {
 287		read_lock(&hp_sdc.hook_lock);
 288		if (hp_sdc.timer != NULL)
 289			hp_sdc.timer(irq, dev_id, status, 0);
 290		read_unlock(&hp_sdc.hook_lock);
 291	} else {
 292		/* TODO: pass this on to the HIL handler, or do SAK here? */
 293		printk(KERN_WARNING PREFIX "HIL NMI\n");
 294	}
 295#endif
 296
 297	return IRQ_HANDLED;
 298}
 299
 300
 301/***************** Kernel (tasklet) context functions ****************/
 302
 303unsigned long hp_sdc_put(void);
 304
 305static void hp_sdc_tasklet(unsigned long foo)
 306{
 307	write_lock_irq(&hp_sdc.rtq_lock);
 308
 309	if (hp_sdc.rcurr >= 0) {
 310		ktime_t now = ktime_get();
 311
 312		if (ktime_after(now, ktime_add_us(hp_sdc.rtime,
 313						  HP_SDC_MAX_REG_DELAY))) {
 314			hp_sdc_transaction *curr;
 315			uint8_t tmp;
 316
 317			curr = hp_sdc.tq[hp_sdc.rcurr];
 318			/* If this turns out to be a normal failure mode
 319			 * we'll need to figure out a way to communicate
 320			 * it back to the application. and be less verbose.
 321			 */
 322			printk(KERN_WARNING PREFIX "read timeout (%lldus)!\n",
 323			       ktime_us_delta(now, hp_sdc.rtime));
 324			curr->idx += hp_sdc.rqty;
 325			hp_sdc.rqty = 0;
 326			tmp = curr->seq[curr->actidx];
 327			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
 328			if (tmp & HP_SDC_ACT_SEMAPHORE)
 329				if (curr->act.semaphore)
 330					up(curr->act.semaphore);
 331
 332			if (tmp & HP_SDC_ACT_CALLBACK) {
 333				/* Note this means that irqhooks may be called
 334				 * in tasklet/bh context.
 335				 */
 336				if (curr->act.irqhook)
 337					curr->act.irqhook(0, NULL, 0, 0);
 338			}
 339
 340			curr->actidx = curr->idx;
 341			curr->idx++;
 342			hp_sdc.rcurr = -1;
 343		}
 344	}
 345	write_unlock_irq(&hp_sdc.rtq_lock);
 346	hp_sdc_put();
 347}
 348
 349unsigned long hp_sdc_put(void)
 350{
 351	hp_sdc_transaction *curr;
 352	uint8_t act;
 353	int idx, curridx;
 354
 355	int limit = 0;
 356
 357	write_lock(&hp_sdc.lock);
 358
 359	/* If i8042 buffers are full, we cannot do anything that
 360	   requires output, so we skip to the administrativa. */
 361	if (hp_sdc.ibf) {
 362		hp_sdc_status_in8();
 363		if (hp_sdc.ibf)
 364			goto finish;
 365	}
 366
 367 anew:
 368	/* See if we are in the middle of a sequence. */
 369	if (hp_sdc.wcurr < 0)
 370		hp_sdc.wcurr = 0;
 371	read_lock_irq(&hp_sdc.rtq_lock);
 372	if (hp_sdc.rcurr == hp_sdc.wcurr)
 373		hp_sdc.wcurr++;
 374	read_unlock_irq(&hp_sdc.rtq_lock);
 375	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
 376		hp_sdc.wcurr = 0;
 377	curridx = hp_sdc.wcurr;
 378
 379	if (hp_sdc.tq[curridx] != NULL)
 380		goto start;
 381
 382	while (++curridx != hp_sdc.wcurr) {
 383		if (curridx >= HP_SDC_QUEUE_LEN) {
 384			curridx = -1; /* Wrap to top */
 385			continue;
 386		}
 387		read_lock_irq(&hp_sdc.rtq_lock);
 388		if (hp_sdc.rcurr == curridx) {
 389			read_unlock_irq(&hp_sdc.rtq_lock);
 390			continue;
 391		}
 392		read_unlock_irq(&hp_sdc.rtq_lock);
 393		if (hp_sdc.tq[curridx] != NULL)
 394			break; /* Found one. */
 395	}
 396	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
 397		curridx = -1;
 398	}
 399	hp_sdc.wcurr = curridx;
 400
 401 start:
 402
 403	/* Check to see if the interrupt mask needs to be set. */
 404	if (hp_sdc.set_im) {
 405		hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
 406		hp_sdc.set_im = 0;
 407		goto finish;
 408	}
 409
 410	if (hp_sdc.wcurr == -1)
 411		goto done;
 412
 413	curr = hp_sdc.tq[curridx];
 414	idx = curr->actidx;
 415
 416	if (curr->actidx >= curr->endidx) {
 417		hp_sdc.tq[curridx] = NULL;
 418		/* Interleave outbound data between the transactions. */
 419		hp_sdc.wcurr++;
 420		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
 421			hp_sdc.wcurr = 0;
 422		goto finish;
 423	}
 424
 425	act = curr->seq[idx];
 426	idx++;
 427
 428	if (curr->idx >= curr->endidx) {
 429		if (act & HP_SDC_ACT_DEALLOC)
 430			kfree(curr);
 431		hp_sdc.tq[curridx] = NULL;
 432		/* Interleave outbound data between the transactions. */
 433		hp_sdc.wcurr++;
 434		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
 435			hp_sdc.wcurr = 0;
 436		goto finish;
 437	}
 438
 439	while (act & HP_SDC_ACT_PRECMD) {
 440		if (curr->idx != idx) {
 441			idx++;
 442			act &= ~HP_SDC_ACT_PRECMD;
 443			break;
 444		}
 445		hp_sdc_status_out8(curr->seq[idx]);
 446		curr->idx++;
 447		/* act finished? */
 448		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
 449			goto actdone;
 450		/* skip quantity field if data-out sequence follows. */
 451		if (act & HP_SDC_ACT_DATAOUT)
 452			curr->idx++;
 453		goto finish;
 454	}
 455	if (act & HP_SDC_ACT_DATAOUT) {
 456		int qty;
 457
 458		qty = curr->seq[idx];
 459		idx++;
 460		if (curr->idx - idx < qty) {
 461			hp_sdc_data_out8(curr->seq[curr->idx]);
 462			curr->idx++;
 463			/* act finished? */
 464			if (curr->idx - idx >= qty &&
 465			    (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
 466				goto actdone;
 467			goto finish;
 468		}
 469		idx += qty;
 470		act &= ~HP_SDC_ACT_DATAOUT;
 471	} else
 472	    while (act & HP_SDC_ACT_DATAREG) {
 473		int mask;
 474		uint8_t w7[4];
 475
 476		mask = curr->seq[idx];
 477		if (idx != curr->idx) {
 478			idx++;
 479			idx += !!(mask & 1);
 480			idx += !!(mask & 2);
 481			idx += !!(mask & 4);
 482			idx += !!(mask & 8);
 483			act &= ~HP_SDC_ACT_DATAREG;
 484			break;
 485		}
 486
 487		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
 488		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
 489		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
 490		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
 491
 492		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
 493		    w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
 494			int i = 0;
 495
 496			/* Need to point the write index register */
 497			while (i < 4 && w7[i] == hp_sdc.r7[i])
 498				i++;
 499
 500			if (i < 4) {
 501				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
 502				hp_sdc.wi = 0x70 + i;
 503				goto finish;
 504			}
 505
 506			idx++;
 507			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
 508				goto actdone;
 509
 510			curr->idx = idx;
 511			act &= ~HP_SDC_ACT_DATAREG;
 512			break;
 513		}
 514
 515		hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
 516		hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
 517		hp_sdc.wi++; /* write index register autoincrements */
 518		{
 519			int i = 0;
 520
 521			while ((i < 4) && w7[i] == hp_sdc.r7[i])
 522				i++;
 523			if (i >= 4) {
 524				curr->idx = idx + 1;
 525				if ((act & HP_SDC_ACT_DURING) ==
 526				    HP_SDC_ACT_DATAREG)
 527					goto actdone;
 528			}
 529		}
 530		goto finish;
 531	}
 532	/* We don't go any further in the command if there is a pending read,
 533	   because we don't want interleaved results. */
 534	read_lock_irq(&hp_sdc.rtq_lock);
 535	if (hp_sdc.rcurr >= 0) {
 536		read_unlock_irq(&hp_sdc.rtq_lock);
 537		goto finish;
 538	}
 539	read_unlock_irq(&hp_sdc.rtq_lock);
 540
 541
 542	if (act & HP_SDC_ACT_POSTCMD) {
 543		uint8_t postcmd;
 544
 545		/* curr->idx should == idx at this point. */
 546		postcmd = curr->seq[idx];
 547		curr->idx++;
 548		if (act & HP_SDC_ACT_DATAIN) {
 549
 550			/* Start a new read */
 551			hp_sdc.rqty = curr->seq[curr->idx];
 552			hp_sdc.rtime = ktime_get();
 553			curr->idx++;
 554			/* Still need to lock here in case of spurious irq. */
 555			write_lock_irq(&hp_sdc.rtq_lock);
 556			hp_sdc.rcurr = curridx;
 557			write_unlock_irq(&hp_sdc.rtq_lock);
 558			hp_sdc_status_out8(postcmd);
 559			goto finish;
 560		}
 561		hp_sdc_status_out8(postcmd);
 562		goto actdone;
 563	}
 564
 565 actdone:
 566	if (act & HP_SDC_ACT_SEMAPHORE)
 567		up(curr->act.semaphore);
 568	else if (act & HP_SDC_ACT_CALLBACK)
 569		curr->act.irqhook(0,NULL,0,0);
 570
 571	if (curr->idx >= curr->endidx) { /* This transaction is over. */
 572		if (act & HP_SDC_ACT_DEALLOC)
 573			kfree(curr);
 574		hp_sdc.tq[curridx] = NULL;
 575	} else {
 576		curr->actidx = idx + 1;
 577		curr->idx = idx + 2;
 578	}
 579	/* Interleave outbound data between the transactions. */
 580	hp_sdc.wcurr++;
 581	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
 582		hp_sdc.wcurr = 0;
 583
 584 finish:
 585	/* If by some quirk IBF has cleared and our ISR has run to
 586	   see that that has happened, do it all again. */
 587	if (!hp_sdc.ibf && limit++ < 20)
 588		goto anew;
 589
 590 done:
 591	if (hp_sdc.wcurr >= 0)
 592		tasklet_schedule(&hp_sdc.task);
 593	write_unlock(&hp_sdc.lock);
 594
 595	return 0;
 596}
 597
 598/******* Functions called in either user or kernel context ****/
 599int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
 600{
 601	int i;
 602
 603	if (this == NULL) {
 604		BUG();
 605		return -EINVAL;
 606	}
 607
 608	/* Can't have same transaction on queue twice */
 609	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
 610		if (hp_sdc.tq[i] == this)
 611			goto fail;
 612
 613	this->actidx = 0;
 614	this->idx = 1;
 615
 616	/* Search for empty slot */
 617	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
 618		if (hp_sdc.tq[i] == NULL) {
 619			hp_sdc.tq[i] = this;
 620			tasklet_schedule(&hp_sdc.task);
 621			return 0;
 622		}
 623
 624	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
 625	return -EBUSY;
 626
 627 fail:
 628	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
 629	return -EINVAL;
 630}
 631
 632int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
 633	unsigned long flags;
 634	int ret;
 635
 636	write_lock_irqsave(&hp_sdc.lock, flags);
 637	ret = __hp_sdc_enqueue_transaction(this);
 638	write_unlock_irqrestore(&hp_sdc.lock,flags);
 639
 640	return ret;
 641}
 642
 643int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
 644{
 645	unsigned long flags;
 646	int i;
 647
 648	write_lock_irqsave(&hp_sdc.lock, flags);
 649
 650	/* TODO: don't remove it if it's not done. */
 651
 652	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
 653		if (hp_sdc.tq[i] == this)
 654			hp_sdc.tq[i] = NULL;
 655
 656	write_unlock_irqrestore(&hp_sdc.lock, flags);
 657	return 0;
 658}
 659
 660
 661
 662/********************** User context functions **************************/
 663int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
 664{
 665	if (callback == NULL || hp_sdc.dev == NULL)
 666		return -EINVAL;
 667
 668	write_lock_irq(&hp_sdc.hook_lock);
 669	if (hp_sdc.timer != NULL) {
 670		write_unlock_irq(&hp_sdc.hook_lock);
 671		return -EBUSY;
 672	}
 673
 674	hp_sdc.timer = callback;
 675	/* Enable interrupts from the timers */
 676	hp_sdc.im &= ~HP_SDC_IM_FH;
 677        hp_sdc.im &= ~HP_SDC_IM_PT;
 678	hp_sdc.im &= ~HP_SDC_IM_TIMERS;
 679	hp_sdc.set_im = 1;
 680	write_unlock_irq(&hp_sdc.hook_lock);
 681
 682	tasklet_schedule(&hp_sdc.task);
 683
 684	return 0;
 685}
 686
 687int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
 688{
 689	if (callback == NULL || hp_sdc.dev == NULL)
 690		return -EINVAL;
 691
 692	write_lock_irq(&hp_sdc.hook_lock);
 693	if (hp_sdc.hil != NULL) {
 694		write_unlock_irq(&hp_sdc.hook_lock);
 695		return -EBUSY;
 696	}
 697
 698	hp_sdc.hil = callback;
 699	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
 700	hp_sdc.set_im = 1;
 701	write_unlock_irq(&hp_sdc.hook_lock);
 702
 703	tasklet_schedule(&hp_sdc.task);
 704
 705	return 0;
 706}
 707
 708int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
 709{
 710	if (callback == NULL || hp_sdc.dev == NULL)
 711		return -EINVAL;
 712
 713	write_lock_irq(&hp_sdc.hook_lock);
 714	if (hp_sdc.cooked != NULL) {
 715		write_unlock_irq(&hp_sdc.hook_lock);
 716		return -EBUSY;
 717	}
 718
 719	/* Enable interrupts from the HIL MLC */
 720	hp_sdc.cooked = callback;
 721	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
 722	hp_sdc.set_im = 1;
 723	write_unlock_irq(&hp_sdc.hook_lock);
 724
 725	tasklet_schedule(&hp_sdc.task);
 726
 727	return 0;
 728}
 729
 730int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
 731{
 732	write_lock_irq(&hp_sdc.hook_lock);
 733	if ((callback != hp_sdc.timer) ||
 734	    (hp_sdc.timer == NULL)) {
 735		write_unlock_irq(&hp_sdc.hook_lock);
 736		return -EINVAL;
 737	}
 738
 739	/* Disable interrupts from the timers */
 740	hp_sdc.timer = NULL;
 741	hp_sdc.im |= HP_SDC_IM_TIMERS;
 742	hp_sdc.im |= HP_SDC_IM_FH;
 743	hp_sdc.im |= HP_SDC_IM_PT;
 744	hp_sdc.set_im = 1;
 745	write_unlock_irq(&hp_sdc.hook_lock);
 746	tasklet_schedule(&hp_sdc.task);
 747
 748	return 0;
 749}
 750
 751int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
 752{
 753	write_lock_irq(&hp_sdc.hook_lock);
 754	if ((callback != hp_sdc.hil) ||
 755	    (hp_sdc.hil == NULL)) {
 756		write_unlock_irq(&hp_sdc.hook_lock);
 757		return -EINVAL;
 758	}
 759
 760	hp_sdc.hil = NULL;
 761	/* Disable interrupts from HIL only if there is no cooked driver. */
 762	if(hp_sdc.cooked == NULL) {
 763		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
 764		hp_sdc.set_im = 1;
 765	}
 766	write_unlock_irq(&hp_sdc.hook_lock);
 767	tasklet_schedule(&hp_sdc.task);
 768
 769	return 0;
 770}
 771
 772int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
 773{
 774	write_lock_irq(&hp_sdc.hook_lock);
 775	if ((callback != hp_sdc.cooked) ||
 776	    (hp_sdc.cooked == NULL)) {
 777		write_unlock_irq(&hp_sdc.hook_lock);
 778		return -EINVAL;
 779	}
 780
 781	hp_sdc.cooked = NULL;
 782	/* Disable interrupts from HIL only if there is no raw HIL driver. */
 783	if(hp_sdc.hil == NULL) {
 784		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
 785		hp_sdc.set_im = 1;
 786	}
 787	write_unlock_irq(&hp_sdc.hook_lock);
 788	tasklet_schedule(&hp_sdc.task);
 789
 790	return 0;
 791}
 792
 793/************************* Keepalive timer task *********************/
 794
 795static void hp_sdc_kicker(struct timer_list *unused)
 796{
 797	tasklet_schedule(&hp_sdc.task);
 798	/* Re-insert the periodic task. */
 799	mod_timer(&hp_sdc.kicker, jiffies + HZ);
 800}
 801
 802/************************** Module Initialization ***************************/
 803
 804#if defined(__hppa__)
 805
 806static const struct parisc_device_id hp_sdc_tbl[] __initconst = {
 807	{
 808		.hw_type =	HPHW_FIO,
 809		.hversion_rev =	HVERSION_REV_ANY_ID,
 810		.hversion =	HVERSION_ANY_ID,
 811		.sversion =	0x73,
 812	 },
 813	{ 0, }
 814};
 815
 816MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
 817
 818static int __init hp_sdc_init_hppa(struct parisc_device *d);
 819static struct delayed_work moduleloader_work;
 820
 821static struct parisc_driver hp_sdc_driver __refdata = {
 822	.name =		"hp_sdc",
 823	.id_table =	hp_sdc_tbl,
 824	.probe =	hp_sdc_init_hppa,
 825};
 826
 827#endif /* __hppa__ */
 828
 829static int __init hp_sdc_init(void)
 830{
 831	char *errstr;
 832	hp_sdc_transaction t_sync;
 833	uint8_t ts_sync[6];
 834	struct semaphore s_sync;
 835
 836	rwlock_init(&hp_sdc.lock);
 837	rwlock_init(&hp_sdc.ibf_lock);
 838	rwlock_init(&hp_sdc.rtq_lock);
 839	rwlock_init(&hp_sdc.hook_lock);
 840
 841	hp_sdc.timer		= NULL;
 842	hp_sdc.hil		= NULL;
 843	hp_sdc.pup		= NULL;
 844	hp_sdc.cooked		= NULL;
 845	hp_sdc.im		= HP_SDC_IM_MASK;  /* Mask maskable irqs */
 846	hp_sdc.set_im		= 1;
 847	hp_sdc.wi		= 0xff;
 848	hp_sdc.r7[0]		= 0xff;
 849	hp_sdc.r7[1]		= 0xff;
 850	hp_sdc.r7[2]		= 0xff;
 851	hp_sdc.r7[3]		= 0xff;
 852	hp_sdc.ibf		= 1;
 853
 854	memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
 855
 856	hp_sdc.wcurr		= -1;
 857        hp_sdc.rcurr		= -1;
 858	hp_sdc.rqty		= 0;
 859
 860	hp_sdc.dev_err = -ENODEV;
 861
 862	errstr = "IO not found for";
 863	if (!hp_sdc.base_io)
 864		goto err0;
 865
 866	errstr = "IRQ not found for";
 867	if (!hp_sdc.irq)
 868		goto err0;
 869
 870	hp_sdc.dev_err = -EBUSY;
 871
 872#if defined(__hppa__)
 873	errstr = "IO not available for";
 874        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
 875		goto err0;
 876#endif
 877
 878	errstr = "IRQ not available for";
 879	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED,
 880			"HP SDC", &hp_sdc))
 881		goto err1;
 882
 883	errstr = "NMI not available for";
 884	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
 885			"HP SDC NMI", &hp_sdc))
 886		goto err2;
 887
 888	pr_info(PREFIX "HP SDC at 0x%08lx, IRQ %d (NMI IRQ %d)\n",
 889	       hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 890
 891	hp_sdc_status_in8();
 892	hp_sdc_data_in8();
 893
 894	tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
 895
 896	/* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
 897	t_sync.actidx	= 0;
 898	t_sync.idx	= 1;
 899	t_sync.endidx	= 6;
 900	t_sync.seq	= ts_sync;
 901	ts_sync[0]	= HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
 902	ts_sync[1]	= 0x0f;
 903	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
 904	t_sync.act.semaphore = &s_sync;
 905	sema_init(&s_sync, 0);
 906	hp_sdc_enqueue_transaction(&t_sync);
 907	down(&s_sync); /* Wait for t_sync to complete */
 908
 909	/* Create the keepalive task */
 910	timer_setup(&hp_sdc.kicker, hp_sdc_kicker, 0);
 911	hp_sdc.kicker.expires = jiffies + HZ;
 912	add_timer(&hp_sdc.kicker);
 913
 914	hp_sdc.dev_err = 0;
 915	return 0;
 916 err2:
 917	free_irq(hp_sdc.irq, &hp_sdc);
 918 err1:
 919	release_region(hp_sdc.data_io, 2);
 920 err0:
 921	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
 922		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 923	hp_sdc.dev = NULL;
 924
 925	return hp_sdc.dev_err;
 926}
 927
 928#if defined(__hppa__)
 929
 930static void request_module_delayed(struct work_struct *work)
 931{
 932	request_module("hp_sdc_mlc");
 933}
 934
 935static int __init hp_sdc_init_hppa(struct parisc_device *d)
 936{
 937	int ret;
 938
 939	if (!d)
 940		return 1;
 941	if (hp_sdc.dev != NULL)
 942		return 1;	/* We only expect one SDC */
 943
 944	hp_sdc.dev		= d;
 945	hp_sdc.irq		= d->irq;
 946	hp_sdc.nmi		= d->aux_irq;
 947	hp_sdc.base_io		= d->hpa.start;
 948	hp_sdc.data_io		= d->hpa.start + 0x800;
 949	hp_sdc.status_io	= d->hpa.start + 0x801;
 950
 951	INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed);
 952
 953	ret = hp_sdc_init();
 954	/* after successful initialization give SDC some time to settle
 955	 * and then load the hp_sdc_mlc upper layer driver */
 956	if (!ret)
 957		schedule_delayed_work(&moduleloader_work,
 958			msecs_to_jiffies(2000));
 959
 960	return ret;
 961}
 962
 963#endif /* __hppa__ */
 964
 965static void hp_sdc_exit(void)
 966{
 967	/* do nothing if we don't have a SDC */
 968	if (!hp_sdc.dev)
 969		return;
 970
 971	write_lock_irq(&hp_sdc.lock);
 972
 973	/* Turn off all maskable "sub-function" irq's. */
 974	hp_sdc_spin_ibf();
 975	sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
 976
 977	/* Wait until we know this has been processed by the i8042 */
 978	hp_sdc_spin_ibf();
 979
 980	free_irq(hp_sdc.nmi, &hp_sdc);
 981	free_irq(hp_sdc.irq, &hp_sdc);
 982	write_unlock_irq(&hp_sdc.lock);
 983
 984	timer_delete_sync(&hp_sdc.kicker);
 985
 986	tasklet_kill(&hp_sdc.task);
 987
 988#if defined(__hppa__)
 989	cancel_delayed_work_sync(&moduleloader_work);
 990	if (unregister_parisc_driver(&hp_sdc_driver))
 991		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
 992#endif
 993}
 994
 995static int __init hp_sdc_register(void)
 996{
 997	hp_sdc_transaction tq_init;
 998	uint8_t tq_init_seq[5];
 999	struct semaphore tq_init_sem;
1000#if defined(__mc68000__)
1001	unsigned char i;
1002#endif
1003
1004	if (hp_sdc_disabled) {
1005		printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
1006		return -ENODEV;
1007	}
1008
1009	hp_sdc.dev = NULL;
1010	hp_sdc.dev_err = 0;
1011#if defined(__hppa__)
1012	if (register_parisc_driver(&hp_sdc_driver)) {
1013		printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
1014		return -ENODEV;
1015	}
1016#elif defined(__mc68000__)
1017	if (!MACH_IS_HP300)
1018	    return -ENODEV;
1019
1020	hp_sdc.irq	 = 1;
1021	hp_sdc.nmi	 = 7;
1022	hp_sdc.base_io	 = (unsigned long) 0xf0428000;
1023	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
1024	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
1025	if (!copy_from_kernel_nofault(&i, (unsigned char *)hp_sdc.data_io, 1))
1026		hp_sdc.dev = (void *)1;
1027	hp_sdc.dev_err   = hp_sdc_init();
1028#endif
1029	if (hp_sdc.dev == NULL) {
1030		printk(KERN_WARNING PREFIX "No SDC found.\n");
1031		return hp_sdc.dev_err;
1032	}
1033
1034	sema_init(&tq_init_sem, 0);
1035
1036	tq_init.actidx		= 0;
1037	tq_init.idx		= 1;
1038	tq_init.endidx		= 5;
1039	tq_init.seq		= tq_init_seq;
1040	tq_init.act.semaphore	= &tq_init_sem;
1041
1042	tq_init_seq[0] =
1043		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
1044	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
1045	tq_init_seq[2] = 1;
1046	tq_init_seq[3] = 0;
1047	tq_init_seq[4] = 0;
1048
1049	hp_sdc_enqueue_transaction(&tq_init);
1050
1051	down(&tq_init_sem);
1052	up(&tq_init_sem);
1053
1054	if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
1055		printk(KERN_WARNING PREFIX "Error reading config byte.\n");
1056		hp_sdc_exit();
1057		return -ENODEV;
1058	}
1059	hp_sdc.r11 = tq_init_seq[4];
1060	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
1061		const char *str;
1062		printk(KERN_INFO PREFIX "New style SDC\n");
1063		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
1064		tq_init.actidx		= 0;
1065		tq_init.idx		= 1;
1066		down(&tq_init_sem);
1067		hp_sdc_enqueue_transaction(&tq_init);
1068		down(&tq_init_sem);
1069		up(&tq_init_sem);
1070		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
1071			printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
1072			return -ENODEV;
1073		}
1074		hp_sdc.r7e = tq_init_seq[4];
1075		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
1076		printk(KERN_INFO PREFIX "Revision: %s\n", str);
1077		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
1078			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
1079		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
1080			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
1081		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
1082		       "on next firmware reset.\n");
1083		tq_init_seq[0] = HP_SDC_ACT_PRECMD |
1084			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
1085		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
1086		tq_init_seq[2] = 1;
1087		tq_init_seq[3] = 0;
1088		tq_init.actidx		= 0;
1089		tq_init.idx		= 1;
1090		tq_init.endidx		= 4;
1091		down(&tq_init_sem);
1092		hp_sdc_enqueue_transaction(&tq_init);
1093		down(&tq_init_sem);
1094		up(&tq_init_sem);
1095	} else
1096		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1097		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
1098
1099        return 0;
1100}
1101
1102module_init(hp_sdc_register);
1103module_exit(hp_sdc_exit);
1104
1105/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
1106 *                                              cycles cycles-adj    time
1107 * between two consecutive mfctl(16)'s:              4        n/a    63ns
1108 * hp_sdc_spin_ibf when idle:                      119        115   1.7us
1109 * gsc_writeb status register:                      83         79   1.2us
1110 * IBF to clear after sending SET_IM:             6204       6006    93us
1111 * IBF to clear after sending LOAD_RT:            4467       4352    68us
1112 * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
1113 * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
1114 * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
1115 * between IRQ received and ~IBF for above:    2578877        n/a    40ms
1116 *
1117 * Performance stats after a run of this module configuring HIL and
1118 * receiving a few mouse events:
1119 *
1120 * status in8  282508 cycles 7128 calls
1121 * status out8   8404 cycles  341 calls
1122 * data out8     1734 cycles   78 calls
1123 * isr         174324 cycles  617 calls (includes take)
1124 * take          1241 cycles    2 calls
1125 * put        1411504 cycles 6937 calls
1126 * task       1655209 cycles 6937 calls (includes put)
1127 *
1128 */
~/ Read-only file preview.