From ab525dcccfd6ad11a0313fd58222b72cee4ca7ad Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Jan 2018 10:50:34 -0200 Subject: clk: Print the clock name and warning cause When getting the clock related warnings, it is useful to know what is the clock name that is causing the problem and the cause of the problem. Add the clock name and the the warning cause to the log, so that the output becomes clearer like this: [ 2.383969] ------------[ cut here ]------------ [ 2.388720] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:814 clk_core_disable+0xd4/0xf8 [ 2.396658] uart4_ipg_gate already disabled Signed-off-by: Fabio Estevam Reviewed-by: Geert Uytterhoeven Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0f686a9dac3e..c95dc09a1ca7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -548,7 +548,8 @@ static void clk_core_rate_unprotect(struct clk_core *core) if (!core) return; - if (WARN_ON(core->protect_count == 0)) + if (WARN(core->protect_count == 0, + "%s already unprotected\n", core->name)) return; if (--core->protect_count > 0) @@ -681,16 +682,18 @@ static void clk_core_unprepare(struct clk_core *core) if (!core) return; - if (WARN_ON(core->prepare_count == 0)) + if (WARN(core->prepare_count == 0, + "%s already unprepared\n", core->name)) return; - if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL)) + if (WARN(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL, + "Unpreparing critical %s\n", core->name)) return; if (--core->prepare_count > 0) return; - WARN_ON(core->enable_count > 0); + WARN(core->enable_count > 0, "Unpreparing enabled %s\n", core->name); trace_clk_unprepare(core); @@ -808,10 +811,11 @@ static void clk_core_disable(struct clk_core *core) if (!core) return; - if (WARN_ON(core->enable_count == 0)) + if (WARN(core->enable_count == 0, "%s already disabled\n", core->name)) return; - if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL)) + if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL, + "Disabling critical %s\n", core->name)) return; if (--core->enable_count > 0) @@ -866,7 +870,8 @@ static int clk_core_enable(struct clk_core *core) if (!core) return 0; - if (WARN_ON(core->prepare_count == 0)) + if (WARN(core->prepare_count == 0, + "Enabling unprepared %s\n", core->name)) return -ESHUTDOWN; if (core->enable_count == 0) { -- cgit v1.2.3 From dcbe3ccd8ad5a0cef2a038478ad80e3d6f921815 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Sat, 17 Mar 2018 11:49:56 -0400 Subject: iio: stx104: Implement get_multiple callback The Apex Embedded Systems STX104 series of devices provides 4 TTL compatible lines of inputs accessed via a single 4-bit port. Since four input lines are acquired on a single port input read, the STX104 GPIO driver may improve multiple input reads by utilizing a get_multiple callback. This patch implements the stx104_gpio_get_multiple function which serves as the respective get_multiple callback. Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Signed-off-by: William Breathitt Gray Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stx104.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index 17b021f33180..0662ca199eb0 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -233,6 +233,16 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(inb(stx104gpio->base) & BIT(offset)); } +static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); + + *bits = inb(stx104gpio->base); + + return 0; +} + static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { @@ -342,6 +352,7 @@ static int stx104_probe(struct device *dev, unsigned int id) stx104gpio->chip.direction_input = stx104_gpio_direction_input; stx104gpio->chip.direction_output = stx104_gpio_direction_output; stx104gpio->chip.get = stx104_gpio_get; + stx104gpio->chip.get_multiple = stx104_gpio_get_multiple; stx104gpio->chip.set = stx104_gpio_set; stx104gpio->chip.set_multiple = stx104_gpio_set_multiple; stx104gpio->base = base[id] + 3; -- cgit v1.2.3 From 5a0b8cb46624cc17fda676d6ae44fb72504f0ad9 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Tue, 13 Mar 2018 14:23:28 -0700 Subject: iio: cros_ec: Move cros_ec_sensors_core.h in /include Similar to other common iio frameworks, move cros_ec_sensors_core.h from drivers/iio/common/cros_ec_sensors/ to include/linux/iio/common. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- .../iio/common/cros_ec_sensors/cros_ec_sensors.c | 3 +- .../common/cros_ec_sensors/cros_ec_sensors_core.c | 3 +- .../common/cros_ec_sensors/cros_ec_sensors_core.h | 177 -------------------- drivers/iio/light/cros_ec_light_prox.c | 3 +- drivers/iio/pressure/cros_ec_baro.c | 3 +- include/linux/iio/common/cros_ec_sensors_core.h | 180 +++++++++++++++++++++ 6 files changed, 184 insertions(+), 185 deletions(-) delete mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h create mode 100644 include/linux/iio/common/cros_ec_sensors_core.h diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 705cb3e72663..89cb0066a6e0 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,8 +32,6 @@ #include #include -#include "cros_ec_sensors_core.h" - #define CROS_EC_SENSORS_MAX_CHANNELS 4 /* State data for ec_sensors iio driver. */ diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index a620eb5ce202..07863a6226e4 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -27,8 +28,6 @@ #include #include -#include "cros_ec_sensors_core.h" - static char *cros_ec_loc[] = { [MOTIONSENSE_LOC_BASE] = "base", [MOTIONSENSE_LOC_LID] = "lid", diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h deleted file mode 100644 index 2edf68dc7336..000000000000 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * ChromeOS EC sensor hub - * - * Copyright (C) 2016 Google, Inc - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __CROS_EC_SENSORS_CORE_H -#define __CROS_EC_SENSORS_CORE_H - -#include - -enum { - CROS_EC_SENSOR_X, - CROS_EC_SENSOR_Y, - CROS_EC_SENSOR_Z, - CROS_EC_SENSOR_MAX_AXIS, -}; - -/* EC returns sensor values using signed 16 bit registers */ -#define CROS_EC_SENSOR_BITS 16 - -/* - * 4 16 bit channels are allowed. - * Good enough for current sensors, they use up to 3 16 bit vectors. - */ -#define CROS_EC_SAMPLE_SIZE (sizeof(s64) * 2) - -/* Minimum sampling period to use when device is suspending */ -#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */ - -/** - * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver - * @ec: cros EC device structure - * @cmd_lock: lock used to prevent simultaneous access to the - * commands. - * @msg: cros EC command structure - * @param: motion sensor parameters structure - * @resp: motion sensor response structure - * @type: type of motion sensor - * @loc: location where the motion sensor is placed - * @calib: calibration parameters. Note that trigger - * captured data will always provide the calibrated - * data - * @samples: static array to hold data from a single capture. - * For each channel we need 2 bytes, except for - * the timestamp. The timestamp is always last and - * is always 8-byte aligned. - * @read_ec_sensors_data: function used for accessing sensors values - * @cuur_sampl_freq: current sampling period - */ -struct cros_ec_sensors_core_state { - struct cros_ec_device *ec; - struct mutex cmd_lock; - - struct cros_ec_command *msg; - struct ec_params_motion_sense param; - struct ec_response_motion_sense *resp; - - enum motionsensor_type type; - enum motionsensor_location loc; - - s16 calib[CROS_EC_SENSOR_MAX_AXIS]; - - u8 samples[CROS_EC_SAMPLE_SIZE]; - - int (*read_ec_sensors_data)(struct iio_dev *indio_dev, - unsigned long scan_mask, s16 *data); - - int curr_sampl_freq; -}; - -/** - * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory - * @indio_dev: pointer to IIO device - * @scan_mask: bitmap of the sensor indices to scan - * @data: location to store data - * - * This is the safe function for reading the EC data. It guarantees that the - * data sampled was not modified by the EC while being read. - * - * Return: 0 on success, -errno on failure. - */ -int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask, - s16 *data); - -/** - * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol - * @indio_dev: pointer to IIO device - * @scan_mask: bitmap of the sensor indices to scan - * @data: location to store data - * - * Return: 0 on success, -errno on failure. - */ -int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, - s16 *data); - -/** - * cros_ec_sensors_core_init() - basic initialization of the core structure - * @pdev: platform device created for the sensors - * @indio_dev: iio device structure of the device - * @physical_device: true if the device refers to a physical device - * - * Return: 0 on success, -errno on failure. - */ -int cros_ec_sensors_core_init(struct platform_device *pdev, - struct iio_dev *indio_dev, bool physical_device); - -/** - * cros_ec_sensors_capture() - the trigger handler function - * @irq: the interrupt number. - * @p: a pointer to the poll function. - * - * On a trigger event occurring, if the pollfunc is attached then this - * handler is called as a threaded interrupt (and hence may sleep). It - * is responsible for grabbing data from the device and pushing it into - * the associated buffer. - * - * Return: IRQ_HANDLED - */ -irqreturn_t cros_ec_sensors_capture(int irq, void *p); - -/** - * cros_ec_motion_send_host_cmd() - send motion sense host command - * @st: pointer to state information for device - * @opt_length: optional length to reduce the response size, useful on the data - * path. Otherwise, the maximal allowed response size is used - * - * When called, the sub-command is assumed to be set in param->cmd. - * - * Return: 0 on success, -errno on failure. - */ -int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st, - u16 opt_length); - -/** - * cros_ec_sensors_core_read() - function to request a value from the sensor - * @st: pointer to state information for device - * @chan: channel specification structure table - * @val: will contain one element making up the returned value - * @val2: will contain another element making up the returned value - * @mask: specifies which values to be requested - * - * Return: the type of value returned by the device - */ -int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask); - -/** - * cros_ec_sensors_core_write() - function to write a value to the sensor - * @st: pointer to state information for device - * @chan: channel specification structure table - * @val: first part of value to write - * @val2: second part of value to write - * @mask: specifies which values to write - * - * Return: the type of value returned by the device - */ -int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, - struct iio_chan_spec const *chan, - int val, int val2, long mask); - -extern const struct dev_pm_ops cros_ec_sensors_pm_ops; - -/* List of extended channel specification for all sensors */ -extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; - -#endif /* __CROS_EC_SENSORS_CORE_H */ diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 8e8a0e7f78d1..fd1609e975ab 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -29,8 +30,6 @@ #include #include -#include "../common/cros_ec_sensors/cros_ec_sensors_core.h" - /* * We only represent one entry for light or proximity. EC is merging different * light sensors to return the what the eye would see. For proximity, we diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index 4599fde4dd25..87c07af9181f 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -28,8 +29,6 @@ #include #include -#include "../common/cros_ec_sensors/cros_ec_sensors_core.h" - /* * One channel for pressure, the other for timestamp. */ diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h new file mode 100644 index 000000000000..ce16445411ac --- /dev/null +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -0,0 +1,180 @@ +/* + * ChromeOS EC sensor hub + * + * Copyright (C) 2016 Google, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CROS_EC_SENSORS_CORE_H +#define __CROS_EC_SENSORS_CORE_H + +#include +#include +#include + +enum { + CROS_EC_SENSOR_X, + CROS_EC_SENSOR_Y, + CROS_EC_SENSOR_Z, + CROS_EC_SENSOR_MAX_AXIS, +}; + +/* EC returns sensor values using signed 16 bit registers */ +#define CROS_EC_SENSOR_BITS 16 + +/* + * 4 16 bit channels are allowed. + * Good enough for current sensors, they use up to 3 16 bit vectors. + */ +#define CROS_EC_SAMPLE_SIZE (sizeof(s64) * 2) + +/* Minimum sampling period to use when device is suspending */ +#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */ + +/** + * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver + * @ec: cros EC device structure + * @cmd_lock: lock used to prevent simultaneous access to the + * commands. + * @msg: cros EC command structure + * @param: motion sensor parameters structure + * @resp: motion sensor response structure + * @type: type of motion sensor + * @loc: location where the motion sensor is placed + * @calib: calibration parameters. Note that trigger + * captured data will always provide the calibrated + * data + * @samples: static array to hold data from a single capture. + * For each channel we need 2 bytes, except for + * the timestamp. The timestamp is always last and + * is always 8-byte aligned. + * @read_ec_sensors_data: function used for accessing sensors values + * @cuur_sampl_freq: current sampling period + */ +struct cros_ec_sensors_core_state { + struct cros_ec_device *ec; + struct mutex cmd_lock; + + struct cros_ec_command *msg; + struct ec_params_motion_sense param; + struct ec_response_motion_sense *resp; + + enum motionsensor_type type; + enum motionsensor_location loc; + + s16 calib[CROS_EC_SENSOR_MAX_AXIS]; + + u8 samples[CROS_EC_SAMPLE_SIZE]; + + int (*read_ec_sensors_data)(struct iio_dev *indio_dev, + unsigned long scan_mask, s16 *data); + + int curr_sampl_freq; +}; + +/** + * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * This is the safe function for reading the EC data. It guarantees that the + * data sampled was not modified by the EC while being read. + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask, + s16 *data); + +/** + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol + * @indio_dev: pointer to IIO device + * @scan_mask: bitmap of the sensor indices to scan + * @data: location to store data + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask, + s16 *data); + +struct platform_device; +/** + * cros_ec_sensors_core_init() - basic initialization of the core structure + * @pdev: platform device created for the sensors + * @indio_dev: iio device structure of the device + * @physical_device: true if the device refers to a physical device + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_sensors_core_init(struct platform_device *pdev, + struct iio_dev *indio_dev, bool physical_device); + +/** + * cros_ec_sensors_capture() - the trigger handler function + * @irq: the interrupt number. + * @p: a pointer to the poll function. + * + * On a trigger event occurring, if the pollfunc is attached then this + * handler is called as a threaded interrupt (and hence may sleep). It + * is responsible for grabbing data from the device and pushing it into + * the associated buffer. + * + * Return: IRQ_HANDLED + */ +irqreturn_t cros_ec_sensors_capture(int irq, void *p); + +/** + * cros_ec_motion_send_host_cmd() - send motion sense host command + * @st: pointer to state information for device + * @opt_length: optional length to reduce the response size, useful on the data + * path. Otherwise, the maximal allowed response size is used + * + * When called, the sub-command is assumed to be set in param->cmd. + * + * Return: 0 on success, -errno on failure. + */ +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st, + u16 opt_length); + +/** + * cros_ec_sensors_core_read() - function to request a value from the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: will contain one element making up the returned value + * @val2: will contain another element making up the returned value + * @mask: specifies which values to be requested + * + * Return: the type of value returned by the device + */ +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask); + +/** + * cros_ec_sensors_core_write() - function to write a value to the sensor + * @st: pointer to state information for device + * @chan: channel specification structure table + * @val: first part of value to write + * @val2: second part of value to write + * @mask: specifies which values to write + * + * Return: the type of value returned by the device + */ +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, + struct iio_chan_spec const *chan, + int val, int val2, long mask); + +extern const struct dev_pm_ops cros_ec_sensors_pm_ops; + +/* List of extended channel specification for all sensors */ +extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; + +#endif /* __CROS_EC_SENSORS_CORE_H */ -- cgit v1.2.3 From 7eb6b35d93c356f1afebbfb808bc296d6351e708 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 12 Mar 2018 14:06:53 +0200 Subject: iio: adc: ad7791: remove sample freq sysfs attributes In the current state, these attributes are broken, because they are registered already, and the kernel throws a warning. The first registration happens via the `IIO_CHAN_INFO_SAMP_FREQ` flag from the `ad_sigma_delta` driver. In this commit these attrs are removed, and in the following the IIO_CHAN_INFO_SAMP_FREQ behavior will be implemented, which replaces these hooks. This is done to make things a bit easier to review as there is a bit of overlap in the patch if it's done all at once. Fixes: a13e831fcaa7 ("staging: iio: ad7192: implement IIO_CHAN_INFO_SAMP_FREQ") Signed-off-by: Alexandru Ardelean Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7791.c | 49 ------------------------------------------------ 1 file changed, 49 deletions(-) diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 70fbf92f9827..03a5f7d6cb0c 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -244,58 +244,9 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static const char * const ad7791_sample_freq_avail[] = { - [AD7791_FILTER_RATE_120] = "120", - [AD7791_FILTER_RATE_100] = "100", - [AD7791_FILTER_RATE_33_3] = "33.3", - [AD7791_FILTER_RATE_20] = "20", - [AD7791_FILTER_RATE_16_6] = "16.6", - [AD7791_FILTER_RATE_16_7] = "16.7", - [AD7791_FILTER_RATE_13_3] = "13.3", - [AD7791_FILTER_RATE_9_5] = "9.5", -}; - -static ssize_t ad7791_read_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK; - - return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]); -} - -static ssize_t ad7791_write_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7791_state *st = iio_priv(indio_dev); - int i, ret; - - i = sysfs_match_string(ad7791_sample_freq_avail, buf); - if (i < 0) - return i; - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - st->filter &= ~AD7791_FILTER_RATE_MASK; - st->filter |= i; - ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter), - st->filter); - iio_device_release_direct_mode(indio_dev); - - return len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - ad7791_read_frequency, - ad7791_write_frequency); - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5"); static struct attribute *ad7791_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL }; -- cgit v1.2.3 From 381522c030b5c249b70f4e35e3473ba07fa2cdc5 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 12 Mar 2018 14:06:54 +0200 Subject: iio: adc: ad7791: implement IIO_CHAN_INFO_SAMP_FREQ Now that the old read/write frequency sysfs attrs have been removed, we have a clean slate to implement IIO_CHAN_INFO_SAMP_FREQ. This driver also pre-dates IIO_CHAN_INFO_SAMP_FREQ, and this change implements this behavior. The `ad7791_write_raw` would have overlapped quite a bit with the old read/write frequency functions, making things a bit harder to follow. Fixes: a13e831fcaa7 ("staging: iio: ad7192: implement IIO_CHAN_INFO_SAMP_FREQ") Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7791.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 03a5f7d6cb0c..a9ff0695ddf7 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -153,6 +153,17 @@ struct ad7791_state { const struct ad7791_chip_info *info; }; +static const int ad7791_sample_freq_avail[8][2] = { + [AD7791_FILTER_RATE_120] = { 120, 0 }, + [AD7791_FILTER_RATE_100] = { 100, 0 }, + [AD7791_FILTER_RATE_33_3] = { 33, 300000 }, + [AD7791_FILTER_RATE_20] = { 20, 0 }, + [AD7791_FILTER_RATE_16_6] = { 16, 600000 }, + [AD7791_FILTER_RATE_16_7] = { 16, 700000 }, + [AD7791_FILTER_RATE_13_3] = { 13, 300000 }, + [AD7791_FILTER_RATE_9_5] = { 9, 500000 }, +}; + static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd) { return container_of(sd, struct ad7791_state, sd); @@ -202,6 +213,7 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, { struct ad7791_state *st = iio_priv(indio_dev); bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR); + unsigned int rate; switch (info) { case IIO_CHAN_INFO_RAW: @@ -239,11 +251,53 @@ static int ad7791_read_raw(struct iio_dev *indio_dev, *val2 = chan->scan_type.realbits - 1; return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_SAMP_FREQ: + rate = st->filter & AD7791_FILTER_RATE_MASK; + *val = ad7791_sample_freq_avail[rate][0]; + *val2 = ad7791_sample_freq_avail[rate][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; } +static int ad7791_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct ad7791_state *st = iio_priv(indio_dev); + int ret, i; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) { + if (ad7791_sample_freq_avail[i][0] == val && + ad7791_sample_freq_avail[i][1] == val2) + break; + } + + if (i == ARRAY_SIZE(ad7791_sample_freq_avail)) { + ret = -EINVAL; + break; + } + + st->filter &= ~AD7791_FILTER_RATE_MASK; + st->filter |= i; + ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, + sizeof(st->filter), + st->filter); + break; + default: + ret = -EINVAL; + } + + iio_device_release_direct_mode(indio_dev); + return ret; +} + static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5"); static struct attribute *ad7791_attributes[] = { @@ -257,12 +311,14 @@ static const struct attribute_group ad7791_attribute_group = { static const struct iio_info ad7791_info = { .read_raw = &ad7791_read_raw, + .write_raw = &ad7791_write_raw, .attrs = &ad7791_attribute_group, .validate_trigger = ad_sd_validate_trigger, }; static const struct iio_info ad7791_no_filter_info = { .read_raw = &ad7791_read_raw, + .write_raw = &ad7791_write_raw, .validate_trigger = ad_sd_validate_trigger, }; -- cgit v1.2.3 From 192af06a287bbfcae0de8fa456dca15767ecd056 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 12 Mar 2018 17:48:15 +0200 Subject: iio: adc: ad7780: remove IIO_CHAN_INFO_SAMP_FREQ support The `ad7780` driver does not implement setting/getting the sampling frequency. For the ad7780/ad7781 devices, the control is done via an external pin, and the ad7170/ad7171 devices have a fixed sampling rate (so, no control). For these devices, and similar other that may be added later on, a AD_SD_CHANNEL_NO_SAMPLE_FREQ() macro has been added, which doesn't set the IIO_CHAN_INFO_SAMP_FREQ flag. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7780.c | 2 +- include/linux/iio/adc/ad_sigma_delta.h | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index a7797af579b9..16d72072c076 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -128,7 +128,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { }; #define AD7780_CHANNEL(bits, wordsize) \ - AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits) + AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits) static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { [ID_AD7170] = { diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index 1fc7abd28b0b..730ead1a46df 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -127,7 +127,7 @@ void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev); int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig); #define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ - _storagebits, _shift, _extend_name, _type) \ + _storagebits, _shift, _extend_name, _type, _mask_all) \ { \ .type = (_type), \ .differential = (_channel2 == -1 ? 0 : 1), \ @@ -139,7 +139,7 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig); .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_OFFSET), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all = _mask_all, \ .scan_index = (_si), \ .scan_type = { \ .sign = 'u', \ @@ -153,25 +153,35 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig); #define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ _storagebits, _shift) \ __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ - _storagebits, _shift, NULL, IIO_VOLTAGE) + _storagebits, _shift, NULL, IIO_VOLTAGE, \ + BIT(IIO_CHAN_INFO_SAMP_FREQ)) #define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \ _storagebits, _shift) \ __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \ - _storagebits, _shift, "shorted", IIO_VOLTAGE) + _storagebits, _shift, "shorted", IIO_VOLTAGE, \ + BIT(IIO_CHAN_INFO_SAMP_FREQ)) #define AD_SD_CHANNEL(_si, _channel, _address, _bits, \ _storagebits, _shift) \ __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \ - _storagebits, _shift, NULL, IIO_VOLTAGE) + _storagebits, _shift, NULL, IIO_VOLTAGE, \ + BIT(IIO_CHAN_INFO_SAMP_FREQ)) + +#define AD_SD_CHANNEL_NO_SAMP_FREQ(_si, _channel, _address, _bits, \ + _storagebits, _shift) \ + __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \ + _storagebits, _shift, NULL, IIO_VOLTAGE, 0) #define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \ __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \ - _storagebits, _shift, NULL, IIO_TEMP) + _storagebits, _shift, NULL, IIO_TEMP, \ + BIT(IIO_CHAN_INFO_SAMP_FREQ)) #define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \ _shift) \ __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \ - _storagebits, _shift, "supply", IIO_VOLTAGE) + _storagebits, _shift, "supply", IIO_VOLTAGE, \ + BIT(IIO_CHAN_INFO_SAMP_FREQ)) #endif -- cgit v1.2.3 From 241b91aee5d58da51b650f771132f178028322fc Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:18 +0530 Subject: Staging: iio: accel: adis16201: Rename few macro definitions Rename the macro definitions with suitable names specifying their purpose. * ADIS16201_STARTUP_DELAY_MS: Remove the comment specifying the delay in microseconds and rename it with addtition of _MS suffix. * ADIS16201_MSC_CTRL_ACTIVE_DATA_RDY_HIGH: Rename the macro to make it similar to other misc control registers which denotes the data ready polarity. * ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT: Rename to denote it is a failure bit. * ADIS16201_GLOB_CMD_FACTORY_RESET: Remove ambiguous _CAL suffix and add _RESET suffix instead to denote factory reset command. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 0fae8aaf1cf4..767ebf0901f6 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -20,7 +20,7 @@ #include #include -#define ADIS16201_STARTUP_DELAY 220 /* ms */ +#define ADIS16201_STARTUP_DELAY_MS 220 /* Flash memory write count */ #define ADIS16201_FLASH_CNT 0x00 @@ -118,7 +118,7 @@ #define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1) +#define ADIS16201_MSC_CTRL_ACTIVE_DATA_RDY_HIGH BIT(1) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ #define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) @@ -135,7 +135,7 @@ #define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 /* Flash update failure */ -#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2 +#define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2 /* Power supply above 3.625 V */ #define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 @@ -146,7 +146,7 @@ /* GLOB_CMD */ #define ADIS16201_GLOB_CMD_SW_RESET BIT(7) -#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1) +#define ADIS16201_GLOB_CMD_FACTORY_RESET BIT(1) #define ADIS16201_ERROR_ACTIVE BIT(14) @@ -290,7 +290,7 @@ static const struct iio_info adis16201_info = { static const char * const adis16201_status_error_msgs[] = { [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", - [ADIS16201_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", + [ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT] = "Flash update failed", [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V", }; @@ -303,11 +303,11 @@ static const struct adis_data adis16201_data = { .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16201_STARTUP_DELAY, + .startup_delay = ADIS16201_STARTUP_DELAY_MS, .status_error_msgs = adis16201_status_error_msgs, .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | - BIT(ADIS16201_DIAG_STAT_FLASH_UPT_BIT) | + BIT(ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT) | BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) | BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT), }; -- cgit v1.2.3 From 395f42cb389ff589ecb46e51bcbe55a7b220679b Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:19 +0530 Subject: Staging: iio: accel: adis16201: Remove unnecessary comments Remove few unnecessary comments since the macro definitions clearly justify their purpose. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 36 ----------------------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 767ebf0901f6..6c06c0d71950 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -22,96 +22,66 @@ #define ADIS16201_STARTUP_DELAY_MS 220 -/* Flash memory write count */ #define ADIS16201_FLASH_CNT 0x00 -/* Output, power supply */ #define ADIS16201_SUPPLY_OUT 0x02 -/* Output, x-axis accelerometer */ #define ADIS16201_XACCL_OUT 0x04 -/* Output, y-axis accelerometer */ #define ADIS16201_YACCL_OUT 0x06 -/* Output, auxiliary ADC input */ #define ADIS16201_AUX_ADC 0x08 -/* Output, temperature */ #define ADIS16201_TEMP_OUT 0x0A -/* Output, x-axis inclination */ #define ADIS16201_XINCL_OUT 0x0C -/* Output, y-axis inclination */ #define ADIS16201_YINCL_OUT 0x0E -/* Calibration, x-axis acceleration offset */ #define ADIS16201_XACCL_OFFS 0x10 -/* Calibration, y-axis acceleration offset */ #define ADIS16201_YACCL_OFFS 0x12 -/* x-axis acceleration scale factor */ #define ADIS16201_XACCL_SCALE 0x14 -/* y-axis acceleration scale factor */ #define ADIS16201_YACCL_SCALE 0x16 -/* Calibration, x-axis inclination offset */ #define ADIS16201_XINCL_OFFS 0x18 -/* Calibration, y-axis inclination offset */ #define ADIS16201_YINCL_OFFS 0x1A -/* x-axis inclination scale factor */ #define ADIS16201_XINCL_SCALE 0x1C -/* y-axis inclination scale factor */ #define ADIS16201_YINCL_SCALE 0x1E -/* Alarm 1 amplitude threshold */ #define ADIS16201_ALM_MAG1 0x20 -/* Alarm 2 amplitude threshold */ #define ADIS16201_ALM_MAG2 0x22 -/* Alarm 1, sample period */ #define ADIS16201_ALM_SMPL1 0x24 -/* Alarm 2, sample period */ #define ADIS16201_ALM_SMPL2 0x26 -/* Alarm control */ #define ADIS16201_ALM_CTRL 0x28 -/* Auxiliary DAC data */ #define ADIS16201_AUX_DAC 0x30 -/* General-purpose digital input/output control */ #define ADIS16201_GPIO_CTRL 0x32 -/* Miscellaneous control */ #define ADIS16201_MSC_CTRL 0x34 -/* Internal sample period (rate) control */ #define ADIS16201_SMPL_PRD 0x36 /* Operation, filter configuration */ #define ADIS16201_AVG_CNT 0x38 -/* Operation, sleep mode control */ #define ADIS16201_SLP_CNT 0x3A -/* Diagnostics, system status register */ #define ADIS16201_DIAG_STAT 0x3C -/* Operation, system command register */ #define ADIS16201_GLOB_CMD 0x3E -/* MSC_CTRL */ -/* Self-test enable */ #define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) /* Data-ready enable: 1 = enabled, 0 = disabled */ @@ -123,18 +93,13 @@ /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ #define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) -/* DIAG_STAT */ -/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16201_DIAG_STAT_ALARM2 BIT(9) -/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ #define ADIS16201_DIAG_STAT_ALARM1 BIT(8) -/* SPI communications failure */ #define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 -/* Flash update failure */ #define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2 /* Power supply above 3.625 V */ @@ -143,7 +108,6 @@ /* Power supply below 3.15 V */ #define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 -/* GLOB_CMD */ #define ADIS16201_GLOB_CMD_SW_RESET BIT(7) #define ADIS16201_GLOB_CMD_FACTORY_RESET BIT(1) -- cgit v1.2.3 From a58efed31388e8ebddfb5ea0466178d97c70af70 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:20 +0530 Subject: Staging: iio: accel: adis16201: Add _REG suffix to registers Add a _REG suffix to distinguish between registers and the register bit fileds. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 84 +++++++++++++++++------------------ 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 6c06c0d71950..0c63cd0093eb 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -24,62 +24,62 @@ #define ADIS16201_FLASH_CNT 0x00 -#define ADIS16201_SUPPLY_OUT 0x02 +#define ADIS16201_SUPPLY_OUT_REG 0x02 -#define ADIS16201_XACCL_OUT 0x04 +#define ADIS16201_XACCL_OUT_REG 0x04 -#define ADIS16201_YACCL_OUT 0x06 +#define ADIS16201_YACCL_OUT_REG 0x06 -#define ADIS16201_AUX_ADC 0x08 +#define ADIS16201_AUX_ADC_REG 0x08 -#define ADIS16201_TEMP_OUT 0x0A +#define ADIS16201_TEMP_OUT_REG 0x0A -#define ADIS16201_XINCL_OUT 0x0C +#define ADIS16201_XINCL_OUT_REG 0x0C -#define ADIS16201_YINCL_OUT 0x0E +#define ADIS16201_YINCL_OUT_REG 0x0E -#define ADIS16201_XACCL_OFFS 0x10 +#define ADIS16201_XACCL_OFFS_REG 0x10 -#define ADIS16201_YACCL_OFFS 0x12 +#define ADIS16201_YACCL_OFFS_REG 0x12 -#define ADIS16201_XACCL_SCALE 0x14 +#define ADIS16201_XACCL_SCALE_REG 0x14 -#define ADIS16201_YACCL_SCALE 0x16 +#define ADIS16201_YACCL_SCALE_REG 0x16 -#define ADIS16201_XINCL_OFFS 0x18 +#define ADIS16201_XINCL_OFFS_REG 0x18 -#define ADIS16201_YINCL_OFFS 0x1A +#define ADIS16201_YINCL_OFFS_REG 0x1A -#define ADIS16201_XINCL_SCALE 0x1C +#define ADIS16201_XINCL_SCALE_REG 0x1C -#define ADIS16201_YINCL_SCALE 0x1E +#define ADIS16201_YINCL_SCALE_REG 0x1E -#define ADIS16201_ALM_MAG1 0x20 +#define ADIS16201_ALM_MAG1_REG 0x20 -#define ADIS16201_ALM_MAG2 0x22 +#define ADIS16201_ALM_MAG2_REG 0x22 -#define ADIS16201_ALM_SMPL1 0x24 +#define ADIS16201_ALM_SMPL1_REG 0x24 -#define ADIS16201_ALM_SMPL2 0x26 +#define ADIS16201_ALM_SMPL2_REG 0x26 -#define ADIS16201_ALM_CTRL 0x28 +#define ADIS16201_ALM_CTRL_REG 0x28 -#define ADIS16201_AUX_DAC 0x30 +#define ADIS16201_AUX_DAC_REG 0x30 -#define ADIS16201_GPIO_CTRL 0x32 +#define ADIS16201_GPIO_CTRL_REG 0x32 -#define ADIS16201_MSC_CTRL 0x34 +#define ADIS16201_MSC_CTRL_REG 0x34 -#define ADIS16201_SMPL_PRD 0x36 +#define ADIS16201_SMPL_PRD_REG 0x36 /* Operation, filter configuration */ -#define ADIS16201_AVG_CNT 0x38 +#define ADIS16201_AVG_CNT_REG 0x38 -#define ADIS16201_SLP_CNT 0x3A +#define ADIS16201_SLP_CNT_REG 0x3A -#define ADIS16201_DIAG_STAT 0x3C +#define ADIS16201_DIAG_STAT_REG 0x3C -#define ADIS16201_GLOB_CMD 0x3E +#define ADIS16201_GLOB_CMD_REG 0x3E #define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) @@ -125,10 +125,10 @@ enum adis16201_scan { }; static const u8 adis16201_addresses[] = { - [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS, - [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS, - [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS, - [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS, + [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS_REG, + [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS_REG, + [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS_REG, + [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS_REG, }; static int adis16201_read_raw(struct iio_dev *indio_dev, @@ -232,16 +232,16 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16201_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12), - ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12), - ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT_REG, ADIS16201_SCAN_SUPPLY, 0, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT_REG, ADIS16201_SCAN_TEMP, 0, 12), + ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT_REG, ADIS16201_SCAN_ACC_X, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, + ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT_REG, ADIS16201_SCAN_ACC_Y, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12), - ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X, + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12), + ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y, + ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), IIO_CHAN_SOFT_TIMESTAMP(7) }; @@ -261,9 +261,9 @@ static const char * const adis16201_status_error_msgs[] = { static const struct adis_data adis16201_data = { .read_delay = 20, - .msc_ctrl_reg = ADIS16201_MSC_CTRL, - .glob_cmd_reg = ADIS16201_GLOB_CMD, - .diag_stat_reg = ADIS16201_DIAG_STAT, + .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG, + .glob_cmd_reg = ADIS16201_GLOB_CMD_REG, + .diag_stat_reg = ADIS16201_DIAG_STAT_REG, .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, -- cgit v1.2.3 From 0d0f97d896d7813bfbc19c4650d797f938c4c198 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:21 +0530 Subject: Staging: iio: accel: adis16201: Group register definitions Group register definitions with its register field bits to improve readability and easy identification. A small comment is also added to denote the purpose/functionality of the grouped register definitions. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 138 +++++++++++++--------------------- 1 file changed, 54 insertions(+), 84 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 0c63cd0093eb..4a65e9a3a775 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -20,99 +20,69 @@ #include #include -#define ADIS16201_STARTUP_DELAY_MS 220 - -#define ADIS16201_FLASH_CNT 0x00 - -#define ADIS16201_SUPPLY_OUT_REG 0x02 - -#define ADIS16201_XACCL_OUT_REG 0x04 - -#define ADIS16201_YACCL_OUT_REG 0x06 - -#define ADIS16201_AUX_ADC_REG 0x08 - -#define ADIS16201_TEMP_OUT_REG 0x0A - -#define ADIS16201_XINCL_OUT_REG 0x0C - -#define ADIS16201_YINCL_OUT_REG 0x0E - -#define ADIS16201_XACCL_OFFS_REG 0x10 - -#define ADIS16201_YACCL_OFFS_REG 0x12 - -#define ADIS16201_XACCL_SCALE_REG 0x14 - -#define ADIS16201_YACCL_SCALE_REG 0x16 - -#define ADIS16201_XINCL_OFFS_REG 0x18 - -#define ADIS16201_YINCL_OFFS_REG 0x1A - -#define ADIS16201_XINCL_SCALE_REG 0x1C - -#define ADIS16201_YINCL_SCALE_REG 0x1E - -#define ADIS16201_ALM_MAG1_REG 0x20 - -#define ADIS16201_ALM_MAG2_REG 0x22 - -#define ADIS16201_ALM_SMPL1_REG 0x24 - -#define ADIS16201_ALM_SMPL2_REG 0x26 - -#define ADIS16201_ALM_CTRL_REG 0x28 - -#define ADIS16201_AUX_DAC_REG 0x30 - -#define ADIS16201_GPIO_CTRL_REG 0x32 - -#define ADIS16201_MSC_CTRL_REG 0x34 - -#define ADIS16201_SMPL_PRD_REG 0x36 - +#define ADIS16201_STARTUP_DELAY_MS 220 +#define ADIS16201_FLASH_CNT 0x00 + +/* Data Output Register Information */ +#define ADIS16201_SUPPLY_OUT_REG 0x02 +#define ADIS16201_XACCL_OUT_REG 0x04 +#define ADIS16201_YACCL_OUT_REG 0x06 +#define ADIS16201_AUX_ADC_REG 0x08 +#define ADIS16201_TEMP_OUT_REG 0x0A +#define ADIS16201_XINCL_OUT_REG 0x0C +#define ADIS16201_YINCL_OUT_REG 0x0E + +/* Calibration Register Definition */ +#define ADIS16201_XACCL_OFFS_REG 0x10 +#define ADIS16201_YACCL_OFFS_REG 0x12 +#define ADIS16201_XACCL_SCALE_REG 0x14 +#define ADIS16201_YACCL_SCALE_REG 0x16 +#define ADIS16201_XINCL_OFFS_REG 0x18 +#define ADIS16201_YINCL_OFFS_REG 0x1A +#define ADIS16201_XINCL_SCALE_REG 0x1C +#define ADIS16201_YINCL_SCALE_REG 0x1E + +/* Alarm Register Definition */ +#define ADIS16201_ALM_MAG1_REG 0x20 +#define ADIS16201_ALM_MAG2_REG 0x22 +#define ADIS16201_ALM_SMPL1_REG 0x24 +#define ADIS16201_ALM_SMPL2_REG 0x26 +#define ADIS16201_ALM_CTRL_REG 0x28 + +#define ADIS16201_AUX_DAC_REG 0x30 +#define ADIS16201_GPIO_CTRL_REG 0x32 +#define ADIS16201_SMPL_PRD_REG 0x36 /* Operation, filter configuration */ -#define ADIS16201_AVG_CNT_REG 0x38 - -#define ADIS16201_SLP_CNT_REG 0x3A - -#define ADIS16201_DIAG_STAT_REG 0x3C - -#define ADIS16201_GLOB_CMD_REG 0x3E - - -#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) +#define ADIS16201_AVG_CNT_REG 0x38 +#define ADIS16201_SLP_CNT_REG 0x3A +/* Miscellaneous Control Register Definition */ +#define ADIS16201_MSC_CTRL_REG 0x34 +#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8) /* Data-ready enable: 1 = enabled, 0 = disabled */ -#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) - +#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2) /* Data-ready polarity: 1 = active high, 0 = active low */ -#define ADIS16201_MSC_CTRL_ACTIVE_DATA_RDY_HIGH BIT(1) - +#define ADIS16201_MSC_CTRL_ACTIVE_DATA_RDY_HIGH BIT(1) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ -#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) - - -#define ADIS16201_DIAG_STAT_ALARM2 BIT(9) - -#define ADIS16201_DIAG_STAT_ALARM1 BIT(8) - -#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 - -#define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2 - +#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0) + +/* Diagnostics System Status Register Definition */ +#define ADIS16201_DIAG_STAT_REG 0x3C +#define ADIS16201_DIAG_STAT_ALARM2 BIT(9) +#define ADIS16201_DIAG_STAT_ALARM1 BIT(8) +#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 +#define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2 /* Power supply above 3.625 V */ -#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 - +#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply below 3.15 V */ -#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 - +#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0 -#define ADIS16201_GLOB_CMD_SW_RESET BIT(7) -#define ADIS16201_GLOB_CMD_FACTORY_RESET BIT(1) +/* System Command Register Definition */ +#define ADIS16201_GLOB_CMD_REG 0x3E +#define ADIS16201_GLOB_CMD_SW_RESET BIT(7) +#define ADIS16201_GLOB_CMD_FACTORY_RESET BIT(1) -#define ADIS16201_ERROR_ACTIVE BIT(14) +#define ADIS16201_ERROR_ACTIVE BIT(14) enum adis16201_scan { ADIS16201_SCAN_ACC_X, -- cgit v1.2.3 From 57f9386405a2ec7617d4d3b4cd1dc6c7fe299565 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:22 +0530 Subject: Staging: iio: accel: adis16201: Add comments about units in read_raw() Clarify the conversion and formation of resultant data in the adis16201_read_raw() with sufficient comments and remove the unnecessary comments. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 4a65e9a3a775..87ad3d421c12 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -120,31 +120,43 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_VOLTAGE: if (chan->channel == 0) { + /* Voltage base units are mV hence 1.22 mV */ *val = 1; - *val2 = 220000; /* 1.22 mV */ + *val2 = 220000; } else { + /* Voltage base units are mV hence 0.61 mV */ *val = 0; - *val2 = 610000; /* 0.610 mV */ + *val2 = 610000; } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = -470; /* 0.47 C */ + *val = -470; *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: + /* + * IIO base unit for sensitivity of accelerometer + * is milli g. + * 1 LSB represents 0.244 mg. + */ *val = 0; - *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ + *val2 = IIO_G_TO_M_S_2(462400); return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: *val = 0; - *val2 = 100000; /* 0.1 degree */ + *val2 = 100000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25000 / -470 - 1278; /* 25 C = 1278 */ + /* + * The raw ADC value is 1278 when the temperature + * is 25 degrees and the scale factor per milli + * degree celcius is -470. + */ + *val = 25000 / -470 - 1278; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { @@ -252,13 +264,11 @@ static int adis16201_probe(struct spi_device *spi) struct adis *st; struct iio_dev *indio_dev; - /* setup the industrialio driver allocated elements */ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - /* this is only used for removal purposes */ spi_set_drvdata(spi, indio_dev); indio_dev->name = spi->dev.driver->name; @@ -277,7 +287,6 @@ static int adis16201_probe(struct spi_device *spi) if (ret) return ret; - /* Get the device into a sane initial state */ ret = adis_initial_startup(st); if (ret) goto error_cleanup_buffer_trigger; -- cgit v1.2.3 From e7f3bfb7eb7d9307c0c157f82fceb228f0aec1d9 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:23 +0530 Subject: Staging: iio: accel: adis16201: Use sign_extend32 function Use sign_extned32() for 32 bit sign extending rather than hard coding. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 87ad3d421c12..526dde481f84 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -173,9 +173,8 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, ret = adis_read_reg_16(st, addr, &val16); if (ret) return ret; - val16 &= (1 << bits) - 1; - val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); - *val = val16; + + *val = sign_extend32(val16, bits - 1); return IIO_VAL_INT; } -- cgit v1.2.3 From 58f368f509a6cd18386e812af8681911b3a0f0e0 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:24 +0530 Subject: Staging: iio: accel: adis16201: Prefer reverse christmas tree ordering Prefer reverse christmas tree ordering of declarations to improve readability. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 526dde481f84..67a24eed1a58 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -259,9 +259,9 @@ static const struct adis_data adis16201_data = { static int adis16201_probe(struct spi_device *spi) { - int ret; - struct adis *st; struct iio_dev *indio_dev; + struct adis *st; + int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) -- cgit v1.2.3 From 211d71af696cba4fbaacd87931ce07fc61413775 Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Sat, 17 Mar 2018 01:36:25 +0530 Subject: Staging: iio: accel: adis16201: Adjust argument to match open parentheses In adis16201_read_raw() adjust an argument to match an open parentheses using tabs and spaces. Signed-off-by: Himanshu Jha Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16201.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/accel/adis16201.c b/drivers/staging/iio/accel/adis16201.c index 67a24eed1a58..97e25a3e4573 100644 --- a/drivers/staging/iio/accel/adis16201.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -115,7 +115,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: return adis_single_conversion(indio_dev, chan, - ADIS16201_ERROR_ACTIVE, val); + ADIS16201_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: -- cgit v1.2.3 From bdc3bbdd40ba90ce2953af01007036191572720b Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Thu, 8 Mar 2018 12:48:12 +0530 Subject: clk: qcom: Clear hardware clock control bit of RCG For upcoming targets like sdm845, POR value of the hardware clock control bit is set for most of root clocks which needs to be cleared for software to be able to control. For older targets like MSM8996, this bit is reserved bit and having POR value as 0 so this patch will work for the older targets too. So update the configuration mask to take care of the same to clear hardware clock control bit. Signed-off-by: Amit Nischal Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index bbeaf9c09dbb..e63db103f24e 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -42,6 +42,7 @@ #define CFG_MODE_SHIFT 12 #define CFG_MODE_MASK (0x3 << CFG_MODE_SHIFT) #define CFG_MODE_DUAL_EDGE (0x2 << CFG_MODE_SHIFT) +#define CFG_HW_CLK_CTRL_MASK BIT(20) #define M_REG 0x8 #define N_REG 0xc @@ -276,7 +277,7 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) } mask = BIT(rcg->hid_width) - 1; - mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK; + mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK; cfg = f->pre_div << CFG_SRC_DIV_SHIFT; cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; if (rcg->mnd_width && f->n && (f->m != f->n)) -- cgit v1.2.3 From 687d7a0caa7736de53e3c5efdef6b5343d1470ac Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Thu, 8 Mar 2018 12:48:14 +0530 Subject: clk: qcom: Add support for controlling Fabia PLL Fabia PLL is a Digital Frequency Locked Loop (DFLL) clock generator which has a wide range of frequency output. It supports dynamic updating of the output frequency ("frequency slewing") without need to turn off the PLL before configuration. Add support for initial configuration and programming sequence to control fabia PLLs. Signed-off-by: Amit Nischal [sboyd: Shorten code a little] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 301 ++++++++++++++++++++++++++++++++++++++- drivers/clk/qcom/clk-alpha-pll.h | 18 ++- 2 files changed, 311 insertions(+), 8 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 6d04cd96482a..9722b701fbdb 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -58,6 +58,8 @@ #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) +#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) +#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [CLK_ALPHA_PLL_TYPE_DEFAULT] = { @@ -90,6 +92,18 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_TEST_CTL] = 0x1c, [PLL_OFF_STATUS] = 0x24, }, + [CLK_ALPHA_PLL_TYPE_FABIA] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_USER_CTL_U] = 0x10, + [PLL_OFF_CONFIG_CTL] = 0x14, + [PLL_OFF_CONFIG_CTL_U] = 0x18, + [PLL_OFF_TEST_CTL] = 0x1c, + [PLL_OFF_TEST_CTL_U] = 0x20, + [PLL_OFF_STATUS] = 0x24, + [PLL_OFF_OPMODE] = 0x2c, + [PLL_OFF_FRAC] = 0x38, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -108,6 +122,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_HUAYRA_N_MASK 0xff #define PLL_HUAYRA_ALPHA_WIDTH 16 +#define FABIA_OPMODE_STANDBY 0x0 +#define FABIA_OPMODE_RUN 0x1 + +#define FABIA_PLL_OUT_MASK 0x7 +#define FABIA_PLL_RATE_MARGIN 500 + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -441,16 +461,12 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) return alpha_pll_calc_rate(prate, l, a, alpha_width); } -static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll, - int (*is_enabled)(struct clk_hw *)) + +static int __clk_alpha_pll_update_latch(struct clk_alpha_pll *pll) { int ret; u32 mode; - if (!is_enabled(&pll->clkr.hw) || - !(pll->flags & SUPPORTS_DYNAMIC_UPDATE)) - return 0; - regmap_read(pll->clkr.regmap, PLL_MODE(pll), &mode); /* Latch the input to the PLL */ @@ -489,6 +505,16 @@ static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll, return 0; } +static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll, + int (*is_enabled)(struct clk_hw *)) +{ + if (!is_enabled(&pll->clkr.hw) || + !(pll->flags & SUPPORTS_DYNAMIC_UPDATE)) + return 0; + + return __clk_alpha_pll_update_latch(pll); +} + static int __clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate, int (*is_enabled)(struct clk_hw *)) @@ -832,3 +858,264 @@ const struct clk_ops clk_alpha_pll_postdiv_ro_ops = { .recalc_rate = clk_alpha_pll_postdiv_recalc_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops); + +void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + u32 val, mask; + + if (config->l) + regmap_write(regmap, PLL_L_VAL(pll), config->l); + + if (config->alpha) + regmap_write(regmap, PLL_FRAC(pll), config->alpha); + + if (config->config_ctl_val) + regmap_write(regmap, PLL_CONFIG_CTL(pll), + config->config_ctl_val); + + if (config->post_div_mask) { + mask = config->post_div_mask; + val = config->post_div_val; + regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); + } + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, + PLL_UPDATE_BYPASS); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} + +static int alpha_pll_fabia_enable(struct clk_hw *hw) +{ + int ret; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 val, opmode_val; + struct regmap *regmap = pll->clkr.regmap; + + ret = regmap_read(regmap, PLL_MODE(pll), &val); + if (ret) + return ret; + + /* If in FSM mode, just vote for it */ + if (val & PLL_VOTE_FSM_ENA) { + ret = clk_enable_regmap(hw); + if (ret) + return ret; + return wait_for_pll_enable_active(pll); + } + + ret = regmap_read(regmap, PLL_OPMODE(pll), &opmode_val); + if (ret) + return ret; + + /* Skip If PLL is already running */ + if ((opmode_val & FABIA_OPMODE_RUN) && (val & PLL_OUTCTRL)) + return 0; + + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + if (ret) + return ret; + + ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY); + if (ret) + return ret; + + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, + PLL_RESET_N); + if (ret) + return ret; + + ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_RUN); + if (ret) + return ret; +