197fb5e8dSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 2cd6484e1SRob Herring /* 3cd6484e1SRob Herring * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <[email protected]> 4cd6484e1SRob Herring */ 5cd6484e1SRob Herring #ifndef _LINUX_SERDEV_H 6cd6484e1SRob Herring #define _LINUX_SERDEV_H 7cd6484e1SRob Herring 8cd6484e1SRob Herring #include <linux/types.h> 9cd6484e1SRob Herring #include <linux/device.h> 1096e82989SAndy Shevchenko #include <linux/iopoll.h> 1189bbeb7eSAl Viro #include <linux/uaccess.h> 125659dab2SSebastian Reichel #include <linux/termios.h> 13756db778SSebastian Reichel #include <linux/delay.h> 14cd6484e1SRob Herring 15cd6484e1SRob Herring struct serdev_controller; 16cd6484e1SRob Herring struct serdev_device; 17cd6484e1SRob Herring 18cd6484e1SRob Herring /* 19cd6484e1SRob Herring * serdev device structures 20cd6484e1SRob Herring */ 21cd6484e1SRob Herring 22cd6484e1SRob Herring /** 23cd6484e1SRob Herring * struct serdev_device_ops - Callback operations for a serdev device 2410f9e033SJohan Hovold * @receive_buf: Function called with data received from device; 2510f9e033SJohan Hovold * returns number of bytes accepted; may sleep. 2610f9e033SJohan Hovold * @write_wakeup: Function called when ready to transmit more data; must 2710f9e033SJohan Hovold * not sleep. 28cd6484e1SRob Herring */ 29cd6484e1SRob Herring struct serdev_device_ops { 30cd6484e1SRob Herring int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); 31cd6484e1SRob Herring void (*write_wakeup)(struct serdev_device *); 32cd6484e1SRob Herring }; 33cd6484e1SRob Herring 34cd6484e1SRob Herring /** 35cd6484e1SRob Herring * struct serdev_device - Basic representation of an serdev device 36cd6484e1SRob Herring * @dev: Driver model representation of the device. 37cd6484e1SRob Herring * @nr: Device number on serdev bus. 38cd6484e1SRob Herring * @ctrl: serdev controller managing this device. 39cd6484e1SRob Herring * @ops: Device operations. 406fe729c4SAndrey Smirnov * @write_comp Completion used by serdev_device_write() internally 416fe729c4SAndrey Smirnov * @write_lock Lock to serialize access when writing data 42cd6484e1SRob Herring */ 43cd6484e1SRob Herring struct serdev_device { 44cd6484e1SRob Herring struct device dev; 45cd6484e1SRob Herring int nr; 46cd6484e1SRob Herring struct serdev_controller *ctrl; 47cd6484e1SRob Herring const struct serdev_device_ops *ops; 486fe729c4SAndrey Smirnov struct completion write_comp; 496fe729c4SAndrey Smirnov struct mutex write_lock; 50cd6484e1SRob Herring }; 51cd6484e1SRob Herring 52cd6484e1SRob Herring static inline struct serdev_device *to_serdev_device(struct device *d) 53cd6484e1SRob Herring { 54cd6484e1SRob Herring return container_of(d, struct serdev_device, dev); 55cd6484e1SRob Herring } 56cd6484e1SRob Herring 57cd6484e1SRob Herring /** 58cd6484e1SRob Herring * struct serdev_device_driver - serdev slave device driver 59cd6484e1SRob Herring * @driver: serdev device drivers should initialize name field of this 60cd6484e1SRob Herring * structure. 61cd6484e1SRob Herring * @probe: binds this driver to a serdev device. 62cd6484e1SRob Herring * @remove: unbinds this driver from the serdev device. 63cd6484e1SRob Herring */ 64cd6484e1SRob Herring struct serdev_device_driver { 65cd6484e1SRob Herring struct device_driver driver; 66cd6484e1SRob Herring int (*probe)(struct serdev_device *); 67cd6484e1SRob Herring void (*remove)(struct serdev_device *); 68cd6484e1SRob Herring }; 69cd6484e1SRob Herring 70cd6484e1SRob Herring static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) 71cd6484e1SRob Herring { 72cd6484e1SRob Herring return container_of(d, struct serdev_device_driver, driver); 73cd6484e1SRob Herring } 74cd6484e1SRob Herring 753a19cfccSUlrich Hecht enum serdev_parity { 763a19cfccSUlrich Hecht SERDEV_PARITY_NONE, 773a19cfccSUlrich Hecht SERDEV_PARITY_EVEN, 783a19cfccSUlrich Hecht SERDEV_PARITY_ODD, 793a19cfccSUlrich Hecht }; 803a19cfccSUlrich Hecht 81cd6484e1SRob Herring /* 82cd6484e1SRob Herring * serdev controller structures 83cd6484e1SRob Herring */ 84cd6484e1SRob Herring struct serdev_controller_ops { 85cd6484e1SRob Herring int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t); 86cd6484e1SRob Herring void (*write_flush)(struct serdev_controller *); 87cd6484e1SRob Herring int (*write_room)(struct serdev_controller *); 88cd6484e1SRob Herring int (*open)(struct serdev_controller *); 89cd6484e1SRob Herring void (*close)(struct serdev_controller *); 90cd6484e1SRob Herring void (*set_flow_control)(struct serdev_controller *, bool); 913a19cfccSUlrich Hecht int (*set_parity)(struct serdev_controller *, enum serdev_parity); 92cd6484e1SRob Herring unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int); 93b3f80c8fSSebastian Reichel void (*wait_until_sent)(struct serdev_controller *, long); 945659dab2SSebastian Reichel int (*get_tiocm)(struct serdev_controller *); 955659dab2SSebastian Reichel int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int); 968eaf839eSNeeraj Sanjay Kale int (*break_ctl)(struct serdev_controller *ctrl, unsigned int break_state); 97cd6484e1SRob Herring }; 98cd6484e1SRob Herring 99cd6484e1SRob Herring /** 100cd6484e1SRob Herring * struct serdev_controller - interface to the serdev controller 101cd6484e1SRob Herring * @dev: Driver model representation of the device. 102*b286f4e8STony Lindgren * @host: Serial port hardware controller device 103cd6484e1SRob Herring * @nr: number identifier for this controller/bus. 104cd6484e1SRob Herring * @serdev: Pointer to slave device for this controller. 105cd6484e1SRob Herring * @ops: Controller operations. 106cd6484e1SRob Herring */ 107cd6484e1SRob Herring struct serdev_controller { 108cd6484e1SRob Herring struct device dev; 109*b286f4e8STony Lindgren struct device *host; 110cd6484e1SRob Herring unsigned int nr; 111cd6484e1SRob Herring struct serdev_device *serdev; 112cd6484e1SRob Herring const struct serdev_controller_ops *ops; 113cd6484e1SRob Herring }; 114cd6484e1SRob Herring 115cd6484e1SRob Herring static inline struct serdev_controller *to_serdev_controller(struct device *d) 116cd6484e1SRob Herring { 117cd6484e1SRob Herring return container_of(d, struct serdev_controller, dev); 118cd6484e1SRob Herring } 119cd6484e1SRob Herring 120cd6484e1SRob Herring static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) 121cd6484e1SRob Herring { 122cd6484e1SRob Herring return dev_get_drvdata(&serdev->dev); 123cd6484e1SRob Herring } 124cd6484e1SRob Herring 125cd6484e1SRob Herring static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data) 126cd6484e1SRob Herring { 127cd6484e1SRob Herring dev_set_drvdata(&serdev->dev, data); 128cd6484e1SRob Herring } 129cd6484e1SRob Herring 130cd6484e1SRob Herring /** 131cd6484e1SRob Herring * serdev_device_put() - decrement serdev device refcount 132cd6484e1SRob Herring * @serdev serdev device. 133cd6484e1SRob Herring */ 134cd6484e1SRob Herring static inline void serdev_device_put(struct serdev_device *serdev) 135cd6484e1SRob Herring { 136cd6484e1SRob Herring if (serdev) 137cd6484e1SRob Herring put_device(&serdev->dev); 138cd6484e1SRob Herring } 139cd6484e1SRob Herring 140cd6484e1SRob Herring static inline void serdev_device_set_client_ops(struct serdev_device *serdev, 141cd6484e1SRob Herring const struct serdev_device_ops *ops) 142cd6484e1SRob Herring { 143cd6484e1SRob Herring serdev->ops = ops; 144cd6484e1SRob Herring } 145cd6484e1SRob Herring 146cd6484e1SRob Herring static inline 147cd6484e1SRob Herring void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl) 148cd6484e1SRob Herring { 149cd6484e1SRob Herring return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL; 150cd6484e1SRob Herring } 151cd6484e1SRob Herring 152cd6484e1SRob Herring static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl, 153cd6484e1SRob Herring void *data) 154cd6484e1SRob Herring { 155cd6484e1SRob Herring dev_set_drvdata(&ctrl->dev, data); 156cd6484e1SRob Herring } 157cd6484e1SRob Herring 158cd6484e1SRob Herring /** 159cd6484e1SRob Herring * serdev_controller_put() - decrement controller refcount 160cd6484e1SRob Herring * @ctrl serdev controller. 161cd6484e1SRob Herring */ 162cd6484e1SRob Herring static inline void serdev_controller_put(struct serdev_controller *ctrl) 163cd6484e1SRob Herring { 164cd6484e1SRob Herring if (ctrl) 165cd6484e1SRob Herring put_device(&ctrl->dev); 166cd6484e1SRob Herring } 167cd6484e1SRob Herring 168cd6484e1SRob Herring struct serdev_device *serdev_device_alloc(struct serdev_controller *); 169cd6484e1SRob Herring int serdev_device_add(struct serdev_device *); 170cd6484e1SRob Herring void serdev_device_remove(struct serdev_device *); 171cd6484e1SRob Herring 172*b286f4e8STony Lindgren struct serdev_controller *serdev_controller_alloc(struct device *host, 173*b286f4e8STony Lindgren struct device *parent, 174*b286f4e8STony Lindgren size_t size); 175cd6484e1SRob Herring int serdev_controller_add(struct serdev_controller *); 176cd6484e1SRob Herring void serdev_controller_remove(struct serdev_controller *); 177cd6484e1SRob Herring 178cd6484e1SRob Herring static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl) 179cd6484e1SRob Herring { 180cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 181cd6484e1SRob Herring 182cd6484e1SRob Herring if (!serdev || !serdev->ops->write_wakeup) 183cd6484e1SRob Herring return; 184cd6484e1SRob Herring 1859d1d994dSAndrey Smirnov serdev->ops->write_wakeup(serdev); 186cd6484e1SRob Herring } 187cd6484e1SRob Herring 188cd6484e1SRob Herring static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, 189cd6484e1SRob Herring const unsigned char *data, 190cd6484e1SRob Herring size_t count) 191cd6484e1SRob Herring { 192cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 193cd6484e1SRob Herring 194cd6484e1SRob Herring if (!serdev || !serdev->ops->receive_buf) 195fd00cf81SJohan Hovold return 0; 196cd6484e1SRob Herring 1979d1d994dSAndrey Smirnov return serdev->ops->receive_buf(serdev, data, count); 198cd6484e1SRob Herring } 199cd6484e1SRob Herring 200cd6484e1SRob Herring #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS) 201cd6484e1SRob Herring 202cd6484e1SRob Herring int serdev_device_open(struct serdev_device *); 203cd6484e1SRob Herring void serdev_device_close(struct serdev_device *); 2042cb67d20SAndrey Smirnov int devm_serdev_device_open(struct device *, struct serdev_device *); 205cd6484e1SRob Herring unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); 206cd6484e1SRob Herring void serdev_device_set_flow_control(struct serdev_device *, bool); 2076bdc00d0SStefan Wahren int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); 208b3f80c8fSSebastian Reichel void serdev_device_wait_until_sent(struct serdev_device *, long); 2095659dab2SSebastian Reichel int serdev_device_get_tiocm(struct serdev_device *); 2105659dab2SSebastian Reichel int serdev_device_set_tiocm(struct serdev_device *, int, int); 2118eaf839eSNeeraj Sanjay Kale int serdev_device_break_ctl(struct serdev_device *serdev, int break_state); 2126fe729c4SAndrey Smirnov void serdev_device_write_wakeup(struct serdev_device *); 21370d18804SJohan Hovold int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, long); 214cd6484e1SRob Herring void serdev_device_write_flush(struct serdev_device *); 215cd6484e1SRob Herring int serdev_device_write_room(struct serdev_device *); 216cd6484e1SRob Herring 217cd6484e1SRob Herring /* 218cd6484e1SRob Herring * serdev device driver functions 219cd6484e1SRob Herring */ 220cd6484e1SRob Herring int __serdev_device_driver_register(struct serdev_device_driver *, struct module *); 221cd6484e1SRob Herring #define serdev_device_driver_register(sdrv) \ 222cd6484e1SRob Herring __serdev_device_driver_register(sdrv, THIS_MODULE) 223cd6484e1SRob Herring 224cd6484e1SRob Herring /** 225cd6484e1SRob Herring * serdev_device_driver_unregister() - unregister an serdev client driver 226cd6484e1SRob Herring * @sdrv: the driver to unregister 227cd6484e1SRob Herring */ 228cd6484e1SRob Herring static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv) 229cd6484e1SRob Herring { 230cd6484e1SRob Herring if (sdrv) 231cd6484e1SRob Herring driver_unregister(&sdrv->driver); 232cd6484e1SRob Herring } 233cd6484e1SRob Herring 234cd6484e1SRob Herring #define module_serdev_device_driver(__serdev_device_driver) \ 235cd6484e1SRob Herring module_driver(__serdev_device_driver, serdev_device_driver_register, \ 236cd6484e1SRob Herring serdev_device_driver_unregister) 237cd6484e1SRob Herring 238cd6484e1SRob Herring #else 239cd6484e1SRob Herring 240cd6484e1SRob Herring static inline int serdev_device_open(struct serdev_device *sdev) 241cd6484e1SRob Herring { 242cd6484e1SRob Herring return -ENODEV; 243cd6484e1SRob Herring } 244cd6484e1SRob Herring static inline void serdev_device_close(struct serdev_device *sdev) {} 245cd6484e1SRob Herring static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev, unsigned int baudrate) 246cd6484e1SRob Herring { 247cd6484e1SRob Herring return 0; 248cd6484e1SRob Herring } 249cd6484e1SRob Herring static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} 2506bdc00d0SStefan Wahren static inline int serdev_device_write_buf(struct serdev_device *serdev, 2516bdc00d0SStefan Wahren const unsigned char *buf, 2526bdc00d0SStefan Wahren size_t count) 2536bdc00d0SStefan Wahren { 2546bdc00d0SStefan Wahren return -ENODEV; 2556bdc00d0SStefan Wahren } 256b3f80c8fSSebastian Reichel static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} 2575659dab2SSebastian Reichel static inline int serdev_device_get_tiocm(struct serdev_device *serdev) 2585659dab2SSebastian Reichel { 25929f93a68SNeeraj Sanjay Kale return -EOPNOTSUPP; 2605659dab2SSebastian Reichel } 2615659dab2SSebastian Reichel static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear) 2625659dab2SSebastian Reichel { 26329f93a68SNeeraj Sanjay Kale return -EOPNOTSUPP; 2645659dab2SSebastian Reichel } 2658eaf839eSNeeraj Sanjay Kale static inline int serdev_device_break_ctl(struct serdev_device *serdev, int break_state) 2668eaf839eSNeeraj Sanjay Kale { 2678eaf839eSNeeraj Sanjay Kale return -EOPNOTSUPP; 2688eaf839eSNeeraj Sanjay Kale } 2696fe729c4SAndrey Smirnov static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf, 2706fe729c4SAndrey Smirnov size_t count, unsigned long timeout) 271cd6484e1SRob Herring { 272cd6484e1SRob Herring return -ENODEV; 273cd6484e1SRob Herring } 274cd6484e1SRob Herring static inline void serdev_device_write_flush(struct serdev_device *sdev) {} 275cd6484e1SRob Herring static inline int serdev_device_write_room(struct serdev_device *sdev) 276cd6484e1SRob Herring { 277cd6484e1SRob Herring return 0; 278cd6484e1SRob Herring } 279cd6484e1SRob Herring 280cd6484e1SRob Herring #define serdev_device_driver_register(x) 281cd6484e1SRob Herring #define serdev_device_driver_unregister(x) 282cd6484e1SRob Herring 283cd6484e1SRob Herring #endif /* CONFIG_SERIAL_DEV_BUS */ 284cd6484e1SRob Herring 285756db778SSebastian Reichel static inline bool serdev_device_get_cts(struct serdev_device *serdev) 286756db778SSebastian Reichel { 287756db778SSebastian Reichel int status = serdev_device_get_tiocm(serdev); 288756db778SSebastian Reichel return !!(status & TIOCM_CTS); 289756db778SSebastian Reichel } 290756db778SSebastian Reichel 291756db778SSebastian Reichel static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms) 292756db778SSebastian Reichel { 293756db778SSebastian Reichel bool signal; 294756db778SSebastian Reichel 29596e82989SAndy Shevchenko return readx_poll_timeout(serdev_device_get_cts, serdev, signal, signal == state, 29696e82989SAndy Shevchenko 2000, timeout_ms * 1000); 297756db778SSebastian Reichel } 298756db778SSebastian Reichel 299756db778SSebastian Reichel static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable) 300756db778SSebastian Reichel { 301756db778SSebastian Reichel if (enable) 302756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, TIOCM_RTS, 0); 303756db778SSebastian Reichel else 304756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS); 305756db778SSebastian Reichel } 306756db778SSebastian Reichel 3073a19cfccSUlrich Hecht int serdev_device_set_parity(struct serdev_device *serdev, 3083a19cfccSUlrich Hecht enum serdev_parity parity); 3093a19cfccSUlrich Hecht 310bed35c6dSRob Herring /* 311bed35c6dSRob Herring * serdev hooks into TTY core 312bed35c6dSRob Herring */ 313bed35c6dSRob Herring struct tty_port; 314bed35c6dSRob Herring struct tty_driver; 315bed35c6dSRob Herring 316bed35c6dSRob Herring #ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT 317bed35c6dSRob Herring struct device *serdev_tty_port_register(struct tty_port *port, 318*b286f4e8STony Lindgren struct device *host, 319bed35c6dSRob Herring struct device *parent, 320bed35c6dSRob Herring struct tty_driver *drv, int idx); 3218cde11b2SJohan Hovold int serdev_tty_port_unregister(struct tty_port *port); 322bed35c6dSRob Herring #else 323bed35c6dSRob Herring static inline struct device *serdev_tty_port_register(struct tty_port *port, 324*b286f4e8STony Lindgren struct device *host, 325bed35c6dSRob Herring struct device *parent, 326bed35c6dSRob Herring struct tty_driver *drv, int idx) 327bed35c6dSRob Herring { 328bed35c6dSRob Herring return ERR_PTR(-ENODEV); 329bed35c6dSRob Herring } 3308cde11b2SJohan Hovold static inline int serdev_tty_port_unregister(struct tty_port *port) 3318cde11b2SJohan Hovold { 3328cde11b2SJohan Hovold return -ENODEV; 3338cde11b2SJohan Hovold } 334bed35c6dSRob Herring #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ 335bed35c6dSRob Herring 3360a732d7dSAndy Shevchenko struct acpi_resource; 3370a732d7dSAndy Shevchenko struct acpi_resource_uart_serialbus; 3380a732d7dSAndy Shevchenko 3390a732d7dSAndy Shevchenko #ifdef CONFIG_ACPI 3400a732d7dSAndy Shevchenko bool serdev_acpi_get_uart_resource(struct acpi_resource *ares, 3410a732d7dSAndy Shevchenko struct acpi_resource_uart_serialbus **uart); 3420a732d7dSAndy Shevchenko #else 3430a732d7dSAndy Shevchenko static inline bool serdev_acpi_get_uart_resource(struct acpi_resource *ares, 3440a732d7dSAndy Shevchenko struct acpi_resource_uart_serialbus **uart) 3450a732d7dSAndy Shevchenko { 3460a732d7dSAndy Shevchenko return false; 3470a732d7dSAndy Shevchenko } 3480a732d7dSAndy Shevchenko #endif /* CONFIG_ACPI */ 3490a732d7dSAndy Shevchenko 350cd6484e1SRob Herring #endif /*_LINUX_SERDEV_H */ 351