18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Access to HP-HIL MLC through HP System Device Controller.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2001 Brian S. Julin
58c2ecf20Sopenharmony_ci * All rights reserved.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
88c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
98c2ecf20Sopenharmony_ci * are met:
108c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
118c2ecf20Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
128c2ecf20Sopenharmony_ci *    without modification.
138c2ecf20Sopenharmony_ci * 2. The name of the author may not be used to endorse or promote products
148c2ecf20Sopenharmony_ci *    derived from this software without specific prior written permission.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
178c2ecf20Sopenharmony_ci * GNU General Public License ("GPL").
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
208c2ecf20Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
218c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
228c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
238c2ecf20Sopenharmony_ci * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
248c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
258c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
268c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
278c2ecf20Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * References:
308c2ecf20Sopenharmony_ci * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
318c2ecf20Sopenharmony_ci * System Device Controller Microprocessor Firmware Theory of Operation
328c2ecf20Sopenharmony_ci *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <linux/hil_mlc.h>
378c2ecf20Sopenharmony_ci#include <linux/hp_sdc.h>
388c2ecf20Sopenharmony_ci#include <linux/errno.h>
398c2ecf20Sopenharmony_ci#include <linux/kernel.h>
408c2ecf20Sopenharmony_ci#include <linux/module.h>
418c2ecf20Sopenharmony_ci#include <linux/init.h>
428c2ecf20Sopenharmony_ci#include <linux/string.h>
438c2ecf20Sopenharmony_ci#include <linux/semaphore.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define PREFIX "HP SDC MLC: "
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic hil_mlc hp_sdc_mlc;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
508c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
518c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic struct hp_sdc_mlc_priv_s {
548c2ecf20Sopenharmony_ci	int emtestmode;
558c2ecf20Sopenharmony_ci	hp_sdc_transaction trans;
568c2ecf20Sopenharmony_ci	u8 tseq[16];
578c2ecf20Sopenharmony_ci	int got5x;
588c2ecf20Sopenharmony_ci} hp_sdc_mlc_priv;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/************************* Interrupt context ******************************/
618c2ecf20Sopenharmony_cistatic void hp_sdc_mlc_isr (int irq, void *dev_id,
628c2ecf20Sopenharmony_ci			    uint8_t status, uint8_t data)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	int idx;
658c2ecf20Sopenharmony_ci	hil_mlc *mlc = &hp_sdc_mlc;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	write_lock(&mlc->lock);
688c2ecf20Sopenharmony_ci	if (mlc->icount < 0) {
698c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "HIL Overflow!\n");
708c2ecf20Sopenharmony_ci		up(&mlc->isem);
718c2ecf20Sopenharmony_ci		goto out;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci	idx = 15 - mlc->icount;
748c2ecf20Sopenharmony_ci	if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
758c2ecf20Sopenharmony_ci		mlc->ipacket[idx] |= data | HIL_ERR_INT;
768c2ecf20Sopenharmony_ci		mlc->icount--;
778c2ecf20Sopenharmony_ci		if (hp_sdc_mlc_priv.got5x || !idx)
788c2ecf20Sopenharmony_ci			goto check;
798c2ecf20Sopenharmony_ci		if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) !=
808c2ecf20Sopenharmony_ci		    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
818c2ecf20Sopenharmony_ci			mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
828c2ecf20Sopenharmony_ci			mlc->ipacket[idx] |= (mlc->ipacket[idx - 1]
838c2ecf20Sopenharmony_ci						& HIL_PKT_ADDR_MASK);
848c2ecf20Sopenharmony_ci		}
858c2ecf20Sopenharmony_ci		goto check;
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci	/* We know status is 5X */
888c2ecf20Sopenharmony_ci	if (data & HP_SDC_HIL_ISERR)
898c2ecf20Sopenharmony_ci		goto err;
908c2ecf20Sopenharmony_ci	mlc->ipacket[idx] =
918c2ecf20Sopenharmony_ci		(data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
928c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.got5x = 1;
938c2ecf20Sopenharmony_ci	goto out;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci check:
968c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.got5x = 0;
978c2ecf20Sopenharmony_ci	if (mlc->imatch == 0)
988c2ecf20Sopenharmony_ci		goto done;
998c2ecf20Sopenharmony_ci	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
1008c2ecf20Sopenharmony_ci	    && (mlc->ipacket[idx] == (mlc->imatch | idx)))
1018c2ecf20Sopenharmony_ci		goto done;
1028c2ecf20Sopenharmony_ci	if (mlc->ipacket[idx] == mlc->imatch)
1038c2ecf20Sopenharmony_ci		goto done;
1048c2ecf20Sopenharmony_ci	goto out;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci err:
1078c2ecf20Sopenharmony_ci	printk(KERN_DEBUG PREFIX "err code %x\n", data);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	switch (data) {
1108c2ecf20Sopenharmony_ci	case HP_SDC_HIL_RC_DONE:
1118c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
1128c2ecf20Sopenharmony_ci		break;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	case HP_SDC_HIL_ERR:
1158c2ecf20Sopenharmony_ci		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
1168c2ecf20Sopenharmony_ci					HIL_ERR_FERR | HIL_ERR_FOF;
1178c2ecf20Sopenharmony_ci		break;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	case HP_SDC_HIL_TO:
1208c2ecf20Sopenharmony_ci		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
1218c2ecf20Sopenharmony_ci		break;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	case HP_SDC_HIL_RC:
1248c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
1258c2ecf20Sopenharmony_ci		break;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	default:
1288c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "Unknown HIL Error status (%x)!\n", data);
1298c2ecf20Sopenharmony_ci		break;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	/* No more data will be coming due to an error. */
1338c2ecf20Sopenharmony_ci done:
1348c2ecf20Sopenharmony_ci	tasklet_schedule(mlc->tasklet);
1358c2ecf20Sopenharmony_ci	up(&mlc->isem);
1368c2ecf20Sopenharmony_ci out:
1378c2ecf20Sopenharmony_ci	write_unlock(&mlc->lock);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/******************** Tasklet or userspace context functions ****************/
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	struct hp_sdc_mlc_priv_s *priv;
1468c2ecf20Sopenharmony_ci	int rc = 2;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	priv = mlc->priv;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/* Try to down the semaphore */
1518c2ecf20Sopenharmony_ci	if (down_trylock(&mlc->isem)) {
1528c2ecf20Sopenharmony_ci		if (priv->emtestmode) {
1538c2ecf20Sopenharmony_ci			mlc->ipacket[0] =
1548c2ecf20Sopenharmony_ci				HIL_ERR_INT | (mlc->opacket &
1558c2ecf20Sopenharmony_ci					       (HIL_PKT_CMD |
1568c2ecf20Sopenharmony_ci						HIL_PKT_ADDR_MASK |
1578c2ecf20Sopenharmony_ci						HIL_PKT_DATA_MASK));
1588c2ecf20Sopenharmony_ci			mlc->icount = 14;
1598c2ecf20Sopenharmony_ci			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
1608c2ecf20Sopenharmony_ci			goto wasup;
1618c2ecf20Sopenharmony_ci		}
1628c2ecf20Sopenharmony_ci		if (time_after(jiffies, mlc->instart + mlc->intimeout)) {
1638c2ecf20Sopenharmony_ci			/*	printk("!%i %i",
1648c2ecf20Sopenharmony_ci				tv.tv_usec - mlc->instart.tv_usec,
1658c2ecf20Sopenharmony_ci				mlc->intimeout);
1668c2ecf20Sopenharmony_ci			 */
1678c2ecf20Sopenharmony_ci			rc = 1;
1688c2ecf20Sopenharmony_ci			up(&mlc->isem);
1698c2ecf20Sopenharmony_ci		}
1708c2ecf20Sopenharmony_ci		goto done;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci wasup:
1738c2ecf20Sopenharmony_ci	up(&mlc->isem);
1748c2ecf20Sopenharmony_ci	rc = 0;
1758c2ecf20Sopenharmony_ci done:
1768c2ecf20Sopenharmony_ci	return rc;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic int hp_sdc_mlc_cts(hil_mlc *mlc)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	struct hp_sdc_mlc_priv_s *priv;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	priv = mlc->priv;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	/* Try to down the semaphores -- they should be up. */
1868c2ecf20Sopenharmony_ci	BUG_ON(down_trylock(&mlc->isem));
1878c2ecf20Sopenharmony_ci	BUG_ON(down_trylock(&mlc->osem));
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	up(&mlc->isem);
1908c2ecf20Sopenharmony_ci	up(&mlc->osem);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (down_trylock(&mlc->csem)) {
1938c2ecf20Sopenharmony_ci		if (priv->trans.act.semaphore != &mlc->csem)
1948c2ecf20Sopenharmony_ci			goto poll;
1958c2ecf20Sopenharmony_ci		else
1968c2ecf20Sopenharmony_ci			goto busy;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (!(priv->tseq[4] & HP_SDC_USE_LOOP))
2008c2ecf20Sopenharmony_ci		goto done;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci poll:
2038c2ecf20Sopenharmony_ci	priv->trans.act.semaphore = &mlc->csem;
2048c2ecf20Sopenharmony_ci	priv->trans.actidx = 0;
2058c2ecf20Sopenharmony_ci	priv->trans.idx = 1;
2068c2ecf20Sopenharmony_ci	priv->trans.endidx = 5;
2078c2ecf20Sopenharmony_ci	priv->tseq[0] =
2088c2ecf20Sopenharmony_ci		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
2098c2ecf20Sopenharmony_ci	priv->tseq[1] = HP_SDC_CMD_READ_USE;
2108c2ecf20Sopenharmony_ci	priv->tseq[2] = 1;
2118c2ecf20Sopenharmony_ci	priv->tseq[3] = 0;
2128c2ecf20Sopenharmony_ci	priv->tseq[4] = 0;
2138c2ecf20Sopenharmony_ci	return __hp_sdc_enqueue_transaction(&priv->trans);
2148c2ecf20Sopenharmony_ci busy:
2158c2ecf20Sopenharmony_ci	return 1;
2168c2ecf20Sopenharmony_ci done:
2178c2ecf20Sopenharmony_ci	priv->trans.act.semaphore = &mlc->osem;
2188c2ecf20Sopenharmony_ci	up(&mlc->csem);
2198c2ecf20Sopenharmony_ci	return 0;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistatic int hp_sdc_mlc_out(hil_mlc *mlc)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct hp_sdc_mlc_priv_s *priv;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	priv = mlc->priv;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	/* Try to down the semaphore -- it should be up. */
2298c2ecf20Sopenharmony_ci	BUG_ON(down_trylock(&mlc->osem));
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (mlc->opacket & HIL_DO_ALTER_CTRL)
2328c2ecf20Sopenharmony_ci		goto do_control;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci do_data:
2358c2ecf20Sopenharmony_ci	if (priv->emtestmode) {
2368c2ecf20Sopenharmony_ci		up(&mlc->osem);
2378c2ecf20Sopenharmony_ci		return 0;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci	/* Shouldn't be sending commands when loop may be busy */
2408c2ecf20Sopenharmony_ci	BUG_ON(down_trylock(&mlc->csem));
2418c2ecf20Sopenharmony_ci	up(&mlc->csem);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	priv->trans.actidx = 0;
2448c2ecf20Sopenharmony_ci	priv->trans.idx = 1;
2458c2ecf20Sopenharmony_ci	priv->trans.act.semaphore = &mlc->osem;
2468c2ecf20Sopenharmony_ci	priv->trans.endidx = 6;
2478c2ecf20Sopenharmony_ci	priv->tseq[0] =
2488c2ecf20Sopenharmony_ci		HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
2498c2ecf20Sopenharmony_ci	priv->tseq[1] = 0x7;
2508c2ecf20Sopenharmony_ci	priv->tseq[2] =
2518c2ecf20Sopenharmony_ci		(mlc->opacket &
2528c2ecf20Sopenharmony_ci		 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
2538c2ecf20Sopenharmony_ci		   >> HIL_PKT_ADDR_SHIFT;
2548c2ecf20Sopenharmony_ci	priv->tseq[3] =
2558c2ecf20Sopenharmony_ci		(mlc->opacket & HIL_PKT_DATA_MASK)
2568c2ecf20Sopenharmony_ci		  >> HIL_PKT_DATA_SHIFT;
2578c2ecf20Sopenharmony_ci	priv->tseq[4] = 0;  /* No timeout */
2588c2ecf20Sopenharmony_ci	if (priv->tseq[3] == HIL_CMD_DHR)
2598c2ecf20Sopenharmony_ci		priv->tseq[4] = 1;
2608c2ecf20Sopenharmony_ci	priv->tseq[5] = HP_SDC_CMD_DO_HIL;
2618c2ecf20Sopenharmony_ci	goto enqueue;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci do_control:
2648c2ecf20Sopenharmony_ci	priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* we cannot emulate this, it should not be used. */
2678c2ecf20Sopenharmony_ci	BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY)
2708c2ecf20Sopenharmony_ci		goto control_only;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	/* Should not send command/data after engaging APE */
2738c2ecf20Sopenharmony_ci	BUG_ON(mlc->opacket & HIL_CTRL_APE);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* Disengaging APE this way would not be valid either since
2768c2ecf20Sopenharmony_ci	 * the loop must be allowed to idle.
2778c2ecf20Sopenharmony_ci	 *
2788c2ecf20Sopenharmony_ci	 * So, it works out that we really never actually send control
2798c2ecf20Sopenharmony_ci	 * and data when using SDC, we just send the data.
2808c2ecf20Sopenharmony_ci	 */
2818c2ecf20Sopenharmony_ci	goto do_data;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci control_only:
2848c2ecf20Sopenharmony_ci	priv->trans.actidx = 0;
2858c2ecf20Sopenharmony_ci	priv->trans.idx = 1;
2868c2ecf20Sopenharmony_ci	priv->trans.act.semaphore = &mlc->osem;
2878c2ecf20Sopenharmony_ci	priv->trans.endidx = 4;
2888c2ecf20Sopenharmony_ci	priv->tseq[0] =
2898c2ecf20Sopenharmony_ci	  HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
2908c2ecf20Sopenharmony_ci	priv->tseq[1] = HP_SDC_CMD_SET_LPC;
2918c2ecf20Sopenharmony_ci	priv->tseq[2] = 1;
2928c2ecf20Sopenharmony_ci	/* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */
2938c2ecf20Sopenharmony_ci	priv->tseq[3] = 0;
2948c2ecf20Sopenharmony_ci	if (mlc->opacket & HIL_CTRL_APE) {
2958c2ecf20Sopenharmony_ci		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
2968c2ecf20Sopenharmony_ci		BUG_ON(down_trylock(&mlc->csem));
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci enqueue:
2998c2ecf20Sopenharmony_ci	return hp_sdc_enqueue_transaction(&priv->trans);
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_cistatic int __init hp_sdc_mlc_init(void)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	hil_mlc *mlc = &hp_sdc_mlc;
3058c2ecf20Sopenharmony_ci	int err;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci#ifdef __mc68000__
3088c2ecf20Sopenharmony_ci	if (!MACH_IS_HP300)
3098c2ecf20Sopenharmony_ci		return -ENODEV;
3108c2ecf20Sopenharmony_ci#endif
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n");
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.emtestmode = 0;
3158c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
3168c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem;
3178c2ecf20Sopenharmony_ci	hp_sdc_mlc_priv.got5x = 0;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	mlc->cts = &hp_sdc_mlc_cts;
3208c2ecf20Sopenharmony_ci	mlc->in	= &hp_sdc_mlc_in;
3218c2ecf20Sopenharmony_ci	mlc->out = &hp_sdc_mlc_out;
3228c2ecf20Sopenharmony_ci	mlc->priv = &hp_sdc_mlc_priv;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	err = hil_mlc_register(mlc);
3258c2ecf20Sopenharmony_ci	if (err) {
3268c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
3278c2ecf20Sopenharmony_ci		return err;
3288c2ecf20Sopenharmony_ci	}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
3318c2ecf20Sopenharmony_ci		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
3328c2ecf20Sopenharmony_ci		if (hil_mlc_unregister(mlc))
3338c2ecf20Sopenharmony_ci			printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
3348c2ecf20Sopenharmony_ci				"This is bad.  Could cause an oops.\n");
3358c2ecf20Sopenharmony_ci		return -EBUSY;
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	return 0;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic void __exit hp_sdc_mlc_exit(void)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	hil_mlc *mlc = &hp_sdc_mlc;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr))
3468c2ecf20Sopenharmony_ci		printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
3478c2ecf20Sopenharmony_ci			"This is bad.  Could cause an oops.\n");
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	if (hil_mlc_unregister(mlc))
3508c2ecf20Sopenharmony_ci		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
3518c2ecf20Sopenharmony_ci			"This is bad.  Could cause an oops.\n");
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cimodule_init(hp_sdc_mlc_init);
3558c2ecf20Sopenharmony_cimodule_exit(hp_sdc_mlc_exit);
356