1cd6484e1SRob Herring /* 2cd6484e1SRob Herring * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <[email protected]> 3cd6484e1SRob Herring * 4cd6484e1SRob Herring * This program is free software; you can redistribute it and/or modify 5cd6484e1SRob Herring * it under the terms of the GNU General Public License version 2 and 6cd6484e1SRob Herring * only version 2 as published by the Free Software Foundation. 7cd6484e1SRob Herring * 8cd6484e1SRob Herring * This program is distributed in the hope that it will be useful, 9cd6484e1SRob Herring * but WITHOUT ANY WARRANTY; without even the implied warranty of 10cd6484e1SRob Herring * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11cd6484e1SRob Herring * GNU General Public License for more details. 12cd6484e1SRob Herring */ 13cd6484e1SRob Herring #ifndef _LINUX_SERDEV_H 14cd6484e1SRob Herring #define _LINUX_SERDEV_H 15cd6484e1SRob Herring 16cd6484e1SRob Herring #include <linux/types.h> 17cd6484e1SRob Herring #include <linux/device.h> 185659dab2SSebastian Reichel #include <linux/termios.h> 19756db778SSebastian Reichel #include <linux/delay.h> 20cd6484e1SRob Herring 21cd6484e1SRob Herring struct serdev_controller; 22cd6484e1SRob Herring struct serdev_device; 23cd6484e1SRob Herring 24cd6484e1SRob Herring /* 25cd6484e1SRob Herring * serdev device structures 26cd6484e1SRob Herring */ 27cd6484e1SRob Herring 28cd6484e1SRob Herring /** 29cd6484e1SRob Herring * struct serdev_device_ops - Callback operations for a serdev device 30cd6484e1SRob Herring * @receive_buf: Function called with data received from device. 31cd6484e1SRob Herring * @write_wakeup: Function called when ready to transmit more data. 32cd6484e1SRob Herring */ 33cd6484e1SRob Herring struct serdev_device_ops { 34cd6484e1SRob Herring int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t); 35cd6484e1SRob Herring void (*write_wakeup)(struct serdev_device *); 36cd6484e1SRob Herring }; 37cd6484e1SRob Herring 38cd6484e1SRob Herring /** 39cd6484e1SRob Herring * struct serdev_device - Basic representation of an serdev device 40cd6484e1SRob Herring * @dev: Driver model representation of the device. 41cd6484e1SRob Herring * @nr: Device number on serdev bus. 42cd6484e1SRob Herring * @ctrl: serdev controller managing this device. 43cd6484e1SRob Herring * @ops: Device operations. 446fe729c4SAndrey Smirnov * @write_comp Completion used by serdev_device_write() internally 456fe729c4SAndrey Smirnov * @write_lock Lock to serialize access when writing data 46cd6484e1SRob Herring */ 47cd6484e1SRob Herring struct serdev_device { 48cd6484e1SRob Herring struct device dev; 49cd6484e1SRob Herring int nr; 50cd6484e1SRob Herring struct serdev_controller *ctrl; 51cd6484e1SRob Herring const struct serdev_device_ops *ops; 526fe729c4SAndrey Smirnov struct completion write_comp; 536fe729c4SAndrey Smirnov struct mutex write_lock; 54cd6484e1SRob Herring }; 55cd6484e1SRob Herring 56cd6484e1SRob Herring static inline struct serdev_device *to_serdev_device(struct device *d) 57cd6484e1SRob Herring { 58cd6484e1SRob Herring return container_of(d, struct serdev_device, dev); 59cd6484e1SRob Herring } 60cd6484e1SRob Herring 61cd6484e1SRob Herring /** 62cd6484e1SRob Herring * struct serdev_device_driver - serdev slave device driver 63cd6484e1SRob Herring * @driver: serdev device drivers should initialize name field of this 64cd6484e1SRob Herring * structure. 65cd6484e1SRob Herring * @probe: binds this driver to a serdev device. 66cd6484e1SRob Herring * @remove: unbinds this driver from the serdev device. 67cd6484e1SRob Herring */ 68cd6484e1SRob Herring struct serdev_device_driver { 69cd6484e1SRob Herring struct device_driver driver; 70cd6484e1SRob Herring int (*probe)(struct serdev_device *); 71cd6484e1SRob Herring void (*remove)(struct serdev_device *); 72cd6484e1SRob Herring }; 73cd6484e1SRob Herring 74cd6484e1SRob Herring static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) 75cd6484e1SRob Herring { 76cd6484e1SRob Herring return container_of(d, struct serdev_device_driver, driver); 77cd6484e1SRob Herring } 78cd6484e1SRob Herring 79*3a19cfccSUlrich Hecht enum serdev_parity { 80*3a19cfccSUlrich Hecht SERDEV_PARITY_NONE, 81*3a19cfccSUlrich Hecht SERDEV_PARITY_EVEN, 82*3a19cfccSUlrich Hecht SERDEV_PARITY_ODD, 83*3a19cfccSUlrich Hecht }; 84*3a19cfccSUlrich Hecht 85cd6484e1SRob Herring /* 86cd6484e1SRob Herring * serdev controller structures 87cd6484e1SRob Herring */ 88cd6484e1SRob Herring struct serdev_controller_ops { 89cd6484e1SRob Herring int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t); 90cd6484e1SRob Herring void (*write_flush)(struct serdev_controller *); 91cd6484e1SRob Herring int (*write_room)(struct serdev_controller *); 92cd6484e1SRob Herring int (*open)(struct serdev_controller *); 93cd6484e1SRob Herring void (*close)(struct serdev_controller *); 94cd6484e1SRob Herring void (*set_flow_control)(struct serdev_controller *, bool); 95*3a19cfccSUlrich Hecht int (*set_parity)(struct serdev_controller *, enum serdev_parity); 96cd6484e1SRob Herring unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int); 97b3f80c8fSSebastian Reichel void (*wait_until_sent)(struct serdev_controller *, long); 985659dab2SSebastian Reichel int (*get_tiocm)(struct serdev_controller *); 995659dab2SSebastian Reichel int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int); 100cd6484e1SRob Herring }; 101cd6484e1SRob Herring 102cd6484e1SRob Herring /** 103cd6484e1SRob Herring * struct serdev_controller - interface to the serdev controller 104cd6484e1SRob Herring * @dev: Driver model representation of the device. 105cd6484e1SRob Herring * @nr: number identifier for this controller/bus. 106cd6484e1SRob Herring * @serdev: Pointer to slave device for this controller. 107cd6484e1SRob Herring * @ops: Controller operations. 108cd6484e1SRob Herring */ 109cd6484e1SRob Herring struct serdev_controller { 110cd6484e1SRob Herring struct device dev; 111cd6484e1SRob Herring unsigned int nr; 112cd6484e1SRob Herring struct serdev_device *serdev; 113cd6484e1SRob Herring const struct serdev_controller_ops *ops; 114cd6484e1SRob Herring }; 115cd6484e1SRob Herring 116cd6484e1SRob Herring static inline struct serdev_controller *to_serdev_controller(struct device *d) 117cd6484e1SRob Herring { 118cd6484e1SRob Herring return container_of(d, struct serdev_controller, dev); 119cd6484e1SRob Herring } 120cd6484e1SRob Herring 121cd6484e1SRob Herring static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) 122cd6484e1SRob Herring { 123cd6484e1SRob Herring return dev_get_drvdata(&serdev->dev); 124cd6484e1SRob Herring } 125cd6484e1SRob Herring 126cd6484e1SRob Herring static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data) 127cd6484e1SRob Herring { 128cd6484e1SRob Herring dev_set_drvdata(&serdev->dev, data); 129cd6484e1SRob Herring } 130cd6484e1SRob Herring 131cd6484e1SRob Herring /** 132cd6484e1SRob Herring * serdev_device_put() - decrement serdev device refcount 133cd6484e1SRob Herring * @serdev serdev device. 134cd6484e1SRob Herring */ 135cd6484e1SRob Herring static inline void serdev_device_put(struct serdev_device *serdev) 136cd6484e1SRob Herring { 137cd6484e1SRob Herring if (serdev) 138cd6484e1SRob Herring put_device(&serdev->dev); 139cd6484e1SRob Herring } 140cd6484e1SRob Herring 141cd6484e1SRob Herring static inline void serdev_device_set_client_ops(struct serdev_device *serdev, 142cd6484e1SRob Herring const struct serdev_device_ops *ops) 143cd6484e1SRob Herring { 144cd6484e1SRob Herring serdev->ops = ops; 145cd6484e1SRob Herring } 146cd6484e1SRob Herring 147cd6484e1SRob Herring static inline 148cd6484e1SRob Herring void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl) 149cd6484e1SRob Herring { 150cd6484e1SRob Herring return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL; 151cd6484e1SRob Herring } 152cd6484e1SRob Herring 153cd6484e1SRob Herring static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl, 154cd6484e1SRob Herring void *data) 155cd6484e1SRob Herring { 156cd6484e1SRob Herring dev_set_drvdata(&ctrl->dev, data); 157cd6484e1SRob Herring } 158cd6484e1SRob Herring 159cd6484e1SRob Herring /** 160cd6484e1SRob Herring * serdev_controller_put() - decrement controller refcount 161cd6484e1SRob Herring * @ctrl serdev controller. 162cd6484e1SRob Herring */ 163cd6484e1SRob Herring static inline void serdev_controller_put(struct serdev_controller *ctrl) 164cd6484e1SRob Herring { 165cd6484e1SRob Herring if (ctrl) 166cd6484e1SRob Herring put_device(&ctrl->dev); 167cd6484e1SRob Herring } 168cd6484e1SRob Herring 169cd6484e1SRob Herring struct serdev_device *serdev_device_alloc(struct serdev_controller *); 170cd6484e1SRob Herring int serdev_device_add(struct serdev_device *); 171cd6484e1SRob Herring void serdev_device_remove(struct serdev_device *); 172cd6484e1SRob Herring 173cd6484e1SRob Herring struct serdev_controller *serdev_controller_alloc(struct device *, size_t); 174cd6484e1SRob Herring int serdev_controller_add(struct serdev_controller *); 175cd6484e1SRob Herring void serdev_controller_remove(struct serdev_controller *); 176cd6484e1SRob Herring 177cd6484e1SRob Herring static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl) 178cd6484e1SRob Herring { 179cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 180cd6484e1SRob Herring 181cd6484e1SRob Herring if (!serdev || !serdev->ops->write_wakeup) 182cd6484e1SRob Herring return; 183cd6484e1SRob Herring 1849d1d994dSAndrey Smirnov serdev->ops->write_wakeup(serdev); 185cd6484e1SRob Herring } 186cd6484e1SRob Herring 187cd6484e1SRob Herring static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl, 188cd6484e1SRob Herring const unsigned char *data, 189cd6484e1SRob Herring size_t count) 190cd6484e1SRob Herring { 191cd6484e1SRob Herring struct serdev_device *serdev = ctrl->serdev; 192cd6484e1SRob Herring 193cd6484e1SRob Herring if (!serdev || !serdev->ops->receive_buf) 194fd00cf81SJohan Hovold return 0; 195cd6484e1SRob Herring 1969d1d994dSAndrey Smirnov return serdev->ops->receive_buf(serdev, data, count); 197cd6484e1SRob Herring } 198cd6484e1SRob Herring 199cd6484e1SRob Herring #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS) 200cd6484e1SRob Herring 201cd6484e1SRob Herring int serdev_device_open(struct serdev_device *); 202cd6484e1SRob Herring void serdev_device_close(struct serdev_device *); 203cd6484e1SRob Herring unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); 204cd6484e1SRob Herring void serdev_device_set_flow_control(struct serdev_device *, bool); 2056bdc00d0SStefan Wahren int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); 206b3f80c8fSSebastian Reichel void serdev_device_wait_until_sent(struct serdev_device *, long); 2075659dab2SSebastian Reichel int serdev_device_get_tiocm(struct serdev_device *); 2085659dab2SSebastian Reichel int serdev_device_set_tiocm(struct serdev_device *, int, int); 2096fe729c4SAndrey Smirnov void serdev_device_write_wakeup(struct serdev_device *); 2106fe729c4SAndrey Smirnov int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, unsigned long); 211cd6484e1SRob Herring void serdev_device_write_flush(struct serdev_device *); 212cd6484e1SRob Herring int serdev_device_write_room(struct serdev_device *); 213cd6484e1SRob Herring 214cd6484e1SRob Herring /* 215cd6484e1SRob Herring * serdev device driver functions 216cd6484e1SRob Herring */ 217cd6484e1SRob Herring int __serdev_device_driver_register(struct serdev_device_driver *, struct module *); 218cd6484e1SRob Herring #define serdev_device_driver_register(sdrv) \ 219cd6484e1SRob Herring __serdev_device_driver_register(sdrv, THIS_MODULE) 220cd6484e1SRob Herring 221cd6484e1SRob Herring /** 222cd6484e1SRob Herring * serdev_device_driver_unregister() - unregister an serdev client driver 223cd6484e1SRob Herring * @sdrv: the driver to unregister 224cd6484e1SRob Herring */ 225cd6484e1SRob Herring static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv) 226cd6484e1SRob Herring { 227cd6484e1SRob Herring if (sdrv) 228cd6484e1SRob Herring driver_unregister(&sdrv->driver); 229cd6484e1SRob Herring } 230cd6484e1SRob Herring 231cd6484e1SRob Herring #define module_serdev_device_driver(__serdev_device_driver) \ 232cd6484e1SRob Herring module_driver(__serdev_device_driver, serdev_device_driver_register, \ 233cd6484e1SRob Herring serdev_device_driver_unregister) 234cd6484e1SRob Herring 235cd6484e1SRob Herring #else 236cd6484e1SRob Herring 237cd6484e1SRob Herring static inline int serdev_device_open(struct serdev_device *sdev) 238cd6484e1SRob Herring { 239cd6484e1SRob Herring return -ENODEV; 240cd6484e1SRob Herring } 241cd6484e1SRob Herring static inline void serdev_device_close(struct serdev_device *sdev) {} 242cd6484e1SRob Herring static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev, unsigned int baudrate) 243cd6484e1SRob Herring { 244cd6484e1SRob Herring return 0; 245cd6484e1SRob Herring } 246cd6484e1SRob Herring static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} 2476bdc00d0SStefan Wahren static inline int serdev_device_write_buf(struct serdev_device *serdev, 2486bdc00d0SStefan Wahren const unsigned char *buf, 2496bdc00d0SStefan Wahren size_t count) 2506bdc00d0SStefan Wahren { 2516bdc00d0SStefan Wahren return -ENODEV; 2526bdc00d0SStefan Wahren } 253b3f80c8fSSebastian Reichel static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} 2545659dab2SSebastian Reichel static inline int serdev_device_get_tiocm(struct serdev_device *serdev) 2555659dab2SSebastian Reichel { 2565659dab2SSebastian Reichel return -ENOTSUPP; 2575659dab2SSebastian Reichel } 2585659dab2SSebastian Reichel static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear) 2595659dab2SSebastian Reichel { 2605659dab2SSebastian Reichel return -ENOTSUPP; 2615659dab2SSebastian Reichel } 2626fe729c4SAndrey Smirnov static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf, 2636fe729c4SAndrey Smirnov size_t count, unsigned long timeout) 264cd6484e1SRob Herring { 265cd6484e1SRob Herring return -ENODEV; 266cd6484e1SRob Herring } 267cd6484e1SRob Herring static inline void serdev_device_write_flush(struct serdev_device *sdev) {} 268cd6484e1SRob Herring static inline int serdev_device_write_room(struct serdev_device *sdev) 269cd6484e1SRob Herring { 270cd6484e1SRob Herring return 0; 271cd6484e1SRob Herring } 272cd6484e1SRob Herring 273cd6484e1SRob Herring #define serdev_device_driver_register(x) 274cd6484e1SRob Herring #define serdev_device_driver_unregister(x) 275cd6484e1SRob Herring 276cd6484e1SRob Herring #endif /* CONFIG_SERIAL_DEV_BUS */ 277cd6484e1SRob Herring 278756db778SSebastian Reichel static inline bool serdev_device_get_cts(struct serdev_device *serdev) 279756db778SSebastian Reichel { 280756db778SSebastian Reichel int status = serdev_device_get_tiocm(serdev); 281756db778SSebastian Reichel return !!(status & TIOCM_CTS); 282756db778SSebastian Reichel } 283756db778SSebastian Reichel 284756db778SSebastian Reichel static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms) 285756db778SSebastian Reichel { 286756db778SSebastian Reichel unsigned long timeout; 287756db778SSebastian Reichel bool signal; 288756db778SSebastian Reichel 289756db778SSebastian Reichel timeout = jiffies + msecs_to_jiffies(timeout_ms); 290756db778SSebastian Reichel while (time_is_after_jiffies(timeout)) { 291756db778SSebastian Reichel signal = serdev_device_get_cts(serdev); 292756db778SSebastian Reichel if (signal == state) 293756db778SSebastian Reichel return 0; 294756db778SSebastian Reichel usleep_range(1000, 2000); 295756db778SSebastian Reichel } 296756db778SSebastian Reichel 297756db778SSebastian Reichel return -ETIMEDOUT; 298756db778SSebastian Reichel } 299756db778SSebastian Reichel 300756db778SSebastian Reichel static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable) 301756db778SSebastian Reichel { 302756db778SSebastian Reichel if (enable) 303756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, TIOCM_RTS, 0); 304756db778SSebastian Reichel else 305756db778SSebastian Reichel return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS); 306756db778SSebastian Reichel } 307756db778SSebastian Reichel 308*3a19cfccSUlrich Hecht int serdev_device_set_parity(struct serdev_device *serdev, 309*3a19cfccSUlrich Hecht enum serdev_parity parity); 310*3a19cfccSUlrich Hecht 311bed35c6dSRob Herring /* 312bed35c6dSRob Herring * serdev hooks into TTY core 313bed35c6dSRob Herring */ 314bed35c6dSRob Herring struct tty_port; 315bed35c6dSRob Herring struct tty_driver; 316bed35c6dSRob Herring 317bed35c6dSRob Herring #ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT 318bed35c6dSRob Herring struct device *serdev_tty_port_register(struct tty_port *port, 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, 324bed35c6dSRob Herring struct device *parent, 325bed35c6dSRob Herring struct tty_driver *drv, int idx) 326bed35c6dSRob Herring { 327bed35c6dSRob Herring return ERR_PTR(-ENODEV); 328bed35c6dSRob Herring } 3298cde11b2SJohan Hovold static inline int serdev_tty_port_unregister(struct tty_port *port) 3308cde11b2SJohan Hovold { 3318cde11b2SJohan Hovold return -ENODEV; 3328cde11b2SJohan Hovold } 333bed35c6dSRob Herring #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ 334bed35c6dSRob Herring 335cd6484e1SRob Herring #endif /*_LINUX_SERDEV_H */ 336