diff --git a/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt b/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt new file mode 100644 index 0000000000000000000000000000000000000000..6bdd21404b57c2952ce133b2604379f0655fea67 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/twl4030-madc.txt @@ -0,0 +1,24 @@ +* TWL4030 Monitoring Analog to Digital Converter (MADC) + +The MADC subsystem in the TWL4030 consists of a 10-bit ADC +combined with a 16-input analog multiplexer. + +Required properties: + - compatible: Should contain "ti,twl4030-madc". + - interrupts: IRQ line for the MADC submodule. + - #io-channel-cells: Should be set to <1>. + +Optional properties: + - ti,system-uses-second-madc-irq: boolean, set if the second madc irq register + should be used, which is intended to be used + by Co-Processors (e.g. a modem). + +Example: + +&twl { + madc { + compatible = "ti,twl4030-madc"; + interrupts = <3>; + #io-channel-cells = <1>; + }; +}; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2209f28441e94d013ef435a100c17d6920677e08..427f75c4f69ef03c6c90d8c0c087d1f984c7842b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -183,6 +183,16 @@ config TI_AM335X_ADC Say yes here to build support for Texas Instruments ADC driver which is also a MFD client. +config TWL4030_MADC + tristate "TWL4030 MADC (Monitoring A/D Converter)" + depends on TWL4030_CORE + help + This driver provides support for Triton TWL4030-MADC. The + driver supports both RT and SW conversion methods. + + This driver can also be built as a module. If so, the module will be + called twl4030-madc. + config TWL6030_GPADC tristate "TWL6030 GPADC (General Purpose A/D Converter) Support" depends on TWL4030_CORE diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ba9a10a24cd03ee4d80f4bc2e0a9fd56b106d908..9acf2df2c1a8e32f566c921d07514cdff906d13d 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -20,5 +20,6 @@ obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_NAU7802) += nau7802.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o +obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o diff --git a/drivers/mfd/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c similarity index 74% rename from drivers/mfd/twl4030-madc.c rename to drivers/iio/adc/twl4030-madc.c index 4c583e47133993b59dd512f1e3ec7316fb68c7fb..8a014fbb98bcf50279bed245412fe86e68caffdb 100644 --- a/drivers/mfd/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -47,20 +47,84 @@ #include #include -/* +#include + +/** * struct twl4030_madc_data - a container for madc info - * @dev - pointer to device structure for madc - * @lock - mutex protecting this data structure - * @requests - Array of request struct corresponding to SW1, SW2 and RT - * @imr - Interrupt mask register of MADC - * @isr - Interrupt status register of MADC + * @dev: Pointer to device structure for madc + * @lock: Mutex protecting this data structure + * @requests: Array of request struct corresponding to SW1, SW2 and RT + * @use_second_irq: IRQ selection (main or co-processor) + * @imr: Interrupt mask register of MADC + * @isr: Interrupt status register of MADC */ struct twl4030_madc_data { struct device *dev; struct mutex lock; /* mutex protecting this data structure */ struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS]; - int imr; - int isr; + bool use_second_irq; + u8 imr; + u8 isr; +}; + +static int twl4030_madc_read(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct twl4030_madc_data *madc = iio_priv(iio_dev); + struct twl4030_madc_request req; + int ret; + + req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1; + + req.channels = BIT(chan->channel); + req.active = false; + req.func_cb = NULL; + req.type = TWL4030_MADC_WAIT; + req.raw = !(mask == IIO_CHAN_INFO_PROCESSED); + req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW); + + ret = twl4030_madc_conversion(&req); + if (ret < 0) + return ret; + + *val = req.rbuf[chan->channel]; + + return IIO_VAL_INT; +} + +static const struct iio_info twl4030_madc_iio_info = { + .read_raw = &twl4030_madc_read, + .driver_module = THIS_MODULE, +}; + +#define TWL4030_ADC_CHANNEL(_channel, _type, _name) { \ + .type = _type, \ + .channel = _channel, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ + BIT(IIO_CHAN_INFO_PROCESSED), \ + .datasheet_name = _name, \ + .indexed = 1, \ +} + +static const struct iio_chan_spec twl4030_madc_iio_channels[] = { + TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"), + TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"), + TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"), + TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"), + TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"), + TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"), + TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"), + TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"), + TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"), + TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"), + TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"), + TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"), + TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"), + TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"), + TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"), + TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"), }; static struct twl4030_madc_data *twl4030_madc; @@ -91,17 +155,16 @@ twl4030_divider_ratios[16] = { }; -/* - * Conversion table from -3 to 55 degree Celcius - */ -static int therm_tbl[] = { -30800, 29500, 28300, 27100, -26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900, -17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100, -11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310, -8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830, -5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170, -4040, 3910, 3790, 3670, 3550 +/* Conversion table from -3 to 55 degrees Celcius */ +static int twl4030_therm_tbl[] = { + 30800, 29500, 28300, 27100, + 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, + 17900, 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, + 12600, 12100, 11600, 11200, 10800, 10400, 10000, 9630, 9280, + 8950, 8620, 8310, 8020, 7730, 7460, 7200, 6950, 6710, + 6470, 6250, 6040, 5830, 5640, 5450, 5260, 5090, 4920, + 4760, 4600, 4450, 4310, 4170, 4040, 3910, 3790, 3670, + 3550 }; /* @@ -133,37 +196,32 @@ const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = { }, }; -/* - * Function to read a particular channel value. - * @madc - pointer to struct twl4030_madc_data - * @reg - lsb of ADC Channel - * If the i2c read fails it returns an error else returns 0. +/** + * twl4030_madc_channel_raw_read() - Function to read a particular channel value + * @madc: pointer to struct twl4030_madc_data + * @reg: lsb of ADC Channel + * + * Return: 0 on success, an error code otherwise. */ static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg) { - u8 msb, lsb; + u16 val; int ret; /* * For each ADC channel, we have MSB and LSB register pair. MSB address * is always LSB address+1. reg parameter is the address of LSB register */ - ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1); + ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg); if (ret) { - dev_err(madc->dev, "unable to read MSB register 0x%X\n", - reg + 1); - return ret; - } - ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg); - if (ret) { - dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg); + dev_err(madc->dev, "unable to read register 0x%X\n", reg); return ret; } - return (int)(((msb << 8) | lsb) >> 6); + return (int)(val >> 6); } /* - * Return battery temperature + * Return battery temperature in degrees Celsius * Or < 0 on failure. */ static int twl4030battery_temperature(int raw_volt) @@ -172,18 +230,18 @@ static int twl4030battery_temperature(int raw_volt) int temp, curr, volt, res, ret; volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R; - /* Getting and calculating the supply current in micro ampers */ + /* Getting and calculating the supply current in micro amperes */ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, REG_BCICTL2); if (ret < 0) return ret; + curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10; /* Getting and calculating the thermistor resistance in ohms */ res = volt * 1000 / curr; /* calculating temperature */ for (temp = 58; temp >= 0; temp--) { - int actual = therm_tbl[temp]; - + int actual = twl4030_therm_tbl[temp]; if ((actual - res) >= 0) break; } @@ -205,11 +263,12 @@ static int twl4030battery_current(int raw_volt) else /* slope of 0.88 mV/mA */ return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2; } + /* * Function to read channel values * @madc - pointer to twl4030_madc_data struct * @reg_base - Base address of the first channel - * @Channels - 16 bit bitmap. If the bit is set, channel value is read + * @Channels - 16 bit bitmap. If the bit is set, channel's value is read * @buf - The channel values are stored here. if read fails error * @raw - Return raw values without conversion * value is stored @@ -220,17 +279,17 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, long channels, int *buf, bool raw) { - int count = 0, count_req = 0, i; + int count = 0; + int i; u8 reg; for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) { - reg = reg_base + 2 * i; + reg = reg_base + (2 * i); buf[i] = twl4030_madc_channel_raw_read(madc, reg); if (buf[i] < 0) { - dev_err(madc->dev, - "Unable to read register 0x%X\n", reg); - count_req++; - continue; + dev_err(madc->dev, "Unable to read register 0x%X\n", + reg); + return buf[i]; } if (raw) { count++; @@ -241,7 +300,7 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, buf[i] = twl4030battery_current(buf[i]); if (buf[i] < 0) { dev_err(madc->dev, "err reading current\n"); - count_req++; + return buf[i]; } else { count++; buf[i] = buf[i] - 750; @@ -251,7 +310,7 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, buf[i] = twl4030battery_temperature(buf[i]); if (buf[i] < 0) { dev_err(madc->dev, "err reading temperature\n"); - count_req++; + return buf[i]; } else { buf[i] -= 3; count++; @@ -272,8 +331,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, twl4030_divider_ratios[i].numerator); } } - if (count_req) - dev_err(madc->dev, "%d channel conversion failed\n", count_req); return count; } @@ -297,13 +354,13 @@ static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id) madc->imr); return ret; } + val &= ~(1 << id); ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr); if (ret) { dev_err(madc->dev, "unable to write imr register 0x%X\n", madc->imr); return ret; - } return 0; @@ -366,7 +423,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) continue; ret = twl4030_madc_disable_irq(madc, i); if (ret < 0) - dev_dbg(madc->dev, "Disable interrupt failed%d\n", i); + dev_dbg(madc->dev, "Disable interrupt failed %d\n", i); madc->requests[i].result_pending = 1; } for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { @@ -448,21 +505,17 @@ static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc, { const struct twl4030_madc_conversion_method *method; int ret = 0; + + if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2) + return -ENOTSUPP; + method = &twl4030_conversion_methods[conv_method]; - switch (conv_method) { - case TWL4030_MADC_SW1: - case TWL4030_MADC_SW2: - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, - TWL4030_MADC_SW_START, method->ctrl); - if (ret) { - dev_err(madc->dev, - "unable to write ctrl register 0x%X\n", - method->ctrl); - return ret; - } - break; - default: - break; + ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, TWL4030_MADC_SW_START, + method->ctrl); + if (ret) { + dev_err(madc->dev, "unable to write ctrl register 0x%X\n", + method->ctrl); + return ret; } return 0; @@ -513,7 +566,6 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, int twl4030_madc_conversion(struct twl4030_madc_request *req) { const struct twl4030_madc_conversion_method *method; - u8 ch_msb, ch_lsb; int ret; if (!req || !twl4030_madc) @@ -529,38 +581,22 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) ret = -EBUSY; goto out; } - ch_msb = (req->channels >> 8) & 0xff; - ch_lsb = req->channels & 0xff; method = &twl4030_conversion_methods[req->method]; /* Select channels to be converted */ - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1); - if (ret) { - dev_err(twl4030_madc->dev, - "unable to write sel register 0x%X\n", method->sel + 1); - goto out; - } - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel); + ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel); if (ret) { dev_err(twl4030_madc->dev, - "unable to write sel register 0x%X\n", method->sel + 1); + "unable to write sel register 0x%X\n", method->sel); goto out; } /* Select averaging for all channels if do_avg is set */ if (req->do_avg) { - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, - ch_msb, method->avg + 1); + ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, + method->avg); if (ret) { dev_err(twl4030_madc->dev, "unable to write avg register 0x%X\n", - method->avg + 1); - goto out; - } - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, - ch_lsb, method->avg); - if (ret) { - dev_err(twl4030_madc->dev, - "unable to write sel reg 0x%X\n", - method->sel + 1); + method->avg); goto out; } } @@ -601,10 +637,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) } EXPORT_SYMBOL_GPL(twl4030_madc_conversion); -/* - * Return channel value - * Or < 0 on failure. - */ int twl4030_get_madc_conversion(int channel_no) { struct twl4030_madc_request req; @@ -625,20 +657,25 @@ int twl4030_get_madc_conversion(int channel_no) } EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); -/* +/** + * twl4030_madc_set_current_generator() - setup bias current + * + * @madc: pointer to twl4030_madc_data struct + * @chan: can be one of the two values: + * TWL4030_BCI_ITHEN + * Enables bias current for main battery type reading + * TWL4030_BCI_TYPEN + * Enables bias current for main battery temperature sensing + * @on: enable or disable chan. + * * Function to enable or disable bias current for * main battery type reading or temperature sensing - * @madc - pointer to twl4030_madc_data struct - * @chan - can be one of the two values - * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading - * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature - * sensing - * @on - enable or disable chan. */ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, int chan, int on) { int ret; + int regmask; u8 regval; ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, @@ -648,10 +685,13 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, TWL4030_BCI_BCICTL1); return ret; } + + regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN; if (on) - regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN; + regval |= regmask; else - regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN; + regval &= ~regmask; + ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, regval, TWL4030_BCI_BCICTL1); if (ret) { @@ -666,7 +706,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, /* * Function that sets MADC software power on bit to enable MADC * @madc - pointer to twl4030_madc_data struct - * @on - Enable or disable MADC software powen on bit. + * @on - Enable or disable MADC software power on bit. * returns error if i2c read/write fails else 0 */ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on) @@ -702,31 +742,52 @@ static int twl4030_madc_probe(struct platform_device *pdev) { struct twl4030_madc_data *madc; struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev); - int ret; + struct device_node *np = pdev->dev.of_node; + int irq, ret; u8 regval; + struct iio_dev *iio_dev = NULL; - if (!pdata) { - dev_err(&pdev->dev, "platform_data not available\n"); + if (!pdata && !np) { + dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n"); return -EINVAL; } - madc = kzalloc(sizeof(*madc), GFP_KERNEL); - if (!madc) + + iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc)); + if (!iio_dev) { + dev_err(&pdev->dev, "failed allocating iio device\n"); return -ENOMEM; + } + madc = iio_priv(iio_dev); madc->dev = &pdev->dev; + iio_dev->name = dev_name(&pdev->dev); + iio_dev->dev.parent = &pdev->dev; + iio_dev->dev.of_node = pdev->dev.of_node; + iio_dev->info = &twl4030_madc_iio_info; + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->channels = twl4030_madc_iio_channels; + iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels); + /* * Phoenix provides 2 interrupt lines. The first one is connected to * the OMAP. The other one can be connected to the other processor such * as modem. Hence two separate ISR and IMR registers. */ - madc->imr = (pdata->irq_line == 1) ? - TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2; - madc->isr = (pdata->irq_line == 1) ? - TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2; + if (pdata) + madc->use_second_irq = (pdata->irq_line != 1); + else + madc->use_second_irq = of_property_read_bool(np, + "ti,system-uses-second-madc-irq"); + + madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 : + TWL4030_MADC_IMR1; + madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 : + TWL4030_MADC_ISR1; + ret = twl4030_madc_set_power(madc, 1); if (ret < 0) - goto err_power; + return ret; ret = twl4030_madc_set_current_generator(madc, 0, 1); if (ret < 0) goto err_current_generator; @@ -768,46 +829,63 @@ static int twl4030_madc_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, madc); + platform_set_drvdata(pdev, iio_dev); mutex_init(&madc->lock); - ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL, + + irq = platform_get_irq(pdev, 0); + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, twl4030_madc_threaded_irq_handler, IRQF_TRIGGER_RISING, "twl4030_madc", madc); if (ret) { - dev_dbg(&pdev->dev, "could not request irq\n"); + dev_err(&pdev->dev, "could not request irq\n"); goto err_i2c; } twl4030_madc = madc; + + ret = iio_device_register(iio_dev); + if (ret) { + dev_err(&pdev->dev, "could not register iio device\n"); + goto err_i2c; + } + return 0; + err_i2c: twl4030_madc_set_current_generator(madc, 0, 0); err_current_generator: twl4030_madc_set_power(madc, 0); -err_power: - kfree(madc); - return ret; } static int twl4030_madc_remove(struct platform_device *pdev) { - struct twl4030_madc_data *madc = platform_get_drvdata(pdev); + struct iio_dev *iio_dev = platform_get_drvdata(pdev); + struct twl4030_madc_data *madc = iio_priv(iio_dev); + + iio_device_unregister(iio_dev); - free_irq(platform_get_irq(pdev, 0), madc); twl4030_madc_set_current_generator(madc, 0, 0); twl4030_madc_set_power(madc, 0); - kfree(madc); return 0; } +#ifdef CONFIG_OF +static const struct of_device_id twl_madc_of_match[] = { + { .compatible = "ti,twl4030-madc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, twl_madc_of_match); +#endif + static struct platform_driver twl4030_madc_driver = { .probe = twl4030_madc_probe, .remove = twl4030_madc_remove, .driver = { .name = "twl4030_madc", .owner = THIS_MODULE, - }, + .of_match_table = of_match_ptr(twl_madc_of_match), + }, }; module_platform_driver(twl4030_madc_driver); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 49bb445d846aa76e206dfe7fb7d30ad5f24b6b97..23a8a51f686033356a07fac8fdc66862503b3fec 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -935,16 +935,6 @@ config TWL4030_CORE high speed USB OTG transceiver, an audio codec (on most versions) and many other features. -config TWL4030_MADC - tristate "TI TWL4030 MADC" - depends on TWL4030_CORE - help - This driver provides support for triton TWL4030-MADC. The - driver supports both RT and SW conversion methods. - - This driver can be built as a module. If so it will be - named twl4030-madc - config TWL4030_POWER bool "TI TWL4030 power resources" depends on TWL4030_CORE && ARM diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5aea5ef0a62f51eff03a14404569c68a7700262f..c8eb0bcf4da0601d97c2608c5687f2726d262714 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -71,7 +71,6 @@ obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o -obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o obj-$(CONFIG_TWL6040_CORE) += twl6040.o diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index ade1c06d4cebed9c30b47ea98c69fe51df89508c..d2b16704624c6c6122a09457e00ef716ef8d0393 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -195,6 +195,18 @@ static inline int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg) { return twl_i2c_read(mod_no, val, reg, 1); } +static inline int twl_i2c_write_u16(u8 mod_no, u16 val, u8 reg) { + val = cpu_to_le16(val); + return twl_i2c_write(mod_no, (u8*) &val, reg, 2); +} + +static inline int twl_i2c_read_u16(u8 mod_no, u16 *val, u8 reg) { + int ret; + ret = twl_i2c_read(mod_no, (u8*) val, reg, 2); + *val = le16_to_cpu(*val); + return ret; +} + int twl_get_type(void); int twl_get_version(void); int twl_get_hfclk_rate(void); diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h index 01f5951070489c0a48eeacc290b4428c203ed852..1c0134dd32718f1561c3ced6704f6b65edcad817 100644 --- a/include/linux/i2c/twl4030-madc.h +++ b/include/linux/i2c/twl4030-madc.h @@ -44,7 +44,7 @@ struct twl4030_madc_conversion_method { struct twl4030_madc_request { unsigned long channels; - u16 do_avg; + bool do_avg; u16 method; u16 type; bool active;