Source
x
return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_creg_data);
/*
* Clk driver for NXP LPC18xx/43xx Configuration Registers (CREG)
*
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
enum {
CREG_CLK_1KHZ,
CREG_CLK_32KHZ,
CREG_CLK_MAX,
};
struct clk_creg_data {
struct clk_hw hw;
const char *name;
struct regmap *reg;
unsigned int en_mask;
const struct clk_ops *ops;
};
static int clk_creg_32k_prepare(struct clk_hw *hw)
{
struct clk_creg_data *creg = to_clk_creg(hw);
int ret;
ret = regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
LPC18XX_CREG_CREG0_PD32KHZ |
LPC18XX_CREG_CREG0_RESET32KHZ, 0);
/*
* Powering up the 32k oscillator takes a long while
* and sadly there aren't any status bit to poll.
*/
msleep(2500);
return ret;
}
static void clk_creg_32k_unprepare(struct clk_hw *hw)
{
struct clk_creg_data *creg = to_clk_creg(hw);
regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
LPC18XX_CREG_CREG0_PD32KHZ,
LPC18XX_CREG_CREG0_PD32KHZ);
}
static int clk_creg_32k_is_prepared(struct clk_hw *hw)
{
struct clk_creg_data *creg = to_clk_creg(hw);
u32 reg;
regmap_read(creg->reg, LPC18XX_CREG_CREG0, ®);
return !(reg & LPC18XX_CREG_CREG0_PD32KHZ) &&
!(reg & LPC18XX_CREG_CREG0_RESET32KHZ);
}
static unsigned long clk_creg_1k_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate / 32;
}
static int clk_creg_enable(struct clk_hw *hw)