diff options
| author | Michael Turquette <mturquette@linaro.org> | 2015-03-25 17:51:40 -0400 |
|---|---|---|
| committer | Michael Turquette <mturquette@linaro.org> | 2015-03-25 17:51:40 -0400 |
| commit | fe15dedc02e4ee29edfc84bbbf5ee42827e36ac7 (patch) | |
| tree | b64f9ceebdbf3019f3d10ecb404f6fc002223113 | |
| parent | c77662a4df847e7b75ff8c5f2314dd4f022377e3 (diff) | |
| parent | f1017969661dd33ead5ba7c3f4a0793c6611441a (diff) | |
Merge tag 'sunxi-clocks-for-4.1' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into clk-next
Allwinner clocks changes for 4.1
The usual round of clock changes for the Allwinner SoCs.
There is nothing really standing out here, but a few changes and fixes, most
notably to allow the AHB clock to be parented to a PLL, instead of the CPU
clock to avoid any AHB rate change due to cpufreq.
| -rw-r--r-- | Documentation/devicetree/bindings/clock/sunxi.txt | 3 | ||||
| -rw-r--r-- | drivers/clk/sunxi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 185 | ||||
| -rw-r--r-- | drivers/clk/sunxi/clk-usb.c | 233 |
4 files changed, 319 insertions, 103 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 60b44285250d..4fa11af3d378 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
| @@ -20,6 +20,7 @@ Required properties: | |||
| 20 | "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23 | 20 | "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23 |
| 21 | "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates | 21 | "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates |
| 22 | "allwinner,sun4i-a10-ahb-clk" - for the AHB clock | 22 | "allwinner,sun4i-a10-ahb-clk" - for the AHB clock |
| 23 | "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13 | ||
| 23 | "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80 | 24 | "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80 |
| 24 | "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 | 25 | "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 |
| 25 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 | 26 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 |
| @@ -66,6 +67,8 @@ Required properties: | |||
| 66 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 | 67 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 |
| 67 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 | 68 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 |
| 68 | "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 | 69 | "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 |
| 70 | "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80 | ||
| 71 | "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80 | ||
| 69 | 72 | ||
| 70 | Required properties for all clocks: | 73 | Required properties for all clocks: |
| 71 | - reg : shall be the control register address for the clock. | 74 | - reg : shall be the control register address for the clock. |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 3a5292e3fcf8..058f273d6154 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile | |||
| @@ -9,6 +9,7 @@ obj-y += clk-mod0.o | |||
| 9 | obj-y += clk-sun8i-mbus.o | 9 | obj-y += clk-sun8i-mbus.o |
| 10 | obj-y += clk-sun9i-core.o | 10 | obj-y += clk-sun9i-core.o |
| 11 | obj-y += clk-sun9i-mmc.o | 11 | obj-y += clk-sun9i-mmc.o |
| 12 | obj-y += clk-usb.o | ||
| 12 | 13 | ||
| 13 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ | 14 | obj-$(CONFIG_MFD_SUN6I_PRCM) += \ |
| 14 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ | 15 | clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ |
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 379324eb5486..7e1e2bd189b6 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
| @@ -482,6 +482,45 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, | |||
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | /** | 484 | /** |
| 485 | * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB | ||
| 486 | * AHB rate is calculated as follows | ||
| 487 | * rate = parent_rate >> p | ||
| 488 | */ | ||
| 489 | |||
| 490 | static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, | ||
| 491 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
| 492 | { | ||
| 493 | u32 div; | ||
| 494 | |||
| 495 | /* divide only */ | ||
| 496 | if (parent_rate < *freq) | ||
| 497 | *freq = parent_rate; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * user manual says valid speed is 8k ~ 276M, but tests show it | ||
| 501 | * can work at speeds up to 300M, just after reparenting to pll6 | ||
| 502 | */ | ||
| 503 | if (*freq < 8000) | ||
| 504 | *freq = 8000; | ||
| 505 | if (*freq > 300000000) | ||
| 506 | *freq = 300000000; | ||
| 507 | |||
| 508 | div = order_base_2(DIV_ROUND_UP(parent_rate, *freq)); | ||
| 509 | |||
| 510 | /* p = 0 ~ 3 */ | ||
| 511 | if (div > 3) | ||
| 512 | div = 3; | ||
| 513 | |||
| 514 | *freq = parent_rate >> div; | ||
| 515 | |||
| 516 | /* we were called to round the frequency, we can now return */ | ||
| 517 | if (p == NULL) | ||
| 518 | return; | ||
| 519 | |||
| 520 | *p = div; | ||
| 521 | } | ||
| 522 | |||
| 523 | /** | ||
| 485 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 | 524 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 |
| 486 | * APB1 rate is calculated as follows | 525 | * APB1 rate is calculated as follows |
| 487 | * rate = (parent_rate >> p) / (m + 1); | 526 | * rate = (parent_rate >> p) / (m + 1); |
| @@ -616,6 +655,11 @@ static struct clk_factors_config sun6i_a31_pll6_config = { | |||
| 616 | .n_start = 1, | 655 | .n_start = 1, |
| 617 | }; | 656 | }; |
| 618 | 657 | ||
| 658 | static struct clk_factors_config sun5i_a13_ahb_config = { | ||
| 659 | .pshift = 4, | ||
| 660 | .pwidth = 2, | ||
| 661 | }; | ||
| 662 | |||
| 619 | static struct clk_factors_config sun4i_apb1_config = { | 663 | static struct clk_factors_config sun4i_apb1_config = { |
| 620 | .mshift = 0, | 664 | .mshift = 0, |
| 621 | .mwidth = 5, | 665 | .mwidth = 5, |
| @@ -676,6 +720,13 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = { | |||
| 676 | .name = "pll6x2", | 720 | .name = "pll6x2", |
| 677 | }; | 721 | }; |
| 678 | 722 | ||
| 723 | static const struct factors_data sun5i_a13_ahb_data __initconst = { | ||
| 724 | .mux = 6, | ||
| 725 | .muxmask = BIT(1) | BIT(0), | ||
| 726 | .table = &sun5i_a13_ahb_config, | ||
| 727 | .getter = sun5i_a13_get_ahb_factors, | ||
| 728 | }; | ||
| 729 | |||
| 679 | static const struct factors_data sun4i_apb1_data __initconst = { | 730 | static const struct factors_data sun4i_apb1_data __initconst = { |
| 680 | .mux = 24, | 731 | .mux = 24, |
| 681 | .muxmask = BIT(1) | BIT(0), | 732 | .muxmask = BIT(1) | BIT(0), |
| @@ -838,59 +889,6 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
| 838 | 889 | ||
| 839 | 890 | ||
| 840 | /** | 891 | /** |
| 841 | * sunxi_gates_reset... - reset bits in leaf gate clk registers handling | ||
| 842 | */ | ||
| 843 | |||
| 844 | struct gates_reset_data { | ||
| 845 | void __iomem *reg; | ||
| 846 | spinlock_t *lock; | ||
| 847 | struct reset_controller_dev rcdev; | ||
| 848 | }; | ||
| 849 | |||
| 850 | static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev, | ||
| 851 | unsigned long id) | ||
| 852 | { | ||
| 853 | struct gates_reset_data *data = container_of(rcdev, | ||
| 854 | struct gates_reset_data, | ||
| 855 | rcdev); | ||
| 856 | unsigned long flags; | ||
| 857 | u32 reg; | ||
| 858 | |||
| 859 | spin_lock_irqsave(data->lock, flags); | ||
| 860 | |||
| 861 | reg = readl(data->reg); | ||
| 862 | writel(reg & ~BIT(id), data->reg); | ||
| 863 | |||
| 864 | spin_unlock_irqrestore(data->lock, flags); | ||
| 865 | |||
| 866 | return 0; | ||
| 867 | } | ||
| 868 | |||
| 869 | static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev, | ||
| 870 | unsigned long id) | ||
| 871 | { | ||
| 872 | struct gates_reset_data *data = container_of(rcdev, | ||
| 873 | struct gates_reset_data, | ||
| 874 | rcdev); | ||
| 875 | unsigned long flags; | ||
| 876 | u32 reg; | ||
| 877 | |||
| 878 | spin_lock_irqsave(data->lock, flags); | ||
| 879 | |||
| 880 | reg = readl(data->reg); | ||
| 881 | writel(reg | BIT(id), data->reg); | ||
| 882 | |||
| 883 | spin_unlock_irqrestore(data->lock, flags); | ||
| 884 | |||
| 885 | return 0; | ||
| 886 | } | ||
| 887 | |||
| 888 | static struct reset_control_ops sunxi_gates_reset_ops = { | ||
| 889 | .assert = sunxi_gates_reset_assert, | ||
| 890 | .deassert = sunxi_gates_reset_deassert, | ||
| 891 | }; | ||
| 892 | |||
| 893 | /** | ||
| 894 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks | 892 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks |
| 895 | */ | 893 | */ |
| 896 | 894 | ||
| @@ -898,7 +896,6 @@ static struct reset_control_ops sunxi_gates_reset_ops = { | |||
| 898 | 896 | ||
| 899 | struct gates_data { | 897 | struct gates_data { |
| 900 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); | 898 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); |
| 901 | u32 reset_mask; | ||
| 902 | }; | ||
