#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/clk/clk.h>
#include <arm/mv/clk/armada38x_gen.h>
#include "clkdev_if.h"
#define SAR_A38X_TCLK_FREQ_SHIFT 15
#define SAR_A38X_TCLK_FREQ_MASK 0x00008000
#define TCLK_250MHZ 250 * 1000 * 1000
#define TCLK_200MHZ 200 * 1000 * 1000
#define WR4(_clk, offset, val) \
CLKDEV_WRITE_4(clknode_get_device(_clk), offset, val)
#define RD4(_clk, offset, val) \
CLKDEV_READ_4(clknode_get_device(_clk), offset, val)
#define DEVICE_LOCK(_clk) \
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
#define DEVICE_UNLOCK(_clk) \
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int
armada38x_gen_recalc(struct clknode *clk, uint64_t *freq)
{
uint32_t reg;
DEVICE_LOCK(clk);
RD4(clk, 0, ®);
DEVICE_UNLOCK(clk);
reg = (reg & SAR_A38X_TCLK_FREQ_MASK) >> SAR_A38X_TCLK_FREQ_SHIFT;
*freq = reg ? TCLK_200MHZ : TCLK_250MHZ;
return (0);
}
static int
armada38x_gen_init(struct clknode *clk, device_t dev)
{
return (0);
}
static clknode_method_t armada38x_gen_clknode_methods[] = {
CLKNODEMETHOD(clknode_init, armada38x_gen_init),
CLKNODEMETHOD(clknode_recalc_freq, armada38x_gen_recalc),
CLKNODEMETHOD_END
};
DEFINE_CLASS_1(armada38x_gen_clknode, armada38x_gen_clknode_class,
armada38x_gen_clknode_methods, 0, clknode_class);
int
armada38x_gen_register(struct clkdom *clkdom, const struct armada38x_gen_clknode_def *clkdef)
{
struct clknode *clk;
clk = clknode_create(clkdom, &armada38x_gen_clknode_class, &clkdef->def);
if (clk == NULL)
return (1);
clknode_register(clkdom, clk);
return(0);
}