1*97fb5e8dSThomas 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> 105659dab2SSebastian Reichel #include <linux/termios.h> 11756db778SSebastian Reichel #include <linux/delay.h> 12cd6484e1SRob Herring 13cd6484e1SRob Herring struct serdev_controller; 14cd6484e1SRob Herring struct serdev_device; 15cd6484e1SRob Herring 16cd6484e1SRob Herring /* 17cd6484e1SRob Herring * serdev device structures 18cd6484e1SRob Herring */ 19cd6484e1SRob Herring 20cd6484e1SRob Herring /** 21cd6484e1SRob Herring * struct serdev_device_ops - Callback operations for a serdev device 2210f9e033SJohan Hovold * @receive_buf: Function called with data received from device; 2310f9e033SJohan Hovold * returns number of bytes accepted; may sleep. 2410f9e033SJohan Hovold * @write_wakeup: Function called when ready to transmit more data; must 2510f9e033SJohan Hovold * not sleep. 26cd6484e1SRob Herring */ 27cd6484e1SRob Herring struct serdev_device_ops { 28cd6484e1SRob Herring int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); 29cd6484e1SRob Herring void (*write_wakeup)(struct serdev_device *); 30cd6484e1SRob Herring }; 31cd6484e1SRob Herring 32cd6484e1SRob Herring /** 33cd6484e1SRob Herring * struct serdev_device - Basic representation of an serdev device 34cd6484e1SRob Herring * @dev: Driver model representation of the device. 35cd6484e1SRob Herring * @nr: Device number on serdev bus. 36cd6484e1SRob Herring * @ctrl: serdev controller managing this device. 37cd6484e1SRob Herring * @ops: Device operations. 386fe729c4SAndrey Smirnov * @write_comp Completion used by serdev_device_write() internally 396fe729c4SAndrey Smirnov * @write_lock Lock to serialize access when writing data 40cd6484e1SRob Herring */ 41cd6484e1SRob Herring struct serdev_device { 42cd6484e1SRob Herring struct device dev; 43cd6484e1SRob Herring int nr; 44cd6484e1SRob Herring struct serdev_controller *ctrl; 45cd6484e1SRob Herring const struct serdev_device_ops *ops; 466fe729c4SAndrey Smirnov struct completion write_comp; 476fe729c4SAndrey Smirnov struct mutex write_lock; 48cd6484e1SRob Herring }; 49cd6484e1SRob Herring 50cd6484e1SRob Herring static inline struct serdev_device *to_serdev_device(struct device *d) 51cd6484e1SRob Herring { 52cd6484e1SRob Herring return container_of(d, struct serdev_device, dev); 53cd6484e1SRob Herring } 54cd6484e1SRob Herring 55cd6484e1SRob Herring /** 56cd6484e1SRob Herring * struct serdev_device_driver - serdev slave device driver 57cd6484e1SRob Herring * @driver: serdev device drivers should initialize name field of this 58cd6484e1SRob Herring * structure. 59cd6484e1SRob Herring * @probe: binds this driver to a serdev device. 60cd6484e1SRob Herring * @remove: unbinds this driver from the serdev device. 61cd6484e1SRob Herring */ 62cd6484e1SRob Herring struct serdev_device_driver { 63cd6484e1SRob Herring struct device_driver driver; 64cd6484e1SRob Herring int (*probe)(struct serdev_device *); 65cd6484e1SRob Herring void (*remove)(struct serdev_device *); 66cd6484e1SRob Herring }; 67cd6484e1SRob Herring 68cd6484e1SRob Herring static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) 69cd6484e1SRob Herring { 70cd6484e1SRob Herring return container_of(d, struct serdev_device_driver, driver); 71cd6484e1SRob Herring } 72cd6484e1SRob Herring 733a19cfccSUlrich Hecht enum serdev_parity { 743a19cfccSUlrich Hecht SERDEV_PARITY_NONE, 753a19cfccSUlrich Hecht SERDEV_PARITY_EVEN, 763a19cfccSUlrich Hecht SERDEV_PARITY_ODD, 773a19cfccSUlrich Hecht }; 783a19cfccSUlrich Hecht 79cd6484e1SRob Herring /* 80cd6484e1SRob Herring * serdev controller structures 81cd6484e1SRob Herring */ 82cd6484e1SRob Herring struct serdev_controller_ops { 83cd6484e1SRob Herring int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t); 84cd6484e1SRob Herring void (*write_flush)(struct serdev_controller *); 85cd6484e1SRob Herring int (*write_room)(struct serdev_controller *); 86cd6484e1SRob Herring int (*open)(struct serdev_controller *); 87cd6484e1SRob Herring void (*close)(struct serdev_controller *); 88cd6484e1SRob Herring void (*set_flow_control)(struct serdev_controller *, bool); 893a19cfccSUlrich Hecht int (*set_parity)(struct serdev_controller *, enum serdev_parity); 90cd6484e1SRob Herring unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int); 91b3f80c8fSSebastian Reichel void (*wait_until_sent)(struct serdev_controller *, long); 925659dab2SSebastian Reichel int (*get_tiocm)(struct serdev_controller *); 935659dab2SSebastian Reichel int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int); 94cd6484e1SRob Herring }; 95cd6484e1SRob Herring 96cd6484e1SRob Herring /** 97cd6484e1SRob Herring * struct serdev_controller - interface to the serdev controller 98cd6484e1SRob Herring * @dev: Driver model representation of the device. 99cd6484e1SRob Herring * @nr: number identifier for this controller/bus. 100cd6484e1SRob Herring * @serdev: Pointer to slave device for this controller. 101cd6484e1SRob Herring * @ops: Controller operations. 102cd6484e1SRob Herring */ 103cd6484e1SRob Herring struct serdev_controller { 104cd6484e1SRob Herring struct device dev; 105cd6484e1SRob Herring unsigned int nr; 106cd6484e1SRob Herring struct serdev_device *serdev; 107cd6484e1SRob Herring const struct serdev_controller_ops *ops; 108cd6484e1SRob Herring }; 109cd6484e1SRob Herring 110cd6484e1SRob Herring static inline struct serdev_controller *to_serdev_controller(struct device *d) 111cd6484e1SRob Herring { 112cd6484e1SRob Herring return container_of(d, struct serdev_controller, dev); 113cd6484e1SRob Herring } 114cd6484e1SRob Herring 115cd6484e1SRob Herring static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) 116cd6484e1SRob Herring { 117cd6484e1SRob Herring return dev_get_drvdata(&serdev->dev); 118cd6484e1SRob Herring } 119cd6484e1SRob Herring 120cd6484e1SRob Herring static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data) 121cd6484e1SRob Herring { 122cd6484e1SRob Herring dev_set_drvdata(&serdev->dev, data); 123cd6484e1SRob Herring } 124cd6484e1SRob Herring 125cd6484e1SRob Herring /** 126cd6484e1SRob Herring * serdev_device_put() - decrement serdev device refcount 127cd6484e1SRob Herring * @serdev serdev device. 128cd6484e1SRob Herring */ 129cd6484e1SRob Herring static inline void serdev_device_put(struct serdev_device *serdev) 130cd6484e1SRob Herring { 131cd6484e1SRob Herring if (serdev) 132cd6484e1SRob Herring put_device(&serdev->dev); 133cd6484e1SRob Herring } 134cd6484e1SRob Herring 135cd6484e1SRob Herring static inline void serdev_device_set_client_ops(struct serdev_device *serdev, 136cd6484e1SRob Herring const struct serdev_device_ops *ops) 137cd6484e1SRob Herring { 138cd6484e1SRob Herring serdev->ops = ops; 139cd6484e1SRob Herring } 140cd6484e1SRob Herring 141cd6484e1SRob Herring static inline 142cd6484e1SRob Herring void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl) 143cd6484e1SRob Herring { 144cd6484e1SRob Herring return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL; 145cd6484e1SRob Herring } 146cd6484e1SRob Herring 147cd6484e1SRob Herring static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl, 148cd6484e1SRob Herring void *data) 149cd6484e1SRob Herring { 150cd6484e1SRob Herring dev_set_drvdata(&ctrl->dev, data); 151cd6484e1SRob Herring } 152cd6484e1SRob Herring 153cd6484e1SRob Herring /** 154cd6484e1SRob Herring * serdev_controller_put() - decrement controller refcount 155cd6484e1SRob Herring * @ctrl serdev controller. 156cd6484e1SRob Herring */ 157cd6484e1SRob Herring static inline void serdev_controller_put(struct serdev_controller *ctrl) 158cd6484e1SRob Herring { 159cd6484e1SRob Herring if (ctrl) 160cd6484e1SRob Herring put_device(&ctrl->dev); 161cd6484e1SRob Herring } 162cd6484e1SRob Herring 163cd6484e1SRob Herring struct serdev_device *serdev_device_alloc(struct serdev_controller *); 164cd6484e1SRob Herring int serdev_device_add(struct serdev_device *); 165cd6484e1SRob Herring void serdev_device_remove(struct serdev_device *); 166cd6484e1SRob Herring 167cd6484e1SRob Herring struct serdev_controller *serdev_controller_alloc(struct device *, size_t); 168cd6484e1SRob Herring int serdev_controller_add(struct serdev_controller *); 169cd6484e1SRob Herring void serdev_controller_remove(struct serdev_controller *); 170cd6484e1SRob Herring 171cd6484e1SRob Herring static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl) 172cd6484e1SRob Herring { 173cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 174cd6484e1SRob Herring 175cd6484e1SRob Herring if (!serdev || !serdev->ops->write_wakeup) 176cd6484e1SRob Herring return; 177cd6484e1SRob Herring 1789d1d994dSAndrey Smirnov serdev->ops->write_wakeup(serdev); 179cd6484e1SRob Herring } 180cd6484e1SRob Herring 181cd6484e1SRob Herring static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, 182cd6484e1SRob Herring const unsigned char *data, 183cd6484e1SRob Herring size_t count) 184cd6484e1SRob Herring { 185cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 186cd6484e1SRob Herring 187cd6484e1SRob Herring if (!serdev || !serdev->ops->receive_buf) 188fd00cf81SJohan Hovold return 0; 189cd6484e1SRob Herring 1909d1d994dSAndrey Smirnov return serdev->ops->receive_buf(serdev, data, count); 191cd6484e1SRob Herring } 192cd6484e1SRob Herring 193cd6484e1SRob Herring #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS) 194cd6484e1SRob Herring 195cd6484e1SRob Herring int serdev_device_open(struct serdev_device *); 196cd6484e1SRob Herring void serdev_device_close(struct serdev_device *); 1972cb67d20SAndrey Smirnov int devm_serdev_device_open(struct device *, struct serdev_device *); 198cd6484e1SRob Herring unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); 199cd6484e1SRob Herring void serdev_device_set_flow_control(struct serdev_device *, bool); 2006bdc00d0SStefan Wahren int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); 201b3f80c8fSSebastian Reichel void serdev_device_wait_until_sent(struct serdev_device *, long); 2025659dab2SSebastian Reichel int serdev_device_get_tiocm(struct serdev_device *); 2035659dab2SSebastian Reichel int serdev_device_set_tiocm(struct serdev_device *, int, int); 2046fe729c4SAndrey Smirnov void serdev_device_write_wakeup(struct serdev_device *); 20570d18804SJohan Hovold int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, long); 206cd6484e1SRob Herring void serdev_device_write_flush(struct serdev_device *); 207cd6484e1SRob Herring int serdev_device_write_room(struct serdev_device *); 208cd6484e1SRob Herring 209cd6484e1SRob Herring /* 210cd6484e1SRob Herring * serdev device driver functions 211cd6484e1SRob Herring */ 212cd6484e1SRob Herring int __serdev_device_driver_register(struct serdev_device_driver *, struct module *); 213cd6484e1SRob Herring #define serdev_device_driver_register(sdrv) \ 214cd6484e1SRob Herring __serdev_device_driver_register(sdrv, THIS_MODULE) 215cd6484e1SRob Herring 216cd6484e1SRob Herring /** 217cd6484e1SRob Herring * serdev_device_driver_unregister() - unregister an serdev client driver 218cd6484e1SRob Herring * @sdrv: the driver to unregister 219cd6484e1SRob Herring */ 220cd6484e1SRob Herring static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv) 221cd6484e1SRob Herring { 222cd6484e1SRob Herring if (sdrv) 223cd6484e1SRob Herring driver_unregister(&sdrv->driver); 224cd6484e1SRob Herring } 225cd6484e1SRob Herring 226cd6484e1SRob Herring #define module_serdev_device_driver(__serdev_device_driver) \ 227cd6484e1SRob Herring module_driver(__serdev_device_driver, serdev_device_driver_register, \ 228cd6484e1SRob Herring serdev_device_driver_unregister) 229cd6484e1SRob Herring 230cd6484e1SRob Herring #else 231cd6484e1SRob Herring 232cd6484e1SRob Herring static inline int serdev_device_open(struct serdev_device *sdev) 233cd6484e1SRob Herring { 234cd6484e1SRob Herring return -ENODEV; 235cd6484e1SRob Herring } 236cd6484e1SRob Herring static inline void serdev_device_close(struct serdev_device *sdev) {} 237cd6484e1SRob Herring static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev, unsigned int baudrate) 238cd6484e1SRob Herring { 239cd6484e1SRob Herring return 0; 240cd6484e1SRob Herring } 241cd6484e1SRob Herring static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} 2426bdc00d0SStefan Wahren static inline int serdev_device_write_buf(struct serdev_device *serdev, 2436bdc00d0SStefan Wahren const unsigned char *buf, 2446bdc00d0SStefan Wahren size_t count) 2456bdc00d0SStefan Wahren { 2466bdc00d0SStefan Wahren return -ENODEV; 2476bdc00d0SStefan Wahren } 248b3f80c8fSSebastian Reichel static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} 2495659dab2SSebastian Reichel static inline int serdev_device_get_tiocm(struct serdev_device *serdev) 2505659dab2SSebastian Reichel { 2515659dab2SSebastian Reichel return -ENOTSUPP; 2525659dab2SSebastian Reichel } 2535659dab2SSebastian Reichel static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear) 2545659dab2SSebastian Reichel { 2555659dab2SSebastian Reichel return -ENOTSUPP; 2565659dab2SSebastian Reichel } 2576fe729c4SAndrey Smirnov static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf, 2586fe729c4SAndrey Smirnov size_t count, unsigned long timeout) 259cd6484e1SRob Herring { 260cd6484e1SRob Herring return -ENODEV; 261cd6484e1SRob Herring } 262cd6484e1SRob Herring static inline void serdev_device_write_flush(struct serdev_device *sdev) {} 263cd6484e1SRob Herring static inline int serdev_device_write_room(struct serdev_device *sdev) 264cd6484e1SRob Herring { 265cd6484e1SRob Herring return 0; 266cd6484e1SRob Herring } 267cd6484e1SRob Herring 268cd6484e1SRob Herring #define serdev_device_driver_register(x) 269cd6484e1SRob Herring #define serdev_device_driver_unregister(x) 270cd6484e1SRob Herring 271cd6484e1SRob Herring #endif /* CONFIG_SERIAL_DEV_BUS */ 272cd6484e1SRob Herring 273756db778SSebastian Reichel static inline bool serdev_device_get_cts(struct serdev_device *serdev) 274756db778SSebastian Reichel { 275756db778SSebastian Reichel int status = serdev_device_get_tiocm(serdev); 276756db778SSebastian Reichel return !!(status & TIOCM_CTS); 277756db778SSebastian Reichel } 278756db778SSebastian Reichel 279756db778SSebastian Reichel static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms) 280756db778SSebastian Reichel { 281756db778SSebastian Reichel unsigned long timeout; 282756db778SSebastian Reichel bool signal; 283756db778SSebastian Reichel 284756db778SSebastian Reichel timeout = jiffies + msecs_to_jiffies(timeout_ms); 285756db778SSebastian Reichel while (time_is_after_jiffies(timeout)) { 286756db778SSebastian Reichel signal = serdev_device_get_cts(serdev); 287756db778SSebastian Reichel if (signal == state) 288756db778SSebastian Reichel return 0; 289756db778SSebastian Reichel usleep_range(1000, 2000); 290756db778SSebastian Reichel } 291756db778SSebastian Reichel 292756db778SSebastian Reichel return -ETIMEDOUT; 293756db778SSebastian Reichel } 294756db778SSebastian Reichel 295756db778SSebastian Reichel static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable) 296756db778SSebastian Reichel { 297756db778SSebastian Reichel if (enable) 298756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, TIOCM_RTS, 0); 299756db778SSebastian Reichel else 300756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS); 301756db778SSebastian Reichel } 302756db778SSebastian Reichel 3033a19cfccSUlrich Hecht int serdev_device_set_parity(struct serdev_device *serdev, 3043a19cfccSUlrich Hecht enum serdev_parity parity); 3053a19cfccSUlrich Hecht 306bed35c6dSRob Herring /* 307bed35c6dSRob Herring * serdev hooks into TTY core 308bed35c6dSRob Herring */ 309bed35c6dSRob Herring struct tty_port; 310bed35c6dSRob Herring struct tty_driver; 311bed35c6dSRob Herring 312bed35c6dSRob Herring #ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT 313bed35c6dSRob Herring struct device *serdev_tty_port_register(struct tty_port *port, 314bed35c6dSRob Herring struct device *parent, 315bed35c6dSRob Herring struct tty_driver *drv, int idx); 3168cde11b2SJohan Hovold int serdev_tty_port_unregister(struct tty_port *port); 317bed35c6dSRob Herring #else 318bed35c6dSRob Herring static inline struct device *serdev_tty_port_register(struct tty_port *port, 319bed35c6dSRob Herring struct device *parent, 320bed35c6dSRob Herring struct tty_driver *drv, int idx) 321bed35c6dSRob Herring { 322bed35c6dSRob Herring return ERR_PTR(-ENODEV); 323bed35c6dSRob Herring } 3248cde11b2SJohan Hovold static inline int serdev_tty_port_unregister(struct tty_port *port) 3258cde11b2SJohan Hovold { 3268cde11b2SJohan Hovold return -ENODEV; 3278cde11b2SJohan Hovold } 328bed35c6dSRob Herring #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ 329bed35c6dSRob Herring 330cd6484e1SRob Herring #endif /*_LINUX_SERDEV_H */ 331