drivers/clk/clk-si514.c
Source file repositories/reference/linux-study-clean/drivers/clk/clk-si514.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/clk-si514.c- Extension
.c- Size
- 9662 bytes
- Lines
- 406
- Domain
- Driver Families
- Bucket
- drivers/clk
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk-provider.hlinux/delay.hlinux/module.hlinux/i2c.hlinux/regmap.hlinux/slab.h
Detected Declarations
struct clk_si514struct clk_si514_muldivfunction si514_enable_outputfunction si514_preparefunction si514_unpreparefunction si514_is_preparedfunction si514_get_muldivfunction si514_set_muldivfunction si514_calc_muldivfunction si514_calc_ratefunction si514_recalc_ratefunction si514_determine_ratefunction changesfunction si514_regmap_is_volatilefunction si514_regmap_is_writeablefunction si514_probe
Annotated Snippet
struct clk_si514 {
struct clk_hw hw;
struct regmap *regmap;
struct i2c_client *i2c_client;
};
#define to_clk_si514(_hw) container_of(_hw, struct clk_si514, hw)
/* Multiplier/divider settings */
struct clk_si514_muldiv {
u32 m_frac; /* 29-bit Fractional part of multiplier M */
u8 m_int; /* Integer part of multiplier M, 65..78 */
u8 ls_div_bits; /* 2nd divider, as 2^x */
u16 hs_div; /* 1st divider, must be even and 10<=x<=1022 */
};
/* Enables or disables the output driver */
static int si514_enable_output(struct clk_si514 *data, bool enable)
{
return regmap_update_bits(data->regmap, SI514_REG_CONTROL,
SI514_CONTROL_OE, enable ? SI514_CONTROL_OE : 0);
}
static int si514_prepare(struct clk_hw *hw)
{
struct clk_si514 *data = to_clk_si514(hw);
return si514_enable_output(data, true);
}
static void si514_unprepare(struct clk_hw *hw)
{
struct clk_si514 *data = to_clk_si514(hw);
si514_enable_output(data, false);
}
static int si514_is_prepared(struct clk_hw *hw)
{
struct clk_si514 *data = to_clk_si514(hw);
unsigned int val;
int err;
err = regmap_read(data->regmap, SI514_REG_CONTROL, &val);
if (err < 0)
return err;
return !!(val & SI514_CONTROL_OE);
}
/* Retrieve clock multiplier and dividers from hardware */
static int si514_get_muldiv(struct clk_si514 *data,
struct clk_si514_muldiv *settings)
{
int err;
u8 reg[7];
err = regmap_bulk_read(data->regmap, SI514_REG_M_FRAC1,
reg, ARRAY_SIZE(reg));
if (err)
return err;
settings->m_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
(reg[3] & 0x1F) << 24;
settings->m_int = (reg[4] & 0x3f) << 3 | reg[3] >> 5;
settings->ls_div_bits = (reg[6] >> 4) & 0x07;
settings->hs_div = (reg[6] & 0x03) << 8 | reg[5];
return 0;
}
static int si514_set_muldiv(struct clk_si514 *data,
struct clk_si514_muldiv *settings)
{
u8 lp;
u8 reg[7];
int err;
/* Calculate LP1/LP2 according to table 13 in the datasheet */
/* 65.259980246 */
if (settings->m_int < 65 ||
(settings->m_int == 65 && settings->m_frac <= 139575831))
lp = 0x22;
/* 67.859763463 */
else if (settings->m_int < 67 ||
(settings->m_int == 67 && settings->m_frac <= 461581994))
lp = 0x23;
/* 72.937624981 */
else if (settings->m_int < 72 ||
(settings->m_int == 72 && settings->m_frac <= 503383578))
lp = 0x33;
/* 75.843265046 */
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/delay.h`, `linux/module.h`, `linux/i2c.h`, `linux/regmap.h`, `linux/slab.h`.
- Detected declarations: `struct clk_si514`, `struct clk_si514_muldiv`, `function si514_enable_output`, `function si514_prepare`, `function si514_unprepare`, `function si514_is_prepared`, `function si514_get_muldiv`, `function si514_set_muldiv`, `function si514_calc_muldiv`, `function si514_calc_rate`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.