Selaa lähdekoodia

mmrm: Adding support for api to check if mmrm is supported

Some of targets doesn't need MMRM but need binary compatibility
with targets which support MMRM.

A new api is added to support such scenarios & to ensure that
MMRM is disabled & MM clients can fall back to clk api.

Change-Id: I72514889bffc48174c18e1e764751d2f4595570e
Signed-off-by: Shivendra Kakrania <[email protected]>
Shivendra Kakrania 3 vuotta sitten
vanhempi
sitoutus
4b0b134192
3 muutettua tiedostoa jossa 86 lisäystä ja 7 poistoa
  1. 3 0
      driver/src/mmrm_internal.h
  2. 12 0
      driver/src/mmrm_res_parse.c
  3. 71 7
      driver/src/msm_mmrm.c

+ 3 - 0
driver/src/mmrm_internal.h

@@ -35,6 +35,7 @@ struct mmrm_driver_data {
 	struct mmrm_platform_data *platform_data;
 
 	/* clk */
+	bool is_clk_scaling_supported;
 	struct mmrm_clk_platform_resources clk_res;
 	struct mmrm_clk_mgr *clk_mgr;
 	struct mmrm_clk_mgr_ops *clk_mgr_ops;
@@ -45,6 +46,8 @@ struct mmrm_driver_data {
 
 struct mmrm_platform_data *mmrm_get_platform_data(struct device *dev);
 
+int mmrm_count_clk_clients_frm_dt(struct platform_device *pdev);
+
 int mmrm_read_platform_resources(
 	struct platform_device *pdev,
 	struct mmrm_driver_data *drv_data);

+ 12 - 0
driver/src/mmrm_res_parse.c

@@ -221,6 +221,18 @@ err_load_mmrm_rail_table:
 	return rc;
 }
 
+int mmrm_count_clk_clients_frm_dt(struct platform_device *pdev)
+{
+	u32 size_clk_src = 0, num_clk_src = 0;
+
+	of_find_property(pdev->dev.of_node, "mmrm-client-info", &size_clk_src);
+	num_clk_src = size_clk_src / sizeof(struct nom_clk_src_info);
+	d_mpr_h("%s: found %d clk_srcs size %d\n",
+		__func__, num_clk_src, size_clk_src);
+
+	return num_clk_src;
+}
+
 int mmrm_read_platform_resources(struct platform_device *pdev,
 	struct mmrm_driver_data *drv_data)
 {

+ 71 - 7
driver/src/msm_mmrm.c

@@ -29,6 +29,14 @@
 	drv_data = (void *) -EPROBE_DEFER; \
 }
 
+#define CHECK_SKIP_MMRM_CLK_RSRC(drv_data)	\
+{									\
+	if (!drv_data->is_clk_scaling_supported) {	\
+		d_mpr_h("%s: mmrm clk rsrc not supported\n", __func__);\
+		goto skip_mmrm;				\
+	}								\
+}
+
 #define	MMRM_SYSFS_ENTRY_MAX_LEN PAGE_SIZE
 
 extern int msm_mmrm_debug;
@@ -37,11 +45,30 @@ extern u8 msm_mmrm_allow_multiple_register;
 
 struct mmrm_driver_data *drv_data = (void *) -EPROBE_DEFER;
 
-struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *client_desc)
+bool mmrm_client_check_scaling_supported(enum mmrm_client_type client_type, u32 client_domain)
 {
-	struct mmrm_client *client = NULL;
+	if (drv_data == (void *)-EPROBE_DEFER) {
+		d_mpr_e("%s: mmrm probe_init not done\n", __func__);
+		goto err_exit;
+	}
 
+	if (client_type == MMRM_CLIENT_CLOCK) {
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
 
+		/* TODO: Check for individual domain */
+	}
+
+	return true;
+err_exit:
+	d_mpr_e("%s: error exit\n", __func__);
+skip_mmrm:
+	return false;
+}
+EXPORT_SYMBOL(mmrm_client_check_scaling_supported);
+
+struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *client_desc)
+{
+	struct mmrm_client *client = NULL;
 
 	/* check for null input */
 	if (!client_desc) {
@@ -56,6 +83,9 @@ struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *client_desc)
 
 	/* check for client type, then register */
 	if (client_desc->client_type == MMRM_CLIENT_CLOCK) {
+		/* check for skip mmrm */
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
+
 		client = mmrm_clk_client_register(
 					drv_data->clk_mgr, client_desc);
 		if (!client) {
@@ -68,6 +98,7 @@ struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *client_desc)
 		goto err_exit;
 	}
 
+skip_mmrm:
 	return client;
 
 err_exit:
@@ -80,7 +111,6 @@ int mmrm_client_deregister(struct mmrm_client *client)
 {
 	int rc = 0;
 
-
 	/* check for null input */
 	if (!client) {
 		d_mpr_e("%s: invalid input client\n", __func__);
@@ -95,6 +125,9 @@ int mmrm_client_deregister(struct mmrm_client *client)
 
 	/* check for client type, then deregister */
 	if (client->client_type == MMRM_CLIENT_CLOCK) {
+		/* check for skip mmrm */
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
+
 		rc = mmrm_clk_client_deregister(drv_data->clk_mgr, client);
 		if (rc != 0) {
 			d_mpr_e("%s: failed to deregister client\n", __func__);
@@ -105,6 +138,7 @@ int mmrm_client_deregister(struct mmrm_client *client)
 			__func__, client->client_type);
 	}
 
+skip_mmrm:
 	return rc;
 
 err_exit:
@@ -133,6 +167,9 @@ int mmrm_client_set_value(struct mmrm_client *client,
 
 	/* check for client type, then set value */
 	if (client->client_type == MMRM_CLIENT_CLOCK) {
+		/* check for skip mmrm */
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
+
 		rc = mmrm_clk_client_setval(drv_data->clk_mgr, client,
 				client_data, val);
 		if (rc != 0) {
@@ -144,6 +181,7 @@ int mmrm_client_set_value(struct mmrm_client *client,
 			__func__, client->client_type);
 	}
 
+skip_mmrm:
 	return rc;
 
 err_exit:
@@ -174,6 +212,9 @@ int mmrm_client_set_value_in_range(struct mmrm_client *client,
 
 	/* check for client type, then set value */
 	if (client->client_type == MMRM_CLIENT_CLOCK) {
+		/* check for skip mmrm */
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
+
 		rc = mmrm_clk_client_setval_inrange(drv_data->clk_mgr,
 				client, client_data, val);
 		if (rc != 0) {
@@ -185,6 +226,7 @@ int mmrm_client_set_value_in_range(struct mmrm_client *client,
 			__func__, client->client_type);
 	}
 
+skip_mmrm:
 	return rc;
 
 err_exit:
@@ -213,6 +255,9 @@ int mmrm_client_get_value(struct mmrm_client *client,
 
 	/* check for client type, then get value */
 	if (client->client_type == MMRM_CLIENT_CLOCK) {
+		/* check for skip mmrm */
+		CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
+
 		rc = mmrm_clk_client_getval(drv_data->clk_mgr,
 				client, val);
 		if (rc != 0) {
@@ -224,6 +269,7 @@ int mmrm_client_get_value(struct mmrm_client *client,
 			__func__, client->client_type);
 	}
 
+skip_mmrm:
 	return rc;
 
 err_exit:
@@ -363,6 +409,7 @@ static struct attribute_group mmrm_fs_attrs_group = {
 static int msm_mmrm_probe_init(struct platform_device *pdev)
 {
 	int rc = 0;
+	u32 clk_clients = 0;
 
 	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
 	if (!drv_data) {
@@ -372,6 +419,19 @@ static int msm_mmrm_probe_init(struct platform_device *pdev)
 		goto err_no_mem;
 	}
 
+	/* check for clk clients needing admission control */
+	clk_clients = mmrm_count_clk_clients_frm_dt(pdev);
+	if (clk_clients) {
+		d_mpr_h("%s: %d clk clients managed for admission control\n",
+			__func__, clk_clients);
+		drv_data->is_clk_scaling_supported = true;
+	} else {
+		d_mpr_h("%s: no clk clients managed for admission control\n",
+			__func__);
+		drv_data->is_clk_scaling_supported = false;
+		goto skip_mmrm;
+	}
+
 	drv_data->platform_data = mmrm_get_platform_data(&pdev->dev);
 	if (!drv_data->platform_data) {
 		d_mpr_e("%s: unable to get platform data\n",
@@ -405,6 +465,7 @@ static int msm_mmrm_probe_init(struct platform_device *pdev)
 			__func__);
 	}
 
+skip_mmrm:
 	return rc;
 
 err_mmrm_init:
@@ -449,10 +510,13 @@ static int msm_mmrm_remove(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	sysfs_remove_group(&pdev->dev.kobj, &mmrm_fs_attrs_group);
-	msm_mmrm_debugfs_deinit(drv_data->debugfs_root);
-	mmrm_deinit(drv_data);
-	mmrm_free_platform_resources(drv_data);
+	if (drv_data->is_clk_scaling_supported) {
+		sysfs_remove_group(&pdev->dev.kobj, &mmrm_fs_attrs_group);
+		msm_mmrm_debugfs_deinit(drv_data->debugfs_root);
+		mmrm_deinit(drv_data);
+		mmrm_free_platform_resources(drv_data);
+	}
+
 	dev_set_drvdata(&pdev->dev, NULL);
 	RESET_DRV_DATA(drv_data);