diff options
Diffstat (limited to 'drivers/mfd/twl6040-core.c')
| -rw-r--r-- | drivers/mfd/twl6040-core.c | 114 | 
1 files changed, 68 insertions, 46 deletions
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index b2d8e512d3c..2d6bedadca0 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -30,7 +30,9 @@  #include <linux/platform_device.h>  #include <linux/gpio.h>  #include <linux/delay.h> -#include <linux/i2c/twl.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/err.h>  #include <linux/mfd/core.h>  #include <linux/mfd/twl6040.h> @@ -39,7 +41,7 @@  int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)  {  	int ret; -	u8 val = 0; +	unsigned int val;  	mutex_lock(&twl6040->io_mutex);  	/* Vibra control registers from cache */ @@ -47,7 +49,7 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)  		     reg == TWL6040_REG_VIBCTLR)) {  		val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];  	} else { -		ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); +		ret = regmap_read(twl6040->regmap, reg, &val);  		if (ret < 0) {  			mutex_unlock(&twl6040->io_mutex);  			return ret; @@ -64,7 +66,7 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)  	int ret;  	mutex_lock(&twl6040->io_mutex); -	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); +	ret = regmap_write(twl6040->regmap, reg, val);  	/* Cache the vibra control registers */  	if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)  		twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val; @@ -77,16 +79,9 @@ EXPORT_SYMBOL(twl6040_reg_write);  int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)  {  	int ret; -	u8 val;  	mutex_lock(&twl6040->io_mutex); -	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); -	if (ret) -		goto out; - -	val |= mask; -	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); -out: +	ret = regmap_update_bits(twl6040->regmap, reg, mask, mask);  	mutex_unlock(&twl6040->io_mutex);  	return ret;  } @@ -95,16 +90,9 @@ EXPORT_SYMBOL(twl6040_set_bits);  int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)  {  	int ret; -	u8 val;  	mutex_lock(&twl6040->io_mutex); -	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg); -	if (ret) -		goto out; - -	val &= ~mask; -	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg); -out: +	ret = regmap_update_bits(twl6040->regmap, reg, mask, 0);  	mutex_unlock(&twl6040->io_mutex);  	return ret;  } @@ -494,32 +482,58 @@ static struct resource twl6040_codec_rsrc[] = {  	},  }; -static int __devinit twl6040_probe(struct platform_device *pdev) +static bool twl6040_readable_reg(struct device *dev, unsigned int reg)  { -	struct twl4030_audio_data *pdata = pdev->dev.platform_data; +	/* Register 0 is not readable */ +	if (!reg) +		return false; +	return true; +} + +static struct regmap_config twl6040_regmap_config = { +	.reg_bits = 8, +	.val_bits = 8, +	.max_register = TWL6040_REG_STATUS, /* 0x2e */ + +	.readable_reg = twl6040_readable_reg, +}; + +static int __devinit twl6040_probe(struct i2c_client *client, +				     const struct i2c_device_id *id) +{ +	struct twl6040_platform_data *pdata = client->dev.platform_data;  	struct twl6040 *twl6040;  	struct mfd_cell *cell = NULL;  	int ret, children = 0;  	if (!pdata) { -		dev_err(&pdev->dev, "Platform data is missing\n"); +		dev_err(&client->dev, "Platform data is missing\n");  		return -EINVAL;  	}  	/* In order to operate correctly we need valid interrupt config */ -	if (!pdata->naudint_irq || !pdata->irq_base) { -		dev_err(&pdev->dev, "Invalid IRQ configuration\n"); +	if (!client->irq || !pdata->irq_base) { +		dev_err(&client->dev, "Invalid IRQ configuration\n");  		return -EINVAL;  	} -	twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL); -	if (!twl6040) -		return -ENOMEM; +	twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040), +			       GFP_KERNEL); +	if (!twl6040) { +		ret = -ENOMEM; +		goto err; +	} + +	twl6040->regmap = regmap_init_i2c(client, &twl6040_regmap_config); +	if (IS_ERR(twl6040->regmap)) { +		ret = PTR_ERR(twl6040->regmap); +		goto err; +	} -	platform_set_drvdata(pdev, twl6040); +	i2c_set_clientdata(client, twl6040); -	twl6040->dev = &pdev->dev; -	twl6040->irq = pdata->naudint_irq; +	twl6040->dev = &client->dev; +	twl6040->irq = client->irq;  	twl6040->irq_base = pdata->irq_base;  	mutex_init(&twl6040->mutex); @@ -588,12 +602,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev)  	}  	if (children) { -		ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells, +		ret = mfd_add_devices(&client->dev, -1, twl6040->cells,  				      children, NULL, 0);  		if (ret)  			goto mfd_err;  	} else { -		dev_err(&pdev->dev, "No platform data found for children\n"); +		dev_err(&client->dev, "No platform data found for children\n");  		ret = -ENODEV;  		goto mfd_err;  	} @@ -608,14 +622,15 @@ gpio2_err:  	if (gpio_is_valid(twl6040->audpwron))  		gpio_free(twl6040->audpwron);  gpio1_err: -	platform_set_drvdata(pdev, NULL); -	kfree(twl6040); +	i2c_set_clientdata(client, NULL); +	regmap_exit(twl6040->regmap); +err:  	return ret;  } -static int __devexit twl6040_remove(struct platform_device *pdev) +static int __devexit twl6040_remove(struct i2c_client *client)  { -	struct twl6040 *twl6040 = platform_get_drvdata(pdev); +	struct twl6040 *twl6040 = i2c_get_clientdata(client);  	if (twl6040->power_count)  		twl6040_power(twl6040, 0); @@ -626,23 +641,30 @@ static int __devexit twl6040_remove(struct platform_device *pdev)  	free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);  	twl6040_irq_exit(twl6040); -	mfd_remove_devices(&pdev->dev); -	platform_set_drvdata(pdev, NULL); -	kfree(twl6040); +	mfd_remove_devices(&client->dev); +	i2c_set_clientdata(client, NULL); +	regmap_exit(twl6040->regmap);  	return 0;  } -static struct platform_driver twl6040_driver = { +static const struct i2c_device_id twl6040_i2c_id[] = { +	{ "twl6040", 0, }, +	{ }, +}; +MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id); + +static struct i2c_driver twl6040_driver = { +	.driver = { +		.name = "twl6040", +		.owner = THIS_MODULE, +	},  	.probe		= twl6040_probe,  	.remove		= __devexit_p(twl6040_remove), -	.driver		= { -		.owner	= THIS_MODULE, -		.name	= "twl6040", -	}, +	.id_table	= twl6040_i2c_id,  }; -module_platform_driver(twl6040_driver); +module_i2c_driver(twl6040_driver);  MODULE_DESCRIPTION("TWL6040 MFD");  MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");  |