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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  pti.c - PTI driver for cJTAG data extration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) Intel 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * The PTI (Parallel Trace Interface) driver directs trace data routed from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * various parts in the system out through the Intel Penwell PTI port and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * out of the mobile device for analysis with a debugging tool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * compact JTAG, standard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/tty_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/intel-pti.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define DRIVERNAME		"pti"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define PCINAME			"pciPTI"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define TTYNAME			"ttyPTI"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define CHARNAME		"pti"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define PTITTY_MINOR_START	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define PTITTY_MINOR_NUM	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define MAX_APP_IDS		16   /* 128 channel ids / u8 bit size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define MAX_OS_IDS		16   /* 128 channel ids / u8 bit size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define MAX_MODEM_IDS		16   /* 128 channel ids / u8 bit size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define MODEM_BASE_ID		71   /* modem master ID address    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define CONTROL_ID		72   /* control master ID address  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define CONSOLE_ID		73   /* console master ID address  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define OS_BASE_ID		74   /* base OS master ID address  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define APP_BASE_ID		80   /* base App master ID address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define CONTROL_FRAME_LEN	32   /* PTI control frame maximum size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define USER_COPY_SIZE		8192 /* 8Kb buffer for user space copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define APERTURE_14		0x3800000 /* offset to first OS write addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define APERTURE_LEN		0x400000  /* address length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct pti_tty {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	struct pti_masterchannel *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) struct pti_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct tty_port port[PTITTY_MINOR_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	unsigned long pti_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	unsigned long aperture_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	void __iomem *pti_ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	u8 ia_app[MAX_APP_IDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	u8 ia_os[MAX_OS_IDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	u8 ia_modem[MAX_MODEM_IDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * This protects access to ia_app, ia_os, and ia_modem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * which keeps track of channels allocated in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * an aperture write id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static DEFINE_MUTEX(alloclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static const struct pci_device_id pci_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		{0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static struct tty_driver *pti_tty_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static struct pti_dev *drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static unsigned int pti_console_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) static unsigned int pti_control_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *  pti_write_to_aperture()- The private write function to PTI HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  *  @mc: The 'aperture'. It's part of a write address that holds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  *       a master and channel ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  *  @buf: Data being written to the HW that will ultimately be seen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  *        in a debugging tool (Fido, Lauterbach).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  *  @len: Size of buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  *  Since each aperture is specified by a unique
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  *  master/channel ID, no two processes will be writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  *  to the same aperture at the same time so no lock is required. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  *  PTI-Output agent will send these out in the order that they arrived, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  *  thus, it will intermix these messages. The debug tool can then later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  *  regroup the appropriate message segments together reconstituting each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  *  message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static void pti_write_to_aperture(struct pti_masterchannel *mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 				  u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 				  int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	int dwordcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	int final;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	u32 ptiword;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	u32 __iomem *aperture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	u8 *p = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	 * calculate the aperture offset from the base using the master and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	 * channel id's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	aperture = drv_data->pti_ioaddr + (mc->master << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		+ (mc->channel << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	dwordcnt = len >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	final = len - (dwordcnt << 2);	    /* final = trailing bytes    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (final == 0 && dwordcnt != 0) {  /* always need a final dword */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		final += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		dwordcnt--;
^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) 	for (i = 0; i < dwordcnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		ptiword = be32_to_cpu(*(u32 *)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		iowrite32(ptiword, aperture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	aperture += PTI_LASTDWORD_DTS;	/* adding DTS signals that is EOM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	ptiword = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	for (i = 0; i < final; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		ptiword |= *p++ << (24-(8*i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	iowrite32(ptiword, aperture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  *  pti_control_frame_built_and_sent()- control frame build and send function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  *  @mc:          The master / channel structure on which the function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  *                built a control frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  *  @thread_name: The thread name associated with the master / channel or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  *                'NULL' if using the 'current' global variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  *  To be able to post process the PTI contents on host side, a control frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *  is added before sending any PTI content. So the host side knows on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  *  each PTI frame the name of the thread using a dedicated master / channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  *  The thread name is retrieved from 'current' global variable if 'thread_name'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  *  is 'NULL', else it is retrieved from 'thread_name' parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  *  This function builds this frame and sends it to a master ID CONTROL_ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  *  The overhead is only 32 bytes since the driver only writes to HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  *  in 32 byte chunks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 					     const char *thread_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	 * Since we access the comm member in current's task_struct, we only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	 * need to be as large as what 'comm' in that structure is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	char comm[TASK_COMM_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 					      .channel = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	const char *thread_name_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	const char *control_format = "%3d %3d %s";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	u8 control_frame[CONTROL_FRAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (!thread_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (!in_interrupt())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			get_task_comm(comm, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			strncpy(comm, "Interrupt", TASK_COMM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		/* Absolutely ensure our buffer is zero terminated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		comm[TASK_COMM_LEN-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		thread_name_p = comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		thread_name_p = thread_name;
^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) 	mccontrol.channel = pti_control_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	pti_control_channel = (pti_control_channel + 1) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		mc->channel, thread_name_p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  *  pti_write_full_frame_to_aperture()- high level function to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  *					write to PTI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  *  @mc:  The 'aperture'. It's part of a write address that holds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  *        a master and channel ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  *  @buf: Data being written to the HW that will ultimately be seen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *        in a debugging tool (Fido, Lauterbach).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  *  @len: Size of buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  *  All threads sending data (either console, user space application, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *  are calling the high level function to write to PTI meaning that it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  *  possible to add a control frame before sending the content.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 						const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 						int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	pti_control_frame_built_and_sent(mc, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	pti_write_to_aperture(mc, (u8 *)buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * get_id()- Allocate a master and channel ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * @id_array:    an array of bits representing what channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *               id's are allocated for writing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * @max_ids:     The max amount of available write IDs to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  * @base_id:     The starting SW channel ID, based on the Intel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *               PTI arch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * @thread_name: The thread name associated with the master / channel or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  *               'NULL' if using the 'current' global variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *	pti_masterchannel struct with master, channel ID address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *	0 for error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  * Each bit in the arrays ia_app and ia_os correspond to a master and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  * channel id. The bit is one if the id is taken and 0 if free. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  * every master there are 128 channel id's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static struct pti_masterchannel *get_id(u8 *id_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 					int max_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 					int base_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 					const char *thread_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	struct pti_masterchannel *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	int i, j, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	mc = kmalloc(sizeof(struct pti_masterchannel), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	if (mc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	/* look for a byte with a free bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	for (i = 0; i < max_ids; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		if (id_array[i] != 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (i == max_ids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		kfree(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	/* find the bit in the 128 possible channel opportunities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	mask = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	for (j = 0; j < 8; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		if ((id_array[i] & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		mask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	/* grab it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	id_array[i] |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	mc->master  = base_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	mc->channel = ((i & 0xf)<<3) + j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	/* write new master Id / channel Id allocation to channel control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	pti_control_frame_built_and_sent(mc, thread_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	return mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  * The following three functions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  * pti_request_mastercahannel(), mipi_release_masterchannel()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * and pti_writedata() are an API for other kernel drivers to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  * access PTI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  * pti_request_masterchannel()- Kernel API function used to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  *				a master, channel ID address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  *				to write to PTI HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  * @type:        0- request Application  master, channel aperture ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)  *                  write address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)  *               1- request OS master, channel aperture ID write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)  *                  address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)  *               2- request Modem master, channel aperture ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)  *                  write address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)  *               Other values, error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * @thread_name: The thread name associated with the master / channel or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  *               'NULL' if using the 'current' global variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  *	pti_masterchannel struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  *	0 for error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct pti_masterchannel *pti_request_masterchannel(u8 type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 						    const char *thread_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	struct pti_masterchannel *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	mutex_lock(&alloclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		mc = get_id(drv_data->ia_app, MAX_APP_IDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			    APP_BASE_ID, thread_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		mc = get_id(drv_data->ia_os, MAX_OS_IDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			    OS_BASE_ID, thread_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			    MODEM_BASE_ID, thread_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		mc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	mutex_unlock(&alloclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	return mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) EXPORT_SYMBOL_GPL(pti_request_masterchannel);
^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)  * pti_release_masterchannel()- Kernel API function used to release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  *				a master, channel ID address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  *				used to write to PTI HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * @mc: master, channel apeture ID address to be released.  This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  *      will de-allocate the structure via kfree().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) void pti_release_masterchannel(struct pti_masterchannel *mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	u8 master, channel, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	mutex_lock(&alloclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	if (mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		master = mc->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		channel = mc->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		if (master == APP_BASE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			i = channel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			drv_data->ia_app[i] &=  ~(0x80>>(channel & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		} else if (master == OS_BASE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			i = channel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			drv_data->ia_os[i] &= ~(0x80>>(channel & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			i = channel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			drv_data->ia_modem[i] &= ~(0x80>>(channel & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		kfree(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	mutex_unlock(&alloclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) EXPORT_SYMBOL_GPL(pti_release_masterchannel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)  * pti_writedata()- Kernel API function used to write trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  *                  debugging data to PTI HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)  * @mc:    Master, channel aperture ID address to write to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)  *         Null value will return with no write occurring.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)  * @buf:   Trace debuging data to write to the PTI HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)  *         Null value will return with no write occurring.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  * @count: Size of buf. Value of 0 or a negative number will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)  *         return with no write occuring.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	 * since this function is exported, this is treated like an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	 * API function, thus, all parameters should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	 * be checked for validity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	if ((mc != NULL) && (buf != NULL) && (count > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		pti_write_to_aperture(mc, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) EXPORT_SYMBOL_GPL(pti_writedata);
^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)  * for the tty_driver_*() basic function descriptions, see tty_driver.h.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)  * Specific header comments made for PTI-related specifics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)  * pti_tty_driver_open()- Open an Application master, channel aperture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  * ID to the PTI device via tty device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  * @tty: tty interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)  * @filp: filp interface pased to tty_port_open() call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  *	int, 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)  *	otherwise, fail value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)  * The main purpose of using the tty device interface is for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)  * each tty port to have a unique PTI write aperture.  In an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)  * example use case, ttyPTI0 gets syslogd and an APP aperture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)  * ID and ttyPTI1 is where the n_tracesink ldisc hooks to route
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)  * modem messages into PTI.  Modem trace data does not have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)  * go to ttyPTI1, but ttyPTI0 and ttyPTI1 do need to be distinct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)  * master IDs.  These messages go through the PTI HW and out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)  * the handheld platform and to the Fido/Lauterbach device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int pti_tty_driver_open(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	 * we actually want to allocate a new channel per open, per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	 * system arch.  HW gives more than plenty channels for a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	 * system task to have its own channel to write trace data. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	 * also removes a locking requirement for the actual write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	 * procedure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return tty_port_open(tty->port, tty, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)  * pti_tty_driver_close()- close tty device and release Application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)  * master, channel aperture ID to the PTI device via tty device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  * @tty: tty interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  * @filp: filp interface pased to tty_port_close() call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  * The main purpose of using the tty device interface is to route
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)  * syslog daemon messages to the PTI HW and out of the handheld platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)  * and to the Fido/Lauterbach device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	tty_port_close(tty->port, tty, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)  * pti_tty_install()- Used to set up specific master-channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)  *		      to tty ports for organizational purposes when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)  *		      tracing viewed from debuging tools.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)  * @driver: tty driver information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)  * @tty: tty struct containing pti information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)  *	0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)  *	otherwise, error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	int idx = tty->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	struct pti_tty *pti_tty_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	int ret = tty_standard_install(driver, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		pti_tty_data = kmalloc(sizeof(struct pti_tty), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		if (pti_tty_data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		if (idx == PTITTY_MINOR_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			pti_tty_data->mc = pti_request_masterchannel(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 			pti_tty_data->mc = pti_request_masterchannel(2, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (pti_tty_data->mc == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			kfree(pti_tty_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		tty->driver_data = pti_tty_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)  * pti_tty_cleanup()- Used to de-allocate master-channel resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  *		      tied to tty's of this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)  * @tty: tty struct containing pti information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static void pti_tty_cleanup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	struct pti_tty *pti_tty_data = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	if (pti_tty_data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	pti_release_masterchannel(pti_tty_data->mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	kfree(pti_tty_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	tty->driver_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)  * pti_tty_driver_write()-  Write trace debugging data through the char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)  * interface to the PTI HW.  Part of the misc device implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  * @tty: tty struct containing pti information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  * @buf: trace data to be written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  * @len:  # of byte to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)  *	int, # of bytes written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  *	otherwise, error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int pti_tty_driver_write(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	const unsigned char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	struct pti_tty *pti_tty_data = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	if ((pti_tty_data != NULL) && (pti_tty_data->mc != NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		pti_write_to_aperture(pti_tty_data->mc, (u8 *)buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	 * we can't write to the pti hardware if the private driver_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	 * and the mc address is not there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)  * pti_tty_write_room()- Always returns 2048.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)  * @tty: contains tty info of the pti driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int pti_tty_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	return 2048;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  * pti_char_open()- Open an Application master, channel aperture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  * ID to the PTI device. Part of the misc device implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  * @inode: not used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)  * @filp:  Output- will have a masterchannel struct set containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)  *                 the allocated application PTI aperture write address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)  *	int, 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)  *	otherwise, a fail value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int pti_char_open(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	struct pti_masterchannel *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	 * We really do want to fail immediately if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	 * pti_request_masterchannel() fails,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	 * before assigning the value to filp->private_data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	 * Slightly easier to debug if this driver needs debugging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	mc = pti_request_masterchannel(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	if (mc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	filp->private_data = mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)  * pti_char_release()-  Close a char channel to the PTI device. Part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)  * of the misc device implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  * @inode: Not used in this implementaiton.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)  * @filp:  Contains private_data that contains the master, channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)  *         ID to be released by the PTI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)  *	always 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int pti_char_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	pti_release_masterchannel(filp->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	filp->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)  * pti_char_write()-  Write trace debugging data through the char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)  * interface to the PTI HW.  Part of the misc device implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)  * @filp:  Contains private data which is used to obtain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)  *         master, channel write ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)  * @data:  trace data to be written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)  * @len:   # of byte to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)  * @ppose: Not used in this function implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)  *	int, # of bytes written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)  *	otherwise, error value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)  * Notes: From side discussions with Alan Cox and experimenting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)  * with PTI debug HW like Nokia's Fido box and Lauterbach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)  * devices, 8192 byte write buffer used by USER_COPY_SIZE was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)  * deemed an appropriate size for this type of usage with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)  * debugging HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static ssize_t pti_char_write(struct file *filp, const char __user *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			      size_t len, loff_t *ppose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	struct pti_masterchannel *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	void *kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	const char __user *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	size_t size = USER_COPY_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	size_t n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	tmp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	mc = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	kbuf = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	if (kbuf == NULL)  {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		pr_err("%s(%d): buf allocation failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		if (len - n > USER_COPY_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 			size = USER_COPY_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 			size = len - n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		if (copy_from_user(kbuf, tmp, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 			kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			return n ? n : -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		pti_write_to_aperture(mc, kbuf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		n  += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		tmp += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	} while (len > n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static const struct tty_operations pti_tty_driver_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	.open		= pti_tty_driver_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	.close		= pti_tty_driver_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	.write		= pti_tty_driver_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	.write_room	= pti_tty_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	.install	= pti_tty_install,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	.cleanup	= pti_tty_cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static const struct file_operations pti_char_driver_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	.write		= pti_char_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	.open		= pti_char_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	.release	= pti_char_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static struct miscdevice pti_char_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	.minor		= MISC_DYNAMIC_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	.name		= CHARNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	.fops		= &pti_char_driver_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)  * pti_console_write()-  Write to the console that has been acquired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)  * @c:   Not used in this implementaiton.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)  * @buf: Data to be written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)  * @len: Length of buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static void pti_console_write(struct console *c, const char *buf, unsigned len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	static struct pti_masterchannel mc = {.master  = CONSOLE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 					      .channel = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	mc.channel = pti_console_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	pti_console_channel = (pti_console_channel + 1) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	pti_write_full_frame_to_aperture(&mc, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)  * pti_console_device()-  Return the driver tty structure and set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)  *			  associated index implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)  * @c:     Console device of the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)  * @index: index associated with c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)  *	always value of pti_tty_driver structure when this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)  *	is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static struct tty_driver *pti_console_device(struct console *c, int *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	*index = c->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	return pti_tty_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)  * pti_console_setup()-  Initialize console variables used by the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)  * @c:     Not used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)  * @opts:  Not used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)  *	always 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static int pti_console_setup(struct console *c, char *opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	pti_console_channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	pti_control_channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)  * pti_console struct, used to capture OS printk()'s and shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)  * out to the PTI device for debugging.  This cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)  * enabled upon boot because of the possibility of eating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)  * any serial console printk's (race condition discovered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)  * The console should be enabled upon when the tty port is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)  * used for the first time.  Since the primary purpose for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)  * the tty port is to hook up syslog to it, the tty port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)  * will be open for a really long time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static struct console pti_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	.name		= TTYNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	.write		= pti_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	.device		= pti_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	.setup		= pti_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	.flags		= CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	.index		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)  * pti_port_activate()- Used to start/initialize any items upon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)  * first opening of tty_port().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)  * @port: The tty port number of the PTI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)  * @tty:  The tty struct associated with this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)  *	always returns 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)  * Notes: The primary purpose of the PTI tty port 0 is to hook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)  * the syslog daemon to it; thus this port will be open for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)  * very long time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static int pti_port_activate(struct tty_port *port, struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	if (port->tty->index == PTITTY_MINOR_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		console_start(&pti_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)  * pti_port_shutdown()- Used to stop/shutdown any items upon the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)  * last tty port close.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)  * @port: The tty port number of the PTI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)  * Notes: The primary purpose of the PTI tty port 0 is to hook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)  * the syslog daemon to it; thus this port will be open for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)  * very long time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static void pti_port_shutdown(struct tty_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	if (port->tty->index == PTITTY_MINOR_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		console_stop(&pti_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static const struct tty_port_operations tty_port_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	.activate = pti_port_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	.shutdown = pti_port_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)  * Note the _probe() call sets everything up and ties the char and tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)  * to successfully detecting the PTI device on the pci bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)  * pti_pci_probe()- Used to detect pti on the pci bus and set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)  *		    things up in the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)  * @pdev: pci_dev struct values for pti.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)  * @ent:  pci_device_id struct for pti driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)  *	0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)  *	otherwise, error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static int pti_pci_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 		const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	unsigned int a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	int pci_bar = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 			__func__, __LINE__, pdev->vendor, pdev->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	retval = misc_register(&pti_char_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 		pr_err("%s(%d): CHAR registration failed of pti driver\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 		pr_err("%s(%d): Error value returned: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 			__func__, __LINE__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	retval = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	if (retval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 			"%s: pci_enable_device() returned error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 			__func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		goto err_unreg_misc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	if (drv_data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 		retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 		dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 			"%s(%d): kmalloc() returned NULL memory.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 		goto err_disable_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	drv_data->pti_addr = pci_resource_start(pdev, pci_bar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	retval = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	if (retval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 		dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 			"%s(%d): pci_request_region() returned error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 			__func__, __LINE__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 		goto err_free_dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	drv_data->aperture_base = drv_data->pti_addr+APERTURE_14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	drv_data->pti_ioaddr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 		ioremap((u32)drv_data->aperture_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 		APERTURE_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	if (!drv_data->pti_ioaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 		retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 		goto err_rel_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	pci_set_drvdata(pdev, drv_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	for (a = 0; a < PTITTY_MINOR_NUM; a++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		struct tty_port *port = &drv_data->port[a];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 		tty_port_init(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 		port->ops = &tty_port_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 		tty_port_register_device(port, pti_tty_driver, a, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	register_console(&pti_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) err_rel_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	pci_release_region(pdev, pci_bar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) err_free_dd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 	kfree(drv_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) err_disable_pci:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) err_unreg_misc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	misc_deregister(&pti_char_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)  * pti_pci_remove()- Driver exit method to remove PTI from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)  *		   PCI bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)  * @pdev: variable containing pci info of PTI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static void pti_pci_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	struct pti_dev *drv_data = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	unsigned int a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	unregister_console(&pti_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 	for (a = 0; a < PTITTY_MINOR_NUM; a++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 		tty_unregister_device(pti_tty_driver, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 		tty_port_destroy(&drv_data->port[a]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	iounmap(drv_data->pti_ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	kfree(drv_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	pci_release_region(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 	pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 	misc_deregister(&pti_char_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static struct pci_driver pti_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 	.name		= PCINAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 	.id_table	= pci_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 	.probe		= pti_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 	.remove		= pti_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)  * pti_init()- Overall entry/init call to the pti driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)  *             It starts the registration process with the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)  *	int __init, 0 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)  *	otherwise value is an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static int __init pti_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	/* First register module as tty device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 	pti_tty_driver = alloc_tty_driver(PTITTY_MINOR_NUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 	if (pti_tty_driver == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 		pr_err("%s(%d): Memory allocation failed for ptiTTY driver\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	pti_tty_driver->driver_name		= DRIVERNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 	pti_tty_driver->name			= TTYNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	pti_tty_driver->major			= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 	pti_tty_driver->minor_start		= PTITTY_MINOR_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	pti_tty_driver->type			= TTY_DRIVER_TYPE_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 	pti_tty_driver->subtype			= SYSTEM_TYPE_SYSCONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	pti_tty_driver->flags			= TTY_DRIVER_REAL_RAW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 						  TTY_DRIVER_DYNAMIC_DEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	pti_tty_driver->init_termios		= tty_std_termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	tty_set_operations(pti_tty_driver, &pti_tty_driver_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	retval = tty_register_driver(pti_tty_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 		pr_err("%s(%d): TTY registration failed of pti driver\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 		pr_err("%s(%d): Error value returned: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 			__func__, __LINE__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 		goto put_tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) 	retval = pci_register_driver(&pti_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 	if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 		pr_err("%s(%d): PCI registration failed of pti driver\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 		pr_err("%s(%d): Error value returned: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) 			__func__, __LINE__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 		goto unreg_tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) unreg_tty:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 	tty_unregister_driver(pti_tty_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) put_tty:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 	put_tty_driver(pti_tty_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 	pti_tty_driver = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)  * pti_exit()- Unregisters this module as a tty and pci driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static void __exit pti_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) 	tty_unregister_driver(pti_tty_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 	pci_unregister_driver(&pti_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) 	put_tty_driver(pti_tty_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) module_init(pti_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) module_exit(pti_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) MODULE_AUTHOR("Ken Mills, Jay Freyensee");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) MODULE_DESCRIPTION("PTI Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)