diff options
Diffstat (limited to 'drivers/mfd/stmpe.c')
-rw-r--r-- | drivers/mfd/stmpe.c | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index b0c7bcdaf5df..d8b360147b46 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -26,7 +26,6 @@ /** * struct stmpe_platform_data - STMPE platform data * @id: device id to distinguish between multiple STMPEs on the same board - * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) * @irq_trigger: IRQ trigger to use for the interrupt to the host * @autosleep: bool to enable/disable stmpe autosleep * @autosleep_timeout: inactivity timeout in milliseconds for autosleep @@ -36,7 +35,6 @@ */ struct stmpe_platform_data { int id; - unsigned int blocks; unsigned int irq_trigger; bool autosleep; bool irq_over_gpio; @@ -464,6 +462,32 @@ static const struct mfd_cell stmpe_ts_cell = { }; /* + * ADC (STMPE811) + */ + +static struct resource stmpe_adc_resources[] = { + { + .name = "STMPE_TEMP_SENS", + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, + { + .name = "STMPE_ADC", + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell stmpe_adc_cell = { + .name = "stmpe-adc", + .of_compatible = "st,stmpe-adc", + .resources = stmpe_adc_resources, + .num_resources = ARRAY_SIZE(stmpe_adc_resources), +}; + +/* * STMPE811 or STMPE610 */ @@ -497,6 +521,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = { .irq = STMPE811_IRQ_TOUCH_DET, .block = STMPE_BLOCK_TOUCHSCREEN, }, + { + .cell = &stmpe_adc_cell, + .irq = STMPE811_IRQ_TEMP_SENS, + .block = STMPE_BLOCK_ADC, + }, }; static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, @@ -517,6 +546,35 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, enable ? 0 : mask); } +int stmpe811_adc_common_init(struct stmpe *stmpe) +{ + int ret; + u8 adc_ctrl1, adc_ctrl1_mask; + + adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) | + STMPE_MOD_12B(stmpe->mod_12b) | + STMPE_REF_SEL(stmpe->ref_sel); + adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | + STMPE_REF_SEL(0xff); + + ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1, + adc_ctrl1_mask, adc_ctrl1); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + return ret; + } + + ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2, + STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq)); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(stmpe811_adc_common_init); + static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) { /* 0 for touchscreen, 1 for GPIO */ @@ -1245,7 +1303,7 @@ static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell) static int stmpe_devices_init(struct stmpe *stmpe) { struct stmpe_variant_info *variant = stmpe->variant; - unsigned int platform_blocks = stmpe->pdata->blocks; + unsigned int platform_blocks = stmpe->blocks; int ret = -EINVAL; int i, j; @@ -1281,8 +1339,6 @@ static int stmpe_devices_init(struct stmpe *stmpe) static void stmpe_of_probe(struct stmpe_platform_data *pdata, struct device_node *np) { - struct device_node *child; - pdata->id = of_alias_get_id(np, "stmpe-i2c"); if (pdata->id < 0) pdata->id = -1; @@ -1298,31 +1354,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata, &pdata->autosleep_timeout); pdata->autosleep = (pdata->autosleep_timeout) ? true : false; - - for_each_child_of_node(np, child) { - if (!strcmp(child->name, "stmpe_gpio")) { - pdata->blocks |= STMPE_BLOCK_GPIO; - } else if (!strcmp(child->name, "stmpe_keypad")) { - pdata->blocks |= STMPE_BLOCK_KEYPAD; - } else if (!strcmp(child->name, "stmpe_touchscreen")) { - pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN; - } else if (!strcmp(child->name, "stmpe_adc")) { - pdata->blocks |= STMPE_BLOCK_ADC; - } else if (!strcmp(child->name, "stmpe_pwm")) { - pdata->blocks |= STMPE_BLOCK_PWM; - } else if (!strcmp(child->name, "stmpe_rotator")) { - pdata->blocks |= STMPE_BLOCK_ROTATOR; - } - } } /* Called from client specific probe routines */ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) { + struct device_node *child; struct stmpe_platform_data *pdata; struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; + u32 val; pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1340,6 +1382,31 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) mutex_init(&stmpe->irq_lock); mutex_init(&stmpe->lock); + for_each_child_of_node(np, child) { + if (!strcmp(child->name, "stmpe_gpio")) { + stmpe->blocks |= STMPE_BLOCK_GPIO; + } else if (!strcmp(child->name, "stmpe_keypad")) { + stmpe->blocks |= STMPE_BLOCK_KEYPAD; + } else if (!strcmp(child->name, "stmpe_touchscreen")) { + stmpe->blocks |= STMPE_BLOCK_TOUCHSCREEN; + } else if (!strcmp(child->name, "stmpe_adc")) { + stmpe->blocks |= STMPE_BLOCK_ADC; + } else if (!strcmp(child->name, "stmpe_pwm")) { + stmpe->blocks |= STMPE_BLOCK_PWM; + } else if (!strcmp(child->name, "stmpe_rotator")) { + stmpe->blocks |= STMPE_BLOCK_ROTATOR; + } + } + + if (!of_property_read_u32(np, "st,sample-time", &val)) + stmpe->sample_time = val; + if (!of_property_read_u32(np, "st,mod-12b", &val)) + stmpe->mod_12b = val; + if (!of_property_read_u32(np, "st,ref-sel", &val)) + stmpe->ref_sel = val; + if (!of_property_read_u32(np, "st,adc-freq", &val)) + stmpe->adc_freq = val; + stmpe->dev = ci->dev; stmpe->client = ci->client; stmpe->pdata = pdata; @@ -1431,6 +1498,8 @@ int stmpe_remove(struct stmpe *stmpe) if (!IS_ERR(stmpe->vcc)) regulator_disable(stmpe->vcc); + __stmpe_disable(stmpe, STMPE_BLOCK_ADC); + mfd_remove_devices(stmpe->dev); return 0; |