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

Commit 1b6a4db2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc driver fixes from Greg Kroah-Hartman:
 "Here are some small char/misc driver fixes that resolve issues
  recently reported against the 3.9-rc kernels.  All have been in
  linux-next for a while."

* tag 'char-misc-3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  VMCI: Fix process-to-process DRGAMs.
  mei: ME hardware reset needs to be synchronized
  mei: add mei_stop function to stop mei device
  extcon: max77693: Initialize register of MUIC device to bring up it without platform data
  extcon: max77693: Fix bug of wrong pointer when platform data is not used
  extcon: max8997: Check the pointer of platform data to protect null pointer error
parents dfca53fb 347e0899
Loading
Loading
Loading
Loading
+80 −23
Original line number Diff line number Diff line
@@ -32,6 +32,38 @@
#define	DEV_NAME			"max77693-muic"
#define	DELAY_MS_DEFAULT		20000		/* unit: millisecond */

/*
 * Default value of MAX77693 register to bring up MUIC device.
 * If user don't set some initial value for MUIC device through platform data,
 * extcon-max77693 driver use 'default_init_data' to bring up base operation
 * of MAX77693 MUIC device.
 */
struct max77693_reg_data default_init_data[] = {
	{
		/* STATUS2 - [3]ChgDetRun */
		.addr = MAX77693_MUIC_REG_STATUS2,
		.data = STATUS2_CHGDETRUN_MASK,
	}, {
		/* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */
		.addr = MAX77693_MUIC_REG_INTMASK1,
		.data = INTMASK1_ADC1K_MASK
			| INTMASK1_ADC_MASK,
	}, {
		/* INTMASK2 - Unmask [0]ChgTypM */
		.addr = MAX77693_MUIC_REG_INTMASK2,
		.data = INTMASK2_CHGTYP_MASK,
	}, {
		/* INTMASK3 - Mask all of interrupts */
		.addr = MAX77693_MUIC_REG_INTMASK3,
		.data = 0x0,
	}, {
		/* CDETCTRL2 */
		.addr = MAX77693_MUIC_REG_CDETCTRL2,
		.data = CDETCTRL2_VIDRMEN_MASK
			| CDETCTRL2_DXOVPEN_MASK,
	},
};

enum max77693_muic_adc_debounce_time {
	ADC_DEBOUNCE_TIME_5MS = 0,
	ADC_DEBOUNCE_TIME_10MS,
@@ -1045,8 +1077,9 @@ static int max77693_muic_probe(struct platform_device *pdev)
{
	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
	struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
	struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
	struct max77693_muic_info *info;
	struct max77693_reg_data *init_data;
	int num_init_data;
	int delay_jiffies;
	int ret;
	int i;
@@ -1145,15 +1178,25 @@ static int max77693_muic_probe(struct platform_device *pdev)
		goto err_irq;
	}

	/* Initialize MUIC register by using platform data */
	for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
		enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;

	/* Initialize MUIC register by using platform data or default data */
	if (pdata->muic_data) {
		init_data = pdata->muic_data->init_data;
		num_init_data = pdata->muic_data->num_init_data;
	} else {
		init_data = default_init_data;
		num_init_data = ARRAY_SIZE(default_init_data);
	}

	for (i = 0 ; i < num_init_data ; i++) {
		enum max77693_irq_source irq_src
				= MAX77693_IRQ_GROUP_NR;

		max77693_write_reg(info->max77693->regmap_muic,
				muic_pdata->init_data[i].addr,
				muic_pdata->init_data[i].data);
				init_data[i].addr,
				init_data[i].data);

		switch (muic_pdata->init_data[i].addr) {
		switch (init_data[i].addr) {
		case MAX77693_MUIC_REG_INTMASK1:
			irq_src = MUIC_INT1;
			break;
@@ -1167,9 +1210,12 @@ static int max77693_muic_probe(struct platform_device *pdev)

		if (irq_src < MAX77693_IRQ_GROUP_NR)
			info->max77693->irq_masks_cur[irq_src]
				= muic_pdata->init_data[i].data;
				= init_data[i].data;
	}

	if (pdata->muic_data) {
		struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;

		/*
		 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
		 * h/w path of COMP2/COMN1 on CONTROL1 register.
@@ -1184,6 +1230,21 @@ static int max77693_muic_probe(struct platform_device *pdev)
		else
			info->path_usb = CONTROL1_SW_USB;

		/*
		 * Default delay time for detecting cable state
		 * after certain time.
		 */
		if (muic_pdata->detcable_delay_ms)
			delay_jiffies =
				msecs_to_jiffies(muic_pdata->detcable_delay_ms);
		else
			delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	} else {
		info->path_usb = CONTROL1_SW_USB;
		info->path_uart = CONTROL1_SW_UART;
		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	}

	/* Set initial path for UART */
	 max77693_muic_set_path(info, info->path_uart, true);

@@ -1208,10 +1269,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
	 * driver should notify cable state to upper layer.
	 */
	INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq);
	if (muic_pdata->detcable_delay_ms)
		delay_jiffies = msecs_to_jiffies(muic_pdata->detcable_delay_ms);
	else
		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	schedule_delayed_work(&info->wq_detcable, delay_jiffies);

	return ret;
+34 −22
Original line number Diff line number Diff line
@@ -712,30 +712,46 @@ static int max8997_muic_probe(struct platform_device *pdev)
		goto err_irq;
	}

	/* Initialize registers according to platform data */
	if (pdata->muic_pdata) {
		struct max8997_muic_platform_data *mdata = info->muic_pdata;
		struct max8997_muic_platform_data *muic_pdata
			= pdata->muic_pdata;

		for (i = 0; i < mdata->num_init_data; i++) {
			max8997_write_reg(info->muic, mdata->init_data[i].addr,
					mdata->init_data[i].data);
		}
		/* Initialize registers according to platform data */
		for (i = 0; i < muic_pdata->num_init_data; i++) {
			max8997_write_reg(info->muic,
					muic_pdata->init_data[i].addr,
					muic_pdata->init_data[i].data);
		}

		/*
		 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
		 * h/w path of COMP2/COMN1 on CONTROL1 register.
		 */
	if (pdata->muic_pdata->path_uart)
		info->path_uart = pdata->muic_pdata->path_uart;
		if (muic_pdata->path_uart)
			info->path_uart = muic_pdata->path_uart;
		else
			info->path_uart = CONTROL1_SW_UART;

	if (pdata->muic_pdata->path_usb)
		info->path_usb = pdata->muic_pdata->path_usb;
		if (muic_pdata->path_usb)
			info->path_usb = muic_pdata->path_usb;
		else
			info->path_usb = CONTROL1_SW_USB;

		/*
		 * Default delay time for detecting cable state
		 * after certain time.
		 */
		if (muic_pdata->detcable_delay_ms)
			delay_jiffies =
				msecs_to_jiffies(muic_pdata->detcable_delay_ms);
		else
			delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	} else {
		info->path_uart = CONTROL1_SW_UART;
		info->path_usb = CONTROL1_SW_USB;
		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	}

	/* Set initial path for UART */
	 max8997_muic_set_path(info, info->path_uart, true);

@@ -751,10 +767,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
	 * driver should notify cable state to upper layer.
	 */
	INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
	if (pdata->muic_pdata->detcable_delay_ms)
		delay_jiffies = msecs_to_jiffies(pdata->muic_pdata->detcable_delay_ms);
	else
		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	schedule_delayed_work(&info->wq_detcable, delay_jiffies);

	return 0;
+20 −9
Original line number Diff line number Diff line
@@ -151,6 +151,20 @@ static void mei_me_intr_disable(struct mei_device *dev)
	mei_hcsr_set(hw, hcsr);
}

/**
 * mei_me_hw_reset_release - release device from the reset
 *
 * @dev: the device structure
 */
static void mei_me_hw_reset_release(struct mei_device *dev)
{
	struct mei_me_hw *hw = to_me_hw(dev);
	u32 hcsr = mei_hcsr_read(hw);

	hcsr |= H_IG;
	hcsr &= ~H_RST;
	mei_hcsr_set(hw, hcsr);
}
/**
 * mei_me_hw_reset - resets fw via mei csr register.
 *
@@ -169,18 +183,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
	if (intr_enable)
		hcsr |= H_IE;
	else
		hcsr &= ~H_IE;
		hcsr |= ~H_IE;

	mei_hcsr_set(hw, hcsr);

	hcsr = mei_hcsr_read(hw) | H_IG;
	hcsr &= ~H_RST;
	if (dev->dev_state == MEI_DEV_POWER_DOWN)
		mei_me_hw_reset_release(dev);

	mei_hcsr_set(hw, hcsr);

	hcsr = mei_hcsr_read(hw);

	dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr);
	dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw));
}

/**
@@ -466,7 +476,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
			mutex_unlock(&dev->device_lock);
			return IRQ_HANDLED;
		} else {
			dev_dbg(&dev->pdev->dev, "FW not ready.\n");
			dev_dbg(&dev->pdev->dev, "Reset Completed.\n");
			mei_me_hw_reset_release(dev);
			mutex_unlock(&dev->device_lock);
			return IRQ_HANDLED;
		}
+18 −0
Original line number Diff line number Diff line
@@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
	mei_cl_all_write_clear(dev);
}

void mei_stop(struct mei_device *dev)
{
	dev_dbg(&dev->pdev->dev, "stopping the device.\n");

	mutex_lock(&dev->device_lock);

	cancel_delayed_work(&dev->timer_work);

	mei_wd_stop(dev);

	dev->dev_state = MEI_DEV_POWER_DOWN;
	mei_reset(dev, 0);

	mutex_unlock(&dev->device_lock);

	flush_scheduled_work();
}



+1 −0
Original line number Diff line number Diff line
@@ -381,6 +381,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
void mei_device_init(struct mei_device *dev);
void mei_reset(struct mei_device *dev, int interrupts);
int mei_hw_init(struct mei_device *dev);
void mei_stop(struct mei_device *dev);

/*
 *  MEI interrupt functions prototype
Loading