Blame view

drivers/clk/sunxi/clk-sun8i-apb0.c 2.74 KB
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Copyright (C) 2014 Chen-Yu Tsai
   * Author: Chen-Yu Tsai <wens@csie.org>
   *
   * Allwinner A23 APB0 clock driver
   *
   * License Terms: GNU General Public License v2
   *
   * Based on clk-sun6i-apb0.c
   * Allwinner A31 APB0 clock driver
   *
   * Copyright (C) 2014 Free Electrons
   * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
   *
   */
  
  #include <linux/clk-provider.h>
439a36d7d   Paul Gortmaker   clk: sunxi: make ...
18
  #include <linux/init.h>
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
19
  #include <linux/of.h>
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
20
  #include <linux/of_address.h>
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
21
  #include <linux/platform_device.h>
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  static struct clk *sun8i_a23_apb0_register(struct device_node *node,
  					   void __iomem *reg)
  {
  	const char *clk_name = node->name;
  	const char *clk_parent;
  	struct clk *clk;
  	int ret;
  
  	clk_parent = of_clk_get_parent_name(node, 0);
  	if (!clk_parent)
  		return ERR_PTR(-EINVAL);
  
  	of_property_read_string(node, "clock-output-names", &clk_name);
  
  	/* The A23 APB0 clock is a standard 2 bit wide divider clock */
  	clk = clk_register_divider(NULL, clk_name, clk_parent, 0, reg,
33f60d026   Chen-Yu Tsai   clk: sunxi: Fix s...
38
  				   0, 2, 0, NULL);
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  	if (IS_ERR(clk))
  		return clk;
  
  	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
  	if (ret)
  		goto err_unregister;
  
  	return clk;
  
  err_unregister:
  	clk_unregister_divider(clk);
  
  	return ERR_PTR(ret);
  }
  
  static void sun8i_a23_apb0_setup(struct device_node *node)
  {
  	void __iomem *reg;
  	struct resource res;
  	struct clk *clk;
  
  	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
  	if (IS_ERR(reg)) {
  		/*
  		 * This happens with clk nodes instantiated through mfd,
  		 * as those do not have their resources assigned in the
  		 * device tree. Do not print an error in this case.
  		 */
  		if (PTR_ERR(reg) != -EINVAL)
  			pr_err("Could not get registers for a23-apb0-clk
  ");
  
  		return;
  	}
  
  	clk = sun8i_a23_apb0_register(node, reg);
  	if (IS_ERR(clk))
  		goto err_unmap;
  
  	return;
  
  err_unmap:
  	iounmap(reg);
  	of_address_to_resource(node, 0, &res);
  	release_mem_region(res.start, resource_size(&res));
  }
915128b62   Ricardo Ribalda Delgado   clk: sunxi: apb0:...
85
86
  CLK_OF_DECLARE_DRIVER(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk",
  		      sun8i_a23_apb0_setup);
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
87

57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
88
89
90
  static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
  {
  	struct device_node *np = pdev->dev.of_node;
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
91
92
93
94
95
96
97
98
  	struct resource *r;
  	void __iomem *reg;
  	struct clk *clk;
  
  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	reg = devm_ioremap_resource(&pdev->dev, r);
  	if (IS_ERR(reg))
  		return PTR_ERR(reg);
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
99
  	clk = sun8i_a23_apb0_register(np, reg);
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
100
101
  	if (IS_ERR(clk))
  		return PTR_ERR(clk);
fd9ffd8be   Chen-Yu Tsai   clk: sunxi: Add C...
102
  	return 0;
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
103
  }
381c1ccd6   Emilio López   clk: sunxi: stati...
104
  static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
105
106
107
108
109
110
111
  	{ .compatible = "allwinner,sun8i-a23-apb0-clk" },
  	{ /* sentinel */ }
  };
  
  static struct platform_driver sun8i_a23_apb0_clk_driver = {
  	.driver = {
  		.name = "sun8i-a23-apb0-clk",
57a1fbf28   Chen-Yu Tsai   clk: sunxi: Add A...
112
113
114
115
  		.of_match_table = sun8i_a23_apb0_clk_dt_ids,
  	},
  	.probe = sun8i_a23_apb0_clk_probe,
  };
439a36d7d   Paul Gortmaker   clk: sunxi: make ...
116
  builtin_platform_driver(sun8i_a23_apb0_clk_driver);