diff options
Diffstat (limited to 'drivers/platform/sprd/clock.h')
| -rw-r--r-- | drivers/platform/sprd/clock.h | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/platform/sprd/clock.h b/drivers/platform/sprd/clock.h new file mode 100644 index 00000000..eb8586b8 --- /dev/null +++ b/drivers/platform/sprd/clock.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#undef debug +#define debug(format, arg...) pr_debug("clk: " "@@@%s: " format, __func__, ## arg) +#define debug0(format, arg...)// pr_info("clk: " "@@@%s: " format, __func__, ## arg) +#define debug2(format, arg...) pr_debug("clk: " "@@@%s: " format, __func__, ## arg) + +/** + * struct clk_sel - list of sources for a given clock (pll) + * @sources: array of pointers to clocks + * @nr_sources: The size of @sources + */ +struct clk_sel { + int nr_sources; + u32 sources[]; +}; + +/** + * struct clk_reg - register definition for clock control bits + * @reg: pointer to the register in virtual memory. + * @shift: the shift in bits to where the bitfield is. + * @size: the size in bits of the bitfield. + * @mask: the mask of the bitfield. + * + * This specifies the size and position of the bits we are interested + * in within the register specified by @reg. + */ +struct clk_reg { + u32 reg; + //unsigned short shift, size; + u32 mask; +}; + +struct clk_regs { + int id; + const char *name; + struct clk_reg enb, div, sel; + + //pll sources select + int nr_sources; + struct clk *sources[]; +}; + +/** + * struct clk_ops - standard clock operations + * @set_rate: set the clock rate, see clk_set_rate(). + * @get_rate: get the clock rate, see clk_get_rate(). + * @round_rate: round a given clock rate, see clk_round_rate(). + * @set_parent: set the clock's parent, see clk_set_parent(). + * + * Group the common clock implementations together so that we + * don't have to keep setting the same fields again. We leave + * enable in struct clk. + * + * Adding an extra layer of indirection into the process should + * not be a problem as it is unlikely these operations are going + * to need to be called quickly. + */ +struct clk_ops { + int (*set_rate) (struct clk * c, unsigned long rate); + unsigned long (*get_rate) (struct clk * c); + unsigned long (*round_rate) (struct clk * c, unsigned long rate); + int (*set_parent) (struct clk * c, struct clk * parent); +}; + +/** + * struct clk - class of clock for newer style spreadtrum devices. + * @clk: the standard clock representation + * @sel: the parent sources select for this clock + * @reg_sel: the register definition for selecting the pll clock's source + * @reg_div: the register definition for the clock's output divisor + * @reg_enb: the register definition for enable or disable the clock's source + * + * This clock implements the features required by the newer SoCs where + * the standard clock block provides an input mux and a post-mux divisor + * to provide the periperhal's clock. + * + * The array of @sel provides the mapping of mux position to the + * clock, and @reg_sel shows the code where to modify to change the mux + * position. The @reg_div defines how to change the divider settings on + * the output. + */ + +struct clk { + struct module *owner; + struct clk *parent; + int usage; + unsigned long rate; + struct clk_ops *ops; + int (*enable) (struct clk *, int enable, unsigned long *); + + const struct clk_regs *regs; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ +#endif +}; + +#define MAX_DIV (1000) + +#define SCI_CLK_ADD(ID, RATE, ENB, ENB_BIT, DIV, DIV_MSK, SEL, SEL_MSK, NR_CLKS, ...) \ +static const struct clk_regs REGS_##ID = { \ + .name = #ID, \ + .id = 0, \ + .enb = { \ + .reg = (u32)ENB,.mask = ENB_BIT, \ + }, \ + .div = { \ + .reg = (u32)DIV,.mask = DIV_MSK, \ + }, \ + .sel = { \ + .reg = (u32)SEL,.mask = SEL_MSK, \ + }, \ + .nr_sources = NR_CLKS, \ + .sources = {__VA_ARGS__}, \ +}; \ +static struct clk ID = { \ + .owner = THIS_MODULE, \ + .parent = 0, \ + .usage = 0, \ + .rate = RATE, \ + .regs = ®S_##ID, \ + .ops = 0, \ + .enable = 0, \ +}; \ +const struct clk_lookup __clkinit1 CLK_LK_##ID = { \ + .dev_id = 0, \ + .con_id = #ID, \ + .clk = &ID, \ +}; \ + +int __init sci_clk_register(struct clk_lookup *cl); + +#define __clkinit0 __section(.rodata.clkinit0) +#define __clkinit1 __section(.rodata.clkinit1) +#define __clkinit2 __section(.rodata.clkinit2) |
