/*
* AM33XX Clock data
*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
* Vaibhav Hiremath <hvaibhav@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/clk-private.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include "am33xx.h"
#include "soc.h"
#include "iomap.h"
#include "clock.h"
#include "control.h"
#include "cm.h"
#include "cm33xx.h"
#include "cm-regbits-33xx.h"
#include "prm.h"
/* Modulemode control */
#define AM33XX_MODULEMODE_HWCTRL_SHIFT 0
#define AM33XX_MODULEMODE_SWCTRL_SHIFT 1
/*LIST_HEAD(clocks);*/
/* Root clocks */
/* RTC 32k */
DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0);
/* On-Chip 32KHz RC OSC */
DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0);
/* Crystal input clks */
DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0);
DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0);
DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
/* Oscillator clock */
/* 19.2, 24, 25 or 26 MHz */
static const char *sys_clkin_ck_parents[] = {
"virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck",
"virt_26000000_ck",
};
/*
* sys_clk in: input to the dpll and also used as funtional clock for,
* adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
*
*/
DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT,
AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH,
0, NULL);
/* External clock - 12 MHz */
DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0);
/* Module clocks and DPLL outputs */
/* DPLL_CORE */
static struct dpll_data dpll_core_dd = {
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE,
.clk_bypass = &sys_clkin_ck,
.clk_ref = &sys_clkin_ck,
.control_reg = AM33XX_CM_CLKMODE_DPLL_CORE,
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
.idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE,
.mult_mask = AM33XX_DPLL_MULT_MASK,
.div1_mask = AM33XX_DPLL_DIV_MASK,
.enable_mask = AM33XX_DPLL_EN_MASK,
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
.max_multiplier = 2047,
.max_divider = 128,
.min_divider = 1,
};
/* CLKDCOLDO output */
static const char *dpll_core_ck_parents[] = {
"sys_clkin_ck",
};
static struct clk dpll_core_ck;
static const struct clk_ops dpll_core_ck_ops = {
.recalc_rate = &omap3_dpll_recalc,
.get_parent = &omap2_init_dpll_parent,
};
static struct clk_hw_omap dpll_core_ck_hw = {
.hw = {
.clk = &dpll_core_ck,
},
.dpll_data = &dpll_core_dd,
.ops = &clkhwops_omap3_dpll,
};
DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
static const char *dpll_core_x2_ck_parents[] = {
"dpll_core_ck",
};
static struct clk dpll_core_x2_ck;
static const struct clk_ops dpll_x2_ck_ops = {
.recalc_rate = &omap3_clkoutx2_recalc,
};
static struct clk_hw_omap dpll_core_x2_ck_hw = {
.hw = {
.clk = &dpll_core_x2_ck,
},
.flags = CLOCK_CLKOUTX2,
};
DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops);
DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
0x0, AM33XX_CM_DIV_M4_DPLL_CORE,
AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT,
AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
NULL);
DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
0x0, AM33XX_CM_DIV_M5_DPLL_CORE,
AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT,
AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
0x0, AM33XX_CM_DIV_M6_DPLL_CORE,
AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT,
AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
/* DPLL_MPU */
static struct dpll_data dpll_mpu_dd = {
.mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU,
.clk_bypass = &sys_clkin_ck,
.clk_ref = &sys_clkin_ck,
.control_reg = AM33XX_CM_CLKMODE_DPLL_MPU,
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
.idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU,
.mult_mask = AM33XX_DPLL_MULT_MASK,
.div1_mask = AM33XX_DPLL_DIV_MASK,
.enable_mask = AM33XX_DPLL_EN_MASK,
.idlest_mask = AM33XX_ST_DPLL_CLK_MASK,
.max_multiplier = 2047,
.max_divider = 128,