Date: | 2011-03-18 16:18:03 (13 years 10 days ago) |
---|---|
Author: | Lars C. |
Commit: | c1e9dbcf81ff9a0c04b99748874ae7d088d5ac59 |
Message: | MIPS: JZ47XX: Further generalize clock support Share common clock management functions and structs between the sub-archs. Also use clkdev for clock lookup, which allows us to assign a clock to a device which is usful if we have multiple device instances of the same driver. (Like for the MMC driver). |
Files: |
arch/mips/Kconfig (1 diff) arch/mips/include/asm/clkdev.h (1 diff) arch/mips/include/asm/mach-jz47xx/clkdev.h (1 diff) arch/mips/jz47xx/Makefile (1 diff) arch/mips/jz47xx/clock.c (1 diff) arch/mips/jz47xx/clock.h (3 diffs) arch/mips/jz47xx/jz4740/clock.c (9 diffs) arch/mips/jz47xx/jz4750/clock-jz4750l.c (7 diffs) arch/mips/jz47xx/jz4760/clock.c (11 diffs) |
Change Details
arch/mips/Kconfig | ||
---|---|---|
210 | 210 | select SYS_HAS_EARLY_PRINTK |
211 | 211 | select HAVE_PWM |
212 | 212 | select HAVE_CLK |
213 | select CLKDEV_LOOKUP | |
213 | 214 | |
214 | 215 | config LASAT |
215 | 216 | bool "LASAT Networks platforms" |
arch/mips/include/asm/clkdev.h | ||
---|---|---|
1 | #ifndef __ASM_CLKDEV_H | |
2 | #define __ASM_CLKDEV_H | |
3 | ||
4 | #include <clkdev.h> | |
5 | ||
6 | #endif |
arch/mips/include/asm/mach-jz47xx/clkdev.h | ||
---|---|---|
1 | #ifndef __ASM_MACH_JZ47XX_CLKDEV_H__ | |
2 | #define __ASM_MACH_JZ47XX_CLKDEV_H__ | |
3 | ||
4 | #include <linux/slab.h> | |
5 | #define __clk_get(clk) ({ 1; }) | |
6 | #define __clk_put(clk) do { } while (0) | |
7 | ||
8 | static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) | |
9 | { | |
10 | return kzalloc(size, GFP_KERNEL); | |
11 | } | |
12 | ||
13 | #endif |
arch/mips/jz47xx/Makefile | ||
---|---|---|
5 | 5 | # Object file lists. |
6 | 6 | |
7 | 7 | obj-y += prom.o irq.o reset.o setup.o \ |
8 | timer.o pwm.o serial.o | |
8 | timer.o pwm.o serial.o clock.o | |
9 | 9 | |
10 | 10 | obj-$(CONFIG_JZ47XX_TIMER_CSRC) += timer-csrc.o |
11 | 11 | obj-$(CONFIG_JZ47XX_TIMER_CEVT) += timer-cevt.o |
arch/mips/jz47xx/clock.c | ||
---|---|---|
1 | #include <linux/kernel.h> | |
2 | #include <linux/errno.h> | |
3 | #include <linux/clk.h> | |
4 | #include <linux/spinlock.h> | |
5 | #include <linux/io.h> | |
6 | #include <linux/module.h> | |
7 | #include <linux/list.h> | |
8 | #include <linux/err.h> | |
9 | ||
10 | #include <asm/mach-jz47xx/clock.h> | |
11 | ||
12 | #include <asm/mach-jz47xx/base.h> | |
13 | ||
14 | #include "clock.h" | |
15 | ||
16 | int clk_enable(struct clk *clk) | |
17 | { | |
18 | if (!clk->ops->enable) | |
19 | return -EINVAL; | |
20 | ||
21 | return clk->ops->enable(clk); | |
22 | } | |
23 | EXPORT_SYMBOL_GPL(clk_enable); | |
24 | ||
25 | void clk_disable(struct clk *clk) | |
26 | { | |
27 | if (clk->ops->disable) | |
28 | clk->ops->disable(clk); | |
29 | } | |
30 | EXPORT_SYMBOL_GPL(clk_disable); | |
31 | ||
32 | int clk_is_enabled(struct clk *clk) | |
33 | { | |
34 | if (clk->ops->is_enabled) | |
35 | return clk->ops->is_enabled(clk); | |
36 | ||
37 | return 1; | |
38 | } | |
39 | ||
40 | unsigned long clk_get_rate(struct clk *clk) | |
41 | { | |
42 | if (clk->ops->get_rate) | |
43 | return clk->ops->get_rate(clk); | |
44 | if (clk->parent) | |
45 | return clk_get_rate(clk->parent); | |
46 | ||
47 | return -EINVAL; | |
48 | } | |
49 | EXPORT_SYMBOL_GPL(clk_get_rate); | |
50 | ||
51 | int clk_set_rate(struct clk *clk, unsigned long rate) | |
52 | { | |
53 | if (!clk->ops->set_rate) | |
54 | return -EINVAL; | |
55 | ||
56 | return clk->ops->set_rate(clk, rate); | |
57 | } | |
58 | EXPORT_SYMBOL_GPL(clk_set_rate); | |
59 | ||
60 | long clk_round_rate(struct clk *clk, unsigned long rate) | |
61 | { | |
62 | if (!clk->ops->round_rate) | |
63 | return -EINVAL; | |
64 | ||
65 | return clk->ops->round_rate(clk, rate); | |
66 | } | |
67 | EXPORT_SYMBOL_GPL(clk_round_rate); | |
68 | ||
69 | int clk_set_parent(struct clk *clk, struct clk *parent) | |
70 | { | |
71 | int ret; | |
72 | int enabled; | |
73 | ||
74 | if (!clk->ops->set_parent) | |
75 | return -EINVAL; | |
76 | ||
77 | enabled = clk_is_enabled(clk); | |
78 | if (enabled) | |
79 | clk_disable(clk); | |
80 | ret = clk->ops->set_parent(clk, parent); | |
81 | if (enabled) | |
82 | clk_enable(clk); | |
83 | ||
84 | jz4740_clock_debugfs_update_parent(clk); | |
85 | ||
86 | return ret; | |
87 | } | |
88 | EXPORT_SYMBOL_GPL(clk_set_parent); | |
89 | ||
90 | void __init jz47xx_clock_add_table(struct clk_lookup *table, size_t num) | |
91 | { | |
92 | size_t i; | |
93 | ||
94 | clkdev_add_table(table, num); | |
95 | ||
96 | for (i = 0; i < num; ++i) | |
97 | jz4740_clock_debugfs_add_clk(table[i].clk); | |
98 | } |
arch/mips/jz47xx/clock.h | ||
---|---|---|
17 | 17 | #define __MIPS_JZ4740_CLOCK_H__ |
18 | 18 | |
19 | 19 | #include <linux/list.h> |
20 | #include <linux/clkdev.h> | |
20 | 21 | |
21 | 22 | struct jz47xx_clock_board_data { |
22 | 23 | unsigned long ext_rate; |
... | ... | |
39 | 40 | int (*is_enabled)(struct clk *clk); |
40 | 41 | |
41 | 42 | int (*set_parent)(struct clk *clk, struct clk *parent); |
42 | ||
43 | 43 | }; |
44 | 44 | |
45 | 45 | struct clk { |
46 | const char *name; | |
47 | 46 | struct clk *parent; |
48 | 47 | |
49 | 48 | uint32_t gate_bit; |
50 | 49 | |
51 | const struct clk_ops *ops; | |
50 | const char *name; | |
52 | 51 | |
53 | struct list_head list; | |
52 | const struct clk_ops *ops; | |
54 | 53 | |
55 | 54 | #ifdef CONFIG_DEBUG_FS |
56 | 55 | struct dentry *debugfs_entry; |
... | ... | |
61 | 60 | |
62 | 61 | #define JZ47XX_CLK_NOT_GATED ((uint32_t)-1) |
63 | 62 | |
63 | struct main_clk { | |
64 | struct clk clk; | |
65 | uint32_t div_offset; | |
66 | }; | |
67 | ||
68 | struct divided_clk { | |
69 | struct clk clk; | |
70 | uint32_t reg; | |
71 | uint32_t mask; | |
72 | }; | |
73 | ||
74 | struct static_clk { | |
75 | struct clk clk; | |
76 | unsigned long rate; | |
77 | }; | |
78 | ||
79 | void __init jz47xx_clock_add_table(struct clk_lookup *table, size_t num); | |
64 | 80 | int clk_is_enabled(struct clk *clk); |
65 | 81 | |
66 | 82 | #ifdef CONFIG_DEBUG_FS |
arch/mips/jz47xx/jz4740/clock.c | ||
---|---|---|
99 | 99 | |
100 | 100 | static void __iomem *jz_clock_base; |
101 | 101 | static spinlock_t jz_clock_lock; |
102 | static LIST_HEAD(jz_clocks); | |
103 | ||
104 | struct main_clk { | |
105 | struct clk clk; | |
106 | uint32_t div_offset; | |
107 | }; | |
108 | ||
109 | struct divided_clk { | |
110 | struct clk clk; | |
111 | uint32_t reg; | |
112 | uint32_t mask; | |
113 | }; | |
114 | ||
115 | struct static_clk { | |
116 | struct clk clk; | |
117 | unsigned long rate; | |
118 | }; | |
119 | 102 | |
120 | 103 | static uint32_t jz_clk_reg_read(int reg) |
121 | 104 | { |
122 | 105 | return readl(jz_clock_base + reg); |
123 | 106 | } |
124 | 107 | |
125 | static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask) | |
108 | static void jz_clk_reg_write_mask(unsigned int reg, uint32_t val, uint32_t mask) | |
126 | 109 | { |
127 | 110 | uint32_t val2; |
128 | 111 | |
... | ... | |
134 | 117 | spin_unlock(&jz_clock_lock); |
135 | 118 | } |
136 | 119 | |
137 | static void jz_clk_reg_set_bits(int reg, uint32_t mask) | |
120 | static void jz_clk_reg_set_bits(unsigned int reg, uint32_t mask) | |
138 | 121 | { |
139 | 122 | uint32_t val; |
140 | 123 | |
... | ... | |
145 | 128 | spin_unlock(&jz_clock_lock); |
146 | 129 | } |
147 | 130 | |
148 | static void jz_clk_reg_clear_bits(int reg, uint32_t mask) | |
131 | static void jz_clk_reg_clear_bits(unsigned int reg, uint32_t mask) | |
149 | 132 | { |
150 | 133 | uint32_t val; |
151 | 134 | |
... | ... | |
430 | 413 | JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); |
431 | 414 | } |
432 | 415 | |
433 | static int jz_clk_udc_enable(struct clk *clk) | |
434 | { | |
435 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); | |
436 | ||
437 | return 0; | |
438 | } | |
439 | ||
440 | static int jz_clk_udc_disable(struct clk *clk) | |
441 | { | |
442 | jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); | |
443 | ||
444 | return 0; | |
445 | } | |
446 | ||
447 | static int jz_clk_udc_is_enabled(struct clk *clk) | |
448 | { | |
449 | return !!(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & JZ_CLOCK_GATE_UDC); | |
450 | } | |
451 | ||
452 | 416 | static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) |
453 | 417 | { |
454 | 418 | if (parent == &jz_clk_pll_half) |
... | ... | |
617 | 581 | .is_enabled = jz_clk_is_enabled_gating, |
618 | 582 | }; |
619 | 583 | |
620 | static struct divided_clk jz4740_clock_divided_clks[] = { | |
621 | [0] = { | |
622 | .clk = { | |
623 | .name = "i2s", | |
624 | .parent = &jz_clk_ext.clk, | |
625 | .gate_bit = JZ_CLOCK_GATE_I2S, | |
626 | .ops = &jz_clk_i2s_ops, | |
627 | }, | |
628 | .reg = JZ_REG_CLOCK_I2S, | |
629 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
584 | ||
585 | static struct divided_clk jz_clk_i2s = { | |
586 | .clk = { | |
587 | .name = "i2s", | |
588 | .parent = &jz_clk_ext.clk, | |
589 | .gate_bit = JZ_CLOCK_GATE_I2S, | |
590 | .ops = &jz_clk_i2s_ops, | |
630 | 591 | }, |
631 | [1] = { | |
632 | .clk = { | |
633 | .name = "spi", | |
634 | .parent = &jz_clk_ext.clk, | |
635 | .gate_bit = JZ_CLOCK_GATE_SPI, | |
636 | .ops = &jz_clk_spi_ops, | |
637 | }, | |
638 | .reg = JZ_REG_CLOCK_SPI, | |
639 | .mask = JZ_CLOCK_SPI_DIV_MASK, | |
592 | .reg = JZ_REG_CLOCK_I2S, | |
593 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
594 | }; | |
595 | ||
596 | static struct divided_clk jz_clk_spi = { | |
597 | .clk = { | |
598 | .name = "spi", | |
599 | .parent = &jz_clk_ext.clk, | |
600 | .gate_bit = JZ_CLOCK_GATE_SPI, | |
601 | .ops = &jz_clk_spi_ops, | |
640 | 602 | }, |
641 | [2] = { | |
642 | .clk = { | |
643 | .name = "lcd_pclk", | |
644 | .parent = &jz_clk_pll_half, | |
645 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
646 | .ops = &jz_clk_divided_ops, | |
647 | }, | |
648 | .reg = JZ_REG_CLOCK_LCD, | |
649 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
603 | .reg = JZ_REG_CLOCK_SPI, | |
604 | .mask = JZ_CLOCK_SPI_DIV_MASK, | |
605 | }; | |
606 | ||
607 | ||
608 | static struct divided_clk jz_clk_lcd_pclk = { | |
609 | .clk = { | |
610 | .name = "lcd_pclk", | |
611 | .parent = &jz_clk_pll_half, | |
612 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
613 | .ops = &jz_clk_divided_ops, | |
650 | 614 | }, |
651 | [3] = { | |
652 | .clk = { | |
653 | .name = "mmc", | |
654 | .parent = &jz_clk_pll_half, | |
655 | .gate_bit = JZ_CLOCK_GATE_MMC, | |
656 | .ops = &jz_clk_divided_ops, | |
657 | }, | |
658 | .reg = JZ_REG_CLOCK_MMC, | |
659 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
615 | .reg = JZ_REG_CLOCK_LCD, | |
616 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
617 | }; | |
618 | ||
619 | static struct divided_clk jz_clk_mmc = { | |
620 | .clk = { | |
621 | .name = "mmc", | |
622 | .parent = &jz_clk_pll_half, | |
623 | .gate_bit = JZ_CLOCK_GATE_MMC, | |
624 | .ops = &jz_clk_divided_ops, | |
660 | 625 | }, |
661 | [4] = { | |
662 | .clk = { | |
663 | .name = "uhc", | |
664 | .parent = &jz_clk_pll_half, | |
665 | .gate_bit = JZ_CLOCK_GATE_UHC, | |
666 | .ops = &jz_clk_divided_ops, | |
667 | }, | |
668 | .reg = JZ_REG_CLOCK_UHC, | |
669 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
626 | .reg = JZ_REG_CLOCK_MMC, | |
627 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
628 | }; | |
629 | ||
630 | static struct divided_clk jz_clk_uhc = { | |
631 | .clk = { | |
632 | .name = "uhc", | |
633 | .parent = &jz_clk_pll_half, | |
634 | .gate_bit = JZ_CLOCK_GATE_UHC, | |
635 | .ops = &jz_clk_divided_ops, | |
670 | 636 | }, |
637 | .reg = JZ_REG_CLOCK_UHC, | |
638 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
671 | 639 | }; |
672 | 640 | |
673 | 641 | static const struct clk_ops jz_clk_udc_phy_ops = { |
... | ... | |
680 | 648 | .set_parent = jz_clk_udc_set_parent, |
681 | 649 | .set_rate = jz_clk_udc_set_rate, |
682 | 650 | .get_rate = jz_clk_udc_get_rate, |
683 | .enable = jz_clk_udc_enable, | |
684 | .disable = jz_clk_udc_disable, | |
685 | .is_enabled = jz_clk_udc_is_enabled, | |
651 | .enable = jz_clk_enable_gating, | |
652 | .disable = jz_clk_disable_gating, | |
653 | .is_enabled = jz_clk_is_enabled_gating, | |
686 | 654 | }; |
687 | 655 | |
688 | 656 | static const struct clk_ops jz_clk_simple_ops = { |
... | ... | |
691 | 659 | .is_enabled = jz_clk_is_enabled_gating, |
692 | 660 | }; |
693 | 661 | |
694 | static struct clk jz4740_clock_simple_clks[] = { | |
695 | [0] = { | |
696 | .name = "udc", | |
697 | .parent = &jz_clk_ext.clk, | |
698 | .ops = &jz_clk_udc_ops, | |
699 | }, | |
700 | [1] = { | |
701 | .name = "uart0", | |
702 | .parent = &jz_clk_ext.clk, | |
703 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
704 | .ops = &jz_clk_simple_ops, | |
705 | }, | |
706 | [2] = { | |
707 | .name = "uart1", | |
708 | .parent = &jz_clk_ext.clk, | |
709 | .gate_bit = JZ_CLOCK_GATE_UART1, | |
710 | .ops = &jz_clk_simple_ops, | |
711 | }, | |
712 | [3] = { | |
713 | .name = "dma", | |
714 | .parent = &jz_clk_high_speed_peripheral.clk, | |
715 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
716 | .ops = &jz_clk_simple_ops, | |
717 | }, | |
718 | [4] = { | |
719 | .name = "ipu", | |
720 | .parent = &jz_clk_high_speed_peripheral.clk, | |
721 | .gate_bit = JZ_CLOCK_GATE_IPU, | |
722 | .ops = &jz_clk_simple_ops, | |
723 | }, | |
724 | [5] = { | |
725 | .name = "adc", | |
726 | .parent = &jz_clk_ext.clk, | |
727 | .gate_bit = JZ_CLOCK_GATE_ADC, | |
728 | .ops = &jz_clk_simple_ops, | |
729 | }, | |
730 | [6] = { | |
731 | .name = "i2c", | |
732 | .parent = &jz_clk_ext.clk, | |
733 | .gate_bit = JZ_CLOCK_GATE_I2C, | |
734 | .ops = &jz_clk_simple_ops, | |
735 | }, | |
736 | [7] = { | |
737 | .name = "aic", | |
738 | .parent = &jz_clk_ext.clk, | |
739 | .gate_bit = JZ_CLOCK_GATE_AIC, | |
740 | .ops = &jz_clk_simple_ops, | |
741 | }, | |
742 | [8] = { | |
743 | .name = "udc-phy", | |
744 | .parent = &jz4740_clock_simple_clks[0], /* udc */ | |
745 | .ops = &jz_clk_udc_phy_ops, | |
746 | }, | |
662 | static struct clk jz_clk_udc = { | |
663 | .name = "udc", | |
664 | .parent = &jz_clk_ext.clk, | |
665 | .gate_bit = JZ_CLOCK_GATE_UDC, | |
666 | .ops = &jz_clk_udc_ops, | |
747 | 667 | }; |
748 | 668 | |
749 | static struct static_clk jz_clk_rtc = { | |
750 | .clk = { | |
751 | .name = "rtc", | |
752 | .gate_bit = JZ_CLOCK_GATE_RTC, | |
753 | .ops = &jz_clk_static_ops, | |
754 | }, | |
755 | .rate = 32768, | |
669 | static struct clk jz_clk_uart0 = { | |
670 | .name = "uart0", | |
671 | .parent = &jz_clk_ext.clk, | |
672 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
673 | .ops = &jz_clk_simple_ops, | |
756 | 674 | }; |
757 | 675 | |
758 | int clk_enable(struct clk *clk) | |
759 | { | |
760 | if (!clk->ops->enable) | |
761 | return -EINVAL; | |
762 | ||
763 | return clk->ops->enable(clk); | |
764 | } | |
765 | EXPORT_SYMBOL_GPL(clk_enable); | |
766 | ||
767 | void clk_disable(struct clk *clk) | |
768 | { | |
769 | if (clk->ops->disable) | |
770 | clk->ops->disable(clk); | |
771 | } | |
772 | EXPORT_SYMBOL_GPL(clk_disable); | |
773 | ||
774 | int clk_is_enabled(struct clk *clk) | |
775 | { | |
776 | if (clk->ops->is_enabled) | |
777 | return clk->ops->is_enabled(clk); | |
778 | ||
779 | return 1; | |
780 | } | |
781 | ||
782 | unsigned long clk_get_rate(struct clk *clk) | |
783 | { | |
784 | if (clk->ops->get_rate) | |
785 | return clk->ops->get_rate(clk); | |
786 | if (clk->parent) | |
787 | return clk_get_rate(clk->parent); | |
788 | ||
789 | return -EINVAL; | |
790 | } | |
791 | EXPORT_SYMBOL_GPL(clk_get_rate); | |
792 | ||
793 | int clk_set_rate(struct clk *clk, unsigned long rate) | |
794 | { | |
795 | if (!clk->ops->set_rate) | |
796 | return -EINVAL; | |
797 | return clk->ops->set_rate(clk, rate); | |
798 | } | |
799 | EXPORT_SYMBOL_GPL(clk_set_rate); | |
800 | ||
801 | long clk_round_rate(struct clk *clk, unsigned long rate) | |
802 | { | |
803 | if (clk->ops->round_rate) | |
804 | return clk->ops->round_rate(clk, rate); | |
805 | ||
806 | return -EINVAL; | |
807 | } | |
808 | EXPORT_SYMBOL_GPL(clk_round_rate); | |
809 | ||
810 | int clk_set_parent(struct clk *clk, struct clk *parent) | |
811 | { | |
812 | int ret; | |
813 | int enabled; | |
814 | ||
815 | if (!clk->ops->set_parent) | |
816 | return -EINVAL; | |
676 | static struct clk jz_clk_uart1 = { | |
677 | .name = "uart1", | |
678 | .parent = &jz_clk_ext.clk, | |
679 | .gate_bit = JZ_CLOCK_GATE_UART1, | |
680 | .ops = &jz_clk_simple_ops, | |
681 | }; | |
817 | 682 | |
818 | enabled = clk_is_enabled(clk); | |
819 | if (enabled) | |
820 | clk_disable(clk); | |
821 | ret = clk->ops->set_parent(clk, parent); | |
822 | if (enabled) | |
823 | clk_enable(clk); | |
683 | static struct clk jz_clk_dma = { | |
684 | .name = "dma", | |
685 | .parent = &jz_clk_high_speed_peripheral.clk, | |
686 | .gate_bit = JZ_CLOCK_GATE_DMAC, | |
687 | .ops = &jz_clk_simple_ops, | |
688 | }; | |
824 | 689 | |
825 | jz4740_clock_debugfs_update_parent(clk); | |
690 | static struct clk jz_clk_ipu = { | |
691 | .name = "ipu", | |
692 | .parent = &jz_clk_high_speed_peripheral.clk, | |
693 | .gate_bit = JZ_CLOCK_GATE_IPU, | |
694 | .ops = &jz_clk_simple_ops, | |
695 | }; | |
826 | 696 | |
827 | return ret; | |
828 | } | |
829 | EXPORT_SYMBOL_GPL(clk_set_parent); | |
697 | static struct clk jz_clk_adc = { | |
698 | .name = "adc", | |
699 | .parent = &jz_clk_ext.clk, | |
700 | .gate_bit = JZ_CLOCK_GATE_ADC, | |
701 | .ops = &jz_clk_simple_ops, | |
702 | }; | |
830 | 703 | |
831 | struct clk *clk_get(struct device *dev, const char *name) | |
832 | { | |
833 | struct clk *clk; | |
704 | static struct clk jz_clk_i2c = { | |
705 | .name = "i2c", | |
706 | .parent = &jz_clk_ext.clk, | |
707 | .gate_bit = JZ_CLOCK_GATE_I2C, | |
708 | .ops = &jz_clk_simple_ops, | |
709 | }; | |
834 | 710 | |
835 | list_for_each_entry(clk, &jz_clocks, list) { | |
836 | if (strcmp(clk->name, name) == 0) | |
837 | return clk; | |
838 | } | |
839 | return ERR_PTR(-ENXIO); | |
840 | } | |
841 | EXPORT_SYMBOL_GPL(clk_get); | |
711 | static struct clk jz_clk_aic = { | |
712 | .name = "aic", | |
713 | .parent = &jz_clk_ext.clk, | |
714 | .gate_bit = JZ_CLOCK_GATE_AIC, | |
715 | .ops = &jz_clk_simple_ops, | |
716 | }; | |
842 | 717 | |
843 | void clk_put(struct clk *clk) | |
844 | { | |
845 | } | |
846 | EXPORT_SYMBOL_GPL(clk_put); | |
718 | static struct clk jz_clk_udc_phy = { | |
719 | .name = "udc-phy", | |
720 | .parent = &jz_clk_udc, /* udc */ | |
721 | .ops = &jz_clk_udc_phy_ops, | |
722 | }; | |
847 | 723 | |
848 | static inline void clk_add(struct clk *clk) | |
849 | { | |
850 | list_add_tail(&clk->list, &jz_clocks); | |
724 | static struct static_clk jz_clk_rtc = { | |
725 | .clk = { | |
726 | .name = "rtc", | |
727 | .gate_bit = JZ_CLOCK_GATE_RTC, | |
728 | .ops = &jz_clk_static_ops, | |
729 | }, | |
730 | .rate = 32768, | |
731 | }; | |
851 | 732 | |
852 | jz4740_clock_debugfs_add_clk(clk); | |
853 | } | |
733 | #define INIT_CLOCK(_dev, _con, _clk) \ | |
734 | { .dev_id = _dev, .con_id = _con, .clk = _clk, } | |
735 | ||
736 | static struct clk_lookup jz4740_clk_table[] = { | |
737 | INIT_CLOCK(NULL, "ext", &jz_clk_ext.clk), | |
738 | INIT_CLOCK(NULL, "pll", &jz_clk_pll), | |
739 | INIT_CLOCK(NULL, "pll half", &jz_clk_pll_half), | |
740 | INIT_CLOCK(NULL, "cclk", &jz_clk_cpu.clk), | |
741 | INIT_CLOCK(NULL, "mclk", &jz_clk_memory.clk), | |
742 | INIT_CLOCK(NULL, "hclk", &jz_clk_high_speed_peripheral.clk), | |
743 | INIT_CLOCK(NULL, "pclk", &jz_clk_low_speed_peripheral.clk), | |
744 | INIT_CLOCK(NULL, "cko", &jz_clk_ko), | |
745 | ||
746 | INIT_CLOCK("jz4740-rtc", "rtc", &jz_clk_rtc.clk), | |
747 | INIT_CLOCK("jz4740-fb", "lcd", &jz_clk_ld), | |
748 | INIT_CLOCK("jz4740-fb", "lcd_pclk", &jz_clk_lcd_pclk.clk), | |
749 | INIT_CLOCK(NULL, "spi", &jz_clk_spi.clk), | |
750 | INIT_CLOCK(NULL, "i2c", &jz_clk_i2c), | |
751 | INIT_CLOCK("jz4740-i2s", "i2s", &jz_clk_i2s.clk), | |
752 | INIT_CLOCK("jz4740-i2s", "aic", &jz_clk_aic), | |
753 | INIT_CLOCK("jz4740-adc", "adc", &jz_clk_adc), | |
754 | INIT_CLOCK("jz-udc", "udc", &jz_clk_udc), | |
755 | INIT_CLOCK("jz-udc", "udc-phy", &jz_clk_udc_phy), | |
756 | INIT_CLOCK("jz4740-mmc", "mmc", &jz_clk_mmc.clk), | |
757 | INIT_CLOCK("jz4740-ohci", "uhc", &jz_clk_uhc.clk), | |
758 | ||
759 | INIT_CLOCK(NULL, "uart0", &jz_clk_uart0), | |
760 | INIT_CLOCK(NULL, "uart1", &jz_clk_uart1), | |
761 | INIT_CLOCK(NULL, "dma", &jz_clk_dma), | |
762 | INIT_CLOCK(NULL, "ipu", &jz_clk_ipu), | |
763 | }; | |
854 | 764 | |
855 | 765 | static void clk_register_clks(void) |
856 | 766 | { |
857 | size_t i; | |
858 | ||
859 | clk_add(&jz_clk_ext.clk); | |
860 | clk_add(&jz_clk_pll); | |
861 | clk_add(&jz_clk_pll_half); | |
862 | clk_add(&jz_clk_cpu.clk); | |
863 | clk_add(&jz_clk_high_speed_peripheral.clk); | |
864 | clk_add(&jz_clk_low_speed_peripheral.clk); | |
865 | clk_add(&jz_clk_ko); | |
866 | clk_add(&jz_clk_ld); | |
867 | clk_add(&jz_clk_rtc.clk); | |
868 | ||
869 | for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) | |
870 | clk_add(&jz4740_clock_divided_clks[i].clk); | |
871 | ||
872 | for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) | |
873 | clk_add(&jz4740_clock_simple_clks[i]); | |
767 | jz47xx_clock_add_table(jz4740_clk_table, ARRAY_SIZE(jz4740_clk_table)); | |
874 | 768 | } |
875 | 769 | |
876 | 770 | void jz47xx_clock_set_wait_mode(enum jz47xx_wait_mode mode) |
... | ... | |
907 | 801 | JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); |
908 | 802 | } |
909 | 803 | |
910 | static int jz4740_clock_init(void) | |
804 | static int __init jz4740_clock_init(void) | |
911 | 805 | { |
912 | 806 | uint32_t val; |
913 | 807 | |
... | ... | |
923 | 817 | val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); |
924 | 818 | |
925 | 819 | if (val & JZ_CLOCK_SPI_SRC_PLL) |
926 | jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; | |
820 | jz_clk_spi.clk.parent = &jz_clk_pll_half; | |
927 | 821 | |
928 | 822 | val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); |
929 | 823 | |
930 | 824 | if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) |
931 | jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; | |
825 | jz_clk_i2s.clk.parent = &jz_clk_pll_half; | |
932 | 826 | |
933 | 827 | if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) |
934 | jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; | |
828 | jz_clk_udc.parent = &jz_clk_pll_half; | |
935 | 829 | |
936 | 830 | jz4740_clock_debugfs_init(); |
937 | 831 |
arch/mips/jz47xx/jz4750/clock-jz4750l.c | ||
---|---|---|
115 | 115 | |
116 | 116 | static void __iomem *jz_clock_base; |
117 | 117 | static spinlock_t jz_clock_lock; |
118 | static LIST_HEAD(jz_clocks); | |
119 | ||
120 | struct main_clk { | |
121 | struct clk clk; | |
122 | uint32_t div_offset; | |
123 | }; | |
124 | ||
125 | struct divided_clk { | |
126 | struct clk clk; | |
127 | uint32_t reg; | |
128 | uint32_t mask; | |
129 | }; | |
130 | ||
131 | struct static_clk { | |
132 | struct clk clk; | |
133 | unsigned long rate; | |
134 | }; | |
135 | 118 | |
136 | 119 | static uint32_t jz_clk_reg_read(int reg) |
137 | 120 | { |
... | ... | |
366 | 349 | .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, |
367 | 350 | }; |
368 | 351 | |
369 | static struct main_clk jz_clk_ipu = { | |
352 | static struct main_clk jz4750_clk_ipu = { | |
370 | 353 | .clk = { |
371 | 354 | .name = "ipuclk", |
372 | 355 | .parent = &jz_clk_pll, |
... | ... | |
547 | 530 | .is_enabled = jz_clk_is_enabled_gating, |
548 | 531 | }; |
549 | 532 | |
550 | static struct divided_clk jz4750_clock_divided_clks[] = { | |
551 | [0] = { | |
552 | .clk = { | |
553 | .name = "i2s", | |
554 | .parent = &jz_clk_ext.clk, | |
555 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
556 | .ops = &jz_clk_i2s_ops, | |
557 | }, | |
558 | .reg = JZ_REG_CLOCK_I2S, | |
559 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
533 | static struct divided_clk jz4750_clk_i2s = { | |
534 | .clk = { | |
535 | .name = "i2s", | |
536 | .parent = &jz_clk_ext.clk, | |
537 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
538 | .ops = &jz_clk_i2s_ops, | |
560 | 539 | }, |
561 | [1] = { | |
562 | .clk = { | |
563 | .name = "spi", | |
564 | .parent = &jz_clk_ext.clk, | |
565 | .gate_bit = JZ_CLOCK_GATE_SPI, | |
566 | .ops = &jz_clk_spi_ops, | |
567 | }, | |
568 | .reg = JZ_REG_CLOCK_SPI, | |
569 | .mask = JZ_CLOCK_SPI_DIV_MASK, | |
540 | .reg = JZ_REG_CLOCK_I2S, | |
541 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
542 | }; | |
543 | ||
544 | static struct divided_clk jz4750_clk_spi = { | |
545 | .clk = { | |
546 | .name = "spi", | |
547 | .parent = &jz_clk_ext.clk, | |
548 | .gate_bit = JZ_CLOCK_GATE_SPI, | |
549 | .ops = &jz_clk_spi_ops, | |
570 | 550 | }, |
571 | [2] = { | |
572 | .clk = { | |
573 | .name = "lcd", | |
574 | .parent = &jz_clk_pll_half, | |
575 | .gate_bit = JZ_CLOCK_GATE_LCD, | |
576 | .ops = &jz_clk_divided_ops, | |
577 | }, | |
578 | .reg = JZ_REG_CLOCK_LCD, | |
579 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
551 | .reg = JZ_REG_CLOCK_SPI, | |
552 | .mask = JZ_CLOCK_SPI_DIV_MASK, | |
553 | }; | |
554 | ||
555 | static struct divided_clk jz4750_clk_lcd = { | |
556 | .clk = { | |
557 | .name = "lcd", | |
558 | .parent = &jz_clk_pll_half, | |
559 | .gate_bit = JZ_CLOCK_GATE_LCD, | |
560 | .ops = &jz_clk_divided_ops, | |
580 | 561 | }, |
581 | [3] = { | |
582 | .clk = { | |
583 | .name = "mmc0", | |
584 | .parent = &jz_clk_pll_half, | |
585 | .gate_bit = JZ_CLOCK_GATE_MMC0, | |
586 | .ops = &jz_clk_divided_ops, | |
587 | }, | |
588 | .reg = JZ_REG_CLOCK_MMC, | |
589 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
562 | .reg = JZ_REG_CLOCK_LCD, | |
563 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
564 | }; | |
565 | ||
566 | static struct divided_clk jz4750_clk_mmc0 = { | |
567 | .clk = { | |
568 | .name = "mmc0", | |
569 | .parent = &jz_clk_pll_half, | |
570 | .gate_bit = JZ_CLOCK_GATE_MMC0, | |
571 | .ops = &jz_clk_divided_ops, | |
590 | 572 | }, |
591 | [4] = { | |
592 | .clk = { | |
593 | .name = "mmc1", | |
594 | .parent = &jz_clk_pll_half, | |
595 | .gate_bit = JZ_CLOCK_GATE_MMC1, | |
596 | .ops = &jz_clk_divided_ops, | |
597 | }, | |
598 | /* MMC0 and MMC1 have same divisor, but separate gates */ | |
599 | .reg = JZ_REG_CLOCK_MMC, | |
600 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
573 | .reg = JZ_REG_CLOCK_MMC, | |
574 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
575 | }; | |
576 | ||
577 | static struct divided_clk jz4750_clk_mmc1 = { | |
578 | .clk = { | |
579 | .name = "mmc1", | |
580 | .parent = &jz_clk_pll_half, | |
581 | .gate_bit = JZ_CLOCK_GATE_MMC1, | |
582 | .ops = &jz_clk_divided_ops, | |
601 | 583 | }, |
602 | [5] = { | |
603 | .clk = { | |
604 | .name = "uhc", | |
605 | .parent = &jz_clk_pll_half, | |
606 | .gate_bit = JZ_CLOCK_GATE_UHC, | |
607 | .ops = &jz_clk_divided_ops, | |
608 | }, | |
609 | .reg = JZ_REG_CLOCK_UHC, | |
610 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
584 | /* MMC0 and MMC1 have same divisor, but separate gates */ | |
585 | .reg = JZ_REG_CLOCK_MMC, | |
586 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
587 | }; | |
588 | ||
589 | static struct divided_clk jz4750_clk_uhc = { | |
590 | .clk = { | |
591 | .name = "uhc", | |
592 | .parent = &jz_clk_pll_half, | |
593 | .gate_bit = JZ_CLOCK_GATE_UHC, | |
594 | .ops = &jz_clk_divided_ops, | |
611 | 595 | }, |
596 | .reg = JZ_REG_CLOCK_UHC, | |
597 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
612 | 598 | }; |
613 | 599 | |
614 | 600 | static const struct clk_ops jz_clk_udc_phy_ops = { |
... | ... | |
632 | 618 | .is_enabled = jz_clk_is_enabled_gating, |
633 | 619 | }; |
634 | 620 | |
635 | static struct clk jz4750_clock_simple_clks[] = { | |
636 | [0] = { | |
637 | .name = "udc", | |
638 | .parent = &jz_clk_ext.clk, | |
639 | .ops = &jz_clk_udc_ops, | |
640 | }, | |
641 | [1] = { | |
642 | .name = "uart0", | |
643 | .parent = &jz_clk_ext.clk, | |
644 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
645 | .ops = &jz_clk_simple_ops, | |
646 | }, | |
647 | [2] = { | |
648 | .name = "uart1", | |
649 | .parent = &jz_clk_ext.clk, | |
650 | .gate_bit = JZ_CLOCK_GATE_UART1, | |
651 | .ops = &jz_clk_simple_ops, | |
652 | }, | |
653 | [3] = { | |
654 | .name = "dma", | |
655 | .parent = &jz_clk_high_speed_peripheral.clk, | |
656 | .gate_bit = JZ_CLOCK_GATE_DMAC, | |
657 | .ops = &jz_clk_simple_ops, | |
658 | }, | |
659 | [4] = { | |
660 | .name = "adc", | |
661 | .parent = &jz_clk_ext.clk, | |
662 | .gate_bit = JZ_CLOCK_GATE_ADC, | |
663 | .ops = &jz_clk_simple_ops, | |
664 | }, | |
665 | [5] = { | |
666 | .name = "i2c", | |
667 | .parent = &jz_clk_ext.clk, | |
668 | .gate_bit = JZ_CLOCK_GATE_I2C, | |
669 | .ops = &jz_clk_simple_ops, | |
670 | }, | |
671 | [6] = { | |
672 | .name = "aic", | |
673 | .parent = &jz_clk_ext.clk, | |
674 | .gate_bit = JZ_CLOCK_GATE_AIC, | |
675 | .ops = &jz_clk_simple_ops, | |
676 | }, | |
677 | [7] = { | |
678 | .name = "udc-phy", | |
679 | .parent = &jz4750_clock_simple_clks[0], /* udc */ | |
680 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
681 | .ops = &jz_clk_udc_phy_ops, | |
682 | }, | |
683 | [8] = { | |
684 | .name = "bch", | |
685 | .parent = &jz_clk_low_speed_peripheral.clk, | |
686 | .gate_bit = JZ_CLOCK_GATE_BCH, | |
687 | .ops = &jz_clk_simple_ops, | |
688 | }, | |
621 | static struct clk jz4750_clk_udc = { | |
622 | .name = "udc", | |
623 | .parent = &jz_clk_ext.clk, | |
624 | .ops = &jz_clk_udc_ops, | |
689 | 625 | }; |
690 | 626 | |
691 | static struct static_clk jz_clk_rtc = { | |
692 | .clk = { | |
693 | .name = "rtc", | |
694 | .gate_bit = JZ_CLOCK_GATE_RTC, | |
695 | .ops = &jz_clk_static_ops, | |
696 | }, | |
697 | .rate = 32768, | |
627 | static struct clk jz4750_clk_uart0 = { | |
628 | .name = "uart0", | |
629 | .parent = &jz_clk_ext.clk, | |
630 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
631 | .ops = &jz_clk_simple_ops, | |
698 | 632 | }; |
699 | 633 | |
700 | int clk_enable(struct clk *clk) | |
701 | { | |
702 | if (!clk->ops->enable) | |
703 | return -EINVAL; | |
704 | ||
705 | return clk->ops->enable(clk); | |
706 | } | |
707 | EXPORT_SYMBOL_GPL(clk_enable); | |
708 | ||
709 | void clk_disable(struct clk *clk) | |
710 | { | |
711 | if (clk->ops->disable) | |
712 | clk->ops->disable(clk); | |
713 | } | |
714 | EXPORT_SYMBOL_GPL(clk_disable); | |
715 | ||
716 | int clk_is_enabled(struct clk *clk) | |
717 | { | |
718 | if (clk->ops->is_enabled) | |
719 | return clk->ops->is_enabled(clk); | |
720 | ||
721 | return 1; | |
722 | } | |
634 | static struct clk jz4750_clk_uart1 = { | |
635 | .name = "uart1", | |
636 | .parent = &jz_clk_ext.clk, | |
637 | .gate_bit = JZ_CLOCK_GATE_UART1, | |
638 | .ops = &jz_clk_simple_ops, | |
639 | }; | |
723 | 640 | |
724 | unsigned long clk_get_rate(struct clk *clk) | |
725 | { | |
726 | if (clk->ops->get_rate) | |
727 | return clk->ops->get_rate(clk); | |
728 | if (clk->parent) | |
729 | return clk_get_rate(clk->parent); | |
641 | static struct clk jz4750_clk_dma = { | |
642 | .name = "dma", | |
643 | .parent = &jz_clk_high_speed_peripheral.clk, | |
644 | .gate_bit = JZ_CLOCK_GATE_DMAC, | |
645 | .ops = &jz_clk_simple_ops, | |
646 | }; | |
730 | 647 | |
731 | return -EINVAL; | |
732 | } | |
733 | EXPORT_SYMBOL_GPL(clk_get_rate); | |
648 | static struct clk jz4750_clk_adc = { | |
649 | .name = "adc", | |
650 | .parent = &jz_clk_ext.clk, | |
651 | .gate_bit = JZ_CLOCK_GATE_ADC, | |
652 | .ops = &jz_clk_simple_ops, | |
653 | }; | |
734 | 654 | |
735 | int clk_set_rate(struct clk *clk, unsigned long rate) | |
736 | { | |
737 | if (!clk->ops->set_rate) | |
738 | return -EINVAL; | |
739 | return clk->ops->set_rate(clk, rate); | |
740 | } | |
741 | EXPORT_SYMBOL_GPL(clk_set_rate); | |
655 | static struct clk jz4750_clk_i2c = { | |
656 | .name = "i2c", | |
657 | .parent = &jz_clk_ext.clk, | |
658 | .gate_bit = JZ_CLOCK_GATE_I2C, | |
659 | .ops = &jz_clk_simple_ops, | |
660 | }; | |
742 | 661 | |
743 | long clk_round_rate(struct clk *clk, unsigned long rate) | |
744 | { | |
745 | if (clk->ops->round_rate) | |
746 | return clk->ops->round_rate(clk, rate); | |
662 | static struct clk jz4750_clk_aic = { | |
663 | .name = "aic", | |
664 | .parent = &jz_clk_ext.clk, | |
665 | .gate_bit = JZ_CLOCK_GATE_AIC, | |
666 | .ops = &jz_clk_simple_ops, | |
667 | }; | |
747 | 668 | |
748 | return -EINVAL; | |
749 | } | |
750 | EXPORT_SYMBOL_GPL(clk_round_rate); | |
669 | static struct clk jz4750_clk_udc_phy = { | |
670 | .name = "udc-phy", | |
671 | .parent = &jz4750_clk_udc, | |
672 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
673 | .ops = &jz_clk_udc_phy_ops, | |
674 | }; | |
751 | 675 | |
752 | int clk_set_parent(struct clk *clk, struct clk *parent) | |
753 | { | |
754 | int ret; | |
755 | int enabled; | |
676 | static struct clk jz4750_clk_bch = { | |
677 | .name = "bch", | |
678 | .parent = &jz_clk_low_speed_peripheral.clk, | |
679 | .gate_bit = JZ_CLOCK_GATE_BCH, | |
680 | .ops = &jz_clk_simple_ops, | |
681 | }; | |
756 | 682 | |
757 | if (!clk->ops->set_parent) | |
758 | return -EINVAL; | |
683 | static struct static_clk jz4750_clk_rtc = { | |
684 | .clk = { | |
685 | .name = "rtc", | |
686 | .gate_bit = JZ_CLOCK_GATE_RTC, | |
687 | .ops = &jz_clk_static_ops, | |
688 | }, | |
689 | .rate = 32768, | |
690 | }; | |
759 | 691 | |
760 | enabled = clk_is_enabled(clk); | |
761 | if (enabled) | |
762 | clk_disable(clk); | |
763 | ret = clk->ops->set_parent(clk, parent); | |
764 | if (enabled) | |
765 | clk_enable(clk); | |
692 | #define INIT_CLOCK(_dev, _con, _clk) \ | |
693 | { .dev_id = _dev, .con_id = _con, .clk = _clk, } | |
766 | 694 | |
767 | jz4740_clock_debugfs_update_parent(clk); | |
695 | static struct clk_lookup jz4750_clk_table[] = { | |
696 | INIT_CLOCK(NULL, "ext", &jz_clk_ext.clk), | |
697 | INIT_CLOCK(NULL, "pll", &jz_clk_pll), | |
698 | INIT_CLOCK(NULL, "pll half", &jz_clk_pll_half), | |
699 | INIT_CLOCK(NULL, "cclk", &jz_clk_cpu.clk), | |
700 | INIT_CLOCK(NULL, "mclk", &jz_clk_memory.clk), | |
701 | INIT_CLOCK(NULL, "hclk", &jz_clk_high_speed_peripheral.clk), | |
702 | INIT_CLOCK(NULL, "pclk", &jz_clk_low_speed_peripheral.clk), | |
768 | 703 | |
769 | return ret; | |
770 | } | |
771 | EXPORT_SYMBOL_GPL(clk_set_parent); | |
704 | INIT_CLOCK("jz4750-nand", "bch", &jz4750_clk_bch), | |
772 | 705 | |
773 | struct clk *clk_get(struct device *dev, const char *name) | |
774 | { | |
775 | struct clk *clk; | |
706 | INIT_CLOCK("jz4740-rtc", "rtc", &jz4750_clk_rtc.clk), | |
707 | INIT_CLOCK("jz4740-fb", "lcd", &jz4750_clk_lcd.clk), | |
708 | INIT_CLOCK(NULL, "spi", &jz4750_clk_spi.clk), | |
776 | 709 | |
777 | list_for_each_entry(clk, &jz_clocks, list) { | |
778 | if (strcmp(clk->name, name) == 0) | |
779 | return clk; | |
780 | } | |
781 | return ERR_PTR(-ENXIO); | |
782 | } | |
783 | EXPORT_SYMBOL_GPL(clk_get); | |
710 | INIT_CLOCK(NULL, "i2c", &jz4750_clk_i2c), | |
784 | 711 | |
785 | void clk_put(struct clk *clk) | |
786 | { | |
787 | } | |
788 | EXPORT_SYMBOL_GPL(clk_put); | |
712 | INIT_CLOCK("jz4740-i2s", "i2s", &jz4750_clk_i2s.clk), | |
713 | INIT_CLOCK("jz4740-i2s", "aic", &jz4750_clk_aic), | |
789 | 714 | |
790 | static inline void clk_add(struct clk *clk) | |
791 | { | |
792 | list_add_tail(&clk->list, &jz_clocks); | |
715 | INIT_CLOCK("jz4740-adc", "adc", &jz4750_clk_adc), | |
716 | INIT_CLOCK("jz-udc", "udc", &jz4750_clk_udc), | |
717 | INIT_CLOCK("jz-udc", "udc-phy", &jz4750_clk_udc_phy), | |
718 | INIT_CLOCK("jz4740-mmc.0", "mmc", &jz4750_clk_mmc0.clk), | |
719 | INIT_CLOCK("jz4740-mmc.1", "mmc", &jz4750_clk_mmc1.clk), | |
720 | INIT_CLOCK("jz4740-ohci", "uhc", &jz4750_clk_uhc.clk), | |
793 | 721 | |
794 | jz4740_clock_debugfs_add_clk(clk); | |
795 | } | |
722 | INIT_CLOCK(NULL, "uart0", &jz4750_clk_uart0), | |
723 | INIT_CLOCK(NULL, "uart1", &jz4750_clk_uart1), | |
724 | INIT_CLOCK(NULL, "dma", &jz4750_clk_dma), | |
725 | INIT_CLOCK(NULL, "ipu", &jz4750_clk_ipu.clk), | |
726 | }; | |
796 | 727 | |
797 | static void clk_register_clks(void) | |
728 | static void __init clk_register_clks(void) | |
798 | 729 | { |
799 | size_t i; | |
800 | ||
801 | clk_add(&jz_clk_ext.clk); | |
802 | clk_add(&jz_clk_pll); | |
803 | clk_add(&jz_clk_pll_half); | |
804 | clk_add(&jz_clk_cpu.clk); | |
805 | clk_add(&jz_clk_high_speed_peripheral.clk); | |
806 | clk_add(&jz_clk_low_speed_peripheral.clk); | |
807 | clk_add(&jz_clk_memory.clk); | |
808 | clk_add(&jz_clk_ipu.clk); | |
809 | clk_add(&jz_clk_rtc.clk); | |
810 | ||
811 | for (i = 0; i < ARRAY_SIZE(jz4750_clock_divided_clks); ++i) | |
812 | clk_add(&jz4750_clock_divided_clks[i].clk); | |
813 | ||
814 | for (i = 0; i < ARRAY_SIZE(jz4750_clock_simple_clks); ++i) | |
815 | clk_add(&jz4750_clock_simple_clks[i]); | |
730 | jz47xx_clock_add_table(jz4750_clk_table, ARRAY_SIZE(jz4750_clk_table)); | |
816 | 731 | } |
817 | 732 | |
818 | 733 | void jz47xx_clock_set_wait_mode(enum jz47xx_wait_mode mode) |
... | ... | |
849 | 764 | JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); |
850 | 765 | } |
851 | 766 | |
852 | static int jz4750_clock_init(void) | |
767 | static int __init jz4750_clock_init(void) | |
853 | 768 | { |
854 | 769 | uint32_t val; |
855 | 770 | |
... | ... | |
860 | 775 | spin_lock_init(&jz_clock_lock); |
861 | 776 | |
862 | 777 | jz_clk_ext.rate = jz47xx_clock_bdata.ext_rate; |
863 | jz_clk_rtc.rate = jz47xx_clock_bdata.rtc_rate; | |
778 | jz4750_clk_rtc.rate = jz47xx_clock_bdata.rtc_rate; | |
864 | 779 | |
865 | 780 | jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CHANGE_ENABLE); |
866 | 781 | |
... | ... | |
870 | 785 | val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); |
871 | 786 | |
872 | 787 | if (val & JZ_CLOCK_SPI_SRC_PLL) |
873 | jz4750_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; | |
788 | jz4750_clk_spi.clk.parent = &jz_clk_pll_half; | |
874 | 789 | |
875 | 790 | val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); |
876 | 791 | |
877 | 792 | if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) |
878 | jz4750_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; | |
793 | jz4750_clk_i2s.clk.parent = &jz_clk_pll_half; | |
879 | 794 | |
880 | 795 | if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) |
881 | jz4750_clock_simple_clks[0].parent = &jz_clk_pll_half; | |
796 | jz4750_clk_udc.parent = &jz_clk_pll_half; | |
882 | 797 | |
883 | 798 | jz4740_clock_debugfs_init(); |
884 | 799 |
arch/mips/jz47xx/jz4760/clock.c | ||
---|---|---|
22 | 22 | #include <linux/list.h> |
23 | 23 | #include <linux/err.h> |
24 | 24 | |
25 | #include <jz4740/clock.h> | |
26 | ||
25 | #include <asm/mach-jz47xx/clock.h> | |
27 | 26 | #include <asm/mach-jz47xx/base.h> |
28 | 27 | |
29 | 28 | #include "../clock.h" |
... | ... | |
31 | 30 | #define JZ_REG_CLOCK_CTRL 0x00 |
32 | 31 | #define JZ_REG_CLOCK_LOW_POWER 0x04 |
33 | 32 | #define JZ_REG_CLOCK_PLL 0x10 |
34 | #define JZ_REG_CLOCK_GATE 0x20 | |
33 | #define JZ_REG_CLOCK_GATE0 0x20 | |
34 | #define JZ_REG_CLOCK_GATE1 0x28 | |
35 | 35 | #define JZ_REG_CLOCK_SLEEP_CTRL 0x24 |
36 | 36 | #define JZ_REG_CLOCK_I2S 0x60 |
37 | 37 | #define JZ_REG_CLOCK_LCD 0x64 |
38 | #define JZ_REG_CLOCK_MMC 0x68 | |
38 | #define JZ_REG_CLOCK_MSC 0x68 | |
39 | 39 | #define JZ_REG_CLOCK_UHC 0x6C |
40 | #define JZ_REG_CLOCK_SPI 0x74 | |
40 | #define JZ_REG_CLOCK_SSI 0x74 | |
41 | 41 | |
42 | #define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31) | |
43 | #define JZ_CLOCK_CTRL_KO_ENABLE BIT(30) | |
44 | #define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29) | |
45 | #define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000 | |
46 | 42 | #define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22) |
47 | 43 | #define JZ_CLOCK_CTRL_PLL_HALF BIT(21) |
48 | 44 | #define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000 |
49 | #define JZ_CLOCK_CTRL_UDIV_OFFSET 23 | |
50 | #define JZ_CLOCK_CTRL_LDIV_OFFSET 16 | |
45 | #define JZ_CLOCK_CTRL_SDIV_OFFSET 24 | |
46 | #define JZ_CLOCK_CTRL_H2DIV_OFFSET 16 | |
51 | 47 | #define JZ_CLOCK_CTRL_MDIV_OFFSET 12 |
52 | 48 | #define JZ_CLOCK_CTRL_PDIV_OFFSET 8 |
53 | 49 | #define JZ_CLOCK_CTRL_HDIV_OFFSET 4 |
54 | 50 | #define JZ_CLOCK_CTRL_CDIV_OFFSET 0 |
55 | 51 | |
56 | #define JZ_CLOCK_GATE_UART0 BIT(0) | |
57 | #define JZ_CLOCK_GATE_TCU BIT(1) | |
58 | #define JZ_CLOCK_GATE_RTC BIT(2) | |
59 | #define JZ_CLOCK_GATE_I2C BIT(3) | |
60 | #define JZ_CLOCK_GATE_SPI BIT(4) | |
61 | #define JZ_CLOCK_GATE_AIC BIT(5) | |
62 | #define JZ_CLOCK_GATE_I2S BIT(6) | |
63 | #define JZ_CLOCK_GATE_MMC BIT(7) | |
64 | #define JZ_CLOCK_GATE_ADC BIT(8) | |
65 | #define JZ_CLOCK_GATE_CIM BIT(9) | |
66 | #define JZ_CLOCK_GATE_LCD BIT(10) | |
67 | #define JZ_CLOCK_GATE_UDC BIT(11) | |
68 | #define JZ_CLOCK_GATE_DMAC BIT(12) | |
69 | #define JZ_CLOCK_GATE_IPU BIT(13) | |
70 | #define JZ_CLOCK_GATE_UHC BIT(14) | |
71 | #define JZ_CLOCK_GATE_UART1 BIT(15) | |
72 | ||
52 | #define JZ_CLOCK_GATE0_NMEC BIT(0) | |
53 | #define JZ_CLOCK_GATE0_BCH BIT(1) | |
54 | #define JZ_CLOCK_GATE0_OTG BIT(2) | |
55 | #define JZ_CLOCK_GATE0_MSC0 BIT(3) | |
56 | #define JZ_CLOCK_GATE0_SSI0 BIT(4) | |
57 | #define JZ_CLOCK_GATE0_I2C0 BIT(5) | |
58 | #define JZ_CLOCK_GATE0_I2C1 BIT(6) | |
59 | #define JZ_CLOCK_GATE0_SCC BIT(7) | |
60 | #define JZ_CLOCK_GATE0_AIC BIT(8) | |
61 | #define JZ_CLOCK_GATE0_TSSI BIT(9) | |
62 | #define JZ_CLOCK_GATE0_OWI BIT(10) | |
63 | #define JZ_CLOCK_GATE0_MSC1 BIT(11) | |
64 | #define JZ_CLOCK_GATE0_MSC2 BIT(12) | |
65 | #define JZ_CLOCK_GATE0_KBC BIT(13) | |
66 | #define JZ_CLOCK_GATE0_SADC BIT(14) | |
67 | #define JZ_CLOCK_GATE0_UART0 BIT(15) | |
68 | #define JZ_CLOCK_GATE0_UART1 BIT(16) | |
69 | #define JZ_CLOCK_GATE0_UART2 BIT(17) | |
70 | #define JZ_CLOCK_GATE0_UART3 BIT(18) | |
71 | #define JZ_CLOCK_GATE0_SSI1 BIT(19) | |
72 | #define JZ_CLOCK_GATE0_SSI2 BIT(20) | |
73 | #define JZ_CLOCK_GATE0_DMAC BIT(21) | |
74 | #define JZ_CLOCK_GATE0_GPS BIT(22) | |
75 | #define JZ_CLOCK_GATE0_MAC BIT(23) | |
76 | #define JZ_CLOCK_GATE0_UHC BIT(24) | |
77 | #define JZ_CLOCK_GATE0_MDMA BIT(25) | |
78 | #define JZ_CLOCK_GATE0_CIM BIT(26) | |
79 | #define JZ_CLOCK_GATE0_TVE BIT(27) | |
80 | #define JZ_CLOCK_GATE0_LCD BIT(28) | |
81 | #define JZ_CLOCK_GATE0_IPU BIT(29) | |
82 | #define JZ_CLOCK_GATE0_DDR BIT(30) | |
83 | #define JZ_CLOCK_GATE0_EMC BIT(31) | |
84 | ||
85 | #define JZ_CLOCK_GATE1_GPU BIT(9) | |
86 | #define JZ_CLOCK_GATE1_PCM BIT(8) | |
87 | #define JZ_CLOCK_GATE1_AHB1 BIT(7) | |
88 | #define JZ_CLOCK_GATE1_CABAC BIT(6) | |
89 | #define JZ_CLOCK_GATE1_SRAM BIT(5) | |
90 | #define JZ_CLOCK_GATE1_DCT BIT(4) | |
91 | #define JZ_CLOCK_GATE1_ME BIT(3) | |
92 | #define JZ_CLOCK_GATE1_DBLK BIT(2) | |
93 | #define JZ_CLOCK_GATE1_MC BIT(1) | |
94 | #define JZ_CLOCK_GATE1_BDMA BIT(0) | |
95 | ||
96 | ||
97 | #define JZ_CLOCK_I2S_SRC_PLL BIT(31) | |
98 | #define JZ_CLOCK_I2S_SRC_PLL1 BIT(30) | |
73 | 99 | #define JZ_CLOCK_I2S_DIV_MASK 0x01ff |
74 | 100 | |
75 | #define JZ_CLOCK_LCD_DIV_MASK 0x01ff | |
101 | #define JZ_CLOCK_UDC_SRC_PLL BIT(31) | |
102 | #define JZ_CLOCK_UDC_SRC_PLL1 BIT(30) | |
103 | #define JZ_CLOCK_UDC_DIV_MASK 0x003f | |
76 | 104 | |
77 | #define JZ_CLOCK_MMC_DIV_MASK 0x001f | |
105 | #define JZ_CLOCK_LCD_SRC_PLL1 BIT(29) | |
106 | #define JZ_CLOCK_LCD_DIV_MASK 0x07ff | |
78 | 107 | |
108 | #define JZ_CLOCK_MSC_SRC_PLL0 BIT(31) | |
109 | #define JZ_CLOCK_MSC_DIV_MASK 0x001f | |
110 | ||
111 | #define JZ_CLOCK_UHC_SRC_PLL1 BIT(31) | |
79 | 112 | #define JZ_CLOCK_UHC_DIV_MASK 0x000f |
80 | 113 | |
81 | #define JZ_CLOCK_SPI_SRC_PLL BIT(31) | |
82 | #define JZ_CLOCK_SPI_DIV_MASK 0x000f | |
114 | #define JZ_CLOCK_SSI_SRC_PLL0 BIT(31) | |
115 | #define JZ_CLOCK_SSI_DIV_MASK 0x001f | |
83 | 116 | |
84 | #define JZ_CLOCK_PLL_M_MASK 0x01ff | |
117 | #define JZ_CLOCK_PLL_M_MASK 0x003f | |
85 | 118 | #define JZ_CLOCK_PLL_N_MASK 0x001f |
86 | 119 | #define JZ_CLOCK_PLL_OD_MASK 0x0003 |
87 | 120 | #define JZ_CLOCK_PLL_STABLE BIT(10) |
... | ... | |
95 | 128 | #define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2) |
96 | 129 | #define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0) |
97 | 130 | |
98 | #define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7) | |
99 | #define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6) | |
131 | #define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(5) | |
132 | #define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(7) | |
100 | 133 | |
101 | 134 | static void __iomem *jz_clock_base; |
102 | 135 | static spinlock_t jz_clock_lock; |
103 | static LIST_HEAD(jz_clocks); | |
104 | ||
105 | struct main_clk { | |
106 | struct clk clk; | |
107 | uint32_t div_offset; | |
108 | }; | |
109 | ||
110 | struct divided_clk { | |
111 | struct clk clk; | |
112 | uint32_t reg; | |
113 | uint32_t mask; | |
114 | }; | |
115 | ||
116 | struct static_clk { | |
117 | struct clk clk; | |
118 | unsigned long rate; | |
119 | }; | |
120 | 136 | |
121 | 137 | static uint32_t jz_clk_reg_read(int reg) |
122 | 138 | { |
... | ... | |
157 | 173 | spin_unlock(&jz_clock_lock); |
158 | 174 | } |
159 | 175 | |
160 | static int jz_clk_enable_gating(struct clk *clk) | |
176 | static int jz_clk_enable_gating(struct clk *clk, unsigned int reg) | |
161 | 177 | { |
162 | if (clk->gate_bit == JZ4740_CLK_NOT_GATED) | |
178 | if (clk->gate_bit == JZ47XX_CLK_NOT_GATED) | |
163 | 179 | return -EINVAL; |
164 | 180 | |
165 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); | |
181 | jz_clk_reg_clear_bits(reg, clk->gate_bit); | |
166 | 182 | return 0; |
167 | 183 | } |
168 | 184 | |
169 | static int jz_clk_disable_gating(struct clk *clk) | |
185 | static int jz_clk_disable_gating(struct clk *clk, unsigned int reg) | |
170 | 186 | { |
171 | if (clk->gate_bit == JZ4740_CLK_NOT_GATED) | |
187 | if (clk->gate_bit == JZ47XX_CLK_NOT_GATED) | |
172 | 188 | return -EINVAL; |
173 | 189 | |
174 | jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); | |
190 | jz_clk_reg_set_bits(reg, clk->gate_bit); | |
175 | 191 | return 0; |
176 | 192 | } |
177 | 193 | |
178 | static int jz_clk_is_enabled_gating(struct clk *clk) | |
194 | static int jz_clk_is_enabled_gating(struct clk *clk, unsigned int reg) | |
179 | 195 | { |
180 | if (clk->gate_bit == JZ4740_CLK_NOT_GATED) | |
196 | if (clk->gate_bit == JZ47XX_CLK_NOT_GATED) | |
181 | 197 | return 1; |
182 | 198 | |
183 | return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit); | |
199 | return !(jz_clk_reg_read(reg) & clk->gate_bit); | |
184 | 200 | } |
185 | 201 | |
186 | static unsigned long jz_clk_static_get_rate(struct clk *clk) | |
202 | static int jz_clk_enable_gating0(struct clk *clk) | |
187 | 203 | { |
188 | return ((struct static_clk *)clk)->rate; | |
204 | return jz_clk_enable_gating(clk, JZ_REG_CLOCK_GATE0); | |
189 | 205 | } |
190 | 206 | |
191 | static int jz_clk_ko_enable(struct clk *clk) | |
207 | static int jz_clk_disable_gating0(struct clk *clk) | |
192 | 208 | { |
193 | jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); | |
194 | return 0; | |
209 | return jz_clk_disable_gating(clk, JZ_REG_CLOCK_GATE0); | |
195 | 210 | } |
196 | 211 | |
197 | static int jz_clk_ko_disable(struct clk *clk) | |
212 | static int jz_clk_is_enabled_gating0(struct clk *clk) | |
198 | 213 | { |
199 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE); | |
200 | return 0; | |
214 | return jz_clk_is_enabled_gating(clk, JZ_REG_CLOCK_GATE0); | |
201 | 215 | } |
202 | 216 | |
203 | static int jz_clk_ko_is_enabled(struct clk *clk) | |
217 | static int jz_clk_enable_gating1(struct clk *clk) | |
204 | 218 | { |
205 | return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE); | |
219 | return jz_clk_enable_gating(clk, JZ_REG_CLOCK_GATE1); | |
206 | 220 | } |
207 | 221 | |
208 | static const int pllno[] = {1, 2, 2, 4}; | |
222 | static int jz_clk_disable_gating1(struct clk *clk) | |
223 | { | |
224 | return jz_clk_disable_gating(clk, JZ_REG_CLOCK_GATE1); | |
225 | } | |
226 | ||
227 | static int jz_clk_is_enabled_gating1(struct clk *clk) | |
228 | { | |
229 | return jz_clk_is_enabled_gating(clk, JZ_REG_CLOCK_GATE1); | |
230 | } | |
231 | ||
232 | static unsigned long jz_clk_static_get_rate(struct clk *clk) | |
233 | { | |
234 | return ((struct static_clk *)clk)->rate; | |
235 | } | |
209 | 236 | |
210 | 237 | static unsigned long jz_clk_pll_get_rate(struct clk *clk) |
211 | 238 | { |
239 | unsigned long rate; | |
212 | 240 | uint32_t val; |
213 | 241 | int m; |
214 | 242 | int n; |
... | ... | |
219 | 247 | if (val & JZ_CLOCK_PLL_BYPASS) |
220 | 248 | return clk_get_rate(clk->parent); |
221 | 249 | |
222 | m = ((val >> 23) & 0x1ff) + 2; | |
223 | n = ((val >> 18) & 0x1f) + 2; | |
250 | m = ((val >> 23) & 0xfe); | |
251 | n = ((val >> 18) & 0xf); | |
224 | 252 | od = (val >> 16) & 0x3; |
225 | 253 | |
226 | return ((clk_get_rate(clk->parent) / n) * m) / pllno[od]; | |
254 | rate = ((clk_get_rate(clk->parent) / n) * m) / (1 << od); | |
255 | ||
256 | printk("pll rate: %d %d %d %lu\n", m, n, od, rate); | |
257 | ||
258 | return rate; | |
227 | 259 | } |
228 | 260 | |
229 | 261 | static unsigned long jz_clk_pll_half_get_rate(struct clk *clk) |
... | ... | |
293 | 325 | |
294 | 326 | static struct clk_ops jz_clk_static_ops = { |
295 | 327 | .get_rate = jz_clk_static_get_rate, |
296 | .enable = jz_clk_enable_gating, | |
297 | .disable = jz_clk_disable_gating, | |
298 | .is_enabled = jz_clk_is_enabled_gating, | |
328 | .enable = jz_clk_enable_gating0, | |
329 | .disable = jz_clk_disable_gating0, | |
330 | .is_enabled = jz_clk_is_enabled_gating0, | |
299 | 331 | }; |
300 | 332 | |
301 | 333 | static struct static_clk jz_clk_ext = { |
302 | 334 | .clk = { |
303 | 335 | .name = "ext", |
304 | .gate_bit = JZ4740_CLK_NOT_GATED, | |
336 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
305 | 337 | .ops = &jz_clk_static_ops, |
306 | 338 | }, |
307 | 339 | }; |
... | ... | |
359 | 391 | .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, |
360 | 392 | }; |
361 | 393 | |
362 | ||
363 | 394 | static struct main_clk jz_clk_low_speed_peripheral = { |
364 | 395 | .clk = { |
365 | 396 | .name = "pclk", |
... | ... | |
369 | 400 | .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, |
370 | 401 | }; |
371 | 402 | |
372 | static const struct clk_ops jz_clk_ko_ops = { | |
373 | .enable = jz_clk_ko_enable, | |
374 | .disable = jz_clk_ko_disable, | |
375 | .is_enabled = jz_clk_ko_is_enabled, | |
403 | static struct main_clk jz_clk_high_speed_peripheral2 = { | |
404 | .clk = { | |
405 | .name = "h2clk", | |
406 | .parent = &jz_clk_pll, | |
407 | .ops = &jz_clk_main_ops, | |
408 | }, | |
409 | .div_offset = JZ_CLOCK_CTRL_H2DIV_OFFSET, | |
376 | 410 | }; |
377 | 411 | |
378 | static struct clk jz_clk_ko = { | |
379 | .name = "cko", | |
380 | .parent = &jz_clk_memory.clk, | |
381 | .ops = &jz_clk_ko_ops, | |
412 | static struct main_clk jz_clk_static_peripheral = { | |
413 | .clk = { | |
414 | .name = "sclk", | |
415 | .parent = &jz_clk_pll, | |
416 | .ops = &jz_clk_main_ops, | |
417 | }, | |
418 | .div_offset = JZ_CLOCK_CTRL_SDIV_OFFSET, | |
382 | 419 | }; |
383 | 420 | |
384 | static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) | |
385 | { | |
386 | if (parent == &jz_clk_pll) | |
387 | jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); | |
388 | else if (parent == &jz_clk_ext.clk) | |
389 | jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI); | |
390 | else | |
391 | return -EINVAL; | |
392 | ||
393 | clk->parent = parent; | |
394 | ||
395 | return 0; | |
396 | } | |
397 | ||
398 | static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent) | |
399 | { | |
400 | if (parent == &jz_clk_pll_half) | |
401 | jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); | |
402 | else if (parent == &jz_clk_ext.clk) | |
403 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL); | |
404 | else | |
405 | return -EINVAL; | |
406 | ||
407 | clk->parent = parent; | |
408 | ||
409 | return 0; | |
410 | } | |
411 | ||
412 | static int jz_clk_udc_enable(struct clk *clk) | |
413 | { | |
414 | jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL, | |
415 | JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
420 | static int jz_clk_udc_disable(struct clk *clk) | |
421 | { | |
422 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, | |
423 | JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); | |
424 | ||
425 | return 0; | |
426 | } | |
427 | ||
428 | static int jz_clk_udc_is_enabled(struct clk *clk) | |
429 | { | |
430 | return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) & | |
431 | JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC); | |
432 | } | |
433 | ||
434 | static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) | |
435 | { | |
436 | if (parent == &jz_clk_pll_half) | |
437 | jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); | |
438 | else if (parent == &jz_clk_ext.clk) | |
439 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL); | |
440 | else | |
441 | return -EINVAL; | |
442 | ||
443 | clk->parent = parent; | |
444 | ||
445 | return 0; | |
446 | } | |
447 | ||
448 | static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate) | |
449 | { | |
450 | int div; | |
451 | ||
452 | if (clk->parent == &jz_clk_ext.clk) | |
453 | return -EINVAL; | |
454 | ||
455 | div = clk_get_rate(clk->parent) / rate - 1; | |
456 | ||
457 | if (div < 0) | |
458 | div = 0; | |
459 | else if (div > 63) | |
460 | div = 63; | |
461 | ||
462 | jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET, | |
463 | JZ_CLOCK_CTRL_UDIV_MASK); | |
464 | return 0; | |
465 | } | |
466 | ||
467 | static unsigned long jz_clk_udc_get_rate(struct clk *clk) | |
468 | { | |
469 | int div; | |
470 | ||
471 | if (clk->parent == &jz_clk_ext.clk) | |
472 | return clk_get_rate(clk->parent); | |
473 | ||
474 | div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK); | |
475 | div >>= JZ_CLOCK_CTRL_UDIV_OFFSET; | |
476 | div += 1; | |
477 | ||
478 | return clk_get_rate(clk->parent) / div; | |
479 | } | |
480 | ||
481 | 421 | static unsigned long jz_clk_divided_get_rate(struct clk *clk) |
482 | 422 | { |
483 | 423 | struct divided_clk *dclk = (struct divided_clk *)clk; |
... | ... | |
508 | 448 | |
509 | 449 | jz_clk_reg_write_mask(dclk->reg, div, dclk->mask); |
510 | 450 | |
511 | return 0; | |
512 | } | |
513 | ||
514 | static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate) | |
515 | { | |
516 | int div; | |
517 | unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent); | |
518 | ||
519 | if (rate > 150000000) | |
520 | return 150000000; | |
521 | ||
522 | div = parent_rate / rate; | |
523 | if (div < 1) | |
524 | div = 1; | |
525 | else if (div > 32) | |
526 | div = 32; | |
527 | ||
528 | return parent_rate / div; | |
529 | } | |
530 | ||
531 | static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate) | |
532 | { | |
533 | int div; | |
534 | ||
535 | if (rate > 150000000) | |
536 | return -EINVAL; | |
537 | ||
538 | div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1; | |
539 | if (div < 0) | |
540 | div = 0; | |
541 | else if (div > 31) | |
542 | div = 31; | |
543 | ||
544 | jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET, | |
545 | JZ_CLOCK_CTRL_LDIV_MASK); | |
451 | printk("%s rate: %lu %lu\n", clk->name, rate, clk_get_rate(clk)); | |
546 | 452 | |
547 | 453 | return 0; |
548 | 454 | } |
549 | 455 | |
550 | static unsigned long jz_clk_ldclk_get_rate(struct clk *clk) | |
551 | { | |
552 | int div; | |
553 | ||
554 | div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK; | |
555 | div >>= JZ_CLOCK_CTRL_LDIV_OFFSET; | |
556 | ||
557 | return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); | |
558 | } | |
559 | ||
560 | static const struct clk_ops jz_clk_ops_ld = { | |
561 | .set_rate = jz_clk_ldclk_set_rate, | |
562 | .get_rate = jz_clk_ldclk_get_rate, | |
563 | .round_rate = jz_clk_ldclk_round_rate, | |
564 | .enable = jz_clk_enable_gating, | |
565 | .disable = jz_clk_disable_gating, | |
566 | .is_enabled = jz_clk_is_enabled_gating, | |
567 | }; | |
568 | ||
569 | static struct clk jz_clk_ld = { | |
570 | .name = "lcd", | |
571 | .gate_bit = JZ_CLOCK_GATE_LCD, | |
572 | .parent = &jz_clk_pll_half, | |
573 | .ops = &jz_clk_ops_ld, | |
574 | }; | |
575 | ||
576 | static const struct clk_ops jz_clk_i2s_ops = { | |
456 | static const struct clk_ops jz_clk_divided_ops = { | |
577 | 457 | .set_rate = jz_clk_divided_set_rate, |
578 | 458 | .get_rate = jz_clk_divided_get_rate, |
579 | .enable = jz_clk_enable_gating, | |
580 | .disable = jz_clk_disable_gating, | |
581 | .is_enabled = jz_clk_is_enabled_gating, | |
582 | .set_parent = jz_clk_i2s_set_parent, | |
459 | .enable = jz_clk_enable_gating0, | |
460 | .disable = jz_clk_disable_gating0, | |
461 | .is_enabled = jz_clk_is_enabled_gating0, | |
583 | 462 | }; |
584 | 463 | |
585 | static const struct clk_ops jz_clk_spi_ops = { | |
586 | .set_rate = jz_clk_divided_set_rate, | |
587 | .get_rate = jz_clk_divided_get_rate, | |
588 | .enable = jz_clk_enable_gating, | |
589 | .disable = jz_clk_disable_gating, | |
590 | .is_enabled = jz_clk_is_enabled_gating, | |
591 | .set_parent = jz_clk_spi_set_parent, | |
464 | static struct divided_clk jz_clk_i2s = { | |
465 | .clk = { | |
466 | .name = "i2s", | |
467 | .parent = &jz_clk_ext.clk, | |
468 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
469 | .ops = &jz_clk_divided_ops, | |
470 | }, | |
471 | .reg = JZ_REG_CLOCK_I2S, | |
472 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
592 | 473 | }; |
593 | 474 | |
594 | static const struct clk_ops jz_clk_divided_ops = { | |
595 | .set_rate = jz_clk_divided_set_rate, | |
596 | .get_rate = jz_clk_divided_get_rate, | |
597 | .enable = jz_clk_enable_gating, | |
598 | .disable = jz_clk_disable_gating, | |
599 | .is_enabled = jz_clk_is_enabled_gating, | |
600 | }; | |
601 | ||
602 | static struct divided_clk jz4740_clock_divided_clks[] = { | |
603 | [0] = { | |
604 | .clk = { | |
605 | .name = "i2s", | |
606 | .parent = &jz_clk_ext.clk, | |
607 | .gate_bit = JZ_CLOCK_GATE_I2S, | |
608 | .ops = &jz_clk_i2s_ops, | |
609 | }, | |
610 | .reg = JZ_REG_CLOCK_I2S, | |
611 | .mask = JZ_CLOCK_I2S_DIV_MASK, | |
612 | }, | |
613 | [1] = { | |
614 | .clk = { | |
615 | .name = "spi", | |
616 | .parent = &jz_clk_ext.clk, | |
617 | .gate_bit = JZ_CLOCK_GATE_SPI, | |
618 | .ops = &jz_clk_spi_ops, | |
619 | }, | |
620 | .reg = JZ_REG_CLOCK_SPI, | |
621 | .mask = JZ_CLOCK_SPI_DIV_MASK, | |
475 | static struct divided_clk jz_clk_lcd_pclk = { | |
476 | .clk = { | |
477 | .name = "lcd_pclk", | |
478 | .parent = &jz_clk_pll_half, | |
479 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
480 | .ops = &jz_clk_divided_ops, | |
622 | 481 | }, |
623 | [2] = { | |
624 | .clk = { | |
625 | .name = "lcd_pclk", | |
626 | .parent = &jz_clk_pll_half, | |
627 | .gate_bit = JZ4740_CLK_NOT_GATED, | |
628 | .ops = &jz_clk_divided_ops, | |
629 | }, | |
630 | .reg = JZ_REG_CLOCK_LCD, | |
631 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
482 | .reg = JZ_REG_CLOCK_LCD, | |
483 | .mask = JZ_CLOCK_LCD_DIV_MASK, | |
484 | }; | |
485 | ||
486 | static struct divided_clk jz_clk_msc = { | |
487 | .clk = { | |
488 | .name = "msc", | |
489 | .parent = &jz_clk_ext.clk, | |
490 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
491 | .ops = &jz_clk_divided_ops, | |
632 | 492 | }, |
633 | [3] = { | |
634 | .clk = { | |
635 | .name = "mmc", | |
636 | .parent = &jz_clk_pll_half, | |
637 | .gate_bit = JZ_CLOCK_GATE_MMC, | |
638 | .ops = &jz_clk_divided_ops, | |
639 | }, | |
640 | .reg = JZ_REG_CLOCK_MMC, | |
641 | .mask = JZ_CLOCK_MMC_DIV_MASK, | |
493 | .reg = JZ_REG_CLOCK_MSC, | |
494 | .mask = JZ_CLOCK_MSC_DIV_MASK, | |
495 | }; | |
496 | ||
497 | static struct divided_clk jz_clk_uhc = { | |
498 | .clk = { | |
499 | .name = "uhc", | |
500 | .parent = &jz_clk_pll_half, | |
501 | .gate_bit = JZ_CLOCK_GATE0_UHC, | |
502 | .ops = &jz_clk_divided_ops, | |
642 | 503 | }, |
643 | [4] = { | |
644 | .clk = { | |
645 | .name = "uhc", | |
646 | .parent = &jz_clk_pll_half, | |
647 | .gate_bit = JZ_CLOCK_GATE_UHC, | |
648 | .ops = &jz_clk_divided_ops, | |
649 | }, | |
650 | .reg = JZ_REG_CLOCK_UHC, | |
651 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
504 | .reg = JZ_REG_CLOCK_UHC, | |
505 | .mask = JZ_CLOCK_UHC_DIV_MASK, | |
506 | }; | |
507 | ||
508 | static struct divided_clk jz_clk_ssi = { | |
509 | .clk = { | |
510 | .name = "ssi", | |
511 | .parent = &jz_clk_pll_half, | |
512 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
513 | .ops = &jz_clk_divided_ops, | |
652 | 514 | }, |
515 | .reg = JZ_REG_CLOCK_SSI, | |
516 | .mask = JZ_CLOCK_SSI_DIV_MASK, | |
653 | 517 | }; |
654 | 518 | |
655 | static const struct clk_ops jz_clk_udc_ops = { | |
656 | .set_parent = jz_clk_udc_set_parent, | |
657 | .set_rate = jz_clk_udc_set_rate, | |
658 | .get_rate = jz_clk_udc_get_rate, | |
659 | .enable = jz_clk_udc_enable, | |
660 | .disable = jz_clk_udc_disable, | |
661 | .is_enabled = jz_clk_udc_is_enabled, | |
519 | static const struct clk_ops jz_clk_simple0_ops = { | |
520 | .enable = jz_clk_enable_gating0, | |
521 | .disable = jz_clk_disable_gating0, | |
522 | .is_enabled = jz_clk_is_enabled_gating0, | |
662 | 523 | }; |
663 | 524 | |
664 | static const struct clk_ops jz_clk_simple_ops = { | |
665 | .enable = jz_clk_enable_gating, | |
666 | .disable = jz_clk_disable_gating, | |
667 | .is_enabled = jz_clk_is_enabled_gating, | |
525 | static const struct clk_ops jz_clk_simple1_ops = { | |
526 | .enable = jz_clk_enable_gating1, | |
527 | .disable = jz_clk_disable_gating1, | |
528 | .is_enabled = jz_clk_is_enabled_gating1, | |
668 | 529 | }; |
669 | 530 | |
670 | static struct clk jz4740_clock_simple_clks[] = { | |
671 | [0] = { | |
672 | .name = "udc", | |
673 | .parent = &jz_clk_ext.clk, | |
674 | .ops = &jz_clk_udc_ops, | |
675 | }, | |
676 | [1] = { | |
677 | .name = "uart0", | |
678 | .parent = &jz_clk_ext.clk, | |
679 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
680 | .ops = &jz_clk_simple_ops, | |
681 | }, | |
682 | [2] = { | |
683 | .name = "uart1", | |
684 | .parent = &jz_clk_ext.clk, | |
685 | .gate_bit = JZ_CLOCK_GATE_UART1, | |
686 | .ops = &jz_clk_simple_ops, | |
687 | }, | |
688 | [3] = { | |
689 | .name = "dma", | |
690 | .parent = &jz_clk_high_speed_peripheral.clk, | |
691 | .gate_bit = JZ_CLOCK_GATE_UART0, | |
692 | .ops = &jz_clk_simple_ops, | |
693 | }, | |
694 | [4] = { | |
695 | .name = "ipu", | |
696 | .parent = &jz_clk_high_speed_peripheral.clk, | |
697 | .gate_bit = JZ_CLOCK_GATE_IPU, | |
698 | .ops = &jz_clk_simple_ops, | |
699 | }, | |
700 | [5] = { | |
701 | .name = "adc", | |
702 | .parent = &jz_clk_ext.clk, | |
703 | .gate_bit = JZ_CLOCK_GATE_ADC, | |
704 | .ops = &jz_clk_simple_ops, | |
705 | }, | |
706 | [6] = { | |
707 | .name = "i2c", | |
708 | .parent = &jz_clk_ext.clk, | |
709 | .gate_bit = JZ_CLOCK_GATE_I2C, | |
710 | .ops = &jz_clk_simple_ops, | |
711 | }, | |
712 | [7] = { | |
713 | .name = "aic", | |
714 | .parent = &jz_clk_ext.clk, | |
715 | .gate_bit = JZ_CLOCK_GATE_AIC, | |
716 | .ops = &jz_clk_simple_ops, | |
717 | }, | |
531 | #define DEFINE_GATED_CLOCK0(_name, _parent, _gate_bit) \ | |
532 | struct clk _name = { \ | |
533 | .parent = parent, \ | |
534 | .gate_bit = _gate_bit, \ | |
535 | .ops = jz_clk_simple0_ops, \ | |
536 | }; | |
537 | ||
538 | ||
539 | static struct clk jz_clk_bch = { | |
540 | .name = "bch", | |
541 | .parent = &jz_clk_ext.clk, | |
542 | .gate_bit = JZ_CLOCK_GATE0_BCH, | |
543 | .ops = &jz_clk_simple0_ops, | |
718 | 544 | }; |
719 | 545 | |
720 | static struct static_clk jz_clk_rtc = { | |
721 | .clk = { | |
722 | .name = "rtc", | |
723 | .gate_bit = JZ_CLOCK_GATE_RTC, | |
724 | .ops = &jz_clk_static_ops, | |
725 | }, | |
726 | .rate = 32768, | |
546 | static struct clk jz_clk_emc = { | |
547 | .name = "emc", | |
548 | .parent = &jz_clk_ext.clk, | |
549 | .gate_bit = JZ_CLOCK_GATE0_EMC, | |
550 | .ops = &jz_clk_simple0_ops, | |
727 | 551 | }; |
728 | 552 | |
729 | int clk_enable(struct clk *clk) | |
730 | { | |
731 | if (!clk->ops->enable) | |
732 | return -EINVAL; | |
553 | static struct clk jz_clk_ssi0 = { | |
554 | .name = "ssi0", | |
555 | .parent = &jz_clk_ssi.clk, | |
556 | .gate_bit = JZ_CLOCK_GATE0_SSI0, | |
557 | .ops = &jz_clk_simple0_ops, | |
558 | }; | |
733 | 559 | |
734 | return clk->ops->enable(clk); | |
735 | } | |
736 | EXPORT_SYMBOL_GPL(clk_enable); | |
560 | static struct clk jz_clk_ssi1 = { | |
561 | .name = "ssi1", | |
562 | .parent = &jz_clk_ssi.clk, | |
563 | .gate_bit = JZ_CLOCK_GATE0_SSI1, | |
564 | .ops = &jz_clk_simple0_ops, | |
565 | }; | |
737 | 566 | |
738 | void clk_disable(struct clk *clk) | |
739 | { | |
740 | if (clk->ops->disable) | |
741 | clk->ops->disable(clk); | |
742 | } | |
743 | EXPORT_SYMBOL_GPL(clk_disable); | |
567 | static struct clk jz_clk_ssi2 = { | |
568 | .name = "ssi2", | |
569 | .parent = &jz_clk_ssi.clk, | |
570 | .gate_bit = JZ_CLOCK_GATE0_SSI2, | |
571 | .ops = &jz_clk_simple0_ops, | |
572 | }; | |
744 | 573 | |
745 | int clk_is_enabled(struct clk *clk) | |
746 | { | |
747 | if (clk->ops->is_enabled) | |
748 | return clk->ops->is_enabled(clk); | |
574 | static struct clk jz_clk_msc0 = { | |
575 | .name = "msc0", | |
576 | .parent = &jz_clk_msc.clk, | |
577 | .gate_bit = JZ_CLOCK_GATE0_MSC0, | |
578 | .ops = &jz_clk_simple0_ops, | |
579 | }; | |
749 | 580 | |
750 | return 1; | |
751 | } | |
581 | static struct clk jz_clk_msc1 = { | |
582 | .name = "msc1", | |
583 | .parent = &jz_clk_msc.clk, | |
584 | .gate_bit = JZ_CLOCK_GATE0_MSC1, | |
585 | .ops = &jz_clk_simple0_ops, | |
586 | }; | |
752 | 587 | |
753 | unsigned long clk_get_rate(struct clk *clk) | |
754 | { | |
755 | if (clk->ops->get_rate) | |
756 | return clk->ops->get_rate(clk); | |
757 | if (clk->parent) | |
758 | return clk_get_rate(clk->parent); | |
588 | static struct clk jz_clk_msc2 = { | |
589 | .name = "msc2", | |
590 | .parent = &jz_clk_msc.clk, | |
591 | .gate_bit = JZ_CLOCK_GATE0_MSC2, | |
592 | .ops = &jz_clk_simple0_ops, | |
593 | }; | |
759 | 594 | |
760 | return -EINVAL; | |
761 | } | |
762 | EXPORT_SYMBOL_GPL(clk_get_rate); | |
595 | static struct clk jz_clk_uart0 = { | |
596 | .name = "uart0", | |
597 | .parent = &jz_clk_ext.clk, | |
598 | .gate_bit = JZ_CLOCK_GATE0_UART0, | |
599 | .ops = &jz_clk_simple0_ops, | |
600 | }; | |
763 | 601 | |
764 | int clk_set_rate(struct clk *clk, unsigned long rate) | |
765 | { | |
766 | if (!clk->ops->set_rate) | |
767 | return -EINVAL; | |
768 | return clk->ops->set_rate(clk, rate); | |
769 | } | |
770 | EXPORT_SYMBOL_GPL(clk_set_rate); | |
602 | static struct clk jz_clk_uart1 = { | |
603 | .name = "uart1", | |
604 | .parent = &jz_clk_ext.clk, | |
605 | .gate_bit = JZ_CLOCK_GATE0_UART1, | |
606 | .ops = &jz_clk_simple0_ops, | |
607 | }; | |
771 | 608 | |
772 | long clk_round_rate(struct clk *clk, unsigned long rate) | |
773 | { | |
774 | if (clk->ops->round_rate) | |
775 | return clk->ops->round_rate(clk, rate); | |
609 | static struct clk jz_clk_uart2 = { | |
610 | .name = "uart2", | |
611 | .parent = &jz_clk_ext.clk, | |
612 | .gate_bit = JZ_CLOCK_GATE0_UART2, | |
613 | .ops = &jz_clk_simple0_ops, | |
614 | }; | |
776 | 615 | |
777 | return -EINVAL; | |
778 | } | |
779 | EXPORT_SYMBOL_GPL(clk_round_rate); | |
616 | static struct clk jz_clk_uart3 = { | |
617 | .name = "uart3", | |
618 | .parent = &jz_clk_ext.clk, | |
619 | .gate_bit = JZ_CLOCK_GATE0_UART3, | |
620 | .ops = &jz_clk_simple0_ops, | |
621 | }; | |
780 | 622 | |
781 | int clk_set_parent(struct clk *clk, struct clk *parent) | |
782 | { | |
783 | int ret; | |
784 | int enabled; | |
623 | static struct clk jz_clk_dma = { | |
624 | .name = "dma", | |
625 | .parent = &jz_clk_high_speed_peripheral.clk, | |
626 | .gate_bit = JZ_CLOCK_GATE0_DMAC, | |
627 | .ops = &jz_clk_simple0_ops, | |
628 | }; | |
785 | 629 | |
786 | if (!clk->ops->set_parent) | |
787 | return -EINVAL; | |
630 | static struct clk jz_clk_ipu = { | |
631 | .name = "ipu", | |
632 | .parent = &jz_clk_high_speed_peripheral.clk, | |
633 | .gate_bit = JZ_CLOCK_GATE0_IPU, | |
634 | .ops = &jz_clk_simple0_ops, | |
635 | }; | |
788 | 636 | |
789 | enabled = clk_is_enabled(clk); | |
790 | if (enabled) | |
791 | clk_disable(clk); | |
792 | ret = clk->ops->set_parent(clk, parent); | |
793 | if (enabled) | |
794 | clk_enable(clk); | |
637 | static struct clk jz_clk_adc = { | |
638 | .name = "adc", | |
639 | .parent = &jz_clk_ext.clk, | |
640 | .gate_bit = JZ_CLOCK_GATE0_SADC, | |
641 | .ops = &jz_clk_simple0_ops, | |
642 | }; | |
795 | 643 | |
796 | jz4740_clock_debugfs_update_parent(clk); | |
644 | static struct clk jz_clk_i2c0 = { | |
645 | .name = "i2c0", | |
646 | .parent = &jz_clk_ext.clk, | |
647 | .gate_bit = JZ_CLOCK_GATE0_I2C0, | |
648 | .ops = &jz_clk_simple0_ops, | |
649 | }; | |
797 | 650 | |
798 | return ret; | |
799 | } | |
800 | EXPORT_SYMBOL_GPL(clk_set_parent); | |
651 | static struct clk jz_clk_i2c1 = { | |
652 | .name = "i2c1", | |
653 | .parent = &jz_clk_ext.clk, | |
654 | .gate_bit = JZ_CLOCK_GATE0_I2C1, | |
655 | .ops = &jz_clk_simple0_ops, | |
656 | }; | |
801 | 657 | |
802 | struct clk *clk_get(struct device *dev, const char *name) | |
803 | { | |
804 | struct clk *clk; | |
658 | static struct clk jz_clk_aic = { | |
659 | .name = "aic", | |
660 | .parent = &jz_clk_ext.clk, | |
661 | .gate_bit = JZ_CLOCK_GATE0_AIC, | |
662 | .ops = &jz_clk_simple0_ops, | |
663 | }; | |
805 | 664 | |
806 | list_for_each_entry(clk, &jz_clocks, list) { | |
807 | if (strcmp(clk->name, name) == 0) | |
808 | return clk; | |
809 | } | |
810 | return ERR_PTR(-ENXIO); | |
811 | } | |
812 | EXPORT_SYMBOL_GPL(clk_get); | |
665 | static struct clk jz_clk_ld = { | |
666 | .name = "lcd", | |
667 | .parent = &jz_clk_ext.clk, | |
668 | .gate_bit = JZ_CLOCK_GATE0_AIC, | |
669 | .ops = &jz_clk_simple0_ops, | |
670 | }; | |
813 | 671 | |
814 | void clk_put(struct clk *clk) | |
815 | { | |
816 | } | |
817 | EXPORT_SYMBOL_GPL(clk_put); | |
672 | static struct static_clk jz_clk_rtc = { | |
673 | .clk = { | |
674 | .name = "rtc", | |
675 | .gate_bit = JZ47XX_CLK_NOT_GATED, | |
676 | .ops = &jz_clk_static_ops, | |
677 | }, | |
678 | .rate = 32768, | |
679 | }; | |
818 | 680 | |
819 | static inline void clk_add(struct clk *clk) | |
820 | { | |
821 | list_add_tail(&clk->list, &jz_clocks); | |
681 | #define INIT_CLOCK(_dev, _con, _clk) \ | |
682 | { .dev_id = _dev, .con_id = _con, .clk = _clk, } | |
683 | ||
684 | static struct clk_lookup jz4760_clk_table[] = { | |
685 | INIT_CLOCK(NULL, "ext", &jz_clk_ext.clk), | |
686 | INIT_CLOCK(NULL, "pll", &jz_clk_pll), | |
687 | INIT_CLOCK(NULL, "pll half", &jz_clk_pll_half), | |
688 | INIT_CLOCK(NULL, "cclk", &jz_clk_cpu.clk), | |
689 | INIT_CLOCK(NULL, "mclk", &jz_clk_memory.clk), | |
690 | INIT_CLOCK(NULL, "hclk", &jz_clk_high_speed_peripheral.clk), | |
691 | INIT_CLOCK(NULL, "pclk", &jz_clk_low_speed_peripheral.clk), | |
692 | INIT_CLOCK(NULL, "h2clk", &jz_clk_high_speed_peripheral2.clk), | |
693 | INIT_CLOCK(NULL, "sclk", &jz_clk_static_peripheral.clk), | |
694 | ||
695 | INIT_CLOCK("jz4750-nand", "bch", &jz_clk_bch), | |
696 | INIT_CLOCK("jz4750-nand", "emc", &jz_clk_emc), | |
697 | ||
698 | INIT_CLOCK("jz4740-rtc", "rtc", &jz_clk_rtc.clk), | |
699 | INIT_CLOCK("jz4740-fb", "lcd", &jz_clk_ld), | |
700 | INIT_CLOCK("jz4740-fb", "lcd_pclk", &jz_clk_lcd_pclk.clk), | |
701 | INIT_CLOCK(NULL, "ssi", &jz_clk_ssi.clk), | |
702 | INIT_CLOCK(NULL, "ssi0", &jz_clk_ssi0), | |
703 | INIT_CLOCK(NULL, "ssi1", &jz_clk_ssi1), | |
704 | INIT_CLOCK(NULL, "ssi2", &jz_clk_ssi2), | |
705 | ||
706 | INIT_CLOCK(NULL, "i2c0", &jz_clk_i2c0), | |
707 | INIT_CLOCK(NULL, "i2c1", &jz_clk_i2c1), | |
708 | ||
709 | INIT_CLOCK("jz4740-i2s", "i2s", &jz_clk_i2s.clk), | |
710 | INIT_CLOCK("jz4740-i2s", "aic", &jz_clk_aic), | |
711 | ||
712 | INIT_CLOCK("jz4740-adc", "adc", &jz_clk_adc), | |
713 | /* INIT_CLOCK("jz-udc", "udc", &jz_clk_udc), | |
714 | INIT_CLOCK("jz-udc", "udc-phy", &jz_clk_udc_phy),*/ | |
715 | INIT_CLOCK(NULL, "msc", &jz_clk_msc.clk), | |
716 | INIT_CLOCK("jz4740-mmc.0", "mmc", &jz_clk_msc0), | |
717 | INIT_CLOCK("jz4740-mmc.1", "mmc", &jz_clk_msc1), | |
718 | INIT_CLOCK("jz4740-mmc.2", "mmc", &jz_clk_msc2), | |
719 | INIT_CLOCK("jz4740-ohci", "uhc", &jz_clk_uhc.clk), | |
720 | INIT_CLOCK("jz4740-ohci", "uhc-ohy", &jz_clk_uhc.clk), | |
721 | ||
722 | INIT_CLOCK(NULL, "uart0", &jz_clk_uart0), | |
723 | INIT_CLOCK(NULL, "uart1", &jz_clk_uart1), | |
724 | INIT_CLOCK(NULL, "uart1", &jz_clk_uart2), | |
725 | INIT_CLOCK(NULL, "uart1", &jz_clk_uart3), | |
726 | INIT_CLOCK(NULL, "dma", &jz_clk_dma), | |
727 | INIT_CLOCK(NULL, "ipu", &jz_clk_ipu), | |
728 | }; | |
822 | 729 | |
823 | jz4740_clock_debugfs_add_clk(clk); | |
824 | } | |
825 | 730 | |
826 | static void clk_register_clks(void) | |
731 | static void __init clk_register_clks(void) | |
827 | 732 | { |
828 | size_t i; | |
829 | ||
830 | clk_add(&jz_clk_ext.clk); | |
831 | clk_add(&jz_clk_pll); | |
832 | clk_add(&jz_clk_pll_half); | |
833 | clk_add(&jz_clk_cpu.clk); | |
834 | clk_add(&jz_clk_high_speed_peripheral.clk); | |
835 | clk_add(&jz_clk_low_speed_peripheral.clk); | |
836 | clk_add(&jz_clk_ko); | |
837 | clk_add(&jz_clk_ld); | |
838 | clk_add(&jz_clk_rtc.clk); | |
839 | ||
840 | for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i) | |
841 | clk_add(&jz4740_clock_divided_clks[i].clk); | |
842 | ||
843 | for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i) | |
844 | clk_add(&jz4740_clock_simple_clks[i]); | |
733 | jz47xx_clock_add_table(jz4760_clk_table, ARRAY_SIZE(jz4760_clk_table)); | |
845 | 734 | } |
846 | 735 | |
847 | void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) | |
736 | void jz47xx_clock_set_wait_mode(enum jz47xx_wait_mode mode) | |
848 | 737 | { |
849 | 738 | switch (mode) { |
850 | case JZ4740_WAIT_MODE_IDLE: | |
739 | case JZ47XX_WAIT_MODE_IDLE: | |
851 | 740 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); |
852 | 741 | break; |
853 | case JZ4740_WAIT_MODE_SLEEP: | |
742 | case JZ47XX_WAIT_MODE_SLEEP: | |
854 | 743 | jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP); |
855 | 744 | break; |
856 | 745 | } |
857 | 746 | } |
858 | 747 | |
859 | void jz4740_clock_udc_disable_auto_suspend(void) | |
860 | { | |
861 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); | |
862 | } | |
863 | EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); | |
864 | ||
865 | void jz4740_clock_udc_enable_auto_suspend(void) | |
748 | void jz47xx_clock_suspend(void) | |
866 | 749 | { |
867 | jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC); | |
868 | } | |
869 | EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); | |
870 | ||
871 | void jz4740_clock_suspend(void) | |
872 | { | |
873 | jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, | |
874 | JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); | |
875 | ||
876 | 750 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); |
877 | 751 | } |
878 | 752 | |
879 | void jz4740_clock_resume(void) | |
753 | void jz47xx_clock_resume(void) | |
880 | 754 | { |
881 | 755 | uint32_t pll; |
882 | 756 | |
... | ... | |
885 | 759 | do { |
886 | 760 | pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL); |
887 | 761 | } while (!(pll & JZ_CLOCK_PLL_STABLE)); |
888 | ||
889 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, | |
890 | JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); | |
891 | 762 | } |
892 | 763 | |
893 | static int jz4740_clock_init(void) | |
764 | static int __init jz4760_clock_init(void) | |
894 | 765 | { |
895 | 766 | uint32_t val; |
896 | 767 | |
... | ... | |
900 | 771 | |
901 | 772 | spin_lock_init(&jz_clock_lock); |
902 | 773 | |
903 | jz_clk_ext.rate = jz4740_clock_bdata.ext_rate; | |
904 | jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate; | |
905 | ||
906 | val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); | |
774 | jz_clk_ext.rate = jz47xx_clock_bdata.ext_rate; | |
775 | jz_clk_rtc.rate = jz47xx_clock_bdata.rtc_rate; | |
907 | 776 | |
908 | if (val & JZ_CLOCK_SPI_SRC_PLL) | |
909 | jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half; | |
777 | val = jz_clk_reg_read(JZ_REG_CLOCK_I2S); | |
778 | if (val & JZ_CLOCK_I2S_SRC_PLL) { | |
779 | if (val & JZ_CLOCK_I2S_SRC_PLL1) | |
780 | jz_clk_i2s.clk.parent = &jz_clk_pll_half; | |
781 | else | |
782 | jz_clk_i2s.clk.parent = &jz_clk_pll_half; | |
783 | } | |
910 | 784 | |
911 | val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); | |
785 | val = jz_clk_reg_read(JZ_REG_CLOCK_SSI); | |
786 | if (val & JZ_CLOCK_SSI_SRC_PLL0) | |
787 | jz_clk_ssi.clk.parent = &jz_clk_pll_half; | |
912 | 788 | |
913 | if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) | |
914 | jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half; | |
789 | val = jz_clk_reg_read(JZ_REG_CLOCK_MSC); | |
790 | if (!(val & JZ_CLOCK_MSC_SRC_PLL0)) | |
791 | jz_clk_msc.clk.parent = &jz_clk_pll_half; | |
915 | 792 | |
916 | if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) | |
917 | jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half; | |
793 | clk_set_rate(&jz_clk_msc.clk, 12000000); | |
918 | 794 | |
919 | 795 | jz4740_clock_debugfs_init(); |
920 | 796 | |
797 | jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL, | |
798 | JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC); | |
799 | ||
800 | ||
921 | 801 | clk_register_clks(); |
802 | printk("register clks\n"); | |
803 | ||
922 | 804 | |
923 | 805 | return 0; |
924 | 806 | } |
925 | arch_initcall(jz4740_clock_init); | |
807 | arch_initcall(jz4760_clock_init); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9