#ifndef _ARM_TI_PRCM_H
#define _ARM_TI_PRCM_H
#ifdef TI_PRCM_PRIVATE
#include <dev/clk/clk_backend.h>
struct ti_prcm_clk;
struct ti_prcm_softc;
enum ti_prcm_clktype {
TI_PRCM_UNKNOWN,
TI_PRCM_FIXED,
TI_PRCM_FIXED_FACTOR,
TI_PRCM_HWMOD,
};
struct ti_prcm_fixed {
u_int rate;
};
struct ti_prcm_fixed_factor {
u_int mult;
u_int div;
const char *parent;
};
struct ti_prcm_hwmod {
bus_size_t reg;
uint32_t mask;
const char *parent;
u_int flags;
};
#define TI_HWMOD_DISABLE_AUTOIDLE 0x01
struct ti_prcm_clk {
struct clk base;
enum ti_prcm_clktype type;
union {
struct ti_prcm_fixed fixed;
struct ti_prcm_fixed_factor fixed_factor;
struct ti_prcm_hwmod hwmod;
} u;
int (*enable)(struct ti_prcm_softc *,
struct ti_prcm_clk *, int);
u_int (*get_rate)(struct ti_prcm_softc *,
struct ti_prcm_clk *);
int (*set_rate)(struct ti_prcm_softc *,
struct ti_prcm_clk *, u_int);
const char * (*get_parent)(struct ti_prcm_softc *,
struct ti_prcm_clk *);
int (*set_parent)(struct ti_prcm_softc *,
struct ti_prcm_clk *,
const char *);
};
int ti_prcm_attach(struct ti_prcm_softc *);
struct ti_prcm_clk *ti_prcm_clock_find(struct ti_prcm_softc *, const char *);
static inline u_int
ti_prcm_fixed_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
{
KASSERT(tc->type == TI_PRCM_FIXED);
return tc->u.fixed.rate;
}
#define TI_PRCM_FIXED(_name, _rate) \
{ \
.type = TI_PRCM_FIXED, .base.name = (_name), \
.u.fixed.rate = (_rate), \
.get_rate = ti_prcm_fixed_get_rate, \
}
static inline u_int
ti_prcm_fixed_factor_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
{
KASSERT(tc->type == TI_PRCM_FIXED_FACTOR);
struct ti_prcm_clk *tc_parent;
tc_parent = ti_prcm_clock_find(sc, tc->u.fixed_factor.parent);
KASSERT(tc_parent != NULL);
const u_int mult = tc->u.fixed_factor.mult;
const u_int div = tc->u.fixed_factor.div;
return (clk_get_rate(&tc_parent->base) * mult) / div;
}
static inline const char *
ti_prcm_fixed_factor_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
{
KASSERT(tc->type == TI_PRCM_FIXED_FACTOR);
return tc->u.fixed_factor.parent;
}
#define TI_PRCM_FIXED_FACTOR(_name, _mult, _div, _parent) \
{ \
.type = TI_PRCM_FIXED_FACTOR, .base.name = (_name), \
.u.fixed_factor.mult = (_mult), \
.u.fixed_factor.div = (_div), \
.u.fixed_factor.parent = (_parent), \
.get_rate = ti_prcm_fixed_factor_get_rate, \
.get_parent = ti_prcm_fixed_factor_get_parent, \
}
static inline const char *
ti_prcm_hwmod_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
{
KASSERT(tc->type == TI_PRCM_HWMOD);
return tc->u.hwmod.parent;
}
#define TI_PRCM_HWMOD(_name, _reg, _parent, _enable) \
TI_PRCM_HWMOD_MASK(_name, _reg, 0, _parent, _enable, 0)
#define TI_PRCM_HWMOD_MASK(_name, _reg, _mask, _parent, _enable, _flags) \
{ \
.type = TI_PRCM_HWMOD, .base.name = (_name), \
.u.hwmod.reg = (_reg), \
.u.hwmod.mask = (_mask), \
.u.hwmod.flags = (_flags), \
.u.hwmod.parent = (_parent), \
.enable = (_enable), \
.get_parent = ti_prcm_hwmod_get_parent, \
}
struct ti_prcm_softc {
device_t sc_dev;
int sc_phandle;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
struct clk_domain sc_clkdom;
struct ti_prcm_clk *sc_clks;
u_int sc_nclks;
};
#define PRCM_READ(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
#define PRCM_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
#endif
struct clk * ti_prcm_get_hwmod(const int, u_int);
int ti_prcm_enable_hwmod(const int, u_int);
#endif