Path: blob/main/sys/arm64/freescale/imx/clk/imx_clk_mux.c
39566 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright 2016 Michal Meloun <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/param.h>29#include <sys/conf.h>30#include <sys/bus.h>31#include <sys/kernel.h>32#include <sys/systm.h>3334#include <machine/bus.h>3536#include <dev/clk/clk.h>3738#include <arm64/freescale/imx/clk/imx_clk_mux.h>3940#include "clkdev_if.h"4142#define WR4(_clk, off, val) \43CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)44#define RD4(_clk, off, val) \45CLKDEV_READ_4(clknode_get_device(_clk), off, val)46#define MD4(_clk, off, clr, set ) \47CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)48#define DEVICE_LOCK(_clk) \49CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))50#define DEVICE_UNLOCK(_clk) \51CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))5253static int imx_clk_mux_init(struct clknode *clk, device_t dev);54static int imx_clk_mux_set_mux(struct clknode *clk, int idx);5556struct imx_clk_mux_sc {57uint32_t offset;58uint32_t shift;59uint32_t mask;60int mux_flags;61};6263static clknode_method_t imx_clk_mux_methods[] = {64/* Device interface */65CLKNODEMETHOD(clknode_init, imx_clk_mux_init),66CLKNODEMETHOD(clknode_set_mux, imx_clk_mux_set_mux),67CLKNODEMETHOD_END68};69DEFINE_CLASS_1(imx_clk_mux, imx_clk_mux_class, imx_clk_mux_methods,70sizeof(struct imx_clk_mux_sc), clknode_class);7172static int73imx_clk_mux_init(struct clknode *clk, device_t dev)74{75uint32_t reg;76struct imx_clk_mux_sc *sc;77int rv;7879sc = clknode_get_softc(clk);8081DEVICE_LOCK(clk);82rv = RD4(clk, sc->offset, ®);83DEVICE_UNLOCK(clk);84if (rv != 0) {85return (rv);86}87reg = (reg >> sc->shift) & sc->mask;88clknode_init_parent_idx(clk, reg);89return(0);90}9192static int93imx_clk_mux_set_mux(struct clknode *clk, int idx)94{95uint32_t reg;96struct imx_clk_mux_sc *sc;97int rv;9899sc = clknode_get_softc(clk);100101DEVICE_LOCK(clk);102rv = MD4(clk, sc->offset, sc->mask << sc->shift,103((idx & sc->mask) << sc->shift));104if (rv != 0) {105DEVICE_UNLOCK(clk);106return (rv);107}108RD4(clk, sc->offset, ®);109DEVICE_UNLOCK(clk);110111return(0);112}113114int115imx_clk_mux_register(struct clkdom *clkdom, struct imx_clk_mux_def *clkdef)116{117struct clknode *clk;118struct imx_clk_mux_sc *sc;119120clk = clknode_create(clkdom, &imx_clk_mux_class, &clkdef->clkdef);121if (clk == NULL)122return (1);123124sc = clknode_get_softc(clk);125sc->offset = clkdef->offset;126sc->shift = clkdef->shift;127sc->mask = (1 << clkdef->width) - 1;128sc->mux_flags = clkdef->mux_flags;129130clknode_register(clkdom, clk);131return (0);132}133134135