Commit 1b6a4db2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-3.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

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
...@@ -32,6 +32,38 @@ ...@@ -32,6 +32,38 @@
#define DEV_NAME "max77693-muic" #define DEV_NAME "max77693-muic"
#define DELAY_MS_DEFAULT 20000 /* unit: millisecond */ #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 { enum max77693_muic_adc_debounce_time {
ADC_DEBOUNCE_TIME_5MS = 0, ADC_DEBOUNCE_TIME_5MS = 0,
ADC_DEBOUNCE_TIME_10MS, ADC_DEBOUNCE_TIME_10MS,
...@@ -1045,8 +1077,9 @@ static int max77693_muic_probe(struct platform_device *pdev) ...@@ -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_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); 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_muic_info *info;
struct max77693_reg_data *init_data;
int num_init_data;
int delay_jiffies; int delay_jiffies;
int ret; int ret;
int i; int i;
...@@ -1145,15 +1178,25 @@ static int max77693_muic_probe(struct platform_device *pdev) ...@@ -1145,15 +1178,25 @@ static int max77693_muic_probe(struct platform_device *pdev)
goto err_irq; goto err_irq;
} }
/* Initialize MUIC register by using platform data */
for (i = 0 ; i < muic_pdata->num_init_data ; i++) { /* Initialize MUIC register by using platform data or default data */
enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; 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, max77693_write_reg(info->max77693->regmap_muic,
muic_pdata->init_data[i].addr, init_data[i].addr,
muic_pdata->init_data[i].data); init_data[i].data);
switch (muic_pdata->init_data[i].addr) { switch (init_data[i].addr) {
case MAX77693_MUIC_REG_INTMASK1: case MAX77693_MUIC_REG_INTMASK1:
irq_src = MUIC_INT1; irq_src = MUIC_INT1;
break; break;
...@@ -1167,22 +1210,40 @@ static int max77693_muic_probe(struct platform_device *pdev) ...@@ -1167,22 +1210,40 @@ static int max77693_muic_probe(struct platform_device *pdev)
if (irq_src < MAX77693_IRQ_GROUP_NR) if (irq_src < MAX77693_IRQ_GROUP_NR)
info->max77693->irq_masks_cur[irq_src] info->max77693->irq_masks_cur[irq_src]
= muic_pdata->init_data[i].data; = init_data[i].data;
} }
/* if (pdata->muic_data) {
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
* h/w path of COMP2/COMN1 on CONTROL1 register.
*/
if (muic_pdata->path_uart)
info->path_uart = muic_pdata->path_uart;
else
info->path_uart = CONTROL1_SW_UART;
if (muic_pdata->path_usb) /*
info->path_usb = muic_pdata->path_usb; * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
else * h/w path of COMP2/COMN1 on CONTROL1 register.
*/
if (muic_pdata->path_uart)
info->path_uart = muic_pdata->path_uart;
else
info->path_uart = CONTROL1_SW_UART;
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_usb = CONTROL1_SW_USB; 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 */ /* Set initial path for UART */
max77693_muic_set_path(info, info->path_uart, true); max77693_muic_set_path(info, info->path_uart, true);
...@@ -1208,10 +1269,6 @@ static int max77693_muic_probe(struct platform_device *pdev) ...@@ -1208,10 +1269,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
* driver should notify cable state to upper layer. * driver should notify cable state to upper layer.
*/ */
INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); 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); schedule_delayed_work(&info->wq_detcable, delay_jiffies);
return ret; return ret;
......
...@@ -712,29 +712,45 @@ static int max8997_muic_probe(struct platform_device *pdev) ...@@ -712,29 +712,45 @@ static int max8997_muic_probe(struct platform_device *pdev)
goto err_irq; goto err_irq;
} }
/* Initialize registers according to platform data */
if (pdata->muic_pdata) { 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, /* Initialize registers according to platform data */
mdata->init_data[i].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 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
* h/w path of COMP2/COMN1 on CONTROL1 register. * h/w path of COMP2/COMN1 on CONTROL1 register.
*/ */
if (pdata->muic_pdata->path_uart) if (muic_pdata->path_uart)
info->path_uart = pdata->muic_pdata->path_uart; info->path_uart = muic_pdata->path_uart;
else else
info->path_uart = CONTROL1_SW_UART; info->path_uart = CONTROL1_SW_UART;
if (pdata->muic_pdata->path_usb) if (muic_pdata->path_usb)
info->path_usb = pdata->muic_pdata->path_usb; info->path_usb = muic_pdata->path_usb;
else 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; info->path_usb = CONTROL1_SW_USB;
delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
}
/* Set initial path for UART */ /* Set initial path for UART */
max8997_muic_set_path(info, info->path_uart, true); max8997_muic_set_path(info, info->path_uart, true);
...@@ -751,10 +767,6 @@ static int max8997_muic_probe(struct platform_device *pdev) ...@@ -751,10 +767,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
* driver should notify cable state to upper layer. * driver should notify cable state to upper layer.
*/ */
INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq); 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); schedule_delayed_work(&info->wq_detcable, delay_jiffies);
return 0; return 0;
......
...@@ -151,6 +151,20 @@ static void mei_me_intr_disable(struct mei_device *dev) ...@@ -151,6 +151,20 @@ static void mei_me_intr_disable(struct mei_device *dev)
mei_hcsr_set(hw, hcsr); 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. * 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) ...@@ -169,18 +183,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
if (intr_enable) if (intr_enable)
hcsr |= H_IE; hcsr |= H_IE;
else else
hcsr &= ~H_IE; hcsr |= ~H_IE;
mei_hcsr_set(hw, hcsr);
hcsr = mei_hcsr_read(hw) | H_IG;
hcsr &= ~H_RST;
mei_hcsr_set(hw, hcsr); mei_hcsr_set(hw, hcsr);
hcsr = mei_hcsr_read(hw); if (dev->dev_state == MEI_DEV_POWER_DOWN)
mei_me_hw_reset_release(dev);
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) ...@@ -466,7 +476,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} else { } 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); mutex_unlock(&dev->device_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
mei_cl_all_write_clear(dev); 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();
}
...@@ -381,6 +381,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec) ...@@ -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_device_init(struct mei_device *dev);
void mei_reset(struct mei_device *dev, int interrupts); void mei_reset(struct mei_device *dev, int interrupts);
int mei_hw_init(struct mei_device *dev); int mei_hw_init(struct mei_device *dev);
void mei_stop(struct mei_device *dev);
/* /*
* MEI interrupt functions prototype * MEI interrupt functions prototype
......
...@@ -247,44 +247,14 @@ static void mei_remove(struct pci_dev *pdev) ...@@ -247,44 +247,14 @@ static void mei_remove(struct pci_dev *pdev)
hw = to_me_hw(dev); hw = to_me_hw(dev);
mutex_lock(&dev->device_lock);
cancel_delayed_work(&dev->timer_work);
mei_wd_stop(dev); dev_err(&pdev->dev, "stop\n");
mei_stop(dev);
mei_pdev = NULL; mei_pdev = NULL;
if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
mei_cl_disconnect(&dev->iamthif_cl);
}
if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
dev->wd_cl.state = MEI_FILE_DISCONNECTING;
mei_cl_disconnect(&dev->wd_cl);
}
/* Unregistering watchdog device */
mei_watchdog_unregister(dev); mei_watchdog_unregister(dev);
/* remove entry if already in list */
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
if (dev->open_handle_count > 0)
dev->open_handle_count--;
mei_cl_unlink(&dev->wd_cl);
if (dev->open_handle_count > 0)
dev->open_handle_count--;
mei_cl_unlink(&dev->iamthif_cl);
dev->iamthif_current_cb = NULL;
dev->me_clients_num = 0;
mutex_unlock(&dev->device_lock);
flush_scheduled_work();
/* disable interrupts */ /* disable interrupts */
mei_disable_interrupts(dev); mei_disable_interrupts(dev);
...@@ -308,28 +278,20 @@ static int mei_pci_suspend(struct device *device) ...@@ -308,28 +278,20 @@ static int mei_pci_suspend(struct device *device)
{ {
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
struct mei_device *dev = pci_get_drvdata(pdev); struct mei_device *dev = pci_get_drvdata(pdev);
int err;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&dev->device_lock);
cancel_delayed_work(&dev->timer_work); dev_err(&pdev->dev, "suspend\n");
/* Stop watchdog if exists */ mei_stop(dev);
err = mei_wd_stop(dev);
/* Set new mei state */ mei_disable_interrupts(dev);
if (dev->dev_state == MEI_DEV_ENABLED ||
dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
dev->dev_state = MEI_DEV_POWER_DOWN;
mei_reset(dev, 0);
}
mutex_unlock(&dev->device_lock);
free_irq(pdev->irq, dev); free_irq(pdev->irq, dev);
pci_disable_msi(pdev); pci_disable_msi(pdev);
return err; return 0;
} }
static int mei_pci_resume(struct device *device) static int mei_pci_resume(struct device *device)
......
...@@ -42,9 +42,11 @@ struct datagram_entry { ...@@ -42,9 +42,11 @@ struct datagram_entry {
struct delayed_datagram_info { struct delayed_datagram_info {
struct datagram_entry *entry; struct datagram_entry *entry;
struct vmci_datagram msg;
struct work_struct work; struct work_struct work;
bool in_dg_host_queue; bool in_dg_host_queue;
/* msg and msg_payload must be together. */
struct vmci_datagram msg;
u8 msg_payload[];
}; };
/* Number of in-flight host->host datagrams */ /* Number of in-flight host->host datagrams */
......
...@@ -106,6 +106,29 @@ enum max77693_muic_reg { ...@@ -106,6 +106,29 @@ enum max77693_muic_reg {
MAX77693_MUIC_REG_END, MAX77693_MUIC_REG_END,
}; };
/* MAX77693 INTMASK1~2 Register */
#define INTMASK1_ADC1K_SHIFT 3
#define INTMASK1_ADCERR_SHIFT 2
#define INTMASK1_ADCLOW_SHIFT 1
#define INTMASK1_ADC_SHIFT 0
#define INTMASK1_ADC1K_MASK (1 << INTMASK1_ADC1K_SHIFT)
#define INTMASK1_ADCERR_MASK (1 << INTMASK1_ADCERR_SHIFT)
#define INTMASK1_ADCLOW_MASK (1 << INTMASK1_ADCLOW_SHIFT)
#define INTMASK1_ADC_MASK (1 << INTMASK1_ADC_SHIFT)
#define INTMASK2_VIDRM_SHIFT 5
#define INTMASK2_VBVOLT_SHIFT 4
#define INTMASK2_DXOVP_SHIFT 3
#define INTMASK2_DCDTMR_SHIFT 2
#define INTMASK2_CHGDETRUN_SHIFT 1
#define INTMASK2_CHGTYP_SHIFT 0
#define INTMASK2_VIDRM_MASK (1 << INTMASK2_VIDRM_SHIFT)
#define INTMASK2_VBVOLT_MASK (1 << INTMASK2_VBVOLT_SHIFT)
#define INTMASK2_DXOVP_MASK (1 << INTMASK2_DXOVP_SHIFT)
#define INTMASK2_DCDTMR_MASK (1 << INTMASK2_DCDTMR_SHIFT)
#define INTMASK2_CHGDETRUN_MASK (1 << INTMASK2_CHGDETRUN_SHIFT)
#define INTMASK2_CHGTYP_MASK (1 << INTMASK2_CHGTYP_SHIFT)
/* MAX77693 MUIC - STATUS1~3 Register */ /* MAX77693 MUIC - STATUS1~3 Register */
#define STATUS1_ADC_SHIFT (0) #define STATUS1_ADC_SHIFT (0)
#define STATUS1_ADCLOW_SHIFT (5) #define STATUS1_ADCLOW_SHIFT (5)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment