diff options
author | Tomas Hlavacek <tmshlvck@gmail.com> | 2012-09-05 21:17:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-06 12:22:04 -0400 |
commit | 6915c0e487c822e2436683e14302c0b8a6155cc7 (patch) | |
tree | 3ef744c612c40517ed64d4f370a14c6c51eaab2f | |
parent | d83b54250988758cd3b9d21c242f98ae61fa1435 (diff) |
tty: uartclk value from serial_core exposed to sysfs
Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.
tty_register_device() has been generalized and refactored in order
to add support for setting drvdata and attribute_group to the device.
Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | Documentation/ABI/testing/sysfs-tty | 9 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 34 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 69 | ||||
-rw-r--r-- | include/linux/tty.h | 4 |
4 files changed, 104 insertions, 12 deletions
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index b138b663bf54..0c430150d929 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty | |||
@@ -17,3 +17,12 @@ Description: | |||
17 | device, like 'tty1'. | 17 | device, like 'tty1'. |
18 | The file supports poll() to detect virtual | 18 | The file supports poll() to detect virtual |
19 | console switches. | 19 | console switches. |
20 | |||
21 | What: /sys/class/tty/ttyS0/uartclk | ||
22 | Date: Sep 2012 | ||
23 | Contact: Tomas Hlavacek <tmshlvck@gmail.com> | ||
24 | Description: | ||
25 | Shows the current uartclk value associated with the | ||
26 | UART port in serial_core, that is bound to TTY like ttyS0. | ||
27 | uartclk = 16 * baud_base | ||
28 | |||
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 19993d89db37..f629bdf2a8cf 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -2309,6 +2309,36 @@ struct tty_driver *uart_console_device(struct console *co, int *index) | |||
2309 | return p->tty_driver; | 2309 | return p->tty_driver; |
2310 | } | 2310 | } |
2311 | 2311 | ||
2312 | static ssize_t uart_get_attr_uartclk(struct device *dev, | ||
2313 | struct device_attribute *attr, char *buf) | ||
2314 | { | ||
2315 | int ret; | ||
2316 | |||
2317 | struct tty_port *port = dev_get_drvdata(dev); | ||
2318 | struct uart_state *state = container_of(port, struct uart_state, port); | ||
2319 | mutex_lock(&state->port.mutex); | ||
2320 | ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk); | ||
2321 | mutex_unlock(&state->port.mutex); | ||
2322 | |||
2323 | return ret; | ||
2324 | } | ||
2325 | |||
2326 | static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); | ||
2327 | |||
2328 | static struct attribute *tty_dev_attrs[] = { | ||
2329 | &dev_attr_uartclk.attr, | ||
2330 | NULL, | ||
2331 | }; | ||
2332 | |||
2333 | static struct attribute_group tty_dev_attr_group = { | ||
2334 | .attrs = tty_dev_attrs, | ||
2335 | }; | ||
2336 | |||
2337 | static const struct attribute_group *tty_dev_attr_groups[] = { | ||
2338 | &tty_dev_attr_group, | ||
2339 | NULL | ||
2340 | }; | ||
2341 | |||
2312 | /** | 2342 | /** |
2313 | * uart_add_one_port - attach a driver-defined port structure | 2343 | * uart_add_one_port - attach a driver-defined port structure |
2314 | * @drv: pointer to the uart low level driver structure for this port | 2344 | * @drv: pointer to the uart low level driver structure for this port |
@@ -2362,8 +2392,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
2362 | * Register the port whether it's detected or not. This allows | 2392 | * Register the port whether it's detected or not. This allows |
2363 | * setserial to be used to alter this ports parameters. | 2393 | * setserial to be used to alter this ports parameters. |
2364 | */ | 2394 | */ |
2365 | tty_dev = tty_port_register_device(port, drv->tty_driver, uport->line, | 2395 | tty_dev = tty_register_device_attr(drv->tty_driver, uport->line, |
2366 | uport->dev); | 2396 | uport->dev, port, tty_dev_attr_groups); |
2367 | if (likely(!IS_ERR(tty_dev))) { | 2397 | if (likely(!IS_ERR(tty_dev))) { |
2368 | device_set_wakeup_capable(tty_dev, 1); | 2398 | device_set_wakeup_capable(tty_dev, 1); |
2369 | } else { | 2399 | } else { |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d3bf91a29303..dcb30d55d39c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -3041,9 +3041,39 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev, | |||
3041 | struct device *tty_register_device(struct tty_driver *driver, unsigned index, | 3041 | struct device *tty_register_device(struct tty_driver *driver, unsigned index, |
3042 | struct device *device) | 3042 | struct device *device) |
3043 | { | 3043 | { |
3044 | struct device *ret; | 3044 | return tty_register_device_attr(driver, index, device, NULL, NULL); |
3045 | } | ||
3046 | EXPORT_SYMBOL(tty_register_device); | ||
3047 | |||
3048 | /** | ||
3049 | * tty_register_device_attr - register a tty device | ||
3050 | * @driver: the tty driver that describes the tty device | ||
3051 | * @index: the index in the tty driver for this tty device | ||
3052 | * @device: a struct device that is associated with this tty device. | ||
3053 | * This field is optional, if there is no known struct device | ||
3054 | * for this tty device it can be set to NULL safely. | ||
3055 | * @drvdata: Driver data to be set to device. | ||
3056 | * @attr_grp: Attribute group to be set on device. | ||
3057 | * | ||
3058 | * Returns a pointer to the struct device for this tty device | ||
3059 | * (or ERR_PTR(-EFOO) on error). | ||
3060 | * | ||
3061 | * This call is required to be made to register an individual tty device | ||
3062 | * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If | ||
3063 | * that bit is not set, this function should not be called by a tty | ||
3064 | * driver. | ||
3065 | * | ||
3066 | * Locking: ?? | ||
3067 | */ | ||
3068 | struct device *tty_register_device_attr(struct tty_driver *driver, | ||
3069 | unsigned index, struct device *device, | ||
3070 | void *drvdata, | ||
3071 | const struct attribute_group **attr_grp) | ||
3072 | { | ||
3045 | char name[64]; | 3073 | char name[64]; |
3046 | dev_t dev = MKDEV(driver->major, driver->minor_start) + index; | 3074 | dev_t devt = MKDEV(driver->major, driver->minor_start) + index; |
3075 | struct device *dev = NULL; | ||
3076 | int retval = -ENODEV; | ||
3047 | bool cdev = false; | 3077 | bool cdev = false; |
3048 | 3078 | ||
3049 | if (index >= driver->num) { | 3079 | if (index >= driver->num) { |
@@ -3058,19 +3088,38 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, | |||
3058 | tty_line_name(driver, index, name); | 3088 | tty_line_name(driver, index, name); |
3059 | 3089 | ||
3060 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) { | 3090 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) { |
3061 | int error = tty_cdev_add(driver, dev, index, 1); | 3091 | retval = tty_cdev_add(driver, devt, index, 1); |
3062 | if (error) | 3092 | if (retval) |
3063 | return ERR_PTR(error); | 3093 | goto error; |
3064 | cdev = true; | 3094 | cdev = true; |
3065 | } | 3095 | } |
3066 | 3096 | ||
3067 | ret = device_create(tty_class, device, dev, NULL, name); | 3097 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
3068 | if (IS_ERR(ret) && cdev) | 3098 | if (!dev) { |
3069 | cdev_del(&driver->cdevs[index]); | 3099 | retval = -ENOMEM; |
3100 | goto error; | ||
3101 | } | ||
3070 | 3102 | ||
3071 | return ret; | 3103 | dev->devt = devt; |
3104 | dev->class = tty_class; | ||
3105 | dev->parent = device; | ||
3106 | dev_set_name(dev, "%s", name); | ||
3107 | dev->groups = attr_grp; | ||
3108 | dev_set_drvdata(dev, drvdata); | ||
3109 | |||
3110 | retval = device_register(dev); | ||
3111 | if (retval) | ||
3112 | goto error; | ||
3113 | |||
3114 | return dev; | ||
3115 | |||
3116 | error: | ||
3117 | put_device(dev); | ||
3118 | if (cdev) | ||
3119 | cdev_del(&driver->cdevs[index]); | ||
3120 | return ERR_PTR(retval); | ||
3072 | } | 3121 | } |
3073 | EXPORT_SYMBOL(tty_register_device); | 3122 | EXPORT_SYMBOL_GPL(tty_register_device_attr); |
3074 | 3123 | ||
3075 | /** | 3124 | /** |
3076 | * tty_unregister_device - unregister a tty device | 3125 | * tty_unregister_device - unregister a tty device |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 9892121354cd..599d60347bf0 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -412,6 +412,10 @@ extern int tty_register_driver(struct tty_driver *driver); | |||
412 | extern int tty_unregister_driver(struct tty_driver *driver); | 412 | extern int tty_unregister_driver(struct tty_driver *driver); |
413 | extern struct device *tty_register_device(struct tty_driver *driver, | 413 | extern struct device *tty_register_device(struct tty_driver *driver, |
414 | unsigned index, struct device *dev); | 414 | unsigned index, struct device *dev); |
415 | extern struct device *tty_register_device_attr(struct tty_driver *driver, | ||
416 | unsigned index, struct device *device, | ||
417 | void *drvdata, | ||
418 | const struct attribute_group **attr_grp); | ||
415 | extern void tty_unregister_device(struct tty_driver *driver, unsigned index); | 419 | extern void tty_unregister_device(struct tty_driver *driver, unsigned index); |
416 | extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, | 420 | extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, |
417 | int buflen); | 421 | int buflen); |