1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 1999-2002 Vojtech Pavlik
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun #ifndef _SERIO_H
6*4882a593Smuzhiyun #define _SERIO_H
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/types.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/list.h>
12*4882a593Smuzhiyun #include <linux/spinlock.h>
13*4882a593Smuzhiyun #include <linux/mutex.h>
14*4882a593Smuzhiyun #include <linux/device.h>
15*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
16*4882a593Smuzhiyun #include <linux/android_kabi.h>
17*4882a593Smuzhiyun #include <uapi/linux/serio.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun extern struct bus_type serio_bus;
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun struct serio {
22*4882a593Smuzhiyun void *port_data;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun char name[32];
25*4882a593Smuzhiyun char phys[32];
26*4882a593Smuzhiyun char firmware_id[128];
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun bool manual_bind;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun struct serio_device_id id;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Protects critical sections from port's interrupt handler */
33*4882a593Smuzhiyun spinlock_t lock;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun int (*write)(struct serio *, unsigned char);
36*4882a593Smuzhiyun int (*open)(struct serio *);
37*4882a593Smuzhiyun void (*close)(struct serio *);
38*4882a593Smuzhiyun int (*start)(struct serio *);
39*4882a593Smuzhiyun void (*stop)(struct serio *);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun struct serio *parent;
42*4882a593Smuzhiyun /* Entry in parent->children list */
43*4882a593Smuzhiyun struct list_head child_node;
44*4882a593Smuzhiyun struct list_head children;
45*4882a593Smuzhiyun /* Level of nesting in serio hierarchy */
46*4882a593Smuzhiyun unsigned int depth;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun * serio->drv is accessed from interrupt handlers; when modifying
50*4882a593Smuzhiyun * caller should acquire serio->drv_mutex and serio->lock.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun struct serio_driver *drv;
53*4882a593Smuzhiyun /* Protects serio->drv so attributes can pin current driver */
54*4882a593Smuzhiyun struct mutex drv_mutex;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun struct device dev;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun struct list_head node;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * For use by PS/2 layer when several ports share hardware and
62*4882a593Smuzhiyun * may get indigestion when exposed to concurrent access (i8042).
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun struct mutex *ps2_cmd_mutex;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun ANDROID_KABI_RESERVE(1);
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun #define to_serio_port(d) container_of(d, struct serio, dev)
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct serio_driver {
71*4882a593Smuzhiyun const char *description;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun const struct serio_device_id *id_table;
74*4882a593Smuzhiyun bool manual_bind;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun void (*write_wakeup)(struct serio *);
77*4882a593Smuzhiyun irqreturn_t (*interrupt)(struct serio *, unsigned char, unsigned int);
78*4882a593Smuzhiyun int (*connect)(struct serio *, struct serio_driver *drv);
79*4882a593Smuzhiyun int (*reconnect)(struct serio *);
80*4882a593Smuzhiyun int (*fast_reconnect)(struct serio *);
81*4882a593Smuzhiyun void (*disconnect)(struct serio *);
82*4882a593Smuzhiyun void (*cleanup)(struct serio *);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun struct device_driver driver;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun ANDROID_KABI_RESERVE(1);
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun #define to_serio_driver(d) container_of(d, struct serio_driver, driver)
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun int serio_open(struct serio *serio, struct serio_driver *drv);
91*4882a593Smuzhiyun void serio_close(struct serio *serio);
92*4882a593Smuzhiyun void serio_rescan(struct serio *serio);
93*4882a593Smuzhiyun void serio_reconnect(struct serio *serio);
94*4882a593Smuzhiyun irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun void __serio_register_port(struct serio *serio, struct module *owner);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* use a define to avoid include chaining to get THIS_MODULE */
99*4882a593Smuzhiyun #define serio_register_port(serio) \
100*4882a593Smuzhiyun __serio_register_port(serio, THIS_MODULE)
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun void serio_unregister_port(struct serio *serio);
103*4882a593Smuzhiyun void serio_unregister_child_port(struct serio *serio);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun int __must_check __serio_register_driver(struct serio_driver *drv,
106*4882a593Smuzhiyun struct module *owner, const char *mod_name);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* use a define to avoid include chaining to get THIS_MODULE & friends */
109*4882a593Smuzhiyun #define serio_register_driver(drv) \
110*4882a593Smuzhiyun __serio_register_driver(drv, THIS_MODULE, KBUILD_MODNAME)
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun void serio_unregister_driver(struct serio_driver *drv);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /**
115*4882a593Smuzhiyun * module_serio_driver() - Helper macro for registering a serio driver
116*4882a593Smuzhiyun * @__serio_driver: serio_driver struct
117*4882a593Smuzhiyun *
118*4882a593Smuzhiyun * Helper macro for serio drivers which do not do anything special in
119*4882a593Smuzhiyun * module init/exit. This eliminates a lot of boilerplate. Each module
120*4882a593Smuzhiyun * may only use this macro once, and calling it replaces module_init()
121*4882a593Smuzhiyun * and module_exit().
122*4882a593Smuzhiyun */
123*4882a593Smuzhiyun #define module_serio_driver(__serio_driver) \
124*4882a593Smuzhiyun module_driver(__serio_driver, serio_register_driver, \
125*4882a593Smuzhiyun serio_unregister_driver)
126*4882a593Smuzhiyun
serio_write(struct serio * serio,unsigned char data)127*4882a593Smuzhiyun static inline int serio_write(struct serio *serio, unsigned char data)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun if (serio->write)
130*4882a593Smuzhiyun return serio->write(serio, data);
131*4882a593Smuzhiyun else
132*4882a593Smuzhiyun return -1;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
serio_drv_write_wakeup(struct serio * serio)135*4882a593Smuzhiyun static inline void serio_drv_write_wakeup(struct serio *serio)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun if (serio->drv && serio->drv->write_wakeup)
138*4882a593Smuzhiyun serio->drv->write_wakeup(serio);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /*
142*4882a593Smuzhiyun * Use the following functions to manipulate serio's per-port
143*4882a593Smuzhiyun * driver-specific data.
144*4882a593Smuzhiyun */
serio_get_drvdata(struct serio * serio)145*4882a593Smuzhiyun static inline void *serio_get_drvdata(struct serio *serio)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun return dev_get_drvdata(&serio->dev);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
serio_set_drvdata(struct serio * serio,void * data)150*4882a593Smuzhiyun static inline void serio_set_drvdata(struct serio *serio, void *data)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun dev_set_drvdata(&serio->dev, data);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun * Use the following functions to protect critical sections in
157*4882a593Smuzhiyun * driver code from port's interrupt handler
158*4882a593Smuzhiyun */
serio_pause_rx(struct serio * serio)159*4882a593Smuzhiyun static inline void serio_pause_rx(struct serio *serio)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun spin_lock_irq(&serio->lock);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
serio_continue_rx(struct serio * serio)164*4882a593Smuzhiyun static inline void serio_continue_rx(struct serio *serio)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun spin_unlock_irq(&serio->lock);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun #endif
170