Path: blob/main/sys/dev/clk/rockchip/rk_clk_gate.c
39537 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/systm.h>30#include <sys/bus.h>3132#include <dev/clk/clk.h>3334#include <dev/clk/rockchip/rk_clk_gate.h>3536#include "clkdev_if.h"3738#define WR4(_clk, off, val) \39CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)40#define RD4(_clk, off, val) \41CLKDEV_READ_4(clknode_get_device(_clk), off, val)42#define MD4(_clk, off, clr, set ) \43CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)44#define DEVICE_LOCK(_clk) \45CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))46#define DEVICE_UNLOCK(_clk) \47CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))4849static int rk_clk_gate_init(struct clknode *clk, device_t dev);50static int rk_clk_gate_set_gate(struct clknode *clk, bool enable);51struct rk_clk_gate_sc {52uint32_t offset;53uint32_t shift;54uint32_t mask;55uint32_t on_value;56uint32_t off_value;57int gate_flags;58bool ungated;59};6061static clknode_method_t rk_clk_gate_methods[] = {62/* Device interface */63CLKNODEMETHOD(clknode_init, rk_clk_gate_init),64CLKNODEMETHOD(clknode_set_gate, rk_clk_gate_set_gate),65CLKNODEMETHOD_END66};67DEFINE_CLASS_1(rk_clk_gate, rk_clk_gate_class, rk_clk_gate_methods,68sizeof(struct rk_clk_gate_sc), clknode_class);6970static int71rk_clk_gate_init(struct clknode *clk, device_t dev)72{73uint32_t reg;74struct rk_clk_gate_sc *sc;75int rv;7677sc = clknode_get_softc(clk);78DEVICE_LOCK(clk);79rv = RD4(clk, sc->offset, ®);80DEVICE_UNLOCK(clk);81if (rv != 0)82return (rv);83reg = (reg >> sc->shift) & sc->mask;84sc->ungated = reg == sc->on_value ? 1 : 0;85clknode_init_parent_idx(clk, 0);86return(0);87}8889static int90rk_clk_gate_set_gate(struct clknode *clk, bool enable)91{92uint32_t reg;93struct rk_clk_gate_sc *sc;94int rv;9596sc = clknode_get_softc(clk);97sc->ungated = enable;98DEVICE_LOCK(clk);99rv = MD4(clk, sc->offset, sc->mask << sc->shift,100((sc->ungated ? sc->on_value : sc->off_value) << sc->shift) |101RK_CLK_GATE_MASK);102if (rv != 0) {103DEVICE_UNLOCK(clk);104return (rv);105}106RD4(clk, sc->offset, ®);107DEVICE_UNLOCK(clk);108return(0);109}110111int112rk_clk_gate_register(struct clkdom *clkdom, struct rk_clk_gate_def *clkdef)113{114struct clknode *clk;115struct rk_clk_gate_sc *sc;116117clk = clknode_create(clkdom, &rk_clk_gate_class, &clkdef->clkdef);118if (clk == NULL)119return (1);120121sc = clknode_get_softc(clk);122sc->offset = clkdef->offset;123sc->shift = clkdef->shift;124sc->mask = clkdef->mask;125sc->on_value = clkdef->on_value;126sc->off_value = clkdef->off_value;127sc->gate_flags = clkdef->gate_flags;128129clknode_register(clkdom, clk);130return (0);131}132133134