Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* ------------------------------------------------------------------------ *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * i2c-parport.c I2C bus over parallel port                                 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * ------------------------------------------------------------------------ *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)    Copyright (C) 2003-2011 Jean Delvare <jdelvare@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)    Based on older i2c-philips-par.c driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)    Copyright (C) 1995-2000 Simon G. Vogl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)    With some changes from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)    Frodo Looijaard <frodol@dds.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)    Kyösti Mälkki <kmalkki@cc.hut.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define pr_fmt(fmt) "i2c-parport: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/parport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/i2c-algo-bit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/i2c-smbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define PORT_DATA	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define PORT_STAT	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define PORT_CTRL	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) struct lineop {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u8 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	u8 inverted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) struct adapter_parm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct lineop setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct lineop setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct lineop getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct lineop getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct lineop init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	unsigned int smbus_alert:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static const struct adapter_parm adapter_parm[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	/* type 0: Philips adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		.setsda	= { 0x80, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		.setscl	= { 0x08, PORT_CTRL, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		.getsda	= { 0x80, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		.getscl	= { 0x08, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	/* type 1: home brew teletext adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		.setsda	= { 0x02, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		.setscl	= { 0x01, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		.getsda	= { 0x80, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	/* type 2: Velleman K8000 adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		.setsda	= { 0x02, PORT_CTRL, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		.setscl	= { 0x08, PORT_CTRL, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		.getsda	= { 0x10, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	/* type 3: ELV adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		.setsda	= { 0x02, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		.setscl	= { 0x01, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		.getsda	= { 0x40, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		.getscl	= { 0x08, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	/* type 4: ADM1032 evaluation board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		.setsda	= { 0x02, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		.setscl	= { 0x01, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		.getsda	= { 0x10, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		.init	= { 0xf0, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		.smbus_alert = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	/* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		.setsda	= { 0x02, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		.setscl	= { 0x01, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		.getsda	= { 0x10, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	/* type 6: Barco LPT->DVI (K5800236) adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		.setsda	= { 0x02, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		.setscl	= { 0x01, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		.getsda	= { 0x20, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		.getscl	= { 0x40, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		.init	= { 0xfc, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/* type 7: One For All JP1 parallel port adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		.setsda	= { 0x01, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		.setscl	= { 0x02, PORT_DATA, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		.getsda	= { 0x80, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		.init	= { 0x04, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* type 8: VCT-jig */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		.setsda	= { 0x04, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		.setscl	= { 0x01, PORT_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		.getsda	= { 0x40, PORT_STAT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		.getscl	= { 0x80, PORT_STAT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* ----- Device list ------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct i2c_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	struct pardevice *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct i2c_adapter adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct i2c_algo_bit_data algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct i2c_smbus_alert_setup alert_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	struct i2c_client *ara;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static LIST_HEAD(adapter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static DEFINE_MUTEX(adapter_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define MAX_DEVICE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int parport[MAX_DEVICE] = {0, -1, -1, -1};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) module_param_array(parport, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) MODULE_PARM_DESC(parport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		 "List of parallel ports to bind to, by index.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		 " At most " __stringify(MAX_DEVICE) " devices are supported.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		 " Default is one device connected to parport0.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) module_param(type, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) MODULE_PARM_DESC(type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	"Type of adapter:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	" 0 = Philips adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	" 1 = home brew teletext adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	" 2 = Velleman K8000 adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	" 3 = ELV adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	" 4 = ADM1032 evaluation board\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	" 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	" 6 = Barco LPT->DVI (K5800236) adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	" 7 = One For All JP1 parallel port adapter\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	" 8 = VCT-jig\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* ----- Low-level parallel port access ----------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void port_write_data(struct parport *p, unsigned char d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	parport_write_data(p, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void port_write_control(struct parport *p, unsigned char d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	parport_write_control(p, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static unsigned char port_read_data(struct parport *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return parport_read_data(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static unsigned char port_read_status(struct parport *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	return parport_read_status(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static unsigned char port_read_control(struct parport *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	return parport_read_control(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void (* const port_write[])(struct parport *, unsigned char) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	port_write_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	port_write_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static unsigned char (* const port_read[])(struct parport *) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	port_read_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	port_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	port_read_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* ----- Unified line operation functions --------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static inline void line_set(struct parport *data, int state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	const struct lineop *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	u8 oldval = port_read[op->port](data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/* Touch only the bit(s) needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if ((op->inverted && !state) || (!op->inverted && state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		port_write[op->port](data, oldval | op->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		port_write[op->port](data, oldval & ~op->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static inline int line_get(struct parport *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	const struct lineop *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	u8 oldval = port_read[op->port](data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	return ((op->inverted && (oldval & op->val) != op->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	    || (!op->inverted && (oldval & op->val) == op->val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* ----- I2C algorithm call-back functions and structures ----------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static void parport_setscl(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	line_set((struct parport *) data, state, &adapter_parm[type].setscl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void parport_setsda(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	line_set((struct parport *) data, state, &adapter_parm[type].setsda);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int parport_getscl(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	return line_get((struct parport *) data, &adapter_parm[type].getscl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static int parport_getsda(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	return line_get((struct parport *) data, &adapter_parm[type].getsda);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* Encapsulate the functions above in the correct structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)    Note that this is only a template, from which the real structures are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)    copied. The attaching code will set getscl to NULL for adapters that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)    cannot read SCL back, and will also make the data field point to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)    the parallel port structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct i2c_algo_bit_data parport_algo_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.setsda		= parport_setsda,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.setscl		= parport_setscl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.getsda		= parport_getsda,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	.getscl		= parport_getscl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	.udelay		= 10, /* ~50 kbps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	.timeout	= HZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* ----- I2c and parallel port call-back functions and structures --------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static void i2c_parport_irq(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	struct i2c_par *adapter = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	struct i2c_client *ara = adapter->ara;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (ara) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		dev_dbg(&ara->dev, "SMBus alert received\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		i2c_handle_smbus_alert(ara);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		dev_dbg(&adapter->adapter.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			"SMBus alert received but no ARA client!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static void i2c_parport_attach(struct parport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	struct i2c_par *adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	struct pardev_cb i2c_parport_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	for (i = 0; i < MAX_DEVICE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		if (parport[i] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		if (port->number == parport[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	if (i == MAX_DEVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		pr_debug("Not using parport%d.\n", port->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (!adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	memset(&i2c_parport_cb, 0, sizeof(i2c_parport_cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	i2c_parport_cb.flags = PARPORT_FLAG_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	i2c_parport_cb.irq_func = i2c_parport_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	i2c_parport_cb.private = adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	pr_debug("attaching to %s\n", port->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	parport_disable_irq(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	adapter->pdev = parport_register_dev_model(port, "i2c-parport",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 						   &i2c_parport_cb, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (!adapter->pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		pr_err("Unable to register with parport\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	/* Fill the rest of the structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	adapter->adapter.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	adapter->adapter.class = I2C_CLASS_HWMON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	strlcpy(adapter->adapter.name, "Parallel port adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		sizeof(adapter->adapter.name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	adapter->algo_data = parport_algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	/* Slow down if we can't sense SCL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (!adapter_parm[type].getscl.val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		adapter->algo_data.getscl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		adapter->algo_data.udelay = 50; /* ~10 kbps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	adapter->algo_data.data = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	adapter->adapter.algo_data = &adapter->algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	adapter->adapter.dev.parent = port->physport->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (parport_claim_or_block(adapter->pdev) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		dev_err(&adapter->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			"Could not claim parallel port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		goto err_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	/* Reset hardware to a sane state (SCL and SDA high) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	parport_setsda(port, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	parport_setscl(port, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	/* Other init if needed (power on...) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	if (adapter_parm[type].init.val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		line_set(port, 1, &adapter_parm[type].init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		/* Give powered devices some time to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (i2c_bit_add_bus(&adapter->adapter) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		dev_err(&adapter->pdev->dev, "Unable to register with I2C\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		goto err_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	/* Setup SMBus alert if supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	if (adapter_parm[type].smbus_alert) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		struct i2c_client *ara;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		ara = i2c_new_smbus_alert_device(&adapter->adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 						 &adapter->alert_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		if (!IS_ERR(ara)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 			adapter->ara = ara;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			parport_enable_irq(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			dev_warn(&adapter->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 				 "Failed to register ARA client\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	/* Add the new adapter to the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	mutex_lock(&adapter_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	list_add_tail(&adapter->node, &adapter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	mutex_unlock(&adapter_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  err_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	parport_release(adapter->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	parport_unregister_device(adapter->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	kfree(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static void i2c_parport_detach(struct parport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	struct i2c_par *adapter, *_n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	/* Walk the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	mutex_lock(&adapter_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		if (adapter->pdev->port == port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			if (adapter->ara) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 				parport_disable_irq(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 				i2c_unregister_device(adapter->ara);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			i2c_del_adapter(&adapter->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			/* Un-init if needed (power off...) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			if (adapter_parm[type].init.val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 				line_set(port, 0, &adapter_parm[type].init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			parport_release(adapter->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			parport_unregister_device(adapter->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			list_del(&adapter->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			kfree(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	mutex_unlock(&adapter_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static struct parport_driver i2c_parport_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	.name = "i2c-parport",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	.match_port = i2c_parport_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	.detach = i2c_parport_detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	.devmodel = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* ----- Module loading, unloading and information ------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int __init i2c_parport_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (type < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		pr_warn("adapter type unspecified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (type >= ARRAY_SIZE(adapter_parm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		pr_warn("invalid type (%d)\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	return parport_register_driver(&i2c_parport_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static void __exit i2c_parport_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	parport_unregister_driver(&i2c_parport_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) MODULE_DESCRIPTION("I2C bus over parallel port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) module_init(i2c_parport_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) module_exit(i2c_parport_exit);