11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Access to HP-HIL MLC through HP System Device Controller. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2001 Brian S. Julin 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Redistribution and use in source and binary forms, with or without 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modification, are permitted provided that the following conditions 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are met: 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Redistributions of source code must retain the above copyright 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * notice, this list of conditions, and the following disclaimer, 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without modification. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. The name of the author may not be used to endorse or promote products 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * derived from this software without specific prior written permission. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternatively, this software may be distributed under the terms of the 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License ("GPL"). 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * References: 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * System Device Controller Microprocessor Firmware Theory of Operation 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hil_mlc.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hp_sdc.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 436188e10d38b8d7244ee7776d5f1f88c837b4b93fMatthew Wilcox#include <linux/semaphore.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PREFIX "HP SDC MLC: " 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic hil_mlc hp_sdc_mlc; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines"); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("Dual BSD/GPL"); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53fa14f7e8df9ee8afea23dab21adb0b7a521f1cd6Adrian Bunkstatic struct hp_sdc_mlc_priv_s { 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int emtestmode; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_transaction trans; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 tseq[16]; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int got5x; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} hp_sdc_mlc_priv; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************* Interrupt context ******************************/ 61ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Dellerstatic void hp_sdc_mlc_isr (int irq, void *dev_id, 62ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller uint8_t status, uint8_t data) 63ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller{ 64ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller int idx; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hil_mlc *mlc = &hp_sdc_mlc; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller write_lock(&mlc->lock); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mlc->icount < 0) { 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING PREFIX "HIL Overflow!\n"); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&mlc->isem); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = 15 - mlc->icount; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mlc->ipacket[idx] |= data | HIL_ERR_INT; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mlc->icount--; 77ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (hp_sdc_mlc_priv.got5x || !idx) 78ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto check; 79ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) != 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; 82ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->ipacket[idx] |= (mlc->ipacket[idx - 1] 83ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller & HIL_PKT_ADDR_MASK); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto check; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We know status is 5X */ 88ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (data & HP_SDC_HIL_ISERR) 89ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto err; 90ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->ipacket[idx] = 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_mlc_priv.got5x = 1; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds check: 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_mlc_priv.got5x = 0; 97ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (mlc->imatch == 0) 98ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto done; 99ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 100ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller && (mlc->ipacket[idx] == (mlc->imatch | idx))) 101ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto done; 102ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (mlc->ipacket[idx] == mlc->imatch) 103ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto done; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 106ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller err: 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG PREFIX "err code %x\n", data); 108ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (data) { 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HP_SDC_HIL_RC_DONE: 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 113ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HP_SDC_HIL_ERR: 115ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 116ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller HIL_ERR_FERR | HIL_ERR_FOF; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 118ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HP_SDC_HIL_TO: 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 122ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HP_SDC_HIL_RC: 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 126ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 128af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa printk(KERN_WARNING PREFIX "Unknown HIL Error status (%x)!\n", data); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 131ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No more data will be coming due to an error. */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds done: 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tasklet_schedule(mlc->tasklet); 135ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->isem); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 137ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller write_unlock(&mlc->lock); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************** Tasklet or userspace context functions ****************/ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Dellerstatic int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout) 144ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller{ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hp_sdc_mlc_priv_s *priv; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = 2; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = mlc->priv; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to down the semaphore */ 151ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (down_trylock(&mlc->isem)) { 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timeval tv; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->emtestmode) { 154ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->ipacket[0] = 155ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller HIL_ERR_INT | (mlc->opacket & 156ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller (HIL_PKT_CMD | 157ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller HIL_PKT_ADDR_MASK | 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HIL_PKT_DATA_MASK)); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mlc->icount = 14; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto wasup; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_gettimeofday(&tv); 164ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { 166ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller /* printk("!%i %i", 167ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller tv.tv_usec - mlc->instart.tv_usec, 168ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->intimeout); 169ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 1; 171ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->isem); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wasup: 176ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->isem); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds done: 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 182ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Dellerstatic int hp_sdc_mlc_cts(hil_mlc *mlc) 183ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller{ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hp_sdc_mlc_priv_s *priv; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 186ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv = mlc->priv; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to down the semaphores -- they should be up. */ 189ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller BUG_ON(down_trylock(&mlc->isem)); 190ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller BUG_ON(down_trylock(&mlc->osem)); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->isem); 193ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->osem); 194ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 195ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (down_trylock(&mlc->csem)) { 196ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (priv->trans.act.semaphore != &mlc->csem) 197ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto poll; 198ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller else 199ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto busy; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 201ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 202ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) 203ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto done; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll: 206ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->trans.act.semaphore = &mlc->csem; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.actidx = 0; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.idx = 1; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.endidx = 5; 210ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[0] = 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[1] = HP_SDC_CMD_READ_USE; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[2] = 1; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[3] = 0; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[4] = 0; 2169575499dfebc0f0fbbf122223f02e9e92630661dHelge Deller __hp_sdc_enqueue_transaction(&priv->trans); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds busy: 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds done: 220ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->trans.act.semaphore = &mlc->osem; 221ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->csem); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Dellerstatic void hp_sdc_mlc_out(hil_mlc *mlc) 226ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller{ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hp_sdc_mlc_priv_s *priv; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = mlc->priv; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to down the semaphore -- it should be up. */ 232ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller BUG_ON(down_trylock(&mlc->osem)); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 234ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (mlc->opacket & HIL_DO_ALTER_CTRL) 235ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto do_control; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_data: 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv->emtestmode) { 239ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->osem); 2409575499dfebc0f0fbbf122223f02e9e92630661dHelge Deller return; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shouldn't be sending commands when loop may be busy */ 243ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller BUG_ON(down_trylock(&mlc->csem)); 244ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller up(&mlc->csem); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.actidx = 0; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.idx = 1; 248ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->trans.act.semaphore = &mlc->osem; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.endidx = 6; 250ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[0] = 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[1] = 0x7; 253ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[2] = 254ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller (mlc->opacket & 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds >> HIL_PKT_ADDR_SHIFT; 257ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[3] = 258ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller (mlc->opacket & HIL_PKT_DATA_MASK) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds >> HIL_PKT_DATA_SHIFT; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[4] = 0; /* No timeout */ 261ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (priv->tseq[3] == HIL_CMD_DHR) 262ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[4] = 1; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[5] = HP_SDC_CMD_DO_HIL; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto enqueue; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_control: 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; 268ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 269fddaaae16ba4d9f4d392a9ef94616d9d22485571Eric Sesterhenn /* we cannot emulate this, it should not be used. */ 270fddaaae16ba4d9f4d392a9ef94616d9d22485571Eric Sesterhenn BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE); 271ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 272ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) 273ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller goto control_only; 274ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 275ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller /* Should not send command/data after engaging APE */ 276ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller BUG_ON(mlc->opacket & HIL_CTRL_APE); 277ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 278ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller /* Disengaging APE this way would not be valid either since 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the loop must be allowed to idle. 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller * So, it works out that we really never actually send control 282ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller * and data when using SDC, we just send the data. 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto do_data; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds control_only: 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.actidx = 0; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.idx = 1; 289ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->trans.act.semaphore = &mlc->osem; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->trans.endidx = 4; 291ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller priv->tseq[0] = 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[1] = HP_SDC_CMD_SET_LPC; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[2] = 1; 295ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller /* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[3] = 0; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mlc->opacket & HIL_CTRL_APE) { 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->tseq[3] |= HP_SDC_LPC_APE_IPF; 299c6fe6b0783a8fd923d11dd0388cbd561ff15bdf1Helge Deller BUG_ON(down_trylock(&mlc->csem)); 300ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enqueue: 302ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller hp_sdc_enqueue_transaction(&priv->trans); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init hp_sdc_mlc_init(void) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hil_mlc *mlc = &hp_sdc_mlc; 30839de52104dd92bc0548a20201350111dc9317df9Jesper Juhl int err; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 310eb98630ba02f6a23a2d202be082757a9e9940b2bGeert Uytterhoeven#ifdef __mc68000__ 311eb98630ba02f6a23a2d202be082757a9e9940b2bGeert Uytterhoeven if (!MACH_IS_HP300) 312eb98630ba02f6a23a2d202be082757a9e9940b2bGeert Uytterhoeven return -ENODEV; 313eb98630ba02f6a23a2d202be082757a9e9940b2bGeert Uytterhoeven#endif 314eb98630ba02f6a23a2d202be082757a9e9940b2bGeert Uytterhoeven 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n"); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_mlc_priv.emtestmode = 0; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; 319ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_sdc_mlc_priv.got5x = 0; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 322ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->cts = &hp_sdc_mlc_cts; 323ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->in = &hp_sdc_mlc_in; 324ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->out = &hp_sdc_mlc_out; 325ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller mlc->priv = &hp_sdc_mlc_priv; 3263acaf540a33199141695f2e2fcfa8829053159bfHelge Deller 32739de52104dd92bc0548a20201350111dc9317df9Jesper Juhl err = hil_mlc_register(mlc); 32839de52104dd92bc0548a20201350111dc9317df9Jesper Juhl if (err) { 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); 33039de52104dd92bc0548a20201350111dc9317df9Jesper Juhl return err; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); 33539de52104dd92bc0548a20201350111dc9317df9Jesper Juhl if (hil_mlc_unregister(mlc)) 33639de52104dd92bc0548a20201350111dc9317df9Jesper Juhl printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 33739de52104dd92bc0548a20201350111dc9317df9Jesper Juhl "This is bad. Could cause an oops.\n"); 33839de52104dd92bc0548a20201350111dc9317df9Jesper Juhl return -EBUSY; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34039de52104dd92bc0548a20201350111dc9317df9Jesper Juhl 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit hp_sdc_mlc_exit(void) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hil_mlc *mlc = &hp_sdc_mlc; 347ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 348ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This is bad. Could cause an oops.\n"); 351ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller 352ffd51f46cdf856c0b453d2828a74d552cc15f881Helge Deller if (hil_mlc_unregister(mlc)) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "This is bad. Could cause an oops.\n"); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(hp_sdc_mlc_init); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(hp_sdc_mlc_exit); 359