17cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar/*
27cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * clk-s2mps11.c - Clock driver for S2MPS11.
37cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar *
4e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski * Copyright (C) 2013,2014 Samsung Electornics
57cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar *
67cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * This program is free software; you can redistribute  it and/or modify it
77cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * under  the terms of  the GNU General  Public License as published by the
87cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * Free Software Foundation;  either version 2 of the  License, or (at your
97cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * option) any later version.
107cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar *
117cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * This program is distributed in the hope that it will be useful,
127cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * but WITHOUT ANY WARRANTY; without even the implied warranty of
137cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar * GNU General Public License for more details.
157cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar *
167cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar */
177cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
187cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/module.h>
197cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/err.h>
207cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/of.h>
217cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/clkdev.h>
227cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/regmap.h>
237cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/clk-provider.h>
247cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/platform_device.h>
257cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/mfd/samsung/s2mps11.h>
26e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski#include <linux/mfd/samsung/s2mps14.h>
27e8e6b840c4b646ce5aaef27875a22251ebc4e0d6Tushar Behera#include <linux/mfd/samsung/s5m8767.h>
287cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#include <linux/mfd/samsung/core.h>
297cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
307cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar#define s2mps11_name(a) (a->hw.init->name)
317cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
327cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct clk **clk_table;
337cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct clk_onecell_data clk_data;
347cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
357cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarenum {
367cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	S2MPS11_CLK_AP = 0,
377cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	S2MPS11_CLK_CP,
387cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	S2MPS11_CLK_BT,
397cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	S2MPS11_CLKS_NUM,
407cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
417cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
427cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstruct s2mps11_clk {
437cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct sec_pmic_dev *iodev;
44bf416bd457389bfe7371ba9074bcbd032d7a04ccKrzysztof Kozlowski	struct device_node *clk_np;
457cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct clk_hw hw;
467cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct clk *clk;
477cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct clk_lookup *lookup;
487cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	u32 mask;
4964d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	unsigned int reg;
507cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
517cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
527cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
537cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
547cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return container_of(hw, struct s2mps11_clk, hw);
557cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
567cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
577cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic int s2mps11_clk_prepare(struct clk_hw *hw)
587cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
597cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
607cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	int ret;
617cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
621b1ccee1e821e59c2a45c95b007aeb2c9dafd9beKrzysztof Kozlowski	ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
6364d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera				 s2mps11->reg,
647cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar				 s2mps11->mask, s2mps11->mask);
657cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
667cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return ret;
677cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
687cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
697cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic void s2mps11_clk_unprepare(struct clk_hw *hw)
707cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
717cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
727cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	int ret;
737cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
7464d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
757cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			   s2mps11->mask, ~s2mps11->mask);
767cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
777cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
7889ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wronastatic int s2mps11_clk_is_prepared(struct clk_hw *hw)
797cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
8089ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	int ret;
8189ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	u32 val;
827cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
837cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
8489ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	ret = regmap_read(s2mps11->iodev->regmap_pmic,
8589ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona				s2mps11->reg, &val);
8689ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	if (ret < 0)
8789ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona		return -EINVAL;
8889ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona
8989ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	return val & s2mps11->mask;
907cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
917cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
927cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
937cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar					     unsigned long parent_rate)
947cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
9589ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	return 32768;
967cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
977cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
987cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct clk_ops s2mps11_clk_ops = {
997cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.prepare	= s2mps11_clk_prepare,
1007cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.unprepare	= s2mps11_clk_unprepare,
10189ed7e6e68c176e77c7e2677551c91d4185fe0b4Karol Wrona	.is_prepared	= s2mps11_clk_is_prepared,
1027cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.recalc_rate	= s2mps11_clk_recalc_rate,
1037cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
1047cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1057cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
1067cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	[S2MPS11_CLK_AP] = {
1077cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.name = "s2mps11_ap",
1087cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.ops = &s2mps11_clk_ops,
1097cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.flags = CLK_IS_ROOT,
1107cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	},
1117cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	[S2MPS11_CLK_CP] = {
1127cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.name = "s2mps11_cp",
1137cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.ops = &s2mps11_clk_ops,
1147cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.flags = CLK_IS_ROOT,
1157cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	},
1167cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	[S2MPS11_CLK_BT] = {
1177cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.name = "s2mps11_bt",
1187cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.ops = &s2mps11_clk_ops,
1197cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.flags = CLK_IS_ROOT,
1207cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	},
1217cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
1227cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
123e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowskistatic struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
124e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	[S2MPS11_CLK_AP] = {
125e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.name = "s2mps14_ap",
126e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.ops = &s2mps11_clk_ops,
127e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.flags = CLK_IS_ROOT,
128e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	},
129e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	[S2MPS11_CLK_BT] = {
130e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.name = "s2mps14_bt",
131e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.ops = &s2mps11_clk_ops,
132e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		.flags = CLK_IS_ROOT,
133e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	},
134e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski};
135e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski
136e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowskistatic struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev,
137e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		struct clk_init_data *clks_init)
1387cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
1397cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
1407cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct device_node *clk_np;
1417cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	int i;
1427cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1437cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	if (!iodev->dev->of_node)
144238e14055da87d0d012257788e39fe0df3a82226Krzysztof Kozlowski		return ERR_PTR(-EINVAL);
1457cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
146afbd1a0c309e3d5cb581a3f7c879be97855fe72fKrzysztof Kozlowski	clk_np = of_get_child_by_name(iodev->dev->of_node, "clocks");
1477cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	if (!clk_np) {
1487cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		dev_err(&pdev->dev, "could not find clock sub-node\n");
1497cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		return ERR_PTR(-EINVAL);
1507cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	}
1517cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
152e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
153e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		if (!clks_init[i].name)
154e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski			continue; /* Skip clocks not present in some devices */
1557cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		of_property_read_string_index(clk_np, "clock-output-names", i,
156e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski				&clks_init[i].name);
157e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	}
1587cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1597cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return clk_np;
1607cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
1617cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1627cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic int s2mps11_clk_probe(struct platform_device *pdev)
1637cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
1647cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
1657cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
16664d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	unsigned int s2mps11_reg;
167e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	struct clk_init_data *clks_init;
1687cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	int i, ret = 0;
1697cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1707cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
1717cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar					S2MPS11_CLKS_NUM, GFP_KERNEL);
1727cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	if (!s2mps11_clks)
1737cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		return -ENOMEM;
1747cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1757cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	s2mps11_clk = s2mps11_clks;
1767cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
1777002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski	clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
1787002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski				 S2MPS11_CLKS_NUM, GFP_KERNEL);
1797002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski	if (!clk_table)
1807002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski		return -ENOMEM;
1817002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski
18264d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	switch(platform_get_device_id(pdev)->driver_data) {
18364d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	case S2MPS11X:
18464d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera		s2mps11_reg = S2MPS11_REG_RTC_CTRL;
185e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		clks_init = s2mps11_clks_init;
186e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		break;
187e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	case S2MPS14X:
188e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		s2mps11_reg = S2MPS14_REG_RTCCTRL;
189e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		clks_init = s2mps14_clks_init;
19064d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera		break;
191e8e6b840c4b646ce5aaef27875a22251ebc4e0d6Tushar Behera	case S5M8767X:
192e8e6b840c4b646ce5aaef27875a22251ebc4e0d6Tushar Behera		s2mps11_reg = S5M8767_REG_CTRL1;
193e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		clks_init = s2mps11_clks_init;
194e8e6b840c4b646ce5aaef27875a22251ebc4e0d6Tushar Behera		break;
19564d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	default:
19664d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera		dev_err(&pdev->dev, "Invalid device type\n");
19764d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera		return -EINVAL;
19864d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	};
19964d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera
200e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	/* Store clocks of_node in first element of s2mps11_clks array */
201e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
202e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	if (IS_ERR(s2mps11_clks->clk_np))
203e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		return PTR_ERR(s2mps11_clks->clk_np);
204e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski
2057cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
206e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		if (!clks_init[i].name)
207e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski			continue; /* Skip clocks not present in some devices */
2087cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		s2mps11_clk->iodev = iodev;
209e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		s2mps11_clk->hw.init = &clks_init[i];
2107cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		s2mps11_clk->mask = 1 << i;
21164d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera		s2mps11_clk->reg = s2mps11_reg;
2127cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2137cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		s2mps11_clk->clk = devm_clk_register(&pdev->dev,
2147cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar							&s2mps11_clk->hw);
2157cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		if (IS_ERR(s2mps11_clk->clk)) {
2167cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			dev_err(&pdev->dev, "Fail to register : %s\n",
2177cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar						s2mps11_name(s2mps11_clk));
2187cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			ret = PTR_ERR(s2mps11_clk->clk);
2197cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			goto err_reg;
2207cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		}
2217cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2222a96dfa49c83a2a7cbdb11382976aaa6b2636764Krzysztof Kozlowski		s2mps11_clk->lookup = clkdev_alloc(s2mps11_clk->clk,
2232a96dfa49c83a2a7cbdb11382976aaa6b2636764Krzysztof Kozlowski					s2mps11_name(s2mps11_clk), NULL);
2247cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		if (!s2mps11_clk->lookup) {
2257cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			ret = -ENOMEM;
2267cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			goto err_lup;
2277cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		}
2287cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2297cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		clkdev_add(s2mps11_clk->lookup);
2307cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	}
2317cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
232e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
233e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		/* Skip clocks not present on S2MPS14 */
234e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		if (!clks_init[i].name)
235e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski			continue;
2367002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski		clk_table[i] = s2mps11_clks[i].clk;
237e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	}
2387cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2397002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski	clk_data.clks = clk_table;
2407002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski	clk_data.clk_num = S2MPS11_CLKS_NUM;
2417002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski	of_clk_add_provider(s2mps11_clks->clk_np, of_clk_src_onecell_get,
2427002483c7b28a808d2bd4366b00c48911688c768Krzysztof Kozlowski			&clk_data);
2437cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2447cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	platform_set_drvdata(pdev, s2mps11_clks);
2457cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2467cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return ret;
2477cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarerr_lup:
2487cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
2497cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarerr_reg:
2507cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	while (s2mps11_clk > s2mps11_clks) {
2517cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		if (s2mps11_clk->lookup) {
2527cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			clkdev_drop(s2mps11_clk->lookup);
2537cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar			devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
2547cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		}
2557cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		s2mps11_clk--;
2567cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	}
2577cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2587cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return ret;
2597cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
2607cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2617cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic int s2mps11_clk_remove(struct platform_device *pdev)
2627cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
2637cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
2647cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	int i;
2657cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
266bf416bd457389bfe7371ba9074bcbd032d7a04ccKrzysztof Kozlowski	of_clk_del_provider(s2mps11_clks[0].clk_np);
267bf416bd457389bfe7371ba9074bcbd032d7a04ccKrzysztof Kozlowski	/* Drop the reference obtained in s2mps11_clk_parse_dt */
268bf416bd457389bfe7371ba9074bcbd032d7a04ccKrzysztof Kozlowski	of_node_put(s2mps11_clks[0].clk_np);
269bf416bd457389bfe7371ba9074bcbd032d7a04ccKrzysztof Kozlowski
270e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
271e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		/* Skip clocks not present on S2MPS14 */
272e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski		if (!s2mps11_clks[i].lookup)
273e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski			continue;
2747cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		clkdev_drop(s2mps11_clks[i].lookup);
275e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	}
2767cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2777cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return 0;
2787cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
2797cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2807cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic const struct platform_device_id s2mps11_clk_id[] = {
28164d64c3573b3b6bf2d67fbb54d80bc73a1850f13Tushar Behera	{ "s2mps11-clk", S2MPS11X},
282e8b60a45a54738243d13aeba230af20a68619b1bKrzysztof Kozlowski	{ "s2mps14-clk", S2MPS14X},
283e8e6b840c4b646ce5aaef27875a22251ebc4e0d6Tushar Behera	{ "s5m8767-clk", S5M8767X},
2847cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	{ },
2857cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
2867cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh BrarMODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
2877cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2887cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic struct platform_driver s2mps11_clk_driver = {
2897cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.driver = {
2907cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.name  = "s2mps11-clk",
2917cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar		.owner = THIS_MODULE,
2927cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	},
2937cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.probe = s2mps11_clk_probe,
2947cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.remove = s2mps11_clk_remove,
2957cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	.id_table = s2mps11_clk_id,
2967cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar};
2977cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
2987cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic int __init s2mps11_clk_init(void)
2997cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
3007cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	return platform_driver_register(&s2mps11_clk_driver);
3017cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
3027cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarsubsys_initcall(s2mps11_clk_init);
3037cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
3047cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarstatic void __init s2mps11_clk_cleanup(void)
3057cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar{
3067cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar	platform_driver_unregister(&s2mps11_clk_driver);
3077cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar}
3087cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brarmodule_exit(s2mps11_clk_cleanup);
3097cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh Brar
3107cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh BrarMODULE_DESCRIPTION("S2MPS11 Clock Driver");
3117cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh BrarMODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>");
3127cc560dea4152139e16bea6e56ffa9e1bc461082Yadwinder Singh BrarMODULE_LICENSE("GPL");
313