Changeset View
Standalone View
sys/arm64/rockchip/rk805.c
Show All 37 Lines | |||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <dev/iicbus/iiconf.h> | #include <dev/iicbus/iiconf.h> | ||||
#include <dev/iicbus/iicbus.h> | #include <dev/iicbus/iicbus.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/extres/clk/clk.h> | |||||
#include <dev/extres/regulator/regulator.h> | #include <dev/extres/regulator/regulator.h> | ||||
#include <arm64/rockchip/rk805reg.h> | #include <arm64/rockchip/rk805reg.h> | ||||
#include "clock_if.h" | #include "clock_if.h" | ||||
#include "regdev_if.h" | #include "regdev_if.h" | ||||
MALLOC_DEFINE(M_RK805_REG, "RK805 regulator", "RK805 power regulator"); | MALLOC_DEFINE(M_RK805_REG, "RK805 regulator", "RK805 power regulator"); | ||||
▲ Show 20 Lines • Show All 525 Lines • ▼ Show 20 Lines | rk805_reg_attach(device_t dev, phandle_t node, | ||||
reg_sc->xref = OF_xref_from_node(node); | reg_sc->xref = OF_xref_from_node(node); | ||||
reg_sc->param = regnode_get_stdparam(regnode); | reg_sc->param = regnode_get_stdparam(regnode); | ||||
regnode_register(regnode); | regnode_register(regnode); | ||||
return (reg_sc); | return (reg_sc); | ||||
} | } | ||||
/* -------------------------------------------------------------------------- */ | |||||
/* Clock class and method */ | |||||
struct rk805_clk_sc { | |||||
device_t base_dev; | |||||
}; | |||||
#define CLK32OUT_REG 0x20 | |||||
#define CLK32OUT_CLKOUT2_EN 1 | |||||
static int | static int | ||||
rk805_clk_set_gate_1(struct clknode *clk, bool enable) | |||||
{ | |||||
struct rk805_clk_sc *sc; | |||||
uint8_t val; | |||||
sc = clknode_get_softc(clk); | |||||
rk805_read(sc->base_dev, CLK32OUT_REG, &val, sizeof(val)); | |||||
manu: No need for the (void) cast, not sure it's in style(9) too. | |||||
if (enable) | |||||
val |= CLK32OUT_CLKOUT2_EN; | |||||
else | |||||
val &= ~CLK32OUT_CLKOUT2_EN; | |||||
rk805_write(sc->base_dev, CLK32OUT_REG, &val, 1); | |||||
Done Inline ActionsSame manu: Same | |||||
return (0); | |||||
} | |||||
static int | |||||
rk805_clk_recalc(struct clknode *clk, uint64_t *freq) | |||||
{ | |||||
*freq = 32768; | |||||
return (0); | |||||
} | |||||
static clknode_method_t rk805_clk_clknode_methods_0[] = { | |||||
CLKNODEMETHOD(clknode_recalc_freq, rk805_clk_recalc), | |||||
CLKNODEMETHOD_END | |||||
}; | |||||
DEFINE_CLASS_1(rk805_clk_clknode_0, rk805_clk_clknode_class_0, | |||||
rk805_clk_clknode_methods_0, sizeof(struct rk805_clk_sc), | |||||
clknode_class); | |||||
static clknode_method_t rk805_clk_clknode_methods_1[] = { | |||||
CLKNODEMETHOD(clknode_set_gate, rk805_clk_set_gate_1), | |||||
CLKNODEMETHOD_END | |||||
}; | |||||
DEFINE_CLASS_1(rk805_clk_clknode_1, rk805_clk_clknode_class_1, | |||||
rk805_clk_clknode_methods_1, sizeof(struct rk805_clk_sc), | |||||
rk805_clk_clknode_class_0); | |||||
static int | |||||
rk805_export_clocks(device_t dev) | |||||
Done Inline ActionsYou should be able to subclass the first clock def no ? manu: You should be able to subclass the first clock def no ? | |||||
{ | |||||
struct clkdom *clkdom; | |||||
struct clknode_init_def clkidef; | |||||
struct clknode *clk; | |||||
struct rk805_clk_sc *clksc; | |||||
const char **clknames; | |||||
phandle_t node; | |||||
int nclks, rv; | |||||
node = ofw_bus_get_node(dev); | |||||
/* clock-output-names are optional. Could use them for clkidef.name. */ | |||||
nclks = ofw_bus_string_list_to_array(node, "clock-output-names", | |||||
&clknames); | |||||
clkdom = clkdom_create(dev); | |||||
memset(&clkidef, 0, sizeof(clkidef)); | |||||
clkidef.id = 0; | |||||
clkidef.name = (nclks = 2) ? clknames[0] : "clk32kout1"; | |||||
clk = clknode_create(clkdom, &rk805_clk_clknode_class_0, &clkidef); | |||||
if (clk == NULL) { | |||||
device_printf(dev, "Cannot create '%s'.\n", clkidef.name); | |||||
Done Inline ActionsNo need for this comment. manu: No need for this comment. | |||||
Done Inline Actionss/clknode 0/clkidef.name/ manu: s/clknode 0/clkidef.name/ | |||||
return (ENXIO); | |||||
} | |||||
clksc = clknode_get_softc(clk); | |||||
Done Inline ActionsRK808 datasheet name this clock clk32kout1 manu: RK808 datasheet name this clock clk32kout1 | |||||
Done Inline ActionsCan we always rely on the DTS to get this one right. Is we don't have an "xin32k" more things get cranky. That's the reason I did in the end not name it clk32kout1. We never did in rk3399_cru.c either; so there is some inconsistency somewhere? bz: Can we always rely on the DTS to get this one right. Is we don't have an "xin32k" more things… | |||||
Done Inline ActionsYes we should rely on it. manu: Yes we should rely on it.
We didn't have it in rk3399_cru either as we needed to have the… | |||||
Done Inline Actionsclock-output-names could have only one clock, we should always use the name if provided. manu: clock-output-names could have only one clock, we should always use the name if provided. | |||||
clksc->base_dev = dev; | |||||
clknode_register(clkdom, clk); | |||||
memset(&clkidef, 0, sizeof(clkidef)); | |||||
clkidef.id = 1; | |||||
clkidef.name = (nclks = 2) ? clknames[1] : "clk32kout2"; | |||||
clk = clknode_create(clkdom, &rk805_clk_clknode_class_1, &clkidef); | |||||
if (clk == NULL) { | |||||
device_printf(dev, "Cannot create '%s'.\n", clkidef.name); | |||||
Done Inline Actionss/clknode 1/clkidef.name/ manu: s/clknode 1/clkidef.name/ | |||||
return (ENXIO); | |||||
} | |||||
clksc = clknode_get_softc(clk); | |||||
Done Inline ActionsRK808 datasheet name this clock clk32kout2 manu: RK808 datasheet name this clock clk32kout2 | |||||
clksc->base_dev = dev; | |||||
clknode_register(clkdom, clk); | |||||
rv = clkdom_finit(clkdom); | |||||
if (rv != 0) { | |||||
device_printf(dev, "Cannot finalize clkdom initialization: " | |||||
"%d\n", rv); | |||||
return (ENXIO); | |||||
} | |||||
if (bootverbose) | |||||
clkdom_dump(clkdom); | |||||
return (0); | |||||
} | |||||
/* -------------------------------------------------------------------------- */ | |||||
static int | |||||
rk805_probe(device_t dev) | rk805_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
rk805_attach(device_t dev) | rk805_attach(device_t dev) | ||||
{ | { | ||||
struct rk805_softc *sc; | struct rk805_softc *sc; | ||||
struct rk805_reg_sc *reg; | struct rk805_reg_sc *reg; | ||||
struct rk805_regdef *regdefs; | struct rk805_regdef *regdefs; | ||||
struct reg_list *regp; | struct reg_list *regp; | ||||
phandle_t rnode, child; | phandle_t rnode, child; | ||||
int i; | int error, i; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; | |||||
error = rk805_export_clocks(dev); | |||||
Done Inline ActionsLooking at the rk805 datasheet it seems that it have the same clocks, we should always export them unconditionally. manu: Looking at the rk805 datasheet it seems that it have the same clocks, we should always export… | |||||
if (error != 0) | |||||
return (error); | |||||
Done Inline ActionsWe should fail here, if the xin32k clock isn't exported not a lot of thing would work (and we would panic later when we finish the clock domains I think anyway). manu: We should fail here, if the xin32k clock isn't exported not a lot of thing would work (and we… | |||||
sc->intr_hook.ich_func = rk805_start; | sc->intr_hook.ich_func = rk805_start; | ||||
sc->intr_hook.ich_arg = dev; | sc->intr_hook.ich_arg = dev; | ||||
if (config_intrhook_establish(&sc->intr_hook) != 0) | if (config_intrhook_establish(&sc->intr_hook) != 0) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; | |||||
switch (sc->type) { | switch (sc->type) { | ||||
case RK805: | case RK805: | ||||
regdefs = rk805_regdefs; | regdefs = rk805_regdefs; | ||||
sc->nregs = nitems(rk805_regdefs); | sc->nregs = nitems(rk805_regdefs); | ||||
break; | break; | ||||
case RK808: | case RK808: | ||||
regdefs = rk808_regdefs; | regdefs = rk808_regdefs; | ||||
sc->nregs = nitems(rk808_regdefs); | sc->nregs = nitems(rk808_regdefs); | ||||
▲ Show 20 Lines • Show All 90 Lines • Show Last 20 Lines |
No need for the (void) cast, not sure it's in style(9) too.