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

Commit f103560c authored by Daniel Vetter's avatar Daniel Vetter
Browse files

Merge tag 'topic/designware-baytrail-2017-03-02' of...

Merge tag 'topic/designware-baytrail-2017-03-02' of git://anongit.freedesktop.org/git/drm-intel

 into drm-intel-next-queued

Baytrail PMIC vs. PMU race fixes from Hans de Goede

This time the right version (v4), with the compile fix.

Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
parents 1f3b1fd3 264ec1a8
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@
#ifndef IOSF_MBI_SYMS_H
#define IOSF_MBI_SYMS_H

#include <linux/notifier.h>

#define MBI_MCR_OFFSET		0xD0
#define MBI_MDR_OFFSET		0xD4
#define MBI_MCRX_OFFSET		0xD8
@@ -47,6 +49,10 @@
#define QRK_MBI_UNIT_MM		0x05
#define QRK_MBI_UNIT_SOC	0x31

/* Action values for the pmic_bus_access_notifier functions */
#define MBI_PMIC_BUS_ACCESS_BEGIN	1
#define MBI_PMIC_BUS_ACCESS_END		2

#if IS_ENABLED(CONFIG_IOSF_MBI)

bool iosf_mbi_available(void);
@@ -88,6 +94,65 @@ int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
 */
int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);

/**
 * iosf_mbi_punit_acquire() - Acquire access to the P-Unit
 *
 * One some systems the P-Unit accesses the PMIC to change various voltages
 * through the same bus as other kernel drivers use for e.g. battery monitoring.
 *
 * If a driver sends requests to the P-Unit which require the P-Unit to access
 * the PMIC bus while another driver is also accessing the PMIC bus various bad
 * things happen.
 *
 * To avoid these problems this function must be called before accessing the
 * P-Unit or the PMIC, be it through iosf_mbi* functions or through other means.
 *
 * Note on these systems the i2c-bus driver will request a sempahore from the
 * P-Unit for exclusive access to the PMIC bus when i2c drivers are accessing
 * it, but this does not appear to be sufficient, we still need to avoid making
 * certain P-Unit requests during the access window to avoid problems.
 *
 * This function locks a mutex, as such it may sleep.
 */
void iosf_mbi_punit_acquire(void);

/**
 * iosf_mbi_punit_release() - Release access to the P-Unit
 */
void iosf_mbi_punit_release(void);

/**
 * iosf_mbi_register_pmic_bus_access_notifier - Register PMIC bus notifier
 *
 * This function can be used by drivers which may need to acquire P-Unit
 * managed resources from interrupt context, where iosf_mbi_punit_acquire()
 * can not be used.
 *
 * This function allows a driver to register a notifier to get notified (in a
 * process context) before other drivers start accessing the PMIC bus.
 *
 * This allows the driver to acquire any resources, which it may need during
 * the window the other driver is accessing the PMIC, before hand.
 *
 * @nb: notifier_block to register
 */
int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb);

/**
 * iosf_mbi_register_pmic_bus_access_notifier - Unregister PMIC bus notifier
 *
 * @nb: notifier_block to unregister
 */
int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb);

/**
 * iosf_mbi_call_pmic_bus_access_notifier_chain - Call PMIC bus notifier chain
 *
 * @val: action to pass into listener's notifier_call function
 * @v: data pointer to pass into listener's notifier_call function
 */
int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v);

#else /* CONFIG_IOSF_MBI is not enabled */
static inline
bool iosf_mbi_available(void)
@@ -115,6 +180,28 @@ int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
	WARN(1, "IOSF_MBI driver not available");
	return -EPERM;
}

static inline void iosf_mbi_punit_acquire(void) {}
static inline void iosf_mbi_punit_release(void) {}

static inline
int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb)
{
	return 0;
}

static inline
int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb)
{
	return 0;
}

static inline
int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v)
{
	return 0;
}

#endif /* CONFIG_IOSF_MBI */

#endif /* IOSF_MBI_SYMS_H */
+49 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@

static struct pci_dev *mbi_pdev;
static DEFINE_SPINLOCK(iosf_mbi_lock);
static DEFINE_MUTEX(iosf_mbi_punit_mutex);
static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier);

static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset)
{
@@ -190,6 +192,53 @@ bool iosf_mbi_available(void)
}
EXPORT_SYMBOL(iosf_mbi_available);

void iosf_mbi_punit_acquire(void)
{
	mutex_lock(&iosf_mbi_punit_mutex);
}
EXPORT_SYMBOL(iosf_mbi_punit_acquire);

void iosf_mbi_punit_release(void)
{
	mutex_unlock(&iosf_mbi_punit_mutex);
}
EXPORT_SYMBOL(iosf_mbi_punit_release);

int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb)
{
	int ret;

	/* Wait for the bus to go inactive before registering */
	mutex_lock(&iosf_mbi_punit_mutex);
	ret = blocking_notifier_chain_register(
				&iosf_mbi_pmic_bus_access_notifier, nb);
	mutex_unlock(&iosf_mbi_punit_mutex);

	return ret;
}
EXPORT_SYMBOL(iosf_mbi_register_pmic_bus_access_notifier);

int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb)
{
	int ret;

	/* Wait for the bus to go inactive before unregistering */
	mutex_lock(&iosf_mbi_punit_mutex);
	ret = blocking_notifier_chain_unregister(
				&iosf_mbi_pmic_bus_access_notifier, nb);
	mutex_unlock(&iosf_mbi_punit_mutex);

	return ret;
}
EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier);

int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v)
{
	return blocking_notifier_call_chain(
				&iosf_mbi_pmic_bus_access_notifier, val, v);
}
EXPORT_SYMBOL(iosf_mbi_call_pmic_bus_access_notifier_chain);

#ifdef CONFIG_IOSF_MBI_DEBUG
static u32	dbg_mdr;
static u32	dbg_mcr;
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ config DRM_I915
	select ACPI_VIDEO if ACPI
	select ACPI_BUTTON if ACPI
	select SYNC_FILE
	select IOSF_MBI
	help
	  Choose this option if you have a system that has "Intel Graphics
	  Media Accelerator" or "HD Graphics" integrated graphics,
+3 −3
Original line number Diff line number Diff line
@@ -1512,7 +1512,7 @@ static int i915_drm_suspend(struct drm_device *dev)
	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
	intel_opregion_notify_adapter(dev_priv, opregion_target_state);

	intel_uncore_forcewake_reset(dev_priv, false);
	intel_uncore_suspend(dev_priv);
	intel_opregion_unregister(dev_priv);

	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
@@ -1757,7 +1757,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
		DRM_ERROR("Resume prepare failed: %d, continuing anyway\n",
			  ret);

	intel_uncore_early_sanitize(dev_priv, true);
	intel_uncore_resume_early(dev_priv);

	if (IS_GEN9_LP(dev_priv)) {
		if (!dev_priv->suspended_to_idle)
@@ -2402,7 +2402,7 @@ static int intel_runtime_suspend(struct device *kdev)
		return ret;
	}

	intel_uncore_forcewake_reset(dev_priv, false);
	intel_uncore_suspend(dev_priv);

	enable_rpm_wakeref_asserts(dev_priv);
	WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
+3 −4
Original line number Diff line number Diff line
@@ -762,6 +762,7 @@ struct intel_uncore {
	const struct intel_forcewake_range *fw_domains_table;
	unsigned int fw_domains_table_entries;

	struct notifier_block pmic_bus_access_nb;
	struct intel_uncore_funcs funcs;

	unsigned fifo_count;
@@ -3055,14 +3056,12 @@ int intel_irq_install(struct drm_i915_private *dev_priv);
void intel_irq_uninstall(struct drm_i915_private *dev_priv);

extern void intel_uncore_sanitize(struct drm_i915_private *dev_priv);
extern void intel_uncore_early_sanitize(struct drm_i915_private *dev_priv,
					bool restore_forcewake);
extern void intel_uncore_init(struct drm_i915_private *dev_priv);
extern bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv);
extern bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv);
extern void intel_uncore_fini(struct drm_i915_private *dev_priv);
extern void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv,
					 bool restore);
extern void intel_uncore_suspend(struct drm_i915_private *dev_priv);
extern void intel_uncore_resume_early(struct drm_i915_private *dev_priv);
const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id);
void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
				enum forcewake_domains domains);
Loading