diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-02-16 07:14:33 -0500 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-02-16 07:14:33 -0500 |
commit | 7a5fe2387925405da0319330986184792ce48ad1 (patch) | |
tree | f9f3c3b4a20ff52ed63d3e83bb438136aaafa5db /arch/avr32/mach-at32ap | |
parent | 160f34531a71fdbbdb593a094273711ffb1257d7 (diff) |
[AVR32] Make sure all genclocks have a parent
Initialize the parent field of each generic clock by looking at the
PM registers. This means that the genclock operations can always
assume that the parent field is non-null, so they don't have to
check. Also remove a few unnecessary BUG_ON()s.
Extracted from a patch by David Brownell.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index c1e477ec7576..a5037aa102fb 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -310,8 +310,6 @@ static void genclk_mode(struct clk *clk, int enabled) | |||
310 | { | 310 | { |
311 | u32 control; | 311 | u32 control; |
312 | 312 | ||
313 | BUG_ON(clk->index > 7); | ||
314 | |||
315 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 313 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); |
316 | if (enabled) | 314 | if (enabled) |
317 | control |= SM_BIT(CEN); | 315 | control |= SM_BIT(CEN); |
@@ -325,11 +323,6 @@ static unsigned long genclk_get_rate(struct clk *clk) | |||
325 | u32 control; | 323 | u32 control; |
326 | unsigned long div = 1; | 324 | unsigned long div = 1; |
327 | 325 | ||
328 | BUG_ON(clk->index > 7); | ||
329 | |||
330 | if (!clk->parent) | ||
331 | return 0; | ||
332 | |||
333 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 326 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); |
334 | if (control & SM_BIT(DIVEN)) | 327 | if (control & SM_BIT(DIVEN)) |
335 | div = 2 * (SM_BFEXT(DIV, control) + 1); | 328 | div = 2 * (SM_BFEXT(DIV, control) + 1); |
@@ -342,11 +335,6 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) | |||
342 | u32 control; | 335 | u32 control; |
343 | unsigned long parent_rate, actual_rate, div; | 336 | unsigned long parent_rate, actual_rate, div; |
344 | 337 | ||
345 | BUG_ON(clk->index > 7); | ||
346 | |||
347 | if (!clk->parent) | ||
348 | return 0; | ||
349 | |||
350 | parent_rate = clk->parent->get_rate(clk->parent); | 338 | parent_rate = clk->parent->get_rate(clk->parent); |
351 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 339 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); |
352 | 340 | ||
@@ -373,11 +361,8 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) | |||
373 | { | 361 | { |
374 | u32 control; | 362 | u32 control; |
375 | 363 | ||
376 | BUG_ON(clk->index > 7); | ||
377 | |||
378 | printk("clk %s: new parent %s (was %s)\n", | 364 | printk("clk %s: new parent %s (was %s)\n", |
379 | clk->name, parent->name, | 365 | clk->name, parent->name, clk->parent->name); |
380 | clk->parent ? clk->parent->name : "(null)"); | ||
381 | 366 | ||
382 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 367 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); |
383 | 368 | ||
@@ -399,6 +384,22 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) | |||
399 | return 0; | 384 | return 0; |
400 | } | 385 | } |
401 | 386 | ||
387 | static void __init genclk_init_parent(struct clk *clk) | ||
388 | { | ||
389 | u32 control; | ||
390 | struct clk *parent; | ||
391 | |||
392 | BUG_ON(clk->index > 7); | ||
393 | |||
394 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | ||
395 | if (control & SM_BIT(OSCSEL)) | ||
396 | parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1; | ||
397 | else | ||
398 | parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0; | ||
399 | |||
400 | clk->parent = parent; | ||
401 | } | ||
402 | |||
402 | /* -------------------------------------------------------------------- | 403 | /* -------------------------------------------------------------------- |
403 | * System peripherals | 404 | * System peripherals |
404 | * -------------------------------------------------------------------- */ | 405 | * -------------------------------------------------------------------- */ |
@@ -872,6 +873,50 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) | |||
872 | return pdev; | 873 | return pdev; |
873 | } | 874 | } |
874 | 875 | ||
876 | /* -------------------------------------------------------------------- | ||
877 | * GCLK | ||
878 | * -------------------------------------------------------------------- */ | ||
879 | static struct clk gclk0 = { | ||
880 | .name = "gclk0", | ||
881 | .mode = genclk_mode, | ||
882 | .get_rate = genclk_get_rate, | ||
883 | .set_rate = genclk_set_rate, | ||
884 | .set_parent = genclk_set_parent, | ||
885 | .index = 0, | ||
886 | }; | ||
887 | static struct clk gclk1 = { | ||
888 | .name = "gclk1", | ||
889 | .mode = genclk_mode, | ||
890 | .get_rate = genclk_get_rate, | ||
891 | .set_rate = genclk_set_rate, | ||
892 | .set_parent = genclk_set_parent, | ||
893 | .index = 1, | ||
894 | }; | ||
895 | static struct clk gclk2 = { | ||
896 | .name = "gclk2", | ||
897 | .mode = genclk_mode, | ||
898 | .get_rate = genclk_get_rate, | ||
899 | .set_rate = genclk_set_rate, | ||
900 | .set_parent = genclk_set_parent, | ||
901 | .index = 2, | ||
902 | }; | ||
903 | static struct clk gclk3 = { | ||
904 | .name = "gclk3", | ||
905 | .mode = genclk_mode, | ||
906 | .get_rate = genclk_get_rate, | ||
907 | .set_rate = genclk_set_rate, | ||
908 | .set_parent = genclk_set_parent, | ||
909 | .index = 3, | ||
910 | }; | ||
911 | static struct clk gclk4 = { | ||
912 | .name = "gclk4", | ||
913 | .mode = genclk_mode, | ||
914 | .get_rate = genclk_get_rate, | ||
915 | .set_rate = genclk_set_rate, | ||
916 | .set_parent = genclk_set_parent, | ||
917 | .index = 4, | ||
918 | }; | ||
919 | |||
875 | struct clk *at32_clock_list[] = { | 920 | struct clk *at32_clock_list[] = { |
876 | &osc32k, | 921 | &osc32k, |
877 | &osc0, | 922 | &osc0, |
@@ -908,6 +953,11 @@ struct clk *at32_clock_list[] = { | |||
908 | &atmel_spi1_spi_clk, | 953 | &atmel_spi1_spi_clk, |
909 | &lcdc0_hclk, | 954 | &lcdc0_hclk, |
910 | &lcdc0_pixclk, | 955 | &lcdc0_pixclk, |
956 | &gclk0, | ||
957 | &gclk1, | ||
958 | &gclk2, | ||
959 | &gclk3, | ||
960 | &gclk4, | ||
911 | }; | 961 | }; |
912 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); | 962 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); |
913 | 963 | ||
@@ -936,6 +986,13 @@ void __init at32_clock_init(void) | |||
936 | if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) | 986 | if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) |
937 | pll1.parent = &osc1; | 987 | pll1.parent = &osc1; |
938 | 988 | ||
989 | genclk_init_parent(&gclk0); | ||
990 | genclk_init_parent(&gclk1); | ||
991 | genclk_init_parent(&gclk2); | ||
992 | genclk_init_parent(&gclk3); | ||
993 | genclk_init_parent(&gclk4); | ||
994 | genclk_init_parent(&lcdc0_pixclk); | ||
995 | |||
939 | /* | 996 | /* |
940 | * Turn on all clocks that have at least one user already, and | 997 | * Turn on all clocks that have at least one user already, and |
941 | * turn off everything else. We only do this for module | 998 | * turn off everything else. We only do this for module |