162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * (c) 1998  Grant R. Guenther <grant@torque.net>
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * ktti.c is a low-level protocol driver for the KT Technology
662306a36Sopenharmony_ci * parallel port adapter.  This adapter is used in the "PHd"
762306a36Sopenharmony_ci * portable hard-drives.  As far as I can tell, this device
862306a36Sopenharmony_ci * supports 4-bit mode _only_.
962306a36Sopenharmony_ci*/
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/wait.h>
1762306a36Sopenharmony_ci#include <asm/io.h>
1862306a36Sopenharmony_ci#include "pata_parport.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define j44(a, b)	(((a >> 4) & 0x0f) | (b & 0xf0))
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*
2362306a36Sopenharmony_ci * cont = 0 - access the IDE register file
2462306a36Sopenharmony_ci * cont = 1 - access the IDE command set
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_cistatic int cont_map[2] = { 0x10, 0x08 };
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	int r = regr + cont_map[cont];
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
3362306a36Sopenharmony_ci	w0(val); w2(3); w0(0); w2(6); w2(0xb);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic int ktti_read_regr(struct pi_adapter *pi, int cont, int regr)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	int a, b, r;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci        r = regr + cont_map[cont];
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
4362306a36Sopenharmony_ci	a = r1(); w2(0xc);  b = r1(); w2(9); w2(0xc); w2(9);
4462306a36Sopenharmony_ci	return j44(a, b);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic void ktti_read_block(struct pi_adapter *pi, char *buf, int count)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int k, a, b;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	for (k = 0; k < count / 2; k++) {
5262306a36Sopenharmony_ci		w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
5362306a36Sopenharmony_ci		a = r1(); w2(0xc); b = r1(); w2(9);
5462306a36Sopenharmony_ci		buf[2*k] = j44(a, b);
5562306a36Sopenharmony_ci		a = r1(); w2(0xc); b = r1(); w2(9);
5662306a36Sopenharmony_ci		buf[2*k+1] = j44(a, b);
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic void ktti_write_block(struct pi_adapter *pi, char *buf, int count)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	int k;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	for (k = 0; k < count / 2; k++) {
6562306a36Sopenharmony_ci		w0(0x10); w2(0xb); w2(0xa); w2(3); w2(6);
6662306a36Sopenharmony_ci		w0(buf[2 * k]); w2(3);
6762306a36Sopenharmony_ci		w0(buf[2 * k + 1]); w2(6);
6862306a36Sopenharmony_ci		w2(0xb);
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic void ktti_connect(struct pi_adapter *pi)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	pi->saved_r0 = r0();
7562306a36Sopenharmony_ci	pi->saved_r2 = r2();
7662306a36Sopenharmony_ci	w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void ktti_disconnect(struct pi_adapter *pi)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
8262306a36Sopenharmony_ci	w0(pi->saved_r0);
8362306a36Sopenharmony_ci	w2(pi->saved_r2);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic void ktti_log_adapter(struct pi_adapter *pi)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n",
8962306a36Sopenharmony_ci		 pi->port, pi->delay);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic struct pi_protocol ktti = {
9362306a36Sopenharmony_ci	.owner		= THIS_MODULE,
9462306a36Sopenharmony_ci	.name		= "ktti",
9562306a36Sopenharmony_ci	.max_mode	= 1,
9662306a36Sopenharmony_ci	.epp_first	= 2,
9762306a36Sopenharmony_ci	.default_delay	= 1,
9862306a36Sopenharmony_ci	.max_units	= 1,
9962306a36Sopenharmony_ci	.write_regr	= ktti_write_regr,
10062306a36Sopenharmony_ci	.read_regr	= ktti_read_regr,
10162306a36Sopenharmony_ci	.write_block	= ktti_write_block,
10262306a36Sopenharmony_ci	.read_block	= ktti_read_block,
10362306a36Sopenharmony_ci	.connect	= ktti_connect,
10462306a36Sopenharmony_ci	.disconnect	= ktti_disconnect,
10562306a36Sopenharmony_ci	.log_adapter	= ktti_log_adapter,
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
10962306a36Sopenharmony_ciMODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
11062306a36Sopenharmony_ciMODULE_DESCRIPTION("KT Technology parallel port IDE adapter protocol driver");
11162306a36Sopenharmony_cimodule_pata_parport_driver(ktti);
112