Thread: [Tinyx-devel] [PATCH 1/3] GENERIC: CLOCK: Improving generic clock subsystem.
Status: Planning
Brought to you by:
davidcohen
From: David C. <da...@gm...> - 2008-01-12 16:55:49
|
This patch improves generic clock subsystem. Signed-off-by: David Cohen <da...@gm...> --- arch/common/clock.c | 89 +++++++++++++++++++++++++++++++----------- include/asm-generic/clock.h | 23 +++++++---- 2 files changed, 80 insertions(+), 32 deletions(-) diff --git a/arch/common/clock.c b/arch/common/clock.c index d92f09e..32296f8 100644 --- a/arch/common/clock.c +++ b/arch/common/clock.c @@ -22,54 +22,95 @@ #include <asm-generic/clock.h> #include <tinyx/list.h> -static struct clock *clk_list; -static unsigned int num_clk; +static struct clock **clk_list; -void clk_set_list(struct clock *list, unsigned int num) +unsigned int clk_get_rate(unsigned int id) { - clk_list = list; - num_clk = num; + struct clock **list = clk_list; + struct clock *clk = NULL; + + while (*list) { + clk = *list; + if (clk->id == id) + break; + list++; + } + + return clk ? clk->rate : 0; } -void clk_propagate(struct clock *clk, struct clock *parent) +void clk_propagate(struct clock *clk) { - unsigned int c; - struct clock *child; + struct clock **list; if (clk == NULL) return; if (clk->propagate) - (*clk->propagate)(clk, parent); + (*clk->propagate)(clk); - c = clk->num_child; - child = clk->child; + list = clk->child_list; /* Revisit: fix recursive while */ - while (c--) { - clk_propagate(child, clk); - child++; + while (*list) { + clk_propagate(*list); + list++; } } -unsigned int clk_set_rate(struct clock *clk, unsigned int rate) +unsigned int clk_set_rate(struct clock *clk, unsigned int clk_rate) { - unsigned int clk_rate = rate; - unsigned int c; - struct clock *child; + unsigned int *rate_list; + struct clock **list; if (clk == NULL) return 0; + rate_list = clk->rate_list; + while (*rate_list) { + if (clk_rate >= (*rate_list)) { + clk_rate = *rate_list; + break; + } + rate_list++; + } + if (!(*rate_list)) + clk_rate = 0; + if (clk->set_rate) - clk_rate = (*clk->set_rate)(clk, rate); + clk_rate = (*clk->set_rate)(clk, clk_rate); - c = clk->num_child; - child = clk->child; - while (c--) { - clk_propagate(child, clk); - child++; + list = clk->child_list; + while (*list) { + struct clock *child = *list; + + child = *list; + if (!(child->flags & CLK_INITIALIZED)) { + clk_set_rate(child, child->rate); + child->flags |= CLK_INITIALIZED; + } else + clk_propagate(child); + list++; } return clk_rate; } + +void clk_set_list(struct clock **list, unsigned int num) +{ + clk_list = list; + + while (*list) { + struct clock *clk = *list; + + if ((clk->flags & CLK_PRIMARY) && + !(clk->flags & CLK_INITIALIZED)) { + if (clk->init) + (*clk->init)(clk); + clk_set_rate(clk, clk->rate); + clk->flags |= CLK_INITIALIZED; + } + list++; + } +} + diff --git a/include/asm-generic/clock.h b/include/asm-generic/clock.h index 4ac8e7c..6560eb6 100644 --- a/include/asm-generic/clock.h +++ b/include/asm-generic/clock.h @@ -22,20 +22,27 @@ #ifndef __ASM_GENERIC_CLOCK_H #define __ASM_GENERIC_CLOCK_H +#define CLK_ENABLED (1 << 0) +#define CLK_INITIALIZED (1 << 1) +#define CLK_PRIMARY (1 << 2) + struct clock { unsigned int id; unsigned int rate; + unsigned int flags; struct clock *parent; - struct clock *child; - unsigned int num_child; + struct clock **child_list; + unsigned int (*set_rate) (struct clock *clk, unsigned int rate); - void (*propagate) (struct clock *clk, struct clock *parent); -}; + void (*propagate) (struct clock *clk); + void (*init) (struct clock *clk); -#define clk_get_rate(clk) (clk)->rate + unsigned int rate_list[]; +}; -extern void clk_set_list(struct clock *list, unsigned int num); -extern void clk_propagate(struct clock *clk, struct clock *parent); -extern unsigned int clk_set_rate(struct clock *clk, unsigned int rate); +void clk_set_list(struct clock **list, unsigned int num); +unsigned int clk_get_rate(unsigned int id); +void clk_propagate(struct clock *clk); +unsigned int clk_set_rate(struct clock *clk, unsigned int rate); #endif /* __ASM_GENERIC_CLOCK_H */ -- 1.5.3.7 |
From: David C. <da...@gm...> - 2008-01-12 16:55:58
|
This patch implements clocks for LPC2XXX platform, using the generic clock subsystem. Signed-off-by: David Cohen <da...@gm...> --- arch/arm7/mach-lpc21xx/clock.c | 96 +++++++++++++++++++++++++++++++--------- arch/arm7/mach-lpc21xx/clock.h | 34 +++++++++++++- 2 files changed, 106 insertions(+), 24 deletions(-) diff --git a/arch/arm7/mach-lpc21xx/clock.c b/arch/arm7/mach-lpc21xx/clock.c index 61b00e3..b8003d9 100644 --- a/arch/arm7/mach-lpc21xx/clock.c +++ b/arch/arm7/mach-lpc21xx/clock.c @@ -19,37 +19,91 @@ * along with Tinyx. If not, see <http://www.gnu.org/licenses/>. */ +#include <asm/io.h> +#include <asm/arch/lpc2xxx.h> +#include <asm/arch/start_lpc2148.h> + #include "clock.h" -unsigned int cclk_set_rate(struct clock *clk, unsigned int rate) +#define VAL_FEED1 0xAA +#define VAL_FEED2 0x55 + +#define FCCO_MIN 156000000 +#define FCCO_MAX 320000000 + +#define PLLCON_DIS (0 << 0) /* PLL Disable */ +#define PLLCON_EN (1 << 0) /* PLL Enable */ +#define PLLCON_CON (1 << 1) /* PLL Connect */ +#define PLLSTAT_LOCK (1 << 10) /* PLL Lock Status */ + +static unsigned int psel[4][2] = { + { 1, 0x0 << 5 }, + { 2, 0x1 << 5 }, + { 4, 0x2 << 5 }, + { 8, 0x3 << 5 }, +}; + +static unsigned int cclk_get_psel(unsigned int msel, unsigned int rate) { - return 0; + unsigned int p = 4; + unsigned int fcco = rate * 2 * msel; + + if ((fcco * psel[0][p]) < FCCO_MIN) + /* BUG: FCCO out of range */ + goto end; + + while (p) { + if ((fcco * psel[0][p]) > FCCO_MAX) + p--; + else + goto end; + } + + /* if ((fcco * psel[0][p]) > FCCO_MAX); BUG: FCCO out of range */ + +end: + return psel[1][p]; } -unsigned int pclk_set_rate(struct clock *clk, unsigned int rate) +static void cclk_set_pllcon(unsigned int con) { - return 0; + __raw_writew(con, PLLCON); + __raw_writew(VAL_FEED1, PLLFEED); + __raw_writew(VAL_FEED2, PLLFEED); } -void pclk_propagate(struct clock *clk, struct clock *parent) +static unsigned int cclk_set_rate(struct clock *clk, unsigned int rate) { -} + unsigned int msel; + unsigned int psel; -static struct clock pclk = { - .id = PCLK, - .num_child = 0, - .child = NULL, - .set_rate = pclk_set_rate, - .propagate = pclk_propagate, -}; + msel = rate / FOSC; + msel -= msel ? 1 : 0; -static struct clock cclk = { - .id = CCLK, - .num_child = 1, - .child = &pclk, - .set_rate = cclk_set_rate, - .propagate = NULL, -}; + psel = cclk_get_psel(msel, rate); + + /* Disabling PLL */ + cclk_set_pllcon(PLLCON_DIS); + + /* Configuring PLL */ + __raw_writew((msel | psel), PLLCFG); + cclk_set_pllcon(PLLCON_EN); + + /* Waiting for PLL Lock */ + while (!(__raw_readw(PLLSTAT) & PLLSTAT_LOCK)); + + /* Connecting PLL */ + cclk_set_pllcon(PLLCON_EN | PLLCON_CON); + + return (msel+1) * FOSC; +} -struct clock *lpc2xxx_clk_list[] = { &cclk, &pclk }; +static unsigned int pclk_set_rate(struct clock *clk, unsigned int rate) +{ + return 0; +} + +static void pclk_propagate(struct clock *clk) +{ +} diff --git a/arch/arm7/mach-lpc21xx/clock.h b/arch/arm7/mach-lpc21xx/clock.h index 214fd62..d68f374 100644 --- a/arch/arm7/mach-lpc21xx/clock.h +++ b/arch/arm7/mach-lpc21xx/clock.h @@ -25,8 +25,36 @@ #include <asm/arch-lpc2xxx/clock.h> #include <tinyx/kernel.h> -extern unsigned int cclk_set_rate(struct clock *clk, unsigned int rate); -extern unsigned int pclk_set_rate(struct clock *clk, unsigned int rate); -extern void pclk_propagate(struct clock *clk, struct clock *parent); +static unsigned int cclk_set_rate(struct clock *clk, unsigned int rate); +static unsigned int pclk_set_rate(struct clock *clk, unsigned int rate); +static void pclk_propagate(struct clock *clk); + +static struct clock pclk; +static struct clock cclk; + +static struct clock pclk = { + .id = PCLK, + .flags = CLK_ENABLED, + .rate = 12000000, + .parent = &cclk, + .child_list = NULL, + .set_rate = pclk_set_rate, + .propagate = pclk_propagate, + .rate_list = { 12000000, 0 }, +}; + +static struct clock *cclk_childs[2] = { &pclk, NULL }; + +static struct clock cclk = { + .id = CCLK, + .flags = CLK_ENABLED | CLK_PRIMARY, + .rate = 12000000, + .child_list = cclk_childs, + .set_rate = cclk_set_rate, + .propagate = NULL, + .rate_list = { 12000000, 48000000, 0 }, +}; + +struct clock *lpc2xxx_clk_list[] = { &cclk, &pclk , NULL }; #endif /* __ARCH_MACH_LPC2XXX_CLOCK_H */ -- 1.5.3.7 |
From: David C. <da...@gm...> - 2008-01-12 16:56:05
|
This patch changes temporary UART code on main.c to use clock subsystem. Signed-off-by: David Cohen <da...@gm...> --- kernel/main.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/kernel/main.c b/kernel/main.c index 297562b..68d7f95 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -21,6 +21,7 @@ #include <asm/arch-lpc2xxx/lpc2xxx.h> #include <asm/arch-lpc2xxx/start_lpc2148.h> +#include <asm/arch/clock.h> #include <asm/io.h> #include <tinyx/list.h> #include <tinyx/kernel.h> @@ -39,7 +40,7 @@ static void init_uart0(void) { /* unsigned int clk = B115200((CRYSTAL_FREQUENCY * PLL_FACTOR) / VPBDIV_FACTOR); */ - unsigned int clk = B115200(PCLK); + unsigned int clk = B115200(clk_get_rate(PCLK)); __raw_writel(0x5, PINSEL0); __raw_writel(0x80, U0LCR); __raw_writel((clk & 0xff), U0DLL); -- 1.5.3.7 |
From: David C. <da...@gm...> - 2008-01-13 17:05:56
|
Pushing all three patches. David On Jan 12, 2008 12:55 PM, David Cohen <da...@gm...> wrote: > This patch improves generic clock subsystem. > > Signed-off-by: David Cohen <da...@gm...> > --- > arch/common/clock.c | 89 +++++++++++++++++++++++++++++++----------- > include/asm-generic/clock.h | 23 +++++++---- > 2 files changed, 80 insertions(+), 32 deletions(-) > > diff --git a/arch/common/clock.c b/arch/common/clock.c > index d92f09e..32296f8 100644 > --- a/arch/common/clock.c > +++ b/arch/common/clock.c > @@ -22,54 +22,95 @@ > #include <asm-generic/clock.h> > #include <tinyx/list.h> > > -static struct clock *clk_list; > -static unsigned int num_clk; > +static struct clock **clk_list; > > -void clk_set_list(struct clock *list, unsigned int num) > +unsigned int clk_get_rate(unsigned int id) > { > - clk_list = list; > - num_clk = num; > + struct clock **list = clk_list; > + struct clock *clk = NULL; > + > + while (*list) { > + clk = *list; > + if (clk->id == id) > + break; > + list++; > + } > + > + return clk ? clk->rate : 0; > } > > -void clk_propagate(struct clock *clk, struct clock *parent) > +void clk_propagate(struct clock *clk) > { > - unsigned int c; > - struct clock *child; > + struct clock **list; > > if (clk == NULL) > return; > > if (clk->propagate) > - (*clk->propagate)(clk, parent); > + (*clk->propagate)(clk); > > - c = clk->num_child; > - child = clk->child; > + list = clk->child_list; > > /* Revisit: fix recursive while */ > - while (c--) { > - clk_propagate(child, clk); > - child++; > + while (*list) { > + clk_propagate(*list); > + list++; > } > } > > -unsigned int clk_set_rate(struct clock *clk, unsigned int rate) > +unsigned int clk_set_rate(struct clock *clk, unsigned int clk_rate) > { > - unsigned int clk_rate = rate; > - unsigned int c; > - struct clock *child; > + unsigned int *rate_list; > + struct clock **list; > > if (clk == NULL) > return 0; > > + rate_list = clk->rate_list; > + while (*rate_list) { > + if (clk_rate >= (*rate_list)) { > + clk_rate = *rate_list; > + break; > + } > + rate_list++; > + } > + if (!(*rate_list)) > + clk_rate = 0; > + > if (clk->set_rate) > - clk_rate = (*clk->set_rate)(clk, rate); > + clk_rate = (*clk->set_rate)(clk, clk_rate); > > - c = clk->num_child; > - child = clk->child; > - while (c--) { > - clk_propagate(child, clk); > - child++; > + list = clk->child_list; > + while (*list) { > + struct clock *child = *list; > + > + child = *list; > + if (!(child->flags & CLK_INITIALIZED)) { > + clk_set_rate(child, child->rate); > + child->flags |= CLK_INITIALIZED; > + } else > + clk_propagate(child); > + list++; > } > > return clk_rate; > } > + > +void clk_set_list(struct clock **list, unsigned int num) > +{ > + clk_list = list; > + > + while (*list) { > + struct clock *clk = *list; > + > + if ((clk->flags & CLK_PRIMARY) && > + !(clk->flags & CLK_INITIALIZED)) { > + if (clk->init) > + (*clk->init)(clk); > + clk_set_rate(clk, clk->rate); > + clk->flags |= CLK_INITIALIZED; > + } > + list++; > + } > +} > + > diff --git a/include/asm-generic/clock.h b/include/asm-generic/clock.h > index 4ac8e7c..6560eb6 100644 > --- a/include/asm-generic/clock.h > +++ b/include/asm-generic/clock.h > @@ -22,20 +22,27 @@ > #ifndef __ASM_GENERIC_CLOCK_H > #define __ASM_GENERIC_CLOCK_H > > +#define CLK_ENABLED (1 << 0) > +#define CLK_INITIALIZED (1 << 1) > +#define CLK_PRIMARY (1 << 2) > + > struct clock { > unsigned int id; > unsigned int rate; > + unsigned int flags; > struct clock *parent; > - struct clock *child; > - unsigned int num_child; > + struct clock **child_list; > + > unsigned int (*set_rate) (struct clock *clk, unsigned int rate); > - void (*propagate) (struct clock *clk, struct clock *parent); > -}; > + void (*propagate) (struct clock *clk); > + void (*init) (struct clock *clk); > > -#define clk_get_rate(clk) (clk)->rate > + unsigned int rate_list[]; > +}; > > -extern void clk_set_list(struct clock *list, unsigned int num); > -extern void clk_propagate(struct clock *clk, struct clock *parent); > -extern unsigned int clk_set_rate(struct clock *clk, unsigned int rate); > +void clk_set_list(struct clock **list, unsigned int num); > +unsigned int clk_get_rate(unsigned int id); > +void clk_propagate(struct clock *clk); > +unsigned int clk_set_rate(struct clock *clk, unsigned int rate); > > #endif /* __ASM_GENERIC_CLOCK_H */ > -- > 1.5.3.7 > > -- David Cohen Instituto Nokia de Tecnologia - INdT Manaus - Brazil |