diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-02 19:37:02 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-02 19:37:02 (GMT) |
commit | 6d3a63790c6b280351fbb7cf31690c5d0043ea49 (patch) | |
tree | d182af55501a1b53b86fdb4e7d7ccf20acc11076 | |
parent | 03b7f67bd1a085572539788d07c4630489108a35 (diff) | |
parent | beca9e767e27f756d6aed9a62665e3f73546aabb (diff) | |
download | linux-6d3a63790c6b280351fbb7cf31690c5d0043ea49.tar.xz |
Merge tag 'iio-for-3.10c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Third round of IIO cleanups, graduations and new stuff for the 3.10 cycle.
A small set including 3 things.
1) A short cleanup series for the ak8975.
2) Graduation of ak8975 out of staging.
3) Some additional bits for the at91 adc driver to cover low resolution
modes, sleep and a little bit of missing documentation.
-rw-r--r-- | Documentation/devicetree/bindings/arm/atmel-adc.txt | 13 | ||||
-rw-r--r-- | drivers/iio/adc/at91_adc.c | 90 | ||||
-rw-r--r-- | drivers/iio/magnetometer/Kconfig | 11 | ||||
-rw-r--r-- | drivers/iio/magnetometer/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/magnetometer/ak8975.c (renamed from drivers/staging/iio/magnetometer/ak8975.c) | 69 | ||||
-rw-r--r-- | drivers/staging/iio/magnetometer/Kconfig | 11 | ||||
-rw-r--r-- | drivers/staging/iio/magnetometer/Makefile | 1 |
7 files changed, 127 insertions, 69 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt index c63097d..16769d9 100644 --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt @@ -14,9 +14,19 @@ Required properties: - atmel,adc-status-register: Offset of the Interrupt Status Register - atmel,adc-trigger-register: Offset of the Trigger Register - atmel,adc-vref: Reference voltage in millivolts for the conversions + - atmel,adc-res: List of resolution in bits supported by the ADC. List size + must be two at least. + - atmel,adc-res-names: Contains one identifier string for each resolution + in atmel,adc-res property. "lowres" and "highres" + identifiers are required. Optional properties: - atmel,adc-use-external: Boolean to enable of external triggers + - atmel,adc-use-res: String corresponding to an identifier from + atmel,adc-res-names property. If not specified, the highest + resolution will be used. + - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion + - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds Optional trigger Nodes: - Required properties: @@ -40,6 +50,9 @@ adc0: adc@fffb0000 { atmel,adc-trigger-register = <0x08>; atmel,adc-use-external; atmel,adc-vref = <3300>; + atmel,adc-res = <8 10>; + atmel,adc-res-names = "lowres", "highres"; + atmel,adc-use-res = "lowres"; trigger@0 { trigger-name = "external-rising"; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 6fc43c1..e5b88d5 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -52,11 +52,15 @@ struct at91_adc_state { void __iomem *reg_base; struct at91_adc_reg_desc *registers; u8 startup_time; + u8 sample_hold_time; + bool sleep_mode; struct iio_trigger **trig; struct at91_adc_trigger *trigger_list; u32 trigger_number; bool use_external; u32 vref_mv; + u32 res; /* resolution used for convertions */ + bool low_res; /* the resolution corresponds to the lowest one */ wait_queue_head_t wq_data_avail; }; @@ -138,7 +142,7 @@ static int at91_adc_channel_init(struct iio_dev *idev) chan->channel = bit; chan->scan_index = idx; chan->scan_type.sign = 'u'; - chan->scan_type.realbits = 10; + chan->scan_type.realbits = st->res; chan->scan_type.storagebits = 16; chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); @@ -372,6 +376,59 @@ static int at91_adc_read_raw(struct iio_dev *idev, return -EINVAL; } +static int at91_adc_of_get_resolution(struct at91_adc_state *st, + struct platform_device *pdev) +{ + struct iio_dev *idev = iio_priv_to_dev(st); + struct device_node *np = pdev->dev.of_node; + int count, i, ret = 0; + char *res_name, *s; + u32 *resolutions; + + count = of_property_count_strings(np, "atmel,adc-res-names"); + if (count < 2) { + dev_err(&idev->dev, "You must specified at least two resolution names for " + "adc-res-names property in the DT\n"); + return count; + } + + resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL); + if (!resolutions) + return -ENOMEM; + + if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) { + dev_err(&idev->dev, "Missing adc-res property in the DT.\n"); + ret = -ENODEV; + goto ret; + } + + if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name)) + res_name = "highres"; + + for (i = 0; i < count; i++) { + if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s)) + continue; + + if (strcmp(res_name, s)) + continue; + + st->res = resolutions[i]; + if (!strcmp(res_name, "lowres")) + st->low_res = true; + else + st->low_res = false; + + dev_info(&idev->dev, "Resolution used: %u bits\n", st->res); + goto ret; + } + + dev_err(&idev->dev, "There is no resolution for %s\n", res_name); + +ret: + kfree(resolutions); + return ret; +} + static int at91_adc_probe_dt(struct at91_adc_state *st, struct platform_device *pdev) { @@ -400,6 +457,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->num_channels = prop; + st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode"); + if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) { dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n"); ret = -EINVAL; @@ -407,6 +466,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->startup_time = prop; + prop = 0; + of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop); + st->sample_hold_time = prop; if (of_property_read_u32(node, "atmel,adc-vref", &prop)) { dev_err(&idev->dev, "Missing adc-vref property in the DT.\n"); @@ -415,6 +477,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->vref_mv = prop; + ret = at91_adc_of_get_resolution(st, pdev); + if (ret) + goto error_ret; + st->registers = devm_kzalloc(&idev->dev, sizeof(struct at91_adc_reg_desc), GFP_KERNEL); @@ -516,11 +582,12 @@ static const struct iio_info at91_adc_info = { static int at91_adc_probe(struct platform_device *pdev) { - unsigned int prsc, mstrclk, ticks, adc_clk; + unsigned int prsc, mstrclk, ticks, adc_clk, shtim; int ret; struct iio_dev *idev; struct at91_adc_state *st; struct resource *res; + u32 reg; idev = iio_device_alloc(sizeof(struct at91_adc_state)); if (idev == NULL) { @@ -628,9 +695,22 @@ static int at91_adc_probe(struct platform_device *pdev) */ ticks = round_up((st->startup_time * adc_clk / 1000000) - 1, 8) / 8; - at91_adc_writel(st, AT91_ADC_MR, - (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | - (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); + /* + * a minimal Sample and Hold Time is necessary for the ADC to guarantee + * the best converted final value between two channels selection + * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock + */ + shtim = round_up((st->sample_hold_time * adc_clk / + 1000000) - 1, 1); + + reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL; + reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP; + if (st->low_res) + reg |= AT91_ADC_LOWRES; + if (st->sleep_mode) + reg |= AT91_ADC_SLEEP; + reg |= AT91_ADC_SHTIM_(shtim) & AT91_ADC_SHTIM; + at91_adc_writel(st, AT91_ADC_MR, reg); /* Setup the ADC channels available on the board */ ret = at91_adc_channel_init(idev); diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index cd29be5..bd1cfb6 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -3,6 +3,17 @@ # menu "Magnetometer sensors" +config AK8975 + tristate "Asahi Kasei AK8975 3-Axis Magnetometer" + depends on I2C + depends on GPIOLIB + help + Say yes here to build support for Asahi Kasei AK8975 3-Axis + Magnetometer. + + To compile this driver as a module, choose M here: the module + will be called ak8975. + config HID_SENSOR_MAGNETOMETER_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index e786728..7f328e3 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -2,6 +2,7 @@ # Makefile for industrial I/O Magnetometer sensor drivers # +obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index b614da1..af6c320 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -94,7 +94,6 @@ struct ak8975_data { long raw_to_gauss[3]; u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; - int eoc_irq; }; static const int ak8975_index_to_reg[] = { @@ -124,36 +123,6 @@ static int ak8975_write_data(struct i2c_client *client, } /* - * Helper function to read a contiguous set of the I2C device's registers. - */ -static int ak8975_read_data(struct i2c_client *client, - u8 reg, u8 length, u8 *buffer) -{ - int ret; - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = I2C_M_NOSTART, - .len = 1, - .buf = ®, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = length, - .buf = buffer, - } - }; - - ret = i2c_transfer(client->adapter, msg, 2); - if (ret < 0) { - dev_err(&client->dev, "Read from device fails\n"); - return ret; - } - - return 0; -} - -/* * Perform some start-of-day setup, including reading the asa calibration * values and caching them. */ @@ -165,11 +134,12 @@ static int ak8975_setup(struct i2c_client *client) int ret; /* Confirm that the device we're talking to is really an AK8975. */ - ret = ak8975_read_data(client, AK8975_REG_WIA, 1, &device_id); + ret = i2c_smbus_read_byte_data(client, AK8975_REG_WIA); if (ret < 0) { dev_err(&client->dev, "Error reading WIA\n"); return ret; } + device_id = ret; if (device_id != AK8975_DEVICE_ID) { dev_err(&client->dev, "Device ak8975 not found\n"); return -ENODEV; @@ -187,7 +157,8 @@ static int ak8975_setup(struct i2c_client *client) } /* Get asa data and store in the device data. */ - ret = ak8975_read_data(client, AK8975_REG_ASAX, 3, data->asa); + ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX, + 3, data->asa); if (ret < 0) { dev_err(&client->dev, "Not able to read asa data\n"); return ret; @@ -249,7 +220,6 @@ static int ak8975_setup(struct i2c_client *client) static int wait_conversion_complete_gpio(struct ak8975_data *data) { struct i2c_client *client = data->client; - u8 read_status; u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; int ret; @@ -265,12 +235,11 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data) return -EINVAL; } - ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status); - if (ret < 0) { + ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); + if (ret < 0) dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - return read_status; + + return ret; } static int wait_conversion_complete_polled(struct ak8975_data *data) @@ -283,11 +252,12 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) /* Wait for the conversion to complete. */ while (timeout_ms) { msleep(AK8975_CONVERSION_DONE_POLL_TIME); - ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status); + ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); if (ret < 0) { dev_err(&client->dev, "Error in reading ST1\n"); return ret; } + read_status = ret; if (read_status) break; timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; @@ -308,7 +278,6 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) struct i2c_client *client = data->client; u16 meas_reg; s16 raw; - u8 read_status; int ret; mutex_lock(&data->lock); @@ -332,18 +301,15 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) if (ret < 0) goto exit; - read_status = ret; - - if (read_status & AK8975_REG_ST1_DRDY_MASK) { - ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status); + if (ret & AK8975_REG_ST1_DRDY_MASK) { + ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); goto exit; } - if (read_status & (AK8975_REG_ST2_DERR_MASK | - AK8975_REG_ST2_HOFL_MASK)) { - dev_err(&client->dev, "ST2 status error 0x%x\n", - read_status); + if (ret & (AK8975_REG_ST2_DERR_MASK | + AK8975_REG_ST2_HOFL_MASK)) { + dev_err(&client->dev, "ST2 status error 0x%x\n", ret); ret = -EINVAL; goto exit; } @@ -351,12 +317,12 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ - ret = ak8975_read_data(client, ak8975_index_to_reg[index], - 2, (u8 *)&meas_reg); + ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; } + meas_reg = ret; mutex_unlock(&data->lock); @@ -452,7 +418,6 @@ static int ak8975_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - data->eoc_irq = client->irq; data->eoc_gpio = eoc_gpio; indio_dev->dev.parent = &client->dev; indio_dev->channels = ak8975_channels; diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index df5e0d4..a3ea69e 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -3,17 +3,6 @@ # menu "Magnetometer sensors" -config SENSORS_AK8975 - tristate "Asahi Kasei AK8975 3-Axis Magnetometer" - depends on I2C - depends on GPIOLIB - help - Say yes here to build support for Asahi Kasei AK8975 3-Axis - Magnetometer. - - To compile this driver as a module, choose M here: the module - will be called ak8975. - config SENSORS_HMC5843 tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer" depends on I2C diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile index f2a753f..f9bfb2e 100644 --- a/drivers/staging/iio/magnetometer/Makefile +++ b/drivers/staging/iio/magnetometer/Makefile @@ -2,5 +2,4 @@ # Makefile for industrial I/O Magnetometer sensors # -obj-$(CONFIG_SENSORS_AK8975) += ak8975.o obj-$(CONFIG_SENSORS_HMC5843) += hmc5843.o |