diff options
| author | Jee Su Chang <w20740@motorola.com> | 2014-04-28 14:35:20 -0500 | 
|---|---|---|
| committer | Simon Wilson <simonwilson@google.com> | 2014-04-29 15:16:31 +0000 | 
| commit | bb0dbe94cb8f321e6d7b301a050c9049c774df6f (patch) | |
| tree | 0217aeb33beb59749e3d096395ca1ce6efa86e25 /drivers/misc/c55_ctrl.c | |
| parent | ad8fda20e8dc82958cad9818add101497c5fe195 (diff) | |
| download | olio-linux-3.10-bb0dbe94cb8f321e6d7b301a050c9049c774df6f.tar.xz olio-linux-3.10-bb0dbe94cb8f321e6d7b301a050c9049c774df6f.zip  | |
IKXCLOCK-898 c55: C55 RST pin control moved from OMAP to M4
- The C55 RST pin control is moved from OMAP to M4
- The regulators for C55 are left on at all times
- The DSP shutdown and resume are based on Interactive mode
Change-Id: Iabd9505e0f6309f050b54c087d723bd98edeee3c
Diffstat (limited to 'drivers/misc/c55_ctrl.c')
| -rw-r--r-- | drivers/misc/c55_ctrl.c | 74 | 
1 files changed, 54 insertions, 20 deletions
diff --git a/drivers/misc/c55_ctrl.c b/drivers/misc/c55_ctrl.c index 3c126eabebd..584754bfe50 100644 --- a/drivers/misc/c55_ctrl.c +++ b/drivers/misc/c55_ctrl.c @@ -15,6 +15,7 @@  #include <linux/gpio.h>  #include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/m4sensorhub.h>  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/regulator/consumer.h> @@ -31,7 +32,8 @@ enum {  };  struct c55_ctrl_data { -	int int_gpio; +	int c55_ap_int_gpio; +	int ap_c55_int_gpio;  	struct wake_lock wake_lock;  	struct regulator *reg_vddc;  	struct regulator *reg_vddldo; @@ -39,11 +41,10 @@ struct c55_ctrl_data {  	struct mutex ctrl_mutex;	/* mutex to handle critical area */  }; -#define NUM_GPIOS 3 +#define NUM_GPIOS 2  const char *gpio_labels[NUM_GPIOS] = {  	"gpio_ap_int", -	"gpio_reset",  	"gpio_c55_int"  }; @@ -51,10 +52,11 @@ static irqreturn_t c55_ctrl_isr(int irq, void *data)  {  	struct c55_ctrl_data *cdata = data; -	pr_debug("%s: value=%d\n", __func__, gpio_get_value(cdata->int_gpio)); +	pr_debug("%s: value=%d\n", __func__, +		 gpio_get_value(cdata->c55_ap_int_gpio));  	/* Interrupt is active low */ -	if (gpio_get_value(cdata->int_gpio) == 0) +	if (gpio_get_value(cdata->c55_ap_int_gpio) == 0)  		wake_lock(&cdata->wake_lock);  	else  		wake_unlock(&cdata->wake_lock); @@ -68,7 +70,7 @@ static void c55_ctrl_int_setup(struct c55_ctrl_data *cdata, int gpio)  	int irq = __gpio_to_irq(gpio);  	unsigned int flags = 0; -	if (cdata->int_gpio >= 0) { +	if (cdata->c55_ap_int_gpio >= 0) {  		/* Interrupt already registered */  		return;  	} @@ -85,7 +87,7 @@ static void c55_ctrl_int_setup(struct c55_ctrl_data *cdata, int gpio)  	}  	enable_irq_wake(irq); -	cdata->int_gpio = gpio; +	cdata->c55_ap_int_gpio = gpio;  }  static int c55_ctrl_gpio_setup(struct c55_ctrl_data *cdata, struct device *dev) @@ -116,6 +118,7 @@ static int c55_ctrl_gpio_setup(struct c55_ctrl_data *cdata, struct device *dev)  			gpio_direction_input(gpio);  			c55_ctrl_int_setup(cdata, gpio);  		} else { +			cdata->ap_c55_int_gpio = gpio;  			if ((flags & GPIOF_OUT_INIT_HIGH) == GPIOF_OUT_INIT_HIGH)  				gpio_direction_output(gpio, 1);  			else @@ -130,6 +133,7 @@ static ssize_t c55_ctrl_enable(struct device *dev,  	struct device_attribute *attr, const char *buf, size_t count)  {  	struct c55_ctrl_data *cdata = dev_get_drvdata(dev); +	struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata();  	int mode;  	if (kstrtoint(buf, 10, &mode) < 0) @@ -140,35 +144,60 @@ static ssize_t c55_ctrl_enable(struct device *dev,  		return -EINVAL;  	} +	if (m4sensorhub->mode != NORMALMODE) { +		dev_err(dev, "M4 not ready, Unable to set screen status\n"); +		return -EINVAL; +	} +  	if (mode == cdata->c55_mode)  		return count;  	mutex_lock(&cdata->ctrl_mutex);  	if (mode == C55_ON) { -		if (cdata->reg_vddc && regulator_enable(cdata->reg_vddc)) -			dev_err(dev, "regulator_enable failed for vddc\n"); -		if (cdata->reg_vddldo && regulator_enable(cdata->reg_vddldo)) -			dev_err(dev, "regulator_enable failed for vddldo\n"); +		gpio_set_value(cdata->ap_c55_int_gpio, 1); + +		if (m4sensorhub_reg_write_1byte +		    (m4sensorhub, M4SH_REG_USERSETTINGS_SCREENSTATUS, 0x01, 0xFF +		    ) != 1) { +			dev_err(dev, "Unable to set screen status to 0x01\n"); +			mutex_unlock(&cdata->ctrl_mutex); +			return -EINVAL; +		} + +		enable_irq_wake(__gpio_to_irq(cdata->c55_ap_int_gpio));  	} else { -		if (cdata->reg_vddldo) -			regulator_disable(cdata->reg_vddldo); -		if (cdata->reg_vddc) -			regulator_disable(cdata->reg_vddc); +		/* Disable C55->AP IRQ when turning off C55 */ +		disable_irq_wake(__gpio_to_irq(cdata->c55_ap_int_gpio)); + +		if (m4sensorhub_reg_write_1byte +		    (m4sensorhub, M4SH_REG_USERSETTINGS_SCREENSTATUS, 0x00, 0xFF +				) != 1) { +			dev_err(dev, "Unable to set screen status to 0x00\n"); +			mutex_unlock(&cdata->ctrl_mutex); +			return -EINVAL; +		} + +		/* AP->C55 interrupt needs to be set low when C55 is off +		 * for current drain reasons */ +		gpio_set_value(cdata->ap_c55_int_gpio, 0); + +		/* Unlock wake lock in case it is active */ +		wake_unlock(&cdata->wake_lock);  	}  	cdata->c55_mode = mode;  	mutex_unlock(&cdata->ctrl_mutex); -	dev_info(dev, "%s: power = %d\n", __func__, mode); +	dev_info(dev, "%s: enable = %d\n", __func__, mode);  	return count;  } -static DEVICE_ATTR(enable, S_IWUSR, NULL, c55_ctrl_enable); +static DEVICE_ATTR(enable, S_IWUSR | S_IWGRP, NULL, c55_ctrl_enable); -static int  c55_ctrl_probe(struct platform_device *pdev) +static int c55_ctrl_probe(struct platform_device *pdev)  {  	struct c55_ctrl_data *cdata;  	int ret; @@ -186,7 +215,8 @@ static int  c55_ctrl_probe(struct platform_device *pdev)  	mutex_init(&cdata->ctrl_mutex); -	cdata->int_gpio = -1; +	cdata->c55_ap_int_gpio = -1; +	cdata->ap_c55_int_gpio = -1;  	ret = c55_ctrl_gpio_setup(cdata, &pdev->dev);  	if (ret) { @@ -197,10 +227,14 @@ static int  c55_ctrl_probe(struct platform_device *pdev)  	cdata->reg_vddc = devm_regulator_get(&pdev->dev, "vddc");  	if (IS_ERR(cdata->reg_vddc))  		cdata->reg_vddc = NULL; +	else if (regulator_enable(cdata->reg_vddc)) +		dev_err(&pdev->dev, "regulator_enable failed for vddc\n");  	cdata->reg_vddldo = devm_regulator_get(&pdev->dev, "vddldo");  	if (IS_ERR(cdata->reg_vddldo))  		cdata->reg_vddldo = NULL; +	else if (regulator_enable(cdata->reg_vddldo)) +		dev_err(&pdev->dev, "regulator_enable failed for vddldo\n");  	cdata->c55_mode = C55_OFF; @@ -217,7 +251,7 @@ static int  c55_ctrl_probe(struct platform_device *pdev)  	return 0;  } -static int  c55_ctrl_remove(struct platform_device *pdev) +static int c55_ctrl_remove(struct platform_device *pdev)  {  	device_remove_file(&pdev->dev, &dev_attr_enable);  	return 0;  |