Path: blob/main/sys/arm/mv/clk/armada38x_gateclk.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2022 Semihalf.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.17* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <sys/systm.h>28#include <sys/bus.h>29#include <sys/rman.h>30#include <sys/kernel.h>31#include <sys/lock.h>32#include <sys/module.h>33#include <sys/mutex.h>3435#include <machine/bus.h>3637#include <dev/fdt/simplebus.h>38#include <dev/ofw/ofw_bus.h>39#include <dev/ofw/ofw_bus_subr.h>40#include <dev/clk/clk.h>41#include <dev/clk/clk_gate.h>4243#include "clkdev_if.h"4445#define ARMADA38X_GATECLK_MAXREG 04647static struct resource_spec armada38x_gateclk_specs[] = {48{ SYS_RES_MEMORY, 0, RF_ACTIVE },49{ -1, 0 }50};5152#define RD4(_sc, addr) bus_read_4(_sc->res, addr)53#define WR4(_sc, addr, val) bus_write_4(_sc->res, addr, val)5455struct armada38x_gateclk_softc56{57struct resource *res;58struct clkdom *clkdom;59struct mtx mtx;60const char* parent;61};6263static struct clk_gate_def gateclk_nodes[] =64{65{66.clkdef = {67.name = "gateclk-audio",68.id = 0,69.parent_cnt = 1,70.flags = 0,71},72.shift = 0,73},74{75.clkdef = {76.name = "gateclk-eth2",77.id = 2,78.parent_cnt = 1,79.flags = 0,80},81.shift = 2,82},83{84.clkdef = {85.name = "gateclk-eth1",86.id = 3,87.parent_cnt = 1,88.flags = 0,89},90.shift = 3,91},92{93.clkdef = {94.name = "gateclk-eth0",95.id = 4,96.parent_cnt = 1,97.flags = 0,98},99.shift = 4,100},101{102.clkdef = {103.name = "gateclk-mdio",104.id = 4,105.parent_cnt = 1,106.flags = 0,107},108.shift = 4,109},110{111.clkdef = {112.name = "gateclk-usb3h0",113.id = 9,114.parent_cnt = 1,115.flags = 0,116},117.shift = 9,118},119{120.clkdef = {121.name = "gateclk-usb3h1",122.id = 10,123.parent_cnt = 1,124.flags = 0,125},126.shift = 10,127},128{129.clkdef = {130.name = "gateclk-bm",131.id = 13,132.parent_cnt = 1,133.flags = 0,134},135.shift = 13,136},137{138.clkdef = {139.name = "gateclk-crypto0z",140.id = 14,141.parent_cnt = 1,142.flags = 0,143},144.shift = 14,145},146{147.clkdef = {148.name = "gateclk-sata0",149.id = 15,150.parent_cnt = 1,151.flags = 0,152},153.shift = 15,154},155{156.clkdef = {157.name = "gateclk-crypto1z",158.id = 16,159.parent_cnt = 1,160.flags = 0,161},162.shift = 16,163},164{165.clkdef = {166.name = "gateclk-sdio",167.id = 17,168.parent_cnt = 1,169.flags = 0,170},171.shift = 17,172},173{174.clkdef = {175.name = "gateclk-usb2",176.id = 18,177.parent_cnt = 1,178.flags = 0,179},180.shift = 18,181},182{183.clkdef = {184.name = "gateclk-crypto1",185.id = 21,186.parent_cnt = 1,187.flags = 0,188},189.shift = 21,190},191{192.clkdef = {193.name = "gateclk-xor0",194.id = 22,195.parent_cnt = 1,196.flags = 0,197},198.shift = 22,199},200{201.clkdef = {202.name = "gateclk-crypto0",203.id = 23,204.parent_cnt = 1,205.flags = 0,206},207.shift = 23,208},209{210.clkdef = {211.name = "gateclk-xor1",212.id = 28,213.parent_cnt = 1,214.flags = 0,215},216.shift = 28,217},218{219.clkdef = {220.name = "gateclk-sata1",221.id = 30,222.parent_cnt = 1,223.flags = 0,224},225.shift = 30,226}227};228229static int armada38x_gateclk_probe(device_t dev);230static int armada38x_gateclk_attach(device_t dev);231232static int233armada38x_gateclk_write_4(device_t dev, bus_addr_t addr, uint32_t val)234{235struct armada38x_gateclk_softc *sc = device_get_softc(dev);236237if (addr > ARMADA38X_GATECLK_MAXREG)238return (EINVAL);239240WR4(sc, addr, val);241return (0);242}243244static int245armada38x_gateclk_read_4(device_t dev, bus_addr_t addr, uint32_t *val)246{247struct armada38x_gateclk_softc *sc = device_get_softc(dev);248249if (addr > ARMADA38X_GATECLK_MAXREG)250return (EINVAL);251252*val = RD4(sc, addr);253return (0);254}255256static int257armada38x_gateclk_modify_4(device_t dev, bus_addr_t addr, uint32_t clr,258uint32_t set)259{260struct armada38x_gateclk_softc *sc = device_get_softc(dev);261uint32_t reg;262263if (addr > ARMADA38X_GATECLK_MAXREG)264return (EINVAL);265266reg = RD4(sc, addr);267reg &= ~clr;268reg |= set;269WR4(sc, addr, reg);270271return (0);272}273274static void275armada38x_gateclk_device_lock(device_t dev)276{277struct armada38x_gateclk_softc *sc = device_get_softc(dev);278279mtx_lock(&sc->mtx);280}281282static void283armada38x_gateclk_device_unlock(device_t dev)284{285struct armada38x_gateclk_softc *sc = device_get_softc(dev);286287mtx_unlock(&sc->mtx);288}289290static device_method_t armada38x_gateclk_methods[] = {291DEVMETHOD(device_probe, armada38x_gateclk_probe),292DEVMETHOD(device_attach, armada38x_gateclk_attach),293294/* clkdev interface */295DEVMETHOD(clkdev_write_4, armada38x_gateclk_write_4),296DEVMETHOD(clkdev_read_4, armada38x_gateclk_read_4),297DEVMETHOD(clkdev_modify_4, armada38x_gateclk_modify_4),298DEVMETHOD(clkdev_device_lock, armada38x_gateclk_device_lock),299DEVMETHOD(clkdev_device_unlock, armada38x_gateclk_device_unlock),300301DEVMETHOD_END302};303304static driver_t armada38x_gateclk_driver = {305"armada38x_gateclk",306armada38x_gateclk_methods,307sizeof(struct armada38x_gateclk_softc),308};309310EARLY_DRIVER_MODULE(armada38x_gateclk, simplebus, armada38x_gateclk_driver, 0, 0,311BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 1);312313static int314armada38x_gateclk_probe(device_t dev)315{316317if (!ofw_bus_status_okay(dev))318return (ENXIO);319320if(!ofw_bus_is_compatible(dev, "marvell,armada-380-gating-clock"))321return (ENXIO);322323device_set_desc(dev, "ARMADA38X gateclk");324325return (BUS_PROBE_DEFAULT);326}327328static int329armada38x_gateclk_attach(device_t dev)330{331struct armada38x_gateclk_softc *sc;332struct clk_gate_def *defp;333phandle_t node;334int i, error;335clk_t clock;336337sc = device_get_softc(dev);338node = ofw_bus_get_node(dev);339340if (bus_alloc_resources(dev, armada38x_gateclk_specs, &sc->res) != 0) {341device_printf(dev, "Cannot allocate resources.\n");342return (ENXIO);343}344345mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);346347sc->clkdom = clkdom_create(dev);348if (sc->clkdom == NULL) {349device_printf(dev, "Cannot create clock domain.\n");350return (ENXIO);351}352353error = clk_get_by_ofw_index(dev, node, 0, &clock);354if (error > 0)355return (error);356357sc->parent = clk_get_name(clock);358359for (i = 0; i < nitems(gateclk_nodes); ++i) {360/* Fill clk_gate fields. */361defp = &gateclk_nodes[i];362defp->clkdef.parent_names = &sc->parent;363defp->offset = 0;364defp->mask = 0x1;365defp->on_value = 1;366defp->off_value = 0;367368error = clknode_gate_register(sc->clkdom, defp);369if (error != 0) {370device_printf(dev, "Cannot create gate nodes\n");371return (error);372}373}374375if (clkdom_finit(sc->clkdom) != 0)376panic("Cannot finalize clock domain initialization.\n");377378return (0);379}380381382