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

Commit 547f3350 authored by Andrew Bresticker's avatar Andrew Bresticker Committed by Tomasz Figa
Browse files

clk: exynos-audss: allow input clocks to be specified in device tree



This allows the input clocks to the Exynos AudioSS block to be
specified via device-tree bindings.  Default names will be used
when an input clock is not given.

Signed-off-by: default avatarAndrew Bresticker <abrestic@chromium.org>
Acked-by: default avatarMike Turquette <mturquette@linaro.org>
Acked-by: default avatarKukjin Kim <kgene.kim@samsung.com>
Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
parent b37a4224
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -14,6 +14,21 @@ Required Properties:

- #clock-cells: should be 1.

- clocks:
  - pll_ref: Fixed rate PLL reference clock, parent of mout_audss. "fin_pll"
    is used if not specified.
  - pll_in: Input PLL to the AudioSS block, parent of mout_audss. "fout_epll"
    is used if not specified.
  - cdclk: External i2s clock, parent of mout_i2s. "cdclk0" is used if not
    specified.
  - sclk_audio: Audio bus clock, parent of mout_i2s. "sclk_audio0" is used if
    not specified.
  - sclk_pcm_in: PCM clock, parent of sclk_pcm.  "sclk_pcm0" is used if not
    specified.

- clock-names: Aliases for the above clocks. They should be "pll_ref",
  "pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively.

The following is the list of clocks generated by the controller. Each clock is
assigned an identifier and client nodes use this identifier to specify the
clock which they consume. Some of the clocks are available only on a particular
@@ -35,15 +50,28 @@ sclk_i2s 7
pcm_bus         8
sclk_pcm        9

Example 1: An example of a clock controller node is listed below.
Example 1: An example of a clock controller node using the default input
	   clock names is listed below.

clock_audss: audss-clock-controller@3810000 {
	compatible = "samsung,exynos5250-audss-clock";
	reg = <0x03810000 0x0C>;
	#clock-cells = <1>;
};

Example 2: An example of a clock controller node with the input clocks
           specified.

clock_audss: audss-clock-controller@3810000 {
	compatible = "samsung,exynos5250-audss-clock";
	reg = <0x03810000 0x0C>;
	#clock-cells = <1>;
	clocks = <&clock 1>, <&clock 7>, <&clock 138>, <&clock 160>,
		<&ext_i2s_clk>;
	clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in", "cdclk";
};

Example 2: I2S controller node that consumes the clock generated by the clock
Example 3: I2S controller node that consumes the clock generated by the clock
           controller. Refer to the standard clock bindings for information
           about 'clocks' and 'clock-names' property.

+20 −5
Original line number Diff line number Diff line
@@ -28,10 +28,6 @@ static struct clk_onecell_data clk_data;
#define ASS_CLK_DIV 0x4
#define ASS_CLK_GATE 0x8

/* list of all parent clock list */
static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };

#ifdef CONFIG_PM_SLEEP
static unsigned long reg_save[][2] = {
	{ASS_CLK_SRC,  0},
@@ -68,6 +64,10 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
{
	int i, ret = 0;
	struct resource *res;
	const char *mout_audss_p[] = {"fin_pll", "fout_epll"};
	const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"};
	const char *sclk_pcm_p = "sclk_pcm0";
	struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	reg_base = devm_ioremap_resource(&pdev->dev, res);
@@ -85,11 +85,23 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
	clk_data.clks = clk_table;
	clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS;

	pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
	pll_in = devm_clk_get(&pdev->dev, "pll_in");
	if (!IS_ERR(pll_ref))
		mout_audss_p[0] = __clk_get_name(pll_ref);
	if (!IS_ERR(pll_in))
		mout_audss_p[1] = __clk_get_name(pll_in);
	clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
				mout_audss_p, ARRAY_SIZE(mout_audss_p),
				CLK_SET_RATE_NO_REPARENT,
				reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);

	cdclk = devm_clk_get(&pdev->dev, "cdclk");
	sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio");
	if (!IS_ERR(cdclk))
		mout_i2s_p[1] = __clk_get_name(cdclk);
	if (!IS_ERR(sclk_audio))
		mout_i2s_p[2] = __clk_get_name(sclk_audio);
	clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
				mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
				CLK_SET_RATE_NO_REPARENT,
@@ -123,8 +135,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
				 "sclk_pcm", CLK_SET_RATE_PARENT,
				reg_base + ASS_CLK_GATE, 4, 0, &lock);

	sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
	if (!IS_ERR(sclk_pcm_in))
		sclk_pcm_p = __clk_get_name(sclk_pcm_in);
	clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm",
				"div_pcm0", CLK_SET_RATE_PARENT,
				sclk_pcm_p, CLK_SET_RATE_PARENT,
				reg_base + ASS_CLK_GATE, 5, 0, &lock);

	for (i = 0; i < clk_data.clk_num; i++) {