1*aac64003Sjmcneill /* $NetBSD: sunxi_ccu_fixed_factor.c,v 1.2 2018/05/08 22:05:25 jmcneill Exp $ */
2a5198ca0Sjmcneill
3a5198ca0Sjmcneill /*-
4a5198ca0Sjmcneill * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
5a5198ca0Sjmcneill * All rights reserved.
6a5198ca0Sjmcneill *
7a5198ca0Sjmcneill * Redistribution and use in source and binary forms, with or without
8a5198ca0Sjmcneill * modification, are permitted provided that the following conditions
9a5198ca0Sjmcneill * are met:
10a5198ca0Sjmcneill * 1. Redistributions of source code must retain the above copyright
11a5198ca0Sjmcneill * notice, this list of conditions and the following disclaimer.
12a5198ca0Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
13a5198ca0Sjmcneill * notice, this list of conditions and the following disclaimer in the
14a5198ca0Sjmcneill * documentation and/or other materials provided with the distribution.
15a5198ca0Sjmcneill *
16a5198ca0Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17a5198ca0Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18a5198ca0Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19a5198ca0Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20a5198ca0Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21a5198ca0Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22a5198ca0Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23a5198ca0Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24a5198ca0Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a5198ca0Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a5198ca0Sjmcneill * SUCH DAMAGE.
27a5198ca0Sjmcneill */
28a5198ca0Sjmcneill
29a5198ca0Sjmcneill #include <sys/cdefs.h>
30*aac64003Sjmcneill __KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_fixed_factor.c,v 1.2 2018/05/08 22:05:25 jmcneill Exp $");
31a5198ca0Sjmcneill
32a5198ca0Sjmcneill #include <sys/param.h>
33a5198ca0Sjmcneill #include <sys/bus.h>
34a5198ca0Sjmcneill
35a5198ca0Sjmcneill #include <dev/clk/clk_backend.h>
36a5198ca0Sjmcneill
37a5198ca0Sjmcneill #include <arm/sunxi/sunxi_ccu.h>
38a5198ca0Sjmcneill
39a5198ca0Sjmcneill static u_int
sunxi_ccu_fixed_factor_get_parent_rate(struct clk * clkp)40a5198ca0Sjmcneill sunxi_ccu_fixed_factor_get_parent_rate(struct clk *clkp)
41a5198ca0Sjmcneill {
42a5198ca0Sjmcneill struct clk *clkp_parent;
43a5198ca0Sjmcneill
44a5198ca0Sjmcneill clkp_parent = clk_get_parent(clkp);
45a5198ca0Sjmcneill if (clkp_parent == NULL)
46a5198ca0Sjmcneill return 0;
47a5198ca0Sjmcneill
48a5198ca0Sjmcneill return clk_get_rate(clkp_parent);
49a5198ca0Sjmcneill }
50a5198ca0Sjmcneill
51a5198ca0Sjmcneill u_int
sunxi_ccu_fixed_factor_get_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk)52a5198ca0Sjmcneill sunxi_ccu_fixed_factor_get_rate(struct sunxi_ccu_softc *sc,
53a5198ca0Sjmcneill struct sunxi_ccu_clk *clk)
54a5198ca0Sjmcneill {
55a5198ca0Sjmcneill struct sunxi_ccu_fixed_factor *fixed_factor = &clk->u.fixed_factor;
56a5198ca0Sjmcneill struct clk *clkp = &clk->base;
57a5198ca0Sjmcneill
58a5198ca0Sjmcneill KASSERT(clk->type == SUNXI_CCU_FIXED_FACTOR);
59a5198ca0Sjmcneill
60a5198ca0Sjmcneill const u_int p_rate = sunxi_ccu_fixed_factor_get_parent_rate(clkp);
61a5198ca0Sjmcneill if (p_rate == 0)
62a5198ca0Sjmcneill return 0;
63a5198ca0Sjmcneill
64a5198ca0Sjmcneill return (u_int)(((uint64_t)p_rate * fixed_factor->mult) / fixed_factor->div);
65a5198ca0Sjmcneill }
66a5198ca0Sjmcneill
67*aac64003Sjmcneill static int
sunxi_ccu_fixed_factor_set_parent_rate(struct clk * clkp,u_int rate)68*aac64003Sjmcneill sunxi_ccu_fixed_factor_set_parent_rate(struct clk *clkp, u_int rate)
69*aac64003Sjmcneill {
70*aac64003Sjmcneill struct clk *clkp_parent;
71*aac64003Sjmcneill
72*aac64003Sjmcneill clkp_parent = clk_get_parent(clkp);
73*aac64003Sjmcneill if (clkp_parent == NULL)
74*aac64003Sjmcneill return ENXIO;
75*aac64003Sjmcneill
76*aac64003Sjmcneill return clk_set_rate(clkp_parent, rate);
77*aac64003Sjmcneill }
78*aac64003Sjmcneill
79*aac64003Sjmcneill int
sunxi_ccu_fixed_factor_set_rate(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk,u_int rate)80*aac64003Sjmcneill sunxi_ccu_fixed_factor_set_rate(struct sunxi_ccu_softc *sc,
81*aac64003Sjmcneill struct sunxi_ccu_clk *clk, u_int rate)
82*aac64003Sjmcneill {
83*aac64003Sjmcneill struct sunxi_ccu_fixed_factor *fixed_factor = &clk->u.fixed_factor;
84*aac64003Sjmcneill struct clk *clkp = &clk->base;
85*aac64003Sjmcneill
86*aac64003Sjmcneill KASSERT(clk->type == SUNXI_CCU_FIXED_FACTOR);
87*aac64003Sjmcneill
88*aac64003Sjmcneill rate *= fixed_factor->div;
89*aac64003Sjmcneill rate /= fixed_factor->mult;
90*aac64003Sjmcneill
91*aac64003Sjmcneill return sunxi_ccu_fixed_factor_set_parent_rate(clkp, rate);
92*aac64003Sjmcneill }
93*aac64003Sjmcneill
94a5198ca0Sjmcneill const char *
sunxi_ccu_fixed_factor_get_parent(struct sunxi_ccu_softc * sc,struct sunxi_ccu_clk * clk)95a5198ca0Sjmcneill sunxi_ccu_fixed_factor_get_parent(struct sunxi_ccu_softc *sc,
96a5198ca0Sjmcneill struct sunxi_ccu_clk *clk)
97a5198ca0Sjmcneill {
98a5198ca0Sjmcneill struct sunxi_ccu_fixed_factor *fixed_factor = &clk->u.fixed_factor;
99a5198ca0Sjmcneill
100a5198ca0Sjmcneill KASSERT(clk->type == SUNXI_CCU_FIXED_FACTOR);
101a5198ca0Sjmcneill
102a5198ca0Sjmcneill return fixed_factor->parent;
103a5198ca0Sjmcneill }
104