^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)