Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0caeaede authored by Lee Jones's avatar Lee Jones
Browse files

Merge branch 'ib-mfd-io-3.15' into HEAD

parents 1a55361e b2931b98
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
* 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>;
	};
};
+10 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+199 −121
Original line number Diff line number Diff line
@@ -47,20 +47,84 @@
#include <linux/gfp.h>
#include <linux/err.h>

/*
#include <linux/iio/iio.h>

/**
 * 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[] = {
/* 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
	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;
@@ -448,22 +505,18 @@ 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);
	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",
		dev_err(madc->dev, "unable to write ctrl register 0x%X\n",
			method->ctrl);
		return ret;
	}
		break;
	default:
		break;
	}

	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,45 +829,62 @@ 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),
	},
};

+0 −10
Original line number Diff line number Diff line
@@ -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
Loading