Commit 0dbc3577 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pmdomain fixes from Ulf Hansson:

 - imx:
     - Fix system wakeup support for imx8mp power domains
     - Fix potential out-of-range access for imx8m power domains
     - Fix the imx8mm gpu hang

 - qcom: Fix off-by-one error for highest state in rpmpd

* tag 'pmdomain-v6.19-rc3-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm:
  pmdomain: imx8mp-blk-ctrl: Keep usb phy power domain on for system wakeup
  pmdomain: imx8mp-blk-ctrl: Keep gpc power domain on for system wakeup
  pmdomain: imx8m-blk-ctrl: fix out-of-range access of bc->domains
  pmdomain: imx: gpcv2: Fix the imx8mm gpu hang due to wrong adb400 reset
  pmdomain: qcom: rpmpd: fix off-by-one error in clamping to the highest state
parents 8aa30418 e2c4c5b2
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -165,13 +165,11 @@
#define IMX8M_VPU_HSK_PWRDNREQN			BIT(5)
#define IMX8M_DISP_HSK_PWRDNREQN		BIT(4)

#define IMX8MM_GPUMIX_HSK_PWRDNACKN		BIT(29)
#define IMX8MM_GPU_HSK_PWRDNACKN		(BIT(27) | BIT(28))
#define IMX8MM_GPU_HSK_PWRDNACKN		GENMASK(29, 27)
#define IMX8MM_VPUMIX_HSK_PWRDNACKN		BIT(26)
#define IMX8MM_DISPMIX_HSK_PWRDNACKN		BIT(25)
#define IMX8MM_HSIO_HSK_PWRDNACKN		(BIT(23) | BIT(24))
#define IMX8MM_GPUMIX_HSK_PWRDNREQN		BIT(11)
#define IMX8MM_GPU_HSK_PWRDNREQN		(BIT(9) | BIT(10))
#define IMX8MM_GPU_HSK_PWRDNREQN		GENMASK(11, 9)
#define IMX8MM_VPUMIX_HSK_PWRDNREQN		BIT(8)
#define IMX8MM_DISPMIX_HSK_PWRDNREQN		BIT(7)
#define IMX8MM_HSIO_HSK_PWRDNREQN		(BIT(5) | BIT(6))
@@ -794,8 +792,6 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
		.bits  = {
			.pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
			.map = IMX8MM_GPUMIX_A53_DOMAIN,
			.hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
			.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
		},
		.pgc   = BIT(IMX8MM_PGC_GPUMIX),
		.keep_clocks = true,
+1 −1
Original line number Diff line number Diff line
@@ -340,7 +340,7 @@ static void imx8m_blk_ctrl_remove(struct platform_device *pdev)

	of_genpd_del_provider(pdev->dev.of_node);

	for (i = 0; bc->onecell_data.num_domains; i++) {
	for (i = 0; i < bc->onecell_data.num_domains; i++) {
		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];

		pm_genpd_remove(&domain->genpd);
+30 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ struct imx8mp_blk_ctrl_domain_data {
	const char * const *path_names;
	int num_paths;
	const char *gpc_name;
	const unsigned int flags;
};

#define DOMAIN_MAX_CLKS 3
@@ -65,6 +66,7 @@ struct imx8mp_blk_ctrl_domain {
	struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
	struct device *power_dev;
	struct imx8mp_blk_ctrl *bc;
	struct notifier_block power_nb;
	int num_paths;
	int id;
};
@@ -264,10 +266,12 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
	[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
		.name = "hsioblk-usb-phy1",
		.gpc_name = "usb-phy1",
		.flags = GENPD_FLAG_ACTIVE_WAKEUP,
	},
	[IMX8MP_HSIOBLK_PD_USB_PHY2] = {
		.name = "hsioblk-usb-phy2",
		.gpc_name = "usb-phy2",
		.flags = GENPD_FLAG_ACTIVE_WAKEUP,
	},
	[IMX8MP_HSIOBLK_PD_PCIE] = {
		.name = "hsioblk-pcie",
@@ -594,6 +598,20 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
	return 0;
}

static int imx8mp_blk_ctrl_gpc_notifier(struct notifier_block *nb,
					unsigned long action, void *data)
{
	struct imx8mp_blk_ctrl_domain *domain =
			container_of(nb, struct imx8mp_blk_ctrl_domain, power_nb);

	if (action == GENPD_NOTIFY_PRE_OFF) {
		if (domain->genpd.status == GENPD_STATE_ON)
			return NOTIFY_BAD;
	}

	return NOTIFY_OK;
}

static struct lock_class_key blk_ctrl_genpd_lock_class;

static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
@@ -698,15 +716,25 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
			goto cleanup_pds;
		}

		domain->power_nb.notifier_call = imx8mp_blk_ctrl_gpc_notifier;
		ret = dev_pm_genpd_add_notifier(domain->power_dev, &domain->power_nb);
		if (ret) {
			dev_err_probe(dev, ret, "failed to add power notifier\n");
			dev_pm_domain_detach(domain->power_dev, true);
			goto cleanup_pds;
		}

		domain->genpd.name = data->name;
		domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
		domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
		domain->genpd.flags = data->flags;
		domain->bc = bc;
		domain->id = i;

		ret = pm_genpd_init(&domain->genpd, NULL, true);
		if (ret) {
			dev_err_probe(dev, ret, "failed to init power domain\n");
			dev_pm_genpd_remove_notifier(domain->power_dev);
			dev_pm_domain_detach(domain->power_dev, true);
			goto cleanup_pds;
		}
@@ -755,6 +783,7 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
cleanup_pds:
	for (i--; i >= 0; i--) {
		pm_genpd_remove(&bc->domains[i].genpd);
		dev_pm_genpd_remove_notifier(bc->domains[i].power_dev);
		dev_pm_domain_detach(bc->domains[i].power_dev, true);
	}

@@ -774,6 +803,7 @@ static void imx8mp_blk_ctrl_remove(struct platform_device *pdev)
		struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];

		pm_genpd_remove(&domain->genpd);
		dev_pm_genpd_remove_notifier(domain->power_dev);
		dev_pm_domain_detach(domain->power_dev, true);
	}

+1 −1
Original line number Diff line number Diff line
@@ -1001,7 +1001,7 @@ static int rpmpd_aggregate_corner(struct rpmpd *pd)

	/* Clamp to the highest corner/level if sync_state isn't done yet */
	if (!pd->state_synced)
		this_active_corner = this_sleep_corner = pd->max_state - 1;
		this_active_corner = this_sleep_corner = pd->max_state;
	else
		to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);