diff options
| author | Boris BREZILLON <b.brezillon@overkiz.com> | 2013-10-17 12:55:41 -0400 |
|---|---|---|
| committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2013-12-02 09:31:25 -0500 |
| commit | c84a61d87261f91d378cf26be4ffd3199ffd2493 (patch) | |
| tree | 92da0de1acda1b70872958baaa251b142092efc0 | |
| parent | f090fb37def3eb9ea49b71751dbe43f423f3a152 (diff) | |
clk: at91: add PMC usb clock
This patch adds new at91 usb clock implementation using common clk framework.
This clock is used to clock usb ports (ohci, ehci and udc).
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
| -rw-r--r-- | arch/arm/mach-at91/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/clk/at91/Makefile | 1 | ||||
| -rw-r--r-- | drivers/clk/at91/clk-usb.c | 398 | ||||
| -rw-r--r-- | drivers/clk/at91/pmc.c | 15 | ||||
| -rw-r--r-- | drivers/clk/at91/pmc.h | 9 |
5 files changed, 434 insertions, 0 deletions
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 6ad37daca971..b76dc4c62af9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
| @@ -3,6 +3,9 @@ if ARCH_AT91 | |||
| 3 | config HAVE_AT91_UTMI | 3 | config HAVE_AT91_UTMI |
| 4 | bool | 4 | bool |
| 5 | 5 | ||
| 6 | config HAVE_AT91_USB_CLK | ||
| 7 | bool | ||
| 8 | |||
| 6 | config HAVE_AT91_DBGU0 | 9 | config HAVE_AT91_DBGU0 |
| 7 | bool | 10 | bool |
| 8 | 11 | ||
| @@ -82,6 +85,7 @@ config SOC_SAMA5D3 | |||
| 82 | select HAVE_AT91_DBGU1 | 85 | select HAVE_AT91_DBGU1 |
| 83 | select AT91_USE_OLD_CLK | 86 | select AT91_USE_OLD_CLK |
| 84 | select HAVE_AT91_UTMI | 87 | select HAVE_AT91_UTMI |
| 88 | select HAVE_AT91_USB_CLK | ||
| 85 | help | 89 | help |
| 86 | Select this if you are using one of Atmel's SAMA5D3 family SoC. | 90 | Select this if you are using one of Atmel's SAMA5D3 family SoC. |
| 87 | This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. | 91 | This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35. |
| @@ -96,12 +100,14 @@ config SOC_AT91RM9200 | |||
| 96 | select MULTI_IRQ_HANDLER | 100 | select MULTI_IRQ_HANDLER |
| 97 | select SPARSE_IRQ | 101 | select SPARSE_IRQ |
| 98 | select AT91_USE_OLD_CLK | 102 | select AT91_USE_OLD_CLK |
| 103 | select HAVE_AT91_USB_CLK | ||
| 99 | 104 | ||
| 100 | config SOC_AT91SAM9260 | 105 | config SOC_AT91SAM9260 |
| 101 | bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20" | 106 | bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20" |
| 102 | select HAVE_AT91_DBGU0 | 107 | select HAVE_AT91_DBGU0 |
| 103 | select SOC_AT91SAM9 | 108 | select SOC_AT91SAM9 |
| 104 | select AT91_USE_OLD_CLK | 109 | select AT91_USE_OLD_CLK |
| 110 | select HAVE_AT91_USB_CLK | ||
| 105 | help | 111 | help |
| 106 | Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE | 112 | Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE |
| 107 | or AT91SAM9G20 SoC. | 113 | or AT91SAM9G20 SoC. |
| @@ -112,6 +118,7 @@ config SOC_AT91SAM9261 | |||
| 112 | select HAVE_FB_ATMEL | 118 | select HAVE_FB_ATMEL |
| 113 | select SOC_AT91SAM9 | 119 | select SOC_AT91SAM9 |
| 114 | select AT91_USE_OLD_CLK | 120 | select AT91_USE_OLD_CLK |
| 121 | select HAVE_AT91_USB_CLK | ||
| 115 | help | 122 | help |
| 116 | Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. | 123 | Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. |
| 117 | 124 | ||
| @@ -121,6 +128,7 @@ config SOC_AT91SAM9263 | |||
| 121 | select HAVE_FB_ATMEL | 128 | select HAVE_FB_ATMEL |
| 122 | select SOC_AT91SAM9 | 129 | select SOC_AT91SAM9 |
| 123 | select AT91_USE_OLD_CLK | 130 | select AT91_USE_OLD_CLK |
| 131 | select HAVE_AT91_USB_CLK | ||
| 124 | 132 | ||
| 125 | config SOC_AT91SAM9RL | 133 | config SOC_AT91SAM9RL |
| 126 | bool "AT91SAM9RL" | 134 | bool "AT91SAM9RL" |
| @@ -137,6 +145,7 @@ config SOC_AT91SAM9G45 | |||
| 137 | select SOC_AT91SAM9 | 145 | select SOC_AT91SAM9 |
| 138 | select AT91_USE_OLD_CLK | 146 | select AT91_USE_OLD_CLK |
| 139 | select HAVE_AT91_UTMI | 147 | select HAVE_AT91_UTMI |
| 148 | select HAVE_AT91_USB_CLK | ||
| 140 | help | 149 | help |
| 141 | Select this if you are using one of Atmel's AT91SAM9G45 family SoC. | 150 | Select this if you are using one of Atmel's AT91SAM9G45 family SoC. |
| 142 | This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. | 151 | This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. |
| @@ -148,6 +157,7 @@ config SOC_AT91SAM9X5 | |||
| 148 | select SOC_AT91SAM9 | 157 | select SOC_AT91SAM9 |
| 149 | select AT91_USE_OLD_CLK | 158 | select AT91_USE_OLD_CLK |
| 150 | select HAVE_AT91_UTMI | 159 | select HAVE_AT91_UTMI |
| 160 | select HAVE_AT91_USB_CLK | ||
| 151 | help | 161 | help |
| 152 | Select this if you are using one of Atmel's AT91SAM9x5 family SoC. | 162 | Select this if you are using one of Atmel's AT91SAM9x5 family SoC. |
| 153 | This means that your SAM9 name finishes with a '5' (except if it is | 163 | This means that your SAM9 name finishes with a '5' (except if it is |
| @@ -161,6 +171,7 @@ config SOC_AT91SAM9N12 | |||
| 161 | select HAVE_FB_ATMEL | 171 | select HAVE_FB_ATMEL |
| 162 | select SOC_AT91SAM9 | 172 | select SOC_AT91SAM9 |
| 163 | select AT91_USE_OLD_CLK | 173 | select AT91_USE_OLD_CLK |
| 174 | select HAVE_AT91_USB_CLK | ||
| 164 | help | 175 | help |
| 165 | Select this if you are using Atmel's AT91SAM9N12 SoC. | 176 | Select this if you are using Atmel's AT91SAM9N12 SoC. |
| 166 | 177 | ||
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index a82488323ea4..61db058be0c0 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile | |||
| @@ -8,3 +8,4 @@ obj-y += clk-system.o clk-peripheral.o | |||
| 8 | 8 | ||
| 9 | obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o | 9 | obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o |
| 10 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o | 10 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o |
| 11 | obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o | ||
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c new file mode 100644 index 000000000000..7d1d26a4bd04 --- /dev/null +++ b/drivers/clk/at91/clk-usb.c | |||
| @@ -0,0 +1,398 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/clkdev.h> | ||
| 13 | #include <linux/clk/at91_pmc.h> | ||
| 14 | #include <linux/of.h> | ||
| 15 | #include <linux/of_address.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | |||
| 18 | #include "pmc.h" | ||
| 19 | |||
| 20 | #define USB_SOURCE_MAX 2 | ||
| 21 | |||
| 22 | #define SAM9X5_USB_DIV_SHIFT 8 | ||
| 23 | #define SAM9X5_USB_MAX_DIV 0xf | ||
| 24 | |||
| 25 | #define RM9200_USB_DIV_SHIFT 28 | ||
| 26 | #define RM9200_USB_DIV_TAB_SIZE 4 | ||
| 27 | |||
| 28 | struct at91sam9x5_clk_usb { | ||
| 29 | struct clk_hw hw; | ||
| 30 | struct at91_pmc *pmc; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #define to_at91sam9x5_clk_usb(hw) \ | ||
| 34 | container_of(hw, struct at91sam9x5_clk_usb, hw) | ||
| 35 | |||
| 36 | struct at91rm9200_clk_usb { | ||
| 37 | struct clk_hw hw; | ||
| 38 | struct at91_pmc *pmc; | ||
| 39 | u32 divisors[4]; | ||
| 40 | }; | ||
| 41 | |||
| 42 | #define to_at91rm9200_clk_usb(hw) \ | ||
| 43 | container_of(hw, struct at91rm9200_clk_usb, hw) | ||
| 44 | |||
| 45 | static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, | ||
| 46 | unsigned long parent_rate) | ||
| 47 | { | ||
| 48 | u32 tmp; | ||
| 49 | u8 usbdiv; | ||
| 50 | struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); | ||
| 51 | struct at91_pmc *pmc = usb->pmc; | ||
| 52 | |||
| 53 | tmp = pmc_read(pmc, AT91_PMC_USB); | ||
| 54 | usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; | ||
| 55 | return parent_rate / (usbdiv + 1); | ||
| 56 | } | ||
| 57 | |||
| 58 | static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 59 | unsigned long *parent_rate) | ||
| 60 | { | ||
| 61 | unsigned long div; | ||
| 62 | unsigned long bestrate; | ||
| 63 | unsigned long tmp; | ||
| 64 | |||
| 65 | if (rate >= *parent_rate) | ||
| 66 | return *parent_rate; | ||
| 67 | |||
| 68 | div = *parent_rate / rate; | ||
| 69 | if (div >= SAM9X5_USB_MAX_DIV) | ||
| 70 | return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); | ||
| 71 | |||
| 72 | bestrate = *parent_rate / div; | ||
| 73 | tmp = *parent_rate / (div + 1); | ||
| 74 | if (bestrate - rate > rate - tmp) | ||
| 75 | bestrate = tmp; | ||
| 76 | |||
| 77 | return bestrate; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) | ||
| 81 | { | ||
| 82 | u32 tmp; | ||
| 83 | struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); | ||
| 84 | struct at91_pmc *pmc = usb->pmc; | ||
| 85 | |||
