From baf3d1b4fcee7dafdbc2c26725def2c2f9580f95 Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Thu, 21 Jun 2018 16:49:42 -0500 Subject: [PATCH] madera: Add ref clk for codec Enable the ref clk when the codec is not in reset. Mot-CRs-Fixed: (CR) Change-Id: Ic6d0d3f869621b193747f7ba309c2fb18b6a2573 Signed-off-by: Ravi Vembu Reviewed-on: https://gerrit.mot.com/1197391 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Submit-Approved: Jira Key --- drivers/mfd/madera-core.c | 54 ++++++++++++++++++++++++++++++++- include/linux/mfd/madera/core.h | 3 ++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index a840f4ae5cc2..26a5a1f4f7c0 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -148,6 +148,53 @@ const struct of_device_id madera_of_match[] = { EXPORT_SYMBOL_GPL(madera_of_match); #endif +/* + * Routine to enable clock. + * this routine can be extended to select from multiple + * sources based on clk_src_name. + */ +static int madera_clock_select(struct madera *madera) +{ + int r = 0; + + madera->m_clk = clk_get(madera->dev, "cdc_mclk2"); + + if (madera->m_clk == NULL) + goto err_clk; + + if (madera->clk_run == false) + r = clk_prepare_enable(madera->m_clk); + + if (r) + goto err_clk; + + madera->clk_run = true; + + return r; + +err_clk: + dev_err(madera->dev, "Error enabling Ref Clock\n"); + r = -1; + return r; +} + +/* + * Routine to disable clocks + */ +static int madera_clock_deselect(struct madera *madera) +{ + int r = -1; + + if (madera->m_clk != NULL) { + if (madera->clk_run == true) { + clk_disable_unprepare(madera->m_clk); + madera->clk_run = false; + } + return 0; + } + return r; +} + static int madera_poll_reg(struct madera *madera, int timeout, unsigned int reg, unsigned int mask, unsigned int target) @@ -724,6 +771,8 @@ int madera_dev_init(struct madera *madera) goto err_devs; } + madera_clock_select(madera); + /** * Don't use devres here because the only device we have to get * against is the MFD device and DCVDD will likely be supplied by @@ -734,7 +783,7 @@ int madera_dev_init(struct madera *madera) if (IS_ERR(madera->dcvdd)) { ret = PTR_ERR(madera->dcvdd); dev_err(dev, "Failed to request DCVDD: %d\n", ret); - goto err_devs; + goto err_ref_clk; } madera->dcvdd_notifier.notifier_call = madera_dcvdd_notify; @@ -931,6 +980,8 @@ err_notifier: regulator_unregister_notifier(madera->dcvdd, &madera->dcvdd_notifier); err_dcvdd: regulator_put(madera->dcvdd); +err_ref_clk: + madera_clock_deselect(madera); err_devs: mfd_remove_devices(dev); return ret; @@ -950,6 +1001,7 @@ int madera_dev_exit(struct madera *madera) regulator_bulk_disable(madera->num_core_supplies, madera->core_supplies); + madera_clock_deselect(madera); return 0; } EXPORT_SYMBOL_GPL(madera_dev_exit); diff --git a/include/linux/mfd/madera/core.h b/include/linux/mfd/madera/core.h index 4c28b047c52f..33dae31768a4 100644 --- a/include/linux/mfd/madera/core.h +++ b/include/linux/mfd/madera/core.h @@ -17,6 +17,7 @@ #include #include #include +#include enum madera_type { CS47L35 = 1, @@ -72,6 +73,8 @@ struct madera { struct mutex reg_setting_lock; struct blocking_notifier_head notifier; + struct clk *m_clk; + bool clk_run; }; extern int madera_of_read_uint_array(struct madera *madera, const char *prop,