Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/freescale/imx/clk/imx_clk_mux.c
39566 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright 2016 Michal Meloun <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/conf.h>
31
#include <sys/bus.h>
32
#include <sys/kernel.h>
33
#include <sys/systm.h>
34
35
#include <machine/bus.h>
36
37
#include <dev/clk/clk.h>
38
39
#include <arm64/freescale/imx/clk/imx_clk_mux.h>
40
41
#include "clkdev_if.h"
42
43
#define WR4(_clk, off, val) \
44
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
45
#define RD4(_clk, off, val) \
46
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
47
#define MD4(_clk, off, clr, set ) \
48
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
49
#define DEVICE_LOCK(_clk) \
50
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
51
#define DEVICE_UNLOCK(_clk) \
52
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
53
54
static int imx_clk_mux_init(struct clknode *clk, device_t dev);
55
static int imx_clk_mux_set_mux(struct clknode *clk, int idx);
56
57
struct imx_clk_mux_sc {
58
uint32_t offset;
59
uint32_t shift;
60
uint32_t mask;
61
int mux_flags;
62
};
63
64
static clknode_method_t imx_clk_mux_methods[] = {
65
/* Device interface */
66
CLKNODEMETHOD(clknode_init, imx_clk_mux_init),
67
CLKNODEMETHOD(clknode_set_mux, imx_clk_mux_set_mux),
68
CLKNODEMETHOD_END
69
};
70
DEFINE_CLASS_1(imx_clk_mux, imx_clk_mux_class, imx_clk_mux_methods,
71
sizeof(struct imx_clk_mux_sc), clknode_class);
72
73
static int
74
imx_clk_mux_init(struct clknode *clk, device_t dev)
75
{
76
uint32_t reg;
77
struct imx_clk_mux_sc *sc;
78
int rv;
79
80
sc = clknode_get_softc(clk);
81
82
DEVICE_LOCK(clk);
83
rv = RD4(clk, sc->offset, &reg);
84
DEVICE_UNLOCK(clk);
85
if (rv != 0) {
86
return (rv);
87
}
88
reg = (reg >> sc->shift) & sc->mask;
89
clknode_init_parent_idx(clk, reg);
90
return(0);
91
}
92
93
static int
94
imx_clk_mux_set_mux(struct clknode *clk, int idx)
95
{
96
uint32_t reg;
97
struct imx_clk_mux_sc *sc;
98
int rv;
99
100
sc = clknode_get_softc(clk);
101
102
DEVICE_LOCK(clk);
103
rv = MD4(clk, sc->offset, sc->mask << sc->shift,
104
((idx & sc->mask) << sc->shift));
105
if (rv != 0) {
106
DEVICE_UNLOCK(clk);
107
return (rv);
108
}
109
RD4(clk, sc->offset, &reg);
110
DEVICE_UNLOCK(clk);
111
112
return(0);
113
}
114
115
int
116
imx_clk_mux_register(struct clkdom *clkdom, struct imx_clk_mux_def *clkdef)
117
{
118
struct clknode *clk;
119
struct imx_clk_mux_sc *sc;
120
121
clk = clknode_create(clkdom, &imx_clk_mux_class, &clkdef->clkdef);
122
if (clk == NULL)
123
return (1);
124
125
sc = clknode_get_softc(clk);
126
sc->offset = clkdef->offset;
127
sc->shift = clkdef->shift;
128
sc->mask = (1 << clkdef->width) - 1;
129
sc->mux_flags = clkdef->mux_flags;
130
131
clknode_register(clkdom, clk);
132
return (0);
133
}
134
135