diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2015-01-21 16:10:40 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <greg@kroah.com> | 2015-01-22 11:27:20 +0800 |
commit | 5357cf323110ee4a3f4a12870618eca28672c7b9 (patch) | |
tree | 720634bcfef7037f5431f06ffdc63dd69f74c20a /drivers/staging/greybus/pwm.c | |
parent | f587027e793cf8947c7cc408a2167db2b8218b15 (diff) | |
download | op-kernel-dev-5357cf323110ee4a3f4a12870618eca28672c7b9.zip op-kernel-dev-5357cf323110ee4a3f4a12870618eca28672c7b9.tar.gz |
greybus: Remove "-gb" suffix from .c files
Some files are prefixed with "gb-" and some are suffixed with "-gb". The
rationale behind the first one is that the modules would be named so, i.e.
gb-*.ko. But there is no reason to keep the "-gb" suffix in the second case.
Remove the unnecessary suffix.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Diffstat (limited to 'drivers/staging/greybus/pwm.c')
-rw-r--r-- | drivers/staging/greybus/pwm.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c new file mode 100644 index 0000000..91f7b87 --- /dev/null +++ b/drivers/staging/greybus/pwm.c @@ -0,0 +1,331 @@ +/* + * PWM Greybus driver. + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + * + * Released under the GPLv2 only. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/pwm.h> +#include "greybus.h" + +struct gb_pwm_chip { + struct gb_connection *connection; + u8 version_major; + u8 version_minor; + u8 pwm_max; /* max pwm number */ + + struct pwm_chip chip; + struct pwm_chip *pwm; +}; +#define pwm_chip_to_gb_pwm_chip(chip) \ + container_of(chip, struct gb_pwm_chip, chip) + +/* Version of the Greybus PWM protocol we support */ +#define GB_PWM_VERSION_MAJOR 0x00 +#define GB_PWM_VERSION_MINOR 0x01 + +/* Greybus PWM request types */ +#define GB_PWM_TYPE_INVALID 0x00 +#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01 +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 +#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */ + +/* version request has no payload */ +struct gb_pwm_proto_version_response { + __u8 major; + __u8 minor; +}; + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +}; + +struct gb_pwm_activate_request { + __u8 which; +}; + +struct gb_pwm_deactivate_request { + __u8 which; +}; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty; + __le32 period; +}; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +}; + +struct gb_pwm_enable_request { + __u8 which; +}; + +struct gb_pwm_disable_request { + __u8 which; +}; + +/* + * This request only uses the connection field, and if successful, + * fills in the major and minor protocol version of the target. + */ +static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_pwm_proto_version_response response; + int ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION, + NULL, 0, &response, sizeof(response)); + + if (ret) + return ret; + + if (response.major > GB_PWM_VERSION_MAJOR) { + pr_err("unsupported major version (%hhu > %hhu)\n", + response.major, GB_PWM_VERSION_MAJOR); + return -ENOTSUPP; + } + pwmc->version_major = response.major; + pwmc->version_minor = response.minor; + return 0; +} + +static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc) +{ + struct gb_pwm_count_response response; + int ret; + + ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT, + NULL, 0, &response, sizeof(response)); + if (ret) + return ret; + pwmc->pwm_max = response.count; + return 0; +} + +static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_activate_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_deactivate_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc, + u8 which, u32 duty, u32 period) +{ + struct gb_pwm_config_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.duty = cpu_to_le32(duty); + request.period = cpu_to_le32(period); + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG, + &request, sizeof(request), NULL, 0); +} + + +static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc, + u8 which, u8 polarity) +{ + struct gb_pwm_polarity_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + request.polarity = polarity; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_enable_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc, + u8 which) +{ + struct gb_pwm_disable_request request; + + if (which > pwmc->pwm_max) + return -EINVAL; + + request.which = which; + return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE, + &request, sizeof(request), NULL, 0); +} + +static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_activate_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) + dev_warn(chip->dev, "freeing PWM device without disabling\n"); + + gb_pwm_deactivate_operation(pwmc, pwm->hwpwm); +} + +static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns); +}; + +static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity); +}; + +static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + return gb_pwm_enable_operation(pwmc, pwm->hwpwm); +}; + +static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); + + gb_pwm_disable_operation(pwmc, pwm->hwpwm); +}; + +static const struct pwm_ops gb_pwm_ops = { + .request = gb_pwm_request, + .free = gb_pwm_free, + .config = gb_pwm_config, + .set_polarity = gb_pwm_set_polarity, + .enable = gb_pwm_enable, + .disable = gb_pwm_disable, + .owner = THIS_MODULE, +}; + +static int gb_pwm_connection_init(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc; + struct pwm_chip *pwm; + int ret; + + pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL); + if (!pwmc) + return -ENOMEM; + pwmc->connection = connection; + connection->private = pwmc; + + /* Check for compatible protocol version */ + ret = gb_pwm_proto_version_operation(pwmc); + if (ret) + goto out_err; + + /* Query number of pwms present */ + ret = gb_pwm_count_operation(pwmc); + if (ret) + goto out_err; + + pwm = &pwmc->chip; + + pwm->dev = &connection->dev; + pwm->ops = &gb_pwm_ops; + pwm->base = -1; /* Allocate base dynamically */ + pwm->npwm = pwmc->pwm_max + 1; + pwm->can_sleep = true; /* FIXME */ + + ret = pwmchip_add(pwm); + if (ret) { + pr_err("Failed to register PWM\n"); + return ret; + } + + return 0; +out_err: + kfree(pwmc); + return ret; +} + +static void gb_pwm_connection_exit(struct gb_connection *connection) +{ + struct gb_pwm_chip *pwmc = connection->private; + + if (!pwmc) + return; + + pwmchip_remove(&pwmc->chip); + /* kref_put(pwmc->connection) */ + kfree(pwmc); +} + +static struct gb_protocol pwm_protocol = { + .name = "pwm", + .id = GREYBUS_PROTOCOL_PWM, + .major = 0, + .minor = 1, + .connection_init = gb_pwm_connection_init, + .connection_exit = gb_pwm_connection_exit, + .request_recv = NULL, /* no incoming requests */ +}; + +int gb_pwm_protocol_init(void) +{ + return gb_protocol_register(&pwm_protocol); +} + +void gb_pwm_protocol_exit(void) +{ + gb_protocol_deregister(&pwm_protocol); +} |