diff options
223 files changed, 11289 insertions, 2157 deletions
diff --git a/Documentation/conf.py b/Documentation/conf.py index f9054ab60cb1..63857d33778c 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py | |||
| @@ -271,10 +271,29 @@ latex_elements = { | |||
| 271 | 271 | ||
| 272 | # Additional stuff for the LaTeX preamble. | 272 | # Additional stuff for the LaTeX preamble. |
| 273 | 'preamble': ''' | 273 | 'preamble': ''' |
| 274 | \\usepackage{ifthen} | 274 | % Use some font with UTF-8 support with XeLaTeX |
| 275 | \\usepackage{fontspec} | ||
| 276 | \\setsansfont{DejaVu Serif} | ||
| 277 | \\setromanfont{DejaVu Sans} | ||
| 278 | \\setmonofont{DejaVu Sans Mono} | ||
| 279 | |||
| 280 | ''' | ||
| 281 | } | ||
| 282 | |||
| 283 | # Fix reference escape troubles with Sphinx 1.4.x | ||
| 284 | if major == 1 and minor > 3: | ||
| 285 | latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n' | ||
| 286 | |||
| 287 | if major == 1 and minor <= 4: | ||
| 288 | latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}' | ||
| 289 | elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)): | ||
| 290 | latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in' | ||
| 291 | latex_elements['preamble'] += '\\fvset{fontsize=auto}\n' | ||
| 275 | 292 | ||
| 276 | % Allow generate some pages in landscape | 293 | # Customize notice background colors on Sphinx < 1.6: |
| 277 | \\usepackage{lscape} | 294 | if major == 1 and minor < 6: |
| 295 | latex_elements['preamble'] += ''' | ||
| 296 | \\usepackage{ifthen} | ||
| 278 | 297 | ||
| 279 | % Put notes in color and let them be inside a table | 298 | % Put notes in color and let them be inside a table |
| 280 | \\definecolor{NoteColor}{RGB}{204,255,255} | 299 | \\definecolor{NoteColor}{RGB}{204,255,255} |
| @@ -325,27 +344,26 @@ latex_elements = { | |||
| 325 | } | 344 | } |
| 326 | \\makeatother | 345 | \\makeatother |
| 327 | 346 | ||
| 328 | % Use some font with UTF-8 support with XeLaTeX | ||
| 329 | \\usepackage{fontspec} | ||
| 330 | \\setsansfont{DejaVu Serif} | ||
| 331 | \\setromanfont{DejaVu Sans} | ||
| 332 | \\setmonofont{DejaVu Sans Mono} | ||
| 333 | |||
| 334 | % To allow adjusting table sizes | ||
| 335 | \\usepackage{adjustbox} | ||
| 336 | |||
| 337 | ''' | 347 | ''' |
| 338 | } | ||
| 339 | |||
| 340 | # Fix reference escape troubles with Sphinx 1.4.x | ||
| 341 | if major == 1 and minor > 3: | ||
| 342 | latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n' | ||
| 343 | 348 | ||
| 344 | if major == 1 and minor <= 4: | 349 | # With Sphinx 1.6, it is possible to change the Bg color directly |
| 345 | latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}' | 350 | # by using: |
| 346 | elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)): | 351 | # \definecolor{sphinxnoteBgColor}{RGB}{204,255,255} |
| 347 | latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in' | 352 | # \definecolor{sphinxwarningBgColor}{RGB}{255,204,204} |
| 348 | latex_elements['preamble'] += '\\fvset{fontsize=auto}\n' | 353 | # \definecolor{sphinxattentionBgColor}{RGB}{255,255,204} |
| 354 | # \definecolor{sphinximportantBgColor}{RGB}{192,255,204} | ||
| 355 | # | ||
| 356 | # However, it require to use sphinx heavy box with: | ||
| 357 | # | ||
| 358 | # \renewenvironment{sphinxlightbox} {% | ||
| 359 | # \\begin{sphinxheavybox} | ||
| 360 | # } | ||
| 361 | # \\end{sphinxheavybox} | ||
| 362 | # } | ||
| 363 | # | ||
| 364 | # Unfortunately, the implementation is buggy: if a note is inside a | ||
| 365 | # table, it isn't displayed well. So, for now, let's use boring | ||
| 366 | # black and white notes. | ||
| 349 | 367 | ||
| 350 | # Grouping the document tree into LaTeX files. List of tuples | 368 | # Grouping the document tree into LaTeX files. List of tuples |
| 351 | # (source start file, target name, title, | 369 | # (source start file, target name, title, |
diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt index faa6d8ac5834..786dc39ca904 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt | |||
| @@ -5,9 +5,11 @@ controllers within the Always-On part of the SoC. | |||
| 5 | 5 | ||
| 6 | Required Properties: | 6 | Required Properties: |
| 7 | 7 | ||
| 8 | - compatible: should be "amlogic,gxbb-aoclkc" | 8 | - compatible: value should be different for each SoC family as : |
| 9 | - reg: physical base address of the clock controller and length of memory | 9 | - GXBB (S905) : "amlogic,meson-gxbb-aoclkc" |
| 10 | mapped region. | 10 | - GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc" |
| 11 | - GXM (S912) : "amlogic,meson-gxm-aoclkc" | ||
| 12 | followed by the common "amlogic,meson-gx-aoclkc" | ||
| 11 | 13 | ||
| 12 | - #clock-cells: should be 1. | 14 | - #clock-cells: should be 1. |
| 13 | 15 | ||
| @@ -23,14 +25,22 @@ to specify the reset which they consume. All available resets are defined as | |||
| 23 | preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be | 25 | preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be |
| 24 | used in device tree sources. | 26 | used in device tree sources. |
| 25 | 27 | ||
| 28 | Parent node should have the following properties : | ||
| 29 | - compatible: "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd" | ||
| 30 | - reg: base address and size of the AO system control register space. | ||
| 31 | |||
| 26 | Example: AO Clock controller node: | 32 | Example: AO Clock controller node: |
| 27 | 33 | ||
| 28 | clkc_AO: clock-controller@040 { | 34 | ao_sysctrl: sys-ctrl@0 { |
| 29 | compatible = "amlogic,gxbb-aoclkc"; | 35 | compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd"; |
| 30 | reg = <0x0 0x040 0x0 0x4>; | 36 | reg = <0x0 0x0 0x0 0x100>; |
| 37 | |||
| 38 | clkc_AO: clock-controller { | ||
| 39 | compatible = "amlogic,meson-gxbb-aoclkc", "amlogic,meson-gx-aoclkc"; | ||
| 31 | #clock-cells = <1>; | 40 | #clock-cells = <1>; |
| 32 | #reset-cells = <1>; | 41 | #reset-cells = <1>; |
| 33 | }; | 42 | }; |
| 43 | }; | ||
| 34 | 44 | ||
| 35 | Example: UART controller node that consumes the clock and reset generated | 45 | Example: UART controller node that consumes the clock and reset generated |
| 36 | by the clock controller: | 46 | by the clock controller: |
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt index 5f3ad65daf69..51c259a92d02 100644 --- a/Documentation/devicetree/bindings/clock/at91-clock.txt +++ b/Documentation/devicetree/bindings/clock/at91-clock.txt | |||
| @@ -81,6 +81,16 @@ Required properties: | |||
| 81 | "atmel,sama5d2-clk-generated": | 81 | "atmel,sama5d2-clk-generated": |
| 82 | at91 generated clock | 82 | at91 generated clock |
| 83 | 83 | ||
| 84 | "atmel,sama5d2-clk-audio-pll-frac": | ||
| 85 | at91 audio fractional pll | ||
| 86 | |||
| 87 | "atmel,sama5d2-clk-audio-pll-pad": | ||
| 88 | at91 audio pll CLK_AUDIO output pin | ||
| 89 | |||
| 90 | "atmel,sama5d2-clk-audio-pll-pmc" | ||
| 91 | at91 audio pll output on AUDIOPLLCLK that feeds the PMC | ||
| 92 | and can be used by peripheral clock or generic clock | ||
| 93 | |||
| 84 | Required properties for SCKC node: | 94 | Required properties for SCKC node: |
| 85 | - reg : defines the IO memory reserved for the SCKC. | 95 | - reg : defines the IO memory reserved for the SCKC. |
| 86 | - #size-cells : shall be 0 (reg is used to encode clk id). | 96 | - #size-cells : shall be 0 (reg is used to encode clk id). |
diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt index 53d7e50ed875..05a245c9df08 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt | |||
| @@ -1,24 +1,32 @@ | |||
| 1 | Binding for IDT VersaClock5 programmable i2c clock generator. | 1 | Binding for IDT VersaClock 5,6 programmable i2c clock generators. |
| 2 | 2 | ||
| 3 | The IDT VersaClock5 are programmable i2c clock generators providing | 3 | The IDT VersaClock 5 and VersaClock 6 are programmable i2c clock |
| 4 | from 3 to 12 output clocks. | 4 | generators providing from 3 to 12 output clocks. |
| 5 | 5 | ||
| 6 | ==I2C device node== | 6 | ==I2C device node== |
| 7 | 7 | ||
| 8 | Required properties: | 8 | Required properties: |
| 9 | - compatible: shall be one of "idt,5p49v5923" , "idt,5p49v5933" , | 9 | - compatible: shall be one of |
| 10 | "idt,5p49v5935". | 10 | "idt,5p49v5923" |
| 11 | "idt,5p49v5925" | ||
| 12 | "idt,5p49v5933" | ||
| 13 | "idt,5p49v5935" | ||
| 14 | "idt,5p49v6901" | ||
| 11 | - reg: i2c device address, shall be 0x68 or 0x6a. | 15 | - reg: i2c device address, shall be 0x68 or 0x6a. |
| 12 | - #clock-cells: from common clock binding; shall be set to 1. | 16 | - #clock-cells: from common clock binding; shall be set to 1. |
| 13 | - clocks: from common clock binding; list of parent clock handles, | 17 | - clocks: from common clock binding; list of parent clock handles, |
| 14 | - 5p49v5923: (required) either or both of XTAL or CLKIN | 18 | - 5p49v5923 and |
| 19 | 5p49v5925 and | ||
| 20 | 5p49v6901: (required) either or both of XTAL or CLKIN | ||
| 15 | reference clock. | 21 | reference clock. |
| 16 | - 5p49v5933 and | 22 | - 5p49v5933 and |
| 17 | - 5p49v5935: (optional) property not present (internal | 23 | - 5p49v5935: (optional) property not present (internal |
| 18 | Xtal used) or CLKIN reference | 24 | Xtal used) or CLKIN reference |
| 19 | clock. | 25 | clock. |
| 20 | - clock-names: from common clock binding; clock input names, can be | 26 | - clock-names: from common clock binding; clock input names, can be |
| 21 | - 5p49v5923: (required) either or both of "xin", "clkin". | 27 | - 5p49v5923 and |
| 28 | 5p49v5925 and | ||
| 29 | 5p49v6901: (required) either or both of "xin", "clkin". | ||
| 22 | - 5p49v5933 and | 30 | - 5p49v5933 and |
| 23 | - 5p49v5935: (optional) property not present or "clkin". | 31 | - 5p49v5935: (optional) property not present or "clkin". |
| 24 | 32 | ||
| @@ -37,6 +45,7 @@ clock specifier, the following mapping applies: | |||
| 37 | 1 -- OUT1 | 45 | 1 -- OUT1 |
| 38 | 2 -- OUT4 | 46 | 2 -- OUT4 |
| 39 | 47 | ||
| 48 | 5P49V5925 and | ||
| 40 | 5P49V5935: | 49 | 5P49V5935: |
| 41 | 0 -- OUT0_SEL_I2CB | 50 | 0 -- OUT0_SEL_I2CB |
| 42 | 1 -- OUT1 | 51 | 1 -- OUT1 |
| @@ -44,6 +53,13 @@ clock specifier, the following mapping applies: | |||
| 44 | 3 -- OUT3 | 53 | 3 -- OUT3 |
| 45 | 4 -- OUT4 | 54 | 4 -- OUT4 |
| 46 | 55 | ||
| 56 | 5P49V6901: | ||
| 57 | 0 -- OUT0_SEL_I2CB | ||
| 58 | 1 -- OUT1 | ||
| 59 | 2 -- OUT2 | ||
| 60 | 3 -- OUT3 | ||
| 61 | 4 -- OUT4 | ||
| 62 | |||
| 47 | ==Example== | 63 | ==Example== |
| 48 | 64 | ||
| 49 | /* 25MHz reference crystal */ | 65 | /* 25MHz reference crystal */ |
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index 707a686d8d3e..316e13686568 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt | |||
| @@ -22,6 +22,7 @@ Required Properties: | |||
| 22 | - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) | 22 | - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) |
| 23 | - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) | 23 | - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) |
| 24 | - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) | 24 | - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) |
| 25 | - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) | ||
| 25 | 26 | ||
| 26 | - reg: Base address and length of the memory resource used by the CPG/MSSR | 27 | - reg: Base address and length of the memory resource used by the CPG/MSSR |
| 27 | block | 28 | block |
| @@ -30,7 +31,7 @@ Required Properties: | |||
| 30 | clock-names | 31 | clock-names |
| 31 | - clock-names: List of external parent clock names. Valid names are: | 32 | - clock-names: List of external parent clock names. Valid names are: |
| 32 | - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, | 33 | - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, |
| 33 | r8a7795, r8a7796) | 34 | r8a7795, r8a7796, r8a77995) |
| 34 | - "extalr" (r8a7795, r8a7796) | 35 | - "extalr" (r8a7795, r8a7796) |
| 35 | - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) | 36 | - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) |
| 36 | 37 | ||
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt new file mode 100644 index 000000000000..e96e085271c1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | * Renesas R-Car USB 2.0 clock selector | ||
| 2 | |||
| 3 | This file provides information on what the device node for the R-Car USB 2.0 | ||
| 4 | clock selector. | ||
| 5 | |||
| 6 | If you connect an external clock to the USB_EXTAL pin only, you should set | ||
| 7 | the clock rate to "usb_extal" node only. | ||
| 8 | If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module | ||
| 9 | is not needed because this is default setting. (Of course, you can set the | ||
| 10 | clock rates to both "usb_extal" and "usb_xtal" nodes. | ||
| 11 | |||
| 12 | Case 1: An external clock connects to R-Car SoC | ||
| 13 | +----------+ +--- R-Car ---------------------+ | ||
| 14 | |External |---|USB_EXTAL ---> all usb channels| | ||
| 15 | |clock | |USB_XTAL | | ||
| 16 | +----------+ +-------------------------------+ | ||
| 17 | In this case, we need this driver with "usb_extal" clock. | ||
| 18 | |||
| 19 | Case 2: An oscillator connects to R-Car SoC | ||
| 20 | +----------+ +--- R-Car ---------------------+ | ||
| 21 | |Oscillator|---|USB_EXTAL -+-> all usb channels| | ||
| 22 | | |---|USB_XTAL --+ | | ||
| 23 | +----------+ +-------------------------------+ | ||
| 24 | In this case, we don't need this selector. | ||
| 25 | |||
| 26 | Required properties: | ||
| 27 | - compatible: "renesas,r8a7795-rcar-usb2-clock-sel" if the device is a part of | ||
| 28 | an R8A7795 SoC. | ||
| 29 | "renesas,r8a7796-rcar-usb2-clock-sel" if the device if a part of | ||
| 30 | an R8A7796 SoC. | ||
| 31 | "renesas,rcar-gen3-usb2-clock-sel" for a generic R-Car Gen3 | ||
| 32 | compatible device. | ||
| 33 | |||
| 34 | When compatible with the generic version, nodes must list the | ||
| 35 | SoC-specific version corresponding to the platform first | ||
| 36 | followed by the generic version. | ||
| 37 | |||
| 38 | - reg: offset and length of the USB 2.0 clock selector register block. | ||
| 39 | - clocks: A list of phandles and specifier pairs. | ||
| 40 | - clock-names: Name of the clocks. | ||
| 41 | - The functional clock must be "ehci_ohci" | ||
| 42 | - The USB_EXTAL clock pin must be "usb_extal" | ||
| 43 | - The USB_XTAL clock pin must be "usb_xtal" | ||
| 44 | - #clock-cells: Must be 0 | ||
| 45 | |||
| 46 | Example (R-Car H3): | ||
| 47 | |||
| 48 | usb2_clksel: clock-controller@e6590630 { | ||
| 49 | compatible = "renesas,r8a77950-rcar-usb2-clock-sel", | ||
| 50 | "renesas,rcar-gen3-usb2-clock-sel"; | ||
| 51 | reg = <0 0xe6590630 0 0x02>; | ||
| 52 | clocks = <&cpg CPG_MOD 703>, <&usb_extal>, <&usb_xtal>; | ||
| 53 | clock-names = "ehci_ohci", "usb_extal", "usb_xtal"; | ||
| 54 | #clock-cells = <0>; | ||
| 55 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt index 455a9a00a623..6f8744fd301b 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt | |||
| @@ -1,12 +1,14 @@ | |||
| 1 | * Rockchip RK3128 Clock and Reset Unit | 1 | * Rockchip RK3126/RK3128 Clock and Reset Unit |
| 2 | 2 | ||
| 3 | The RK3128 clock controller generates and supplies clock to various | 3 | The RK3126/RK3128 clock controller generates and supplies clock to various |
| 4 | controllers within the SoC and also implements a reset controller for SoC | 4 | controllers within the SoC and also implements a reset controller for SoC |
| 5 | peripherals. | 5 | peripherals. |
| 6 | 6 | ||
| 7 | Required Properties: | 7 | Required Properties: |
| 8 | 8 | ||
| 9 | - compatible: should be "rockchip,rk3128-cru" | 9 | - compatible: should be "rockchip,rk3126-cru" or "rockchip,rk3128-cru" |
| 10 | "rockchip,rk3126-cru" - controller compatible with RK3126 SoC. | ||
| 11 | "rockchip,rk3128-cru" - controller compatible with RK3128 SoC. | ||
| 10 | - reg: physical base address of the controller and length of memory mapped | 12 | - reg: physical base address of the controller and length of memory mapped |
| 11 | region. | 13 | region. |
| 12 | - #clock-cells: should be 1. | 14 | - #clock-cells: should be 1. |
diff --git a/Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt b/Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt new file mode 100644 index 000000000000..c56c7553c730 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | Binding for the HSDK Generic PLL clock | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible: should be "snps,hsdk-<name>-pll-clock" | ||
| 9 | "snps,hsdk-core-pll-clock" | ||
| 10 | "snps,hsdk-gp-pll-clock" | ||
| 11 | "snps,hsdk-hdmi-pll-clock" | ||
| 12 | - reg : should contain base register location and length. | ||
| 13 | - clocks: shall be the input parent clock phandle for the PLL. | ||
| 14 | - #clock-cells: from common clock binding; Should always be set to 0. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | input_clk: input-clk { | ||
| 18 | clock-frequency = <33333333>; | ||
| 19 | compatible = "fixed-clock"; | ||
| 20 | #clock-cells = <0>; | ||
| 21 | }; | ||
| 22 | |||
| 23 | cpu_clk: cpu-clk@0 { | ||
| 24 | compatible = "snps,hsdk-core-pll-clock"; | ||
| 25 | reg = <0x00 0x10>; | ||
| 26 | #clock-cells = <0>; | ||
| 27 | clocks = <&input_clk>; | ||
| 28 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/snps,pll-clock.txt b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt new file mode 100644 index 000000000000..11fe4876612c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/snps,pll-clock.txt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | Binding for the AXS10X Generic PLL clock | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible: should be "snps,axs10x-<name>-pll-clock" | ||
| 9 | "snps,axs10x-arc-pll-clock" | ||
| 10 | "snps,axs10x-pgu-pll-clock" | ||
| 11 | - reg: should always contain 2 pairs address - length: first for PLL config | ||
| 12 | registers and second for corresponding LOCK CGU register. | ||
| 13 | - clocks: shall be the input parent clock phandle for the PLL. | ||
| 14 | - #clock-cells: from common clock binding; Should always be set to 0. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | input-clk: input-clk { | ||
| 18 | clock-frequency = <33333333>; | ||
| 19 | compatible = "fixed-clock"; | ||
| 20 | #clock-cells = <0>; | ||
| 21 | }; | ||
| 22 | |||
| 23 | core-clk: core-clk@80 { | ||
| 24 | compatible = "snps,axs10x-arc-pll-clock"; | ||
| 25 | reg = <0x80 0x10>, <0x100 0x10>; | ||
| 26 | #clock-cells = <0>; | ||
| 27 | clocks = <&input-clk>; | ||
| 28 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt new file mode 100644 index 000000000000..a135504c7d57 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | STMicroelectronics STM32H7 Reset and Clock Controller | ||
| 2 | ===================================================== | ||
| 3 | |||
| 4 | The RCC IP is both a reset and a clock controller. | ||
| 5 | |||
| 6 | Please refer to clock-bindings.txt for common clock controller binding usage. | ||
| 7 | Please also refer to reset.txt for common reset controller binding usage. | ||
| 8 | |||
| 9 | Required properties: | ||
| 10 | - compatible: Should be: | ||
| 11 | "st,stm32h743-rcc" | ||
| 12 | |||
| 13 | - reg: should be register base and length as documented in the | ||
| 14 | datasheet | ||
| 15 | |||
| 16 | - #reset-cells: 1, see below | ||
| 17 | |||
| 18 | - #clock-cells : from common clock binding; shall be set to 1 | ||
| 19 | |||
| 20 | - clocks: External oscillator clock phandle | ||
| 21 | - high speed external clock signal (HSE) | ||
| 22 | - low speed external clock signal (LSE) | ||
| 23 | - external I2S clock (I2S_CKIN) | ||
| 24 | |||
| 25 | Optional properties: | ||
| 26 | - st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain | ||
| 27 | write protection (RTC clock). | ||
| 28 | |||
| 29 | Example: | ||
| 30 | |||
| 31 | rcc: reset-clock-controller@58024400 { | ||
| 32 | compatible = "st,stm32h743-rcc", "st,stm32-rcc"; | ||
| 33 | reg = <0x58024400 0x400>; | ||
| 34 | #reset-cells = <1>; | ||
| 35 | #clock-cells = <2>; | ||
| 36 | clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>; | ||
| 37 | |||
| 38 | st,syscfg = <&pwrcfg>; | ||
| 39 | }; | ||
| 40 | |||
| 41 | The peripheral clock consumer should specify the desired clock by | ||
| 42 | having the clock ID in its "clocks" phandle cell. | ||
| 43 | |||
| 44 | Example: | ||
| 45 | |||
| 46 | timer5: timer@40000c00 { | ||
| 47 | compatible = "st,stm32-timer"; | ||
| 48 | reg = <0x40000c00 0x400>; | ||
| 49 | interrupts = <50>; | ||
| 50 | clocks = <&rcc TIM5_CK>; | ||
| 51 | }; | ||
| 52 | |||
| 53 | Specifying softreset control of devices | ||
| 54 | ======================================= | ||
| 55 | |||
| 56 | Device nodes should specify the reset channel required in their "resets" | ||
| 57 | property, containing a phandle to the reset device node and an index specifying | ||
| 58 | which channel to use. | ||
| 59 | The index is the bit number within the RCC registers bank, starting from RCC | ||
| 60 | base address. | ||
| 61 | It is calculated as: index = register_offset / 4 * 32 + bit_offset. | ||
| 62 | Where bit_offset is the bit offset within the register. | ||
| 63 | |||
| 64 | For example, for CRC reset: | ||
| 65 | crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107 | ||
| 66 | |||
| 67 | Example: | ||
| 68 | |||
| 69 | timer2 { | ||
| 70 | resets = <&rcc STM32H7_APB1L_RESET(TIM2)>; | ||
| 71 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt index df9fad58facd..7eda08eb8a1e 100644 --- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt +++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt | |||
| @@ -3,18 +3,24 @@ Allwinner Clock Control Unit Binding | |||
| 3 | 3 | ||
| 4 | Required properties : | 4 | Required properties : |
| 5 | - compatible: must contain one of the following compatibles: | 5 | - compatible: must contain one of the following compatibles: |
| 6 | - "allwinner,sun4i-a10-ccu" | ||
| 7 | - "allwinner,sun5i-a10s-ccu" | ||
| 8 | - "allwinner,sun5i-a13-ccu" | ||
| 6 | - "allwinner,sun6i-a31-ccu" | 9 | - "allwinner,sun6i-a31-ccu" |
| 10 | - "allwinner,sun7i-a20-ccu" | ||
| 7 | - "allwinner,sun8i-a23-ccu" | 11 | - "allwinner,sun8i-a23-ccu" |
| 8 | - "allwinner,sun8i-a33-ccu" | 12 | - "allwinner,sun8i-a33-ccu" |
| 9 | - "allwinner,sun8i-a83t-ccu" | 13 | - "allwinner,sun8i-a83t-ccu" |
| 10 | - "allwinner,sun8i-a83t-r-ccu" | 14 | - "allwinner,sun8i-a83t-r-ccu" |
| 11 | - "allwinner,sun8i-h3-ccu" | 15 | - "allwinner,sun8i-h3-ccu" |
| 12 | - "allwinner,sun8i-h3-r-ccu" | 16 | - "allwinner,sun8i-h3-r-ccu" |
| 17 | + - "allwinner,sun8i-r40-ccu" | ||
| 13 | - "allwinner,sun8i-v3s-ccu" | 18 | - "allwinner,sun8i-v3s-ccu" |
| 14 | - "allwinner,sun9i-a80-ccu" | 19 | - "allwinner,sun9i-a80-ccu" |
| 15 | - "allwinner,sun50i-a64-ccu" | 20 | - "allwinner,sun50i-a64-ccu" |
| 16 | - "allwinner,sun50i-a64-r-ccu" | 21 | - "allwinner,sun50i-a64-r-ccu" |
| 17 | - "allwinner,sun50i-h5-ccu" | 22 | - "allwinner,sun50i-h5-ccu" |
| 23 | - "nextthing,gr8-ccu" | ||
| 18 | 24 | ||
| 19 | - reg: Must contain the registers base address and length | 25 | - reg: Must contain the registers base address and length |
| 20 | - clocks: phandle to the oscillators feeding the CCU. Two are needed: | 26 | - clocks: phandle to the oscillators feeding the CCU. Two are needed: |
diff --git a/Documentation/devicetree/bindings/clock/uniphier-clock.txt b/Documentation/devicetree/bindings/clock/uniphier-clock.txt index 812163060fa3..7b5f602765fe 100644 --- a/Documentation/devicetree/bindings/clock/uniphier-clock.txt +++ b/Documentation/devicetree/bindings/clock/uniphier-clock.txt | |||
| @@ -6,7 +6,6 @@ System clock | |||
| 6 | 6 | ||
| 7 | Required properties: | 7 | Required properties: |
| 8 | - compatible: should be one of the following: | 8 | - compatible: should be one of the following: |
| 9 | "socionext,uniphier-sld3-clock" - for sLD3 SoC. | ||
| 10 | "socionext,uniphier-ld4-clock" - for LD4 SoC. | 9 | "socionext,uniphier-ld4-clock" - for LD4 SoC. |
| 11 | "socionext,uniphier-pro4-clock" - for Pro4 SoC. | 10 | "socionext,uniphier-pro4-clock" - for Pro4 SoC. |
| 12 | "socionext,uniphier-sld8-clock" - for sLD8 SoC. | 11 | "socionext,uniphier-sld8-clock" - for sLD8 SoC. |
| @@ -14,6 +13,7 @@ Required properties: | |||
| 14 | "socionext,uniphier-pxs2-clock" - for PXs2/LD6b SoC. | 13 | "socionext,uniphier-pxs2-clock" - for PXs2/LD6b SoC. |
| 15 | "socionext,uniphier-ld11-clock" - for LD11 SoC. | 14 | "socionext,uniphier-ld11-clock" - for LD11 SoC. |
| 16 | "socionext,uniphier-ld20-clock" - for LD20 SoC. | 15 | "socionext,uniphier-ld20-clock" - for LD20 SoC. |
| 16 | "socionext,uniphier-pxs3-clock" - for PXs3 SoC | ||
| 17 | - #clock-cells: should be 1. | 17 | - #clock-cells: should be 1. |
| 18 | 18 | ||
| 19 | Example: | 19 | Example: |
| @@ -48,7 +48,6 @@ Media I/O (MIO) clock, SD clock | |||
| 48 | 48 | ||
| 49 | Required properties: | 49 | Required properties: |
| 50 | - compatible: should be one of the following: | 50 | - compatible: should be one of the following: |
| 51 | "socionext,uniphier-sld3-mio-clock" - for sLD3 SoC. | ||
| 52 | "socionext,uniphier-ld4-mio-clock" - for LD4 SoC. | 51 | "socionext,uniphier-ld4-mio-clock" - for LD4 SoC. |
| 53 | "socionext,uniphier-pro4-mio-clock" - for Pro4 SoC. | 52 | "socionext,uniphier-pro4-mio-clock" - for Pro4 SoC. |
| 54 | "socionext,uniphier-sld8-mio-clock" - for sLD8 SoC. | 53 | "socionext,uniphier-sld8-mio-clock" - for sLD8 SoC. |
| @@ -56,6 +55,7 @@ Required properties: | |||
| 56 | "socionext,uniphier-pxs2-sd-clock" - for PXs2/LD6b SoC. | 55 | "socionext,uniphier-pxs2-sd-clock" - for PXs2/LD6b SoC. |
| 57 | "socionext,uniphier-ld11-mio-clock" - for LD11 SoC. | 56 | "socionext,uniphier-ld11-mio-clock" - for LD11 SoC. |
| 58 | "socionext,uniphier-ld20-sd-clock" - for LD20 SoC. | 57 | "socionext,uniphier-ld20-sd-clock" - for LD20 SoC. |
| 58 | "socionext,uniphier-pxs3-sd-clock" - for PXs3 SoC | ||
| 59 | - #clock-cells: should be 1. | 59 | - #clock-cells: should be 1. |
| 60 | 60 | ||
| 61 | Example: | 61 | Example: |
| @@ -82,11 +82,9 @@ Provided clocks: | |||
| 82 | 8: USB2 ch0 host | 82 | 8: USB2 ch0 host |
| 83 | 9: USB2 ch1 host | 83 | 9: USB2 ch1 host |
| 84 | 10: USB2 ch2 host | 84 | 10: USB2 ch2 host |
| 85 | 11: USB2 ch3 host | ||
| 86 | 12: USB2 ch0 PHY | 85 | 12: USB2 ch0 PHY |
| 87 | 13: USB2 ch1 PHY | 86 | 13: USB2 ch1 PHY |
| 88 | 14: USB2 ch2 PHY | 87 | 14: USB2 ch2 PHY |
| 89 | 15: USB2 ch3 PHY | ||
| 90 | 88 | ||
| 91 | 89 | ||
| 92 | Peripheral clock | 90 | Peripheral clock |
| @@ -94,7 +92,6 @@ Peripheral clock | |||
| 94 | 92 | ||
| 95 | Required properties: | 93 | Required properties: |
| 96 | - compatible: should be one of the following: | 94 | - compatible: should be one of the following: |
| 97 | "socionext,uniphier-sld3-peri-clock" - for sLD3 SoC. | ||
| 98 | "socionext,uniphier-ld4-peri-clock" - for LD4 SoC. | 95 | "socionext,uniphier-ld4-peri-clock" - for LD4 SoC. |
| 99 | "socionext,uniphier-pro4-peri-clock" - for Pro4 SoC. | 96 | "socionext,uniphier-pro4-peri-clock" - for Pro4 SoC. |
| 100 | "socionext,uniphier-sld8-peri-clock" - for sLD8 SoC. | 97 | "socionext,uniphier-sld8-peri-clock" - for sLD8 SoC. |
| @@ -102,6 +99,7 @@ Required properties: | |||
| 102 | "socionext,uniphier-pxs2-peri-clock" - for PXs2/LD6b SoC. | 99 | "socionext,uniphier-pxs2-peri-clock" - for PXs2/LD6b SoC. |
| 103 | "socionext,uniphier-ld11-peri-clock" - for LD11 SoC. | 100 | "socionext,uniphier-ld11-peri-clock" - for LD11 SoC. |
| 104 | "socionext,uniphier-ld20-peri-clock" - for LD20 SoC. | 101 | "socionext,uniphier-ld20-peri-clock" - for LD20 SoC. |
| 102 | "socionext,uniphier-pxs3-peri-clock" - for PXs3 SoC | ||
| 105 | - #clock-cells: should be 1. | 103 | - #clock-cells: should be 1. |
| 106 | 104 | ||
| 107 | Example: | 105 | Example: |
diff --git a/Documentation/devicetree/bindings/power/wakeup-source.txt b/Documentation/devicetree/bindings/power/wakeup-source.txt index 963c6dfd484d..3c81f78b5c27 100644 --- a/Documentation/devicetree/bindings/power/wakeup-source.txt +++ b/Documentation/devicetree/bindings/power/wakeup-source.txt | |||
| @@ -20,13 +20,12 @@ List of legacy properties and respective binding document | |||
| 20 | 1. "enable-sdio-wakeup" Documentation/devicetree/bindings/mmc/mmc.txt | 20 | 1. "enable-sdio-wakeup" Documentation/devicetree/bindings/mmc/mmc.txt |
| 21 | 2. "gpio-key,wakeup" Documentation/devicetree/bindings/input/gpio-keys{,-polled}.txt | 21 | 2. "gpio-key,wakeup" Documentation/devicetree/bindings/input/gpio-keys{,-polled}.txt |
| 22 | 3. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt | 22 | 3. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt |
| 23 | 4. "isil,irq2-can-wakeup-machine" Documentation/devicetree/bindings/rtc/isil,isl12057.txt | 23 | 4. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt |
| 24 | 5. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt | ||
| 25 | Documentation/devicetree/bindings/mfd/tc3589x.txt | 24 | Documentation/devicetree/bindings/mfd/tc3589x.txt |
| 26 | Documentation/devicetree/bindings/input/ads7846.txt | 25 | Documentation/devicetree/bindings/input/ads7846.txt |
| 27 | 6. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt | 26 | 5. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt |
| 28 | 7. "linux,input-wakeup" Documentation/devicetree/bindings/input/samsung-keypad.txt | 27 | 6. "linux,input-wakeup" Documentation/devicetree/bindings/input/samsung-keypad.txt |
| 29 | 8. "nvidia,wakeup-source" Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt | 28 | 7. "nvidia,wakeup-source" Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt |
| 30 | 29 | ||
| 31 | Examples | 30 | Examples |
| 32 | -------- | 31 | -------- |
diff --git a/Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt b/Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt new file mode 100644 index 000000000000..634312dd95ca --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | Android Goldfish RTC | ||
| 2 | |||
| 3 | Android Goldfish RTC device used by Android emulator. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : should contain "google,goldfish-rtc" | ||
| 8 | - reg : <registers mapping> | ||
| 9 | - interrupts : <interrupt mapping> | ||
| 10 | |||
| 11 | Example: | ||
| 12 | |||
| 13 | goldfish_timer@9020000 { | ||
| 14 | compatible = "google,goldfish-rtc"; | ||
| 15 | reg = <0x9020000 0x1000>; | ||
| 16 | interrupts = <0x3>; | ||
| 17 | }; | ||
diff --git a/Documentation/devicetree/bindings/rtc/isil,isl12057.txt b/Documentation/devicetree/bindings/rtc/isil,isl12057.txt index cf83e0940302..fbbdd92e5af9 100644 --- a/Documentation/devicetree/bindings/rtc/isil,isl12057.txt +++ b/Documentation/devicetree/bindings/rtc/isil,isl12057.txt | |||
| @@ -24,7 +24,6 @@ Optional properties: | |||
| 24 | 24 | ||
| 25 | - "wakeup-source": mark the chip as a wakeup source, independently of | 25 | - "wakeup-source": mark the chip as a wakeup source, independently of |
| 26 | the availability of an IRQ line connected to the SoC. | 26 | the availability of an IRQ line connected to the SoC. |
| 27 | (Legacy property supported: "isil,irq2-can-wakeup-machine") | ||
| 28 | 27 | ||
| 29 | - "interrupt-parent", "interrupts": for passing the interrupt line | 28 | - "interrupt-parent", "interrupts": for passing the interrupt line |
| 30 | of the SoC connected to IRQ#2 of the RTC chip. | 29 | of the SoC connected to IRQ#2 of the RTC chip. |
diff --git a/Documentation/devicetree/bindings/rtc/realtek,rtd119x.txt b/Documentation/devicetree/bindings/rtc/realtek,rtd119x.txt new file mode 100644 index 000000000000..bbf1ccb5df31 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/realtek,rtd119x.txt | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | Realtek RTD129x Real-Time Clock | ||
| 2 | =============================== | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : Should be "realtek,rtd1295-rtc" | ||
| 6 | - reg : Specifies the physical base address and size | ||
| 7 | - clocks : Specifies the clock gate | ||
| 8 | |||
| 9 | |||
| 10 | Example: | ||
| 11 | |||
| 12 | rtc@9801b600 { | ||
| 13 | compatible = "realtek,rtd1295-clk"; | ||
| 14 | reg = <0x9801b600 0x100>; | ||
| 15 | clocks = <&clkc RTD1295_CLK_EN_MISC_RTC>; | ||
| 16 | }; | ||
diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt index 945934918b71..d5e26d313f62 100644 --- a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt | |||
| @@ -10,7 +10,7 @@ Required properties: | |||
| 10 | 10 | ||
| 11 | Required properties for new device trees | 11 | Required properties for new device trees |
| 12 | - clocks : phandle to the 32kHz external oscillator | 12 | - clocks : phandle to the 32kHz external oscillator |
| 13 | - clock-output-names : name of the LOSC clock created | 13 | - clock-output-names : names of the LOSC and its external output clocks created |
| 14 | - #clock-cells : must be equals to 1. The RTC provides two clocks: the | 14 | - #clock-cells : must be equals to 1. The RTC provides two clocks: the |
| 15 | LOSC and its external output, with index 0 and 1 | 15 | LOSC and its external output, with index 0 and 1 |
| 16 | respectively. | 16 | respectively. |
| @@ -21,7 +21,7 @@ rtc: rtc@01f00000 { | |||
| 21 | compatible = "allwinner,sun6i-a31-rtc"; | 21 | compatible = "allwinner,sun6i-a31-rtc"; |
| 22 | reg = <0x01f00000 0x54>; | 22 | reg = <0x01f00000 0x54>; |
| 23 | interrupts = <0 40 4>, <0 41 4>; | 23 | interrupts = <0 40 4>, <0 41 4>; |
| 24 | clock-output-names = "osc32k"; | 24 | clock-output-names = "osc32k", "osc32k-out"; |
| 25 | clocks = <&ext_osc32k>; | 25 | clocks = <&ext_osc32k>; |
| 26 | #clock-cells = <1>; | 26 | #clock-cells = <1>; |
| 27 | }; | 27 | }; |
diff --git a/Documentation/devicetree/bindings/sound/atmel-classd.txt b/Documentation/devicetree/bindings/sound/atmel-classd.txt index 549e701cb7a1..898551076382 100644 --- a/Documentation/devicetree/bindings/sound/atmel-classd.txt +++ b/Documentation/devicetree/bindings/sound/atmel-classd.txt | |||
| @@ -13,13 +13,11 @@ Required properties: | |||
| 13 | Must be "tx". | 13 | Must be "tx". |
| 14 | - clock-names | 14 | - clock-names |
| 15 | Tuple listing input clock names. | 15 | Tuple listing input clock names. |
| 16 | Required elements: "pclk", "gclk" and "aclk". | 16 | Required elements: "pclk" and "gclk". |
| 17 | - clocks | 17 | - clocks |
| 18 | Please refer to clock-bindings.txt. | 18 | Please refer to clock-bindings.txt. |
| 19 | - assigned-clocks | 19 | - assigned-clocks |
| 20 | Should be <&classd_gclk>. | 20 | Should be <&classd_gclk>. |
| 21 | - assigned-clock-parents | ||
| 22 | Should be <&audio_pll_pmc>. | ||
| 23 | 21 | ||
| 24 | Optional properties: | 22 | Optional properties: |
| 25 | - pinctrl-names, pinctrl-0 | 23 | - pinctrl-names, pinctrl-0 |
| @@ -45,10 +43,9 @@ classd: classd@fc048000 { | |||
| 45 | (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | 43 | (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
| 46 | | AT91_XDMAC_DT_PERID(47))>; | 44 | | AT91_XDMAC_DT_PERID(47))>; |
| 47 | dma-names = "tx"; | 45 | dma-names = "tx"; |
| 48 | clocks = <&classd_clk>, <&classd_gclk>, <&audio_pll_pmc>; | 46 | clocks = <&classd_clk>, <&classd_gclk>; |
| 49 | clock-names = "pclk", "gclk", "aclk"; | 47 | clock-names = "pclk", "gclk"; |
| 50 | assigned-clocks = <&classd_gclk>; | 48 | assigned-clocks = <&classd_gclk>; |
| 51 | assigned-clock-parents = <&audio_pll_pmc>; | ||
| 52 | 49 | ||
| 53 | pinctrl-names = "default"; | 50 | pinctrl-names = "default"; |
| 54 | pinctrl-0 = <&pinctrl_classd_default>; | 51 | pinctrl-0 = <&pinctrl_classd_default>; |
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index fe25787ff6d4..75d2d57e2c44 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -22,7 +22,7 @@ prototypes: | |||
| 22 | struct vfsmount *(*d_automount)(struct path *path); | 22 | struct vfsmount *(*d_automount)(struct path *path); |
| 23 | int (*d_manage)(const struct path *, bool); | 23 | int (*d_manage)(const struct path *, bool); |
| 24 | struct dentry *(*d_real)(struct dentry *, const struct inode *, | 24 | struct dentry *(*d_real)(struct dentry *, const struct inode *, |
| 25 | unsigned int); | 25 | unsigned int, unsigned int); |
| 26 | 26 | ||
| 27 | locking rules: | 27 | locking rules: |
| 28 | rename_lock ->d_lock may block rcu-walk | 28 | rename_lock ->d_lock may block rcu-walk |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 405a3df759b3..5fd325df59e2 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -988,7 +988,7 @@ struct dentry_operations { | |||
| 988 | struct vfsmount *(*d_automount)(struct path *); | 988 | struct vfsmount *(*d_automount)(struct path *); |
| 989 | int (*d_manage)(const struct path *, bool); | 989 | int (*d_manage)(const struct path *, bool); |
| 990 | struct dentry *(*d_real)(struct dentry *, const struct inode *, | 990 | struct dentry *(*d_real)(struct dentry *, const struct inode *, |
| 991 | unsigned int); | 991 | unsigned int, unsigned int); |
| 992 | }; | 992 | }; |
| 993 | 993 | ||
| 994 | d_revalidate: called when the VFS needs to revalidate a dentry. This | 994 | d_revalidate: called when the VFS needs to revalidate a dentry. This |
diff --git a/Documentation/translations/ko_KR/memory-barriers.txt b/Documentation/translations/ko_KR/memory-barriers.txt index bc80fc0e210f..a7a813258013 100644 --- a/Documentation/translations/ko_KR/memory-barriers.txt +++ b/Documentation/translations/ko_KR/memory-barriers.txt | |||
| @@ -523,11 +523,11 @@ CPU ì—게 ê¸°ëŒ€í• ìˆ˜ 있는 ìµœì†Œí•œì˜ ë³´ìž¥ì‚¬í• ëª‡ê°€ì§€ê°€ 있습니 | |||
| 523 | 즉, ACQUIRE 는 ìµœì†Œí•œì˜ "ì·¨ë“" ë™ìž‘처럼, ê·¸ë¦¬ê³ RELEASE 는 ìµœì†Œí•œì˜ "공개" | 523 | 즉, ACQUIRE 는 ìµœì†Œí•œì˜ "ì·¨ë“" ë™ìž‘처럼, ê·¸ë¦¬ê³ RELEASE 는 ìµœì†Œí•œì˜ "공개" |
| 524 | 처럼 ë™ìž‘한다는 ì˜ë¯¸ìž…니다. | 524 | 처럼 ë™ìž‘한다는 ì˜ë¯¸ìž…니다. |
| 525 | 525 | ||
| 526 | core-api/atomic_ops.rst ì—서 설명ë˜ëŠ” ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜ë“¤ 중ì—는 ì™„ì „ížˆ | 526 | atomic_t.txt ì— ì„¤ëª…ëœ ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜ë“¤ 중 ì¼ë¶€ëŠ” ì™„ì „ížˆ 순서잡힌 것들과 |
| 527 | 순서잡힌 것들과 (배리어를 사용하지 않는) ì™„í™”ëœ ìˆœì„œì˜ ê²ƒë“¤ ì™¸ì— ACQUIRE 와 | 527 | (배리어를 사용하지 않는) ì™„í™”ëœ ìˆœì„œì˜ ê²ƒë“¤ ì™¸ì— ACQUIRE 와 RELEASE ë¶€ë¥˜ì˜ |
| 528 | RELEASE ë¶€ë¥˜ì˜ ê²ƒë“¤ë„ ì¡´ìž¬í•©ë‹ˆë‹¤. 로드와 ìŠ¤í† ì–´ë¥¼ ëª¨ë‘ ìˆ˜í–‰í•˜ëŠ” ì¡°í•©ëœ ì–´í† ë¯¹ | 528 | ê²ƒë“¤ë„ ì¡´ìž¬í•©ë‹ˆë‹¤. 로드와 ìŠ¤í† ì–´ë¥¼ ëª¨ë‘ ìˆ˜í–‰í•˜ëŠ” ì¡°í•©ëœ ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜ì—서, |
| 529 | 오í¼ë ˆì´ì…˜ì—서, ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³ RELEASE 는 | 529 | ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³ RELEASE 는 해당 |
| 530 | 해당 오í¼ë ˆì´ì…˜ì˜ ìŠ¤í† ì–´ 부분ì—ë§Œ ì ìš©ë©ë‹ˆë‹¤. | 530 | 오í¼ë ˆì´ì…˜ì˜ ìŠ¤í† ì–´ 부분ì—ë§Œ ì ìš©ë©ë‹ˆë‹¤. |
| 531 | 531 | ||
| 532 | 메모리 ë°°ë¦¬ì–´ë“¤ì€ ë‘ CPU ê°„, ë˜ëŠ” CPU 와 디바ì´ìФ ê°„ì— ìƒí˜¸ìž‘ìš©ì˜ ê°€ëŠ¥ì„±ì´ ìžˆì„ | 532 | 메모리 ë°°ë¦¬ì–´ë“¤ì€ ë‘ CPU ê°„, ë˜ëŠ” CPU 와 디바ì´ìФ ê°„ì— ìƒí˜¸ìž‘ìš©ì˜ ê°€ëŠ¥ì„±ì´ ìžˆì„ |
| 533 | 때ì—ë§Œ 필요합니다. 만약 ì–´ë–¤ ì½”ë“œì— ê·¸ëŸ° ìƒí˜¸ìž‘ìš©ì´ ì—†ì„ ê²ƒì´ ë³´ìž¥ëœë‹¤ë©´, 해당 | 533 | 때ì—ë§Œ 필요합니다. 만약 ì–´ë–¤ ì½”ë“œì— ê·¸ëŸ° ìƒí˜¸ìž‘ìš©ì´ ì—†ì„ ê²ƒì´ ë³´ìž¥ëœë‹¤ë©´, 해당 |
| @@ -617,7 +617,22 @@ RELEASE ë¶€ë¥˜ì˜ ê²ƒë“¤ë„ ì¡´ìž¬í•©ë‹ˆë‹¤. 로드와 ìŠ¤í† ì–´ë¥¼ ëª¨ë‘ ìˆ˜í | |||
| 617 | ì´ ë³€ê²½ì€ ì•žì˜ ì²˜ìŒ ë‘가지 ê²°ê³¼ 중 í•˜ë‚˜ë§Œì´ ë°œìƒí• 수 ìžˆê³ , ì„¸ë²ˆì§¸ì˜ ê²°ê³¼ëŠ” | 617 | ì´ ë³€ê²½ì€ ì•žì˜ ì²˜ìŒ ë‘가지 ê²°ê³¼ 중 í•˜ë‚˜ë§Œì´ ë°œìƒí• 수 ìžˆê³ , ì„¸ë²ˆì§¸ì˜ ê²°ê³¼ëŠ” |
| 618 | ë°œìƒí• 수 ì—†ë„ë¡ í•©ë‹ˆë‹¤. | 618 | ë°œìƒí• 수 ì—†ë„ë¡ í•©ë‹ˆë‹¤. |
| 619 | 619 | ||
| 620 | ë°ì´í„° ì˜ì¡´ì„± 배리어는 ì˜ì¡´ì ì“°ê¸°ì— ëŒ€í•´ì„œë„ ìˆœì„œë¥¼ 잡아ì¤ë‹ˆë‹¤: | 620 | |
| 621 | [!] ì´ ìƒë‹¹ížˆ ë°˜ì§ê´€ì ì¸ ìƒí™©ì€ ë¶„ë¦¬ëœ ìºì‹œë¥¼ 가지는 기계들ì—서 가장 잘 | ||
| 622 | ë°œìƒí•˜ëŠ”ë°, 예를 들면 한 ìºì‹œ ë±…í¬ëŠ” ì§ìˆ˜ ë²ˆí˜¸ì˜ ìºì‹œ ë¼ì¸ë“¤ì„ ì²˜ë¦¬í•˜ê³ , 다른 | ||
| 623 | ë±…í¬ëŠ” 홀수 ë²ˆí˜¸ì˜ ìºì‹œ ë¼ì¸ë“¤ì„ 처리하는 ê²½ìš°ìž„ì„ ì•Œì•„ë‘시기 ë°”ëžë‹ˆë‹¤. í¬ì¸í„° | ||
| 624 | P 는 ì§ìˆ˜ 번호 ìºì‹œ ë¼ì¸ì— ì €ìž¥ë˜ì–´ ìžˆê³ , 변수 B 는 홀수 번호 ìºì‹œ ë¼ì¸ì— | ||
| 625 | ì €ìž¥ë˜ì–´ ìžˆì„ ìˆ˜ 있습니다. 여기서 ê°’ì„ ì½ì–´ì˜¤ëŠ” CPU ì˜ ìºì‹œì˜ 홀수 번호 처리 | ||
| 626 | ë±…í¬ëŠ” 열심히 ì¼ê°ì„ ì²˜ë¦¬ì¤‘ì¸ ë°˜ë©´ 홀수 번호 처리 ë±…í¬ëŠ” í• ì¼ ì—†ì´ í•œê°€í•œ | ||
| 627 | 중ì´ë¼ë©´ í¬ì¸í„° P (&B) ì˜ ìƒˆë¡œìš´ ê°’ê³¼ 변수 B ì˜ ê¸°ì¡´ ê°’ (2) 를 ë³¼ 수 있습니다. | ||
| 628 | |||
| 629 | |||
| 630 | ì˜ì¡´ì ì“°ê¸°ë“¤ì˜ ìˆœì„œë¥¼ 맞추는ë°ì—는 ë°ì´í„° ì˜ì¡´ì„± 배리어가 필요치 않ì€ë°, ì´ëŠ” | ||
| 631 | 리눅스 커ë„ì´ ì§€ì›í•˜ëŠ” CPU ë“¤ì€ (1) 쓰기가 ì •ë§ë¡œ ì¼ì–´ë‚ ì§€, (2) 쓰기가 ì–´ë””ì— | ||
| 632 | ì´ë£¨ì–´ì§ˆì§€, ê·¸ë¦¬ê³ (3) 쓰여질 ê°’ì„ í™•ì‹¤ížˆ 알기 ì „ê¹Œì§€ëŠ” 쓰기를 수행하지 않기 | ||
| 633 | 때문입니다. 하지만 "컨트롤 ì˜ì¡´ì„±" 섹션과 | ||
| 634 | Documentation/RCU/rcu_dereference.txt 파ì¼ì„ ì£¼ì˜ ê¹Šê²Œ ì½ì–´ 주시기 ë°”ëžë‹ˆë‹¤: | ||
| 635 | 컴파ì¼ëŸ¬ëŠ” 매우 ì°½ì˜ì ì¸ ë§Žì€ ë°©ë²•ìœ¼ë¡œ 종ì†ì„±ì„ ê¹° 수 있습니다. | ||
| 621 | 636 | ||
| 622 | CPU 1 CPU 2 | 637 | CPU 1 CPU 2 |
| 623 | =============== =============== | 638 | =============== =============== |
| @@ -626,28 +641,19 @@ RELEASE ë¶€ë¥˜ì˜ ê²ƒë“¤ë„ ì¡´ìž¬í•©ë‹ˆë‹¤. 로드와 ìŠ¤í† ì–´ë¥¼ ëª¨ë‘ ìˆ˜í | |||
| 626 | <쓰기 배리어> | 641 | <쓰기 배리어> |
| 627 | WRITE_ONCE(P, &B); | 642 | WRITE_ONCE(P, &B); |
| 628 | Q = READ_ONCE(P); | 643 | Q = READ_ONCE(P); |
| 629 | <ë°ì´í„° ì˜ì¡´ì„± 배리어> | 644 | WRITE_ONCE(*Q, 5); |
| 630 | *Q = 5; | ||
| 631 | 645 | ||
| 632 | ì´ ë°ì´í„° ì˜ì¡´ì„± 배리어는 Q ë¡œì˜ ì½ê¸°ê°€ *Q ë¡œì˜ ìŠ¤í† ì–´ì™€ 순서를 맞추게 | 646 | ë”°ë¼ì„œ, Q ë¡œì˜ ì½ê¸°ì™€ *Q ë¡œì˜ ì“°ê¸° 사ì´ì—는 ë°ì´í„° 종ì†ì„± 배리어가 필요치 |
| 633 | í•´ì¤ë‹ˆë‹¤. ì´ëŠ” 다ìŒê³¼ ê°™ì€ ê²°ê³¼ë¥¼ 막습니다: | 647 | 않습니다. 달리 ë§í•˜ë©´, ë°ì´í„° 종ì†ì„± 배리어가 ì—†ë”ë¼ë„ ë‹¤ìŒ ê²°ê³¼ëŠ” ìƒê¸°ì§€ |
| 648 | 않습니다: | ||
| 634 | 649 | ||
| 635 | (Q == &B) && (B == 4) | 650 | (Q == &B) && (B == 4) |
| 636 | 651 | ||
| 637 | ì´ëŸ° íŒ¨í„´ì€ ë“œë¬¼ê²Œ 사용ë˜ì–´ì•¼ í•¨ì„ ì•Œì•„ ë‘시기 ë°”ëžë‹ˆë‹¤. 무엇보다ë„, ì˜ì¡´ì„± | 652 | ì´ëŸ° íŒ¨í„´ì€ ë“œë¬¼ê²Œ 사용ë˜ì–´ì•¼ í•¨ì„ ì•Œì•„ ë‘시기 ë°”ëžë‹ˆë‹¤. 무엇보다ë„, ì˜ì¡´ì„± |
| 638 | 순서 ê·œì¹™ì˜ ì˜ë„는 쓰기 ìž‘ì—…ì„ -예방- 해서 그로 ì¸í•´ ë°œìƒí•˜ëŠ” 비싼 ìºì‹œ ë¯¸ìŠ¤ë„ | 653 | 순서 ê·œì¹™ì˜ ì˜ë„는 쓰기 ìž‘ì—…ì„ -예방- 해서 그로 ì¸í•´ ë°œìƒí•˜ëŠ” 비싼 ìºì‹œ ë¯¸ìŠ¤ë„ |
| 639 | ì—†ì• ë ¤ëŠ” 것입니다. ì´ íŒ¨í„´ì€ ë“œë¬¼ê²Œ ë°œìƒí•˜ëŠ” ì—러 ì¡°ê±´ ê°™ì€ê²ƒë“¤ì„ 기ë¡í•˜ëŠ”ë° | 654 | ì—†ì• ë ¤ëŠ” 것입니다. ì´ íŒ¨í„´ì€ ë“œë¬¼ê²Œ ë°œìƒí•˜ëŠ” ì—러 ì¡°ê±´ ê°™ì€ê²ƒë“¤ì„ 기ë¡í•˜ëŠ”ë° |
| 640 | 사용ë 수 ìžˆê³ , ì´ë ‡ê²Œ 배리어를 사용해 순서를 지키게 í•¨ìœ¼ë¡œì¨ ê·¸ëŸ° 기ë¡ì´ | 655 | 사용ë 수 있으며, CPUì˜ ìžì—°ì ì¸ ìˆœì„œ ë³´ìž¥ì´ ê·¸ëŸ° 기ë¡ë“¤ì„ 사ë¼ì§€ì§€ 않게 |
| 641 | 사ë¼ì§€ëŠ” ê²ƒì„ ë§‰ìŠµë‹ˆë‹¤. | 656 | í•´ì¤ë‹ˆë‹¤. |
| 642 | |||
| 643 | |||
| 644 | [!] ìƒë‹¹ížˆ 비ì§ê´€ì ì¸ ì´ ìƒí™©ì€ ë¶„ë¦¬ëœ ìºì‹œë¥¼ 가진 기계, 예를 들어 한 ìºì‹œ | ||
| 645 | ë±…í¬ê°€ ì§ìˆ˜ë²ˆ ìºì‹œ ë¼ì¸ì„ ì²˜ë¦¬í•˜ê³ ë‹¤ë¥¸ ë±…í¬ëŠ” 홀수번 ìºì‹œ ë¼ì¸ì„ 처리하는 기계 | ||
| 646 | 등ì—서 가장 잘 ë°œìƒí•©ë‹ˆë‹¤. í¬ì¸í„° P 는 홀수 ë²ˆí˜¸ì˜ ìºì‹œ ë¼ì¸ì— ìžˆê³ , 변수 B 는 | ||
| 647 | ì§ìˆ˜ 번호 ìºì‹œ ë¼ì¸ì— ìžˆë‹¤ê³ ìƒê°í•´ 봅시다. 그런 ìƒíƒœì—서 ì½ê¸° ìž‘ì—…ì„ í•˜ëŠ” CPU | ||
| 648 | ì˜ ì§ìˆ˜ë²ˆ ë±…í¬ëŠ” í• ì¼ì´ 쌓여 매우 ë°”ì˜ì§€ë§Œ 홀수번 ë±…í¬ëŠ” í• ì¼ì´ 없어 아무 | ||
| 649 | ì¼ë„ 하지 ì•Šê³ ìžˆì—ˆë‹¤ë©´, í¬ì¸í„° P 는 새 ê°’ (&B) ì„, ê·¸ë¦¬ê³ ë³€ìˆ˜ B 는 ì˜›ë‚ ê°’ | ||
| 650 | (2) ì„ ê°€ì§€ê³ ìžˆëŠ” ìƒíƒœê°€ 보여질 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. | ||
| 651 | 657 | ||
| 652 | 658 | ||
| 653 | ë°ì´í„° ì˜ì¡´ì„± 배리어는 매우 중요한ë°, 예를 들어 RCU 시스템ì—서 ê·¸ë ‡ìŠµë‹ˆë‹¤. | 659 | ë°ì´í„° ì˜ì¡´ì„± 배리어는 매우 중요한ë°, 예를 들어 RCU 시스템ì—서 ê·¸ë ‡ìŠµë‹ˆë‹¤. |
| @@ -1848,8 +1854,7 @@ Mandatory ë°°ë¦¬ì–´ë“¤ì€ SMP 시스템ì—ì„œë„ UP 시스템ì—ì„œë„ SMP íš¨ê³ | |||
| 1848 | ì´ ì½”ë“œëŠ” ê°ì²´ì˜ ì—…ë°ì´íŠ¸ëœ death 마í¬ê°€ ë ˆí¼ëŸ°ìФ ì¹´ìš´í„° ê°ì†Œ ë™ìž‘ | 1854 | ì´ ì½”ë“œëŠ” ê°ì²´ì˜ ì—…ë°ì´íŠ¸ëœ death 마í¬ê°€ ë ˆí¼ëŸ°ìФ ì¹´ìš´í„° ê°ì†Œ ë™ìž‘ |
| 1849 | *ì „ì—* ë³´ì¼ ê²ƒì„ ë³´ìž¥í•©ë‹ˆë‹¤. | 1855 | *ì „ì—* ë³´ì¼ ê²ƒì„ ë³´ìž¥í•©ë‹ˆë‹¤. |
| 1850 | 1856 | ||
| 1851 | ë” ë§Žì€ ì •ë³´ë¥¼ ìœ„í•´ì„ Documentation/core-api/atomic_ops.rst 문서를 ì°¸ê³ í•˜ì„¸ìš”. | 1857 | ë” ë§Žì€ ì •ë³´ë¥¼ ìœ„í•´ì„ Documentation/atomic_{t,bitops}.txt 문서를 |
| 1852 | 어디서 ì´ê²ƒë“¤ì„ 사용해야 í• ì§€ ê¶ê¸ˆí•˜ë‹¤ë©´ "ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜" ì„œë¸Œì„¹ì…˜ì„ | ||
| 1853 | ì°¸ê³ í•˜ì„¸ìš”. | 1858 | ì°¸ê³ í•˜ì„¸ìš”. |
| 1854 | 1859 | ||
| 1855 | 1860 | ||
| @@ -2468,86 +2473,7 @@ _않습니다_. | |||
| 2468 | ì „ì²´ 메모리 배리어를 ë‚´í¬í•˜ê³ ë˜ ì¼ë¶€ëŠ” ë‚´í¬í•˜ì§€ 않지만, 커ë„ì—서 ìƒë‹¹ížˆ | 2473 | ì „ì²´ 메모리 배리어를 ë‚´í¬í•˜ê³ ë˜ ì¼ë¶€ëŠ” ë‚´í¬í•˜ì§€ 않지만, 커ë„ì—서 ìƒë‹¹ížˆ |
| 2469 | ì˜ì¡´ì 으로 사용하는 기능 중 하나입니다. | 2474 | ì˜ì¡´ì 으로 사용하는 기능 중 하나입니다. |
| 2470 | 2475 | ||
| 2471 | ë©”ëª¨ë¦¬ì˜ ì–´ë–¤ ìƒíƒœë¥¼ ìˆ˜ì •í•˜ê³ í•´ë‹¹ ìƒíƒœì— 대한 (ì˜ˆì „ì˜ ë˜ëŠ” ìµœì‹ ì˜) ì •ë³´ë¥¼ | 2476 | ë” ë§Žì€ ë‚´ìš©ì„ ìœ„í•´ì„ Documentation/atomic_t.txt 를 ì°¸ê³ í•˜ì„¸ìš”. |
| 2472 | 리턴하는 ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜ì€ ëª¨ë‘ SMP-ì¡°ê±´ì 범용 메모리 배리어(smp_mb())를 | ||
| 2473 | ì‹¤ì œ 오í¼ë ˆì´ì…˜ì˜ 앞과 ë’¤ì— ë‚´í¬í•©ë‹ˆë‹¤. ì´ëŸ° 오í¼ë ˆì´ì…˜ì€ 다ìŒì˜ ê²ƒë“¤ì„ | ||
| 2474 | í¬í•¨í•©ë‹ˆë‹¤: | ||
| 2475 | |||
| 2476 | xchg(); | ||
| 2477 | atomic_xchg(); atomic_long_xchg(); | ||
| 2478 | atomic_inc_return(); atomic_long_inc_return(); | ||
| 2479 | atomic_dec_return(); atomic_long_dec_return(); | ||
| 2480 | atomic_add_return(); atomic_long_add_return(); | ||
| 2481 | atomic_sub_return(); atomic_long_sub_return(); | ||
| 2482 | atomic_inc_and_test(); atomic_long_inc_and_test(); | ||
| 2483 | atomic_dec_and_test(); atomic_long_dec_and_test(); | ||
| 2484 | atomic_sub_and_test(); atomic_long_sub_and_test(); | ||
| 2485 | atomic_add_negative(); atomic_long_add_negative(); | ||
| 2486 | test_and_set_bit(); | ||
| 2487 | test_and_clear_bit(); | ||
| 2488 | test_and_change_bit(); | ||
| 2489 | |||
| 2490 | /* exchange ì¡°ê±´ì´ ì„±ê³µí• ë•Œ */ | ||
| 2491 | cmpxchg(); | ||
| 2492 | atomic_cmpxchg(); atomic_long_cmpxchg(); | ||
| 2493 | atomic_add_unless(); atomic_long_add_unless(); | ||
| 2494 | |||
| 2495 | ì´ê²ƒë“¤ì€ 메모리 배리어 효과가 필요한 ACQUIRE 부류와 RELEASE 부류 오í¼ë ˆì´ì…˜ë“¤ì„ | ||
| 2496 | êµ¬í˜„í• ë•Œ, ê·¸ë¦¬ê³ ê°ì²´ í•´ì œë¥¼ 위해 ë ˆí¼ëŸ°ìФ 카운터를 ì¡°ì •í• ë•Œ, 암묵ì 메모리 | ||
| 2497 | 배리어 효과가 필요한 ê³³ ë“±ì— ì‚¬ìš©ë©ë‹ˆë‹¤. | ||
| 2498 | |||
| 2499 | |||
| 2500 | 다ìŒì˜ 오í¼ë ˆì´ì…˜ë“¤ì€ 메모리 배리어를 ë‚´í¬í•˜ì§€ _않기_ ë•Œë¬¸ì— ë¬¸ì œê°€ ë 수 | ||
| 2501 | 있지만, RELEASE ë¶€ë¥˜ì˜ ì˜¤í¼ë ˆì´ì…˜ë“¤ê³¼ ê°™ì€ ê²ƒë“¤ì„ êµ¬í˜„í• ë•Œ 사용ë ìˆ˜ë„ | ||
| 2502 | 있습니다: | ||
| 2503 | |||
| 2504 | atomic_set(); | ||
| 2505 | set_bit(); | ||
| 2506 | clear_bit(); | ||
| 2507 | change_bit(); | ||
| 2508 | |||
| 2509 | ì´ê²ƒë“¤ì„ ì‚¬ìš©í• ë•Œì—는 필요하다면 ì ì ˆí•œ (예를 들면 smp_mb__before_atomic() | ||
| 2510 | ê°™ì€) 메모리 배리어가 명시ì 으로 함께 사용ë˜ì–´ì•¼ 합니다. | ||
| 2511 | |||
| 2512 | |||
| 2513 | ì•„ëž˜ì˜ ê²ƒë“¤ë„ ë©”ëª¨ë¦¬ 배리어를 ë‚´í¬í•˜ì§€ _않기_ 때문ì—, ì¼ë¶€ 환경ì—서는 (예를 | ||
| 2514 | 들면 smp_mb__before_atomic() ê³¼ ê°™ì€) 명시ì ì¸ ë©”ëª¨ë¦¬ 배리어 ì‚¬ìš©ì´ í•„ìš”í•©ë‹ˆë‹¤. | ||
| 2515 | |||
| 2516 | atomic_add(); | ||
| 2517 | atomic_sub(); | ||
| 2518 | atomic_inc(); | ||
| 2519 | atomic_dec(); | ||
| 2520 | |||
| 2521 | ì´ê²ƒë“¤ì´ 통계 ìƒì„±ì„ 위해 사용ëœë‹¤ë©´, ê·¸ë¦¬ê³ í†µê³„ ë°ì´í„° 사ì´ì— 관계가 존재하지 | ||
| 2522 | 않는다면 메모리 배리어는 필요치 ì•Šì„ ê²ë‹ˆë‹¤. | ||
| 2523 | |||
| 2524 | ê°ì²´ì˜ ìˆ˜ëª…ì„ ê´€ë¦¬í•˜ê¸° 위해 ë ˆí¼ëŸ°ìФ 카운팅 목ì 으로 사용ëœë‹¤ë©´, ë ˆí¼ëŸ°ìФ | ||
| 2525 | 카운터는 ë½ìœ¼ë¡œ 보호ë˜ëŠ” 섹션ì—서만 ì¡°ì •ë˜ê±°ë‚˜ 호출하는 ìª½ì´ ì´ë¯¸ 충분한 | ||
| 2526 | ë ˆí¼ëŸ°ìŠ¤ë¥¼ ìž¡ê³ ìžˆì„ ê²ƒì´ê¸° ë•Œë¬¸ì— ë©”ëª¨ë¦¬ 배리어는 아마 í•„ìš” ì—†ì„ ê²ë‹ˆë‹¤. | ||
| 2527 | |||
| 2528 | 만약 ì–´ë–¤ ë½ì„ 구성하기 위해 사용ëœë‹¤ë©´, ë½ ê´€ë ¨ ë™ìž‘ì€ ì¼ë°˜ì 으로 ìž‘ì—…ì„ íŠ¹ì • | ||
| 2529 | 순서대로 진행해야 하므로 메모리 배리어가 í•„ìš”í• ìˆ˜ 있습니다. | ||
| 2530 | |||
| 2531 | 기본ì 으로, ê° ì‚¬ìš©ì²˜ì—서는 메모리 배리어가 필요한지 아닌지 충분히 ê³ ë ¤í•´ì•¼ | ||
| 2532 | 합니다. | ||
| 2533 | |||
| 2534 | ì•„ëž˜ì˜ ì˜¤í¼ë ˆì´ì…˜ë“¤ì€ 특별한 ë½ ê´€ë ¨ ë™ìž‘들입니다: | ||
| 2535 | |||
| 2536 | test_and_set_bit_lock(); | ||
| 2537 | clear_bit_unlock(); | ||
| 2538 | __clear_bit_unlock(); | ||
| 2539 | |||
| 2540 | ì´ê²ƒë“¤ì€ ACQUIRE 류와 RELEASE ë¥˜ì˜ ì˜¤í¼ë ˆì´ì…˜ë“¤ì„ 구현합니다. ë½ ê´€ë ¨ ë„구를 | ||
| 2541 | êµ¬í˜„í• ë•Œì—는 ì´ê²ƒë“¤ì„ 좀 ë” ì„ í˜¸í•˜ëŠ” íŽ¸ì´ ë‚˜ì€ë°, ì´ê²ƒë“¤ì˜ êµ¬í˜„ì€ ë§Žì€ | ||
| 2542 | 아키í…ì³ì—서 최ì í™” ë 수 있기 때문입니다. | ||
| 2543 | |||
| 2544 | [!] ì´ëŸ° ìƒí™©ì— ì‚¬ìš©í• ìˆ˜ 있는 특수한 메모리 배리어 ë„êµ¬ë“¤ì´ ìžˆìŠµë‹ˆë‹¤ë§Œ, ì¼ë¶€ | ||
| 2545 | CPU ì—서는 사용ë˜ëŠ” ì–´í† ë¯¹ ì¸ìŠ¤íŠ¸ëŸì…˜ ìžì²´ì— 메모리 배리어가 ë‚´í¬ë˜ì–´ 있어서 | ||
| 2546 | ì–´í† ë¯¹ 오í¼ë ˆì´ì…˜ê³¼ 메모리 배리어를 함께 사용하는 게 불필요한 ì¼ì´ ë 수 | ||
| 2547 | 있는ë°, 그런 ê²½ìš°ì— ì´ íŠ¹ìˆ˜ 메모리 배리어 ë„êµ¬ë“¤ì€ no-op ì´ ë˜ì–´ 실질ì 으로 | ||
| 2548 | 아무ì¼ë„ 하지 않습니다. | ||
| 2549 | |||
| 2550 | ë” ë§Žì€ ë‚´ìš©ì„ ìœ„í•´ì„ Documentation/core-api/atomic_ops.rst 를 ì°¸ê³ í•˜ì„¸ìš”. | ||
| 2551 | 2477 | ||
| 2552 | 2478 | ||
| 2553 | 디바ì´ìФ 액세스 | 2479 | 디바ì´ìФ 액세스 |
diff --git a/MAINTAINERS b/MAINTAINERS index 14e76a41b302..209306019483 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -855,6 +855,12 @@ S: Supported | |||
| 855 | F: drivers/android/ | 855 | F: drivers/android/ |
| 856 | F: drivers/staging/android/ | 856 | F: drivers/staging/android/ |
| 857 | 857 | ||
| 858 | ANDROID GOLDFISH RTC DRIVER | ||
| 859 | M: Miodrag Dinic <miodrag.dinic@imgtec.com> | ||
| 860 | S: Supported | ||
| 861 | F: Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt | ||
| 862 | F: drivers/rtc/rtc-goldfish.c | ||
| 863 | |||
| 858 | ANDROID ION DRIVER | 864 | ANDROID ION DRIVER |
| 859 | M: Laura Abbott <labbott@redhat.com> | 865 | M: Laura Abbott <labbott@redhat.com> |
| 860 | M: Sumit Semwal <sumit.semwal@linaro.org> | 866 | M: Sumit Semwal <sumit.semwal@linaro.org> |
| @@ -4385,6 +4391,12 @@ S: Supported | |||
| 4385 | F: drivers/gpu/drm/nouveau/ | 4391 | F: drivers/gpu/drm/nouveau/ |
| 4386 | F: include/uapi/drm/nouveau_drm.h | 4392 | F: include/uapi/drm/nouveau_drm.h |
| 4387 | 4393 | ||
| 4394 | DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS | ||
| 4395 | M: Noralf Trønnes <noralf@tronnes.org> | ||
| 4396 | S: Maintained | ||
| 4397 | F: drivers/gpu/drm/tinydrm/repaper.c | ||
| 4398 | F: Documentation/devicetree/bindings/display/repaper.txt | ||
| 4399 | |||
| 4388 | DRM DRIVER FOR QEMU'S CIRRUS DEVICE | 4400 | DRM DRIVER FOR QEMU'S CIRRUS DEVICE |
| 4389 | M: Dave Airlie <airlied@redhat.com> | 4401 | M: Dave Airlie <airlied@redhat.com> |
| 4390 | M: Gerd Hoffmann <kraxel@redhat.com> | 4402 | M: Gerd Hoffmann <kraxel@redhat.com> |
| @@ -4403,12 +4415,6 @@ S: Maintained | |||
| 4403 | F: drivers/gpu/drm/qxl/ | 4415 | F: drivers/gpu/drm/qxl/ |
| 4404 | F: include/uapi/drm/qxl_drm.h | 4416 | F: include/uapi/drm/qxl_drm.h |
| 4405 | 4417 | ||
| 4406 | DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS | ||
| 4407 | M: Noralf Trønnes <noralf@tronnes.org> | ||
| 4408 | S: Maintained | ||
| 4409 | F: drivers/gpu/drm/tinydrm/repaper.c | ||
| 4410 | F: Documentation/devicetree/bindings/display/repaper.txt | ||
| 4411 | |||
| 4412 | DRM DRIVER FOR RAGE 128 VIDEO CARDS | 4418 | DRM DRIVER FOR RAGE 128 VIDEO CARDS |
| 4413 | S: Orphan / Obsolete | 4419 | S: Orphan / Obsolete |
| 4414 | F: drivers/gpu/drm/r128/ | 4420 | F: drivers/gpu/drm/r128/ |
| @@ -6202,22 +6208,22 @@ F: include/uapi/linux/if_hippi.h | |||
| 6202 | F: net/802/hippi.c | 6208 | F: net/802/hippi.c |
| 6203 | F: drivers/net/hippi/ | 6209 | F: drivers/net/hippi/ |
| 6204 | 6210 | ||
| 6205 | HISILICON NETWORK SUBSYSTEM DRIVER | 6211 | HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3) |
| 6206 | M: Yisen Zhuang <yisen.zhuang@huawei.com> | 6212 | M: Yisen Zhuang <yisen.zhuang@huawei.com> |
| 6207 | M: Salil Mehta <salil.mehta@huawei.com> | 6213 | M: Salil Mehta <salil.mehta@huawei.com> |
| 6208 | L: netdev@vger.kernel.org | 6214 | L: netdev@vger.kernel.org |
| 6209 | W: http://www.hisilicon.com | 6215 | W: http://www.hisilicon.com |
| 6210 | S: Maintained | 6216 | S: Maintained |
| 6211 | F: drivers/net/ethernet/hisilicon/ | 6217 | F: drivers/net/ethernet/hisilicon/hns3/ |
| 6212 | F: Documentation/devicetree/bindings/net/hisilicon*.txt | ||
| 6213 | 6218 | ||
| 6214 | HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3) | 6219 | HISILICON NETWORK SUBSYSTEM DRIVER |
| 6215 | M: Yisen Zhuang <yisen.zhuang@huawei.com> | 6220 | M: Yisen Zhuang <yisen.zhuang@huawei.com> |
| 6216 | M: Salil Mehta <salil.mehta@huawei.com> | 6221 | M: Salil Mehta <salil.mehta@huawei.com> |
| 6217 | L: netdev@vger.kernel.org | 6222 | L: netdev@vger.kernel.org |
| 6218 | W: http://www.hisilicon.com | 6223 | W: http://www.hisilicon.com |
| 6219 | S: Maintained | 6224 | S: Maintained |
| 6220 | F: drivers/net/ethernet/hisilicon/hns3/ | 6225 | F: drivers/net/ethernet/hisilicon/ |
| 6226 | F: Documentation/devicetree/bindings/net/hisilicon*.txt | ||
| 6221 | 6227 | ||
| 6222 | HISILICON ROCE DRIVER | 6228 | HISILICON ROCE DRIVER |
| 6223 | M: Lijun Ou <oulijun@huawei.com> | 6229 | M: Lijun Ou <oulijun@huawei.com> |
| @@ -6234,6 +6240,13 @@ S: Supported | |||
| 6234 | F: drivers/scsi/hisi_sas/ | 6240 | F: drivers/scsi/hisi_sas/ |
| 6235 | F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 6241 | F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt |
| 6236 | 6242 | ||
| 6243 | HMM - Heterogeneous Memory Management | ||
| 6244 | M: Jérôme Glisse <jglisse@redhat.com> | ||
| 6245 | L: linux-mm@kvack.org | ||
| 6246 | S: Maintained | ||
| 6247 | F: mm/hmm* | ||
| 6248 | F: include/linux/hmm* | ||
| 6249 | |||
| 6237 | HOST AP DRIVER | 6250 | HOST AP DRIVER |
| 6238 | M: Jouni Malinen <j@w1.fi> | 6251 | M: Jouni Malinen <j@w1.fi> |
| 6239 | L: linux-wireless@vger.kernel.org | 6252 | L: linux-wireless@vger.kernel.org |
| @@ -7500,19 +7513,6 @@ F: include/kvm/iodev.h | |||
| 7500 | F: virt/kvm/* | 7513 | F: virt/kvm/* |
| 7501 | F: tools/kvm/ | 7514 | F: tools/kvm/ |
| 7502 | 7515 | ||
| 7503 | KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86) | ||
| 7504 | M: Paolo Bonzini <pbonzini@redhat.com> | ||
| 7505 | M: Radim KrÄmář <rkrcmar@redhat.com> | ||
| 7506 | L: kvm@vger.kernel.org | ||
| 7507 | W: http://www.linux-kvm.org | ||
| 7508 | T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git | ||
| 7509 | S: Supported | ||
| 7510 | F: arch/x86/kvm/ | ||
| 7511 | F: arch/x86/include/uapi/asm/kvm* | ||
| 7512 | F: arch/x86/include/asm/kvm* | ||
| 7513 | F: arch/x86/kernel/kvm.c | ||
| 7514 | F: arch/x86/kernel/kvmclock.c | ||
| 7515 | |||
| 7516 | KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd) | 7516 | KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd) |
| 7517 | M: Joerg Roedel <joro@8bytes.org> | 7517 | M: Joerg Roedel <joro@8bytes.org> |
| 7518 | L: kvm@vger.kernel.org | 7518 | L: kvm@vger.kernel.org |
| @@ -7535,17 +7535,6 @@ F: arch/arm/kvm/ | |||
| 7535 | F: virt/kvm/arm/ | 7535 | F: virt/kvm/arm/ |
| 7536 | F: include/kvm/arm_* | 7536 | F: include/kvm/arm_* |
| 7537 | 7537 | ||
| 7538 | KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc) | ||
| 7539 | M: Alexander Graf <agraf@suse.com> | ||
| 7540 | L: kvm-ppc@vger.kernel.org | ||
| 7541 | W: http://www.linux-kvm.org/ | ||
| 7542 | T: git git://github.com/agraf/linux-2.6.git | ||
| 7543 | S: Supported | ||
| 7544 | F: arch/powerpc/include/uapi/asm/kvm* | ||
| 7545 | F: arch/powerpc/include/asm/kvm* | ||
| 7546 | F: arch/powerpc/kvm/ | ||
| 7547 | F: arch/powerpc/kernel/kvm* | ||
| 7548 | |||
| 7549 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) | 7538 | KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64) |
| 7550 | M: Christoffer Dall <christoffer.dall@linaro.org> | 7539 | M: Christoffer Dall <christoffer.dall@linaro.org> |
| 7551 | M: Marc Zyngier <marc.zyngier@arm.com> | 7540 | M: Marc Zyngier <marc.zyngier@arm.com> |
| @@ -7564,6 +7553,17 @@ F: arch/mips/include/uapi/asm/kvm* | |||
| 7564 | F: arch/mips/include/asm/kvm* | 7553 | F: arch/mips/include/asm/kvm* |
| 7565 | F: arch/mips/kvm/ | 7554 | F: arch/mips/kvm/ |
| 7566 | 7555 | ||
| 7556 | KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc) | ||
| 7557 | M: Alexander Graf <agraf@suse.com> | ||
| 7558 | L: kvm-ppc@vger.kernel.org | ||
| 7559 | W: http://www.linux-kvm.org/ | ||
| 7560 | T: git git://github.com/agraf/linux-2.6.git | ||
| 7561 | S: Supported | ||
| 7562 | F: arch/powerpc/include/uapi/asm/kvm* | ||
| 7563 | F: arch/powerpc/include/asm/kvm* | ||
| 7564 | F: arch/powerpc/kvm/ | ||
| 7565 | F: arch/powerpc/kernel/kvm* | ||
| 7566 | |||
| 7567 | KERNEL VIRTUAL MACHINE for s390 (KVM/s390) | 7567 | KERNEL VIRTUAL MACHINE for s390 (KVM/s390) |
| 7568 | M: Christian Borntraeger <borntraeger@de.ibm.com> | 7568 | M: Christian Borntraeger <borntraeger@de.ibm.com> |
| 7569 | M: Cornelia Huck <cohuck@redhat.com> | 7569 | M: Cornelia Huck <cohuck@redhat.com> |
| @@ -7577,6 +7577,19 @@ F: arch/s390/include/asm/kvm* | |||
| 7577 | F: arch/s390/kvm/ | 7577 | F: arch/s390/kvm/ |
| 7578 | F: arch/s390/mm/gmap.c | 7578 | F: arch/s390/mm/gmap.c |
| 7579 | 7579 | ||
| 7580 | KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86) | ||
| 7581 | M: Paolo Bonzini <pbonzini@redhat.com> | ||
| 7582 | M: Radim KrÄmář <rkrcmar@redhat.com> | ||
| 7583 | L: kvm@vger.kernel.org | ||
| 7584 | W: http://www.linux-kvm.org | ||
| 7585 | T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git | ||
| 7586 | S: Supported | ||
| 7587 | F: arch/x86/kvm/ | ||
| 7588 | F: arch/x86/include/uapi/asm/kvm* | ||
| 7589 | F: arch/x86/include/asm/kvm* | ||
| 7590 | F: arch/x86/kernel/kvm.c | ||
| 7591 | F: arch/x86/kernel/kvmclock.c | ||
| 7592 | |||
| 7580 | KERNFS | 7593 | KERNFS |
| 7581 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 7594 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| 7582 | M: Tejun Heo <tj@kernel.org> | 7595 | M: Tejun Heo <tj@kernel.org> |
| @@ -7816,13 +7829,6 @@ M: Sasha Levin <alexander.levin@verizon.com> | |||
| 7816 | S: Maintained | 7829 | S: Maintained |
| 7817 | F: tools/lib/lockdep/ | 7830 | F: tools/lib/lockdep/ |
| 7818 | 7831 | ||
| 7819 | HMM - Heterogeneous Memory Management | ||
| 7820 | M: Jérôme Glisse <jglisse@redhat.com> | ||
| 7821 | L: linux-mm@kvack.org | ||
| 7822 | S: Maintained | ||
| 7823 | F: mm/hmm* | ||
| 7824 | F: include/linux/hmm* | ||
| 7825 | |||
| 7826 | LIBNVDIMM BLK: MMIO-APERTURE DRIVER | 7832 | LIBNVDIMM BLK: MMIO-APERTURE DRIVER |
| 7827 | M: Ross Zwisler <ross.zwisler@linux.intel.com> | 7833 | M: Ross Zwisler <ross.zwisler@linux.intel.com> |
| 7828 | L: linux-nvdimm@lists.01.org | 7834 | L: linux-nvdimm@lists.01.org |
| @@ -8417,6 +8423,14 @@ T: git git://linuxtv.org/media_tree.git | |||
| 8417 | S: Supported | 8423 | S: Supported |
| 8418 | F: drivers/media/dvb-frontends/cxd2841er* | 8424 | F: drivers/media/dvb-frontends/cxd2841er* |
| 8419 | 8425 | ||
| 8426 | MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES | ||
| 8427 | M: Daniel Scheller <d.scheller.oss@gmail.com> | ||
| 8428 | L: linux-media@vger.kernel.org | ||
| 8429 | W: https://linuxtv.org | ||
| 8430 | T: git git://linuxtv.org/media_tree.git | ||
| 8431 | S: Maintained | ||
| 8432 | F: drivers/media/pci/ddbridge/* | ||
| 8433 | |||
| 8420 | MEDIA DRIVERS FOR FREESCALE IMX | 8434 | MEDIA DRIVERS FOR FREESCALE IMX |
| 8421 | M: Steve Longerbeam <slongerbeam@gmail.com> | 8435 | M: Steve Longerbeam <slongerbeam@gmail.com> |
| 8422 | M: Philipp Zabel <p.zabel@pengutronix.de> | 8436 | M: Philipp Zabel <p.zabel@pengutronix.de> |
| @@ -8538,14 +8552,6 @@ T: git git://linuxtv.org/media_tree.git | |||
| 8538 | S: Maintained | 8552 | S: Maintained |
| 8539 | F: drivers/media/dvb-frontends/stv6111* | 8553 | F: drivers/media/dvb-frontends/stv6111* |
| 8540 | 8554 | ||
| 8541 | MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES | ||
| 8542 | M: Daniel Scheller <d.scheller.oss@gmail.com> | ||
| 8543 | L: linux-media@vger.kernel.org | ||
| 8544 | W: https://linuxtv.org | ||
| 8545 | T: git git://linuxtv.org/media_tree.git | ||
| 8546 | S: Maintained | ||
| 8547 | F: drivers/media/pci/ddbridge/* | ||
| 8548 | |||
| 8549 | MEDIA INPUT INFRASTRUCTURE (V4L/DVB) | 8555 | MEDIA INPUT INFRASTRUCTURE (V4L/DVB) |
| 8550 | M: Mauro Carvalho Chehab <mchehab@s-opensource.com> | 8556 | M: Mauro Carvalho Chehab <mchehab@s-opensource.com> |
| 8551 | M: Mauro Carvalho Chehab <mchehab@kernel.org> | 8557 | M: Mauro Carvalho Chehab <mchehab@kernel.org> |
| @@ -8569,6 +8575,11 @@ F: include/uapi/linux/meye.h | |||
| 8569 | F: include/uapi/linux/ivtv* | 8575 | F: include/uapi/linux/ivtv* |
| 8570 | F: include/uapi/linux/uvcvideo.h | 8576 | F: include/uapi/linux/uvcvideo.h |
| 8571 | 8577 | ||
| 8578 | MEDIATEK CIR DRIVER | ||
| 8579 | M: Sean Wang <sean.wang@mediatek.com> | ||
| 8580 | S: Maintained | ||
| 8581 | F: drivers/media/rc/mtk-cir.c | ||
| 8582 | |||
| 8572 | MEDIATEK ETHERNET DRIVER | 8583 | MEDIATEK ETHERNET DRIVER |
| 8573 | M: Felix Fietkau <nbd@openwrt.org> | 8584 | M: Felix Fietkau <nbd@openwrt.org> |
| 8574 | M: John Crispin <john@phrozen.org> | 8585 | M: John Crispin <john@phrozen.org> |
| @@ -8609,11 +8620,6 @@ L: linux-wireless@vger.kernel.org | |||
| 8609 | S: Maintained | 8620 | S: Maintained |
| 8610 | F: drivers/net/wireless/mediatek/mt7601u/ | 8621 | F: drivers/net/wireless/mediatek/mt7601u/ |
| 8611 | 8622 | ||
| 8612 | MEDIATEK CIR DRIVER | ||
| 8613 | M: Sean Wang <sean.wang@mediatek.com> | ||
| 8614 | S: Maintained | ||
| 8615 | F: drivers/media/rc/mtk-cir.c | ||
| 8616 | |||
| 8617 | MEDIATEK RANDOM NUMBER GENERATOR SUPPORT | 8623 | MEDIATEK RANDOM NUMBER GENERATOR SUPPORT |
| 8618 | M: Sean Wang <sean.wang@mediatek.com> | 8624 | M: Sean Wang <sean.wang@mediatek.com> |
| 8619 | S: Maintained | 8625 | S: Maintained |
| @@ -12836,6 +12842,18 @@ F: drivers/clocksource/arc_timer.c | |||
| 12836 | F: drivers/tty/serial/arc_uart.c | 12842 | F: drivers/tty/serial/arc_uart.c |
| 12837 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git | 12843 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git |
| 12838 | 12844 | ||
| 12845 | SYNOPSYS ARC HSDK SDP pll clock driver | ||
| 12846 | M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | ||
| 12847 | S: Supported | ||
| 12848 | F: drivers/clk/clk-hsdk-pll.c | ||
| 12849 | F: Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt | ||
| 12850 | |||
| 12851 | SYNOPSYS ARC SDP clock driver | ||
| 12852 | M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | ||
| 12853 | S: Supported | ||
| 12854 | F: drivers/clk/axs10x/* | ||
| 12855 | F: Documentation/devicetree/bindings/clock/snps,pll-clock.txt | ||
| 12856 | |||
| 12839 | SYNOPSYS ARC SDP platform support | 12857 | SYNOPSYS ARC SDP platform support |
| 12840 | M: Alexey Brodkin <abrodkin@synopsys.com> | 12858 | M: Alexey Brodkin <abrodkin@synopsys.com> |
| 12841 | S: Supported | 12859 | S: Supported |
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 195da38cb9a2..6d870421a7a6 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
| @@ -26,6 +26,7 @@ config SOC_SAMA5D2 | |||
| 26 | select HAVE_AT91_USB_CLK | 26 | select HAVE_AT91_USB_CLK |
| 27 | select HAVE_AT91_H32MX | 27 | select HAVE_AT91_H32MX |
| 28 | select HAVE_AT91_GENERATED_CLK | 28 | select HAVE_AT91_GENERATED_CLK |
| 29 | select HAVE_AT91_AUDIO_PLL | ||
| 29 | select PINCTRL_AT91PIO4 | 30 | select PINCTRL_AT91PIO4 |
| 30 | help | 31 | help |
| 31 | Select this if ou are using one of Atmel's SAMA5D2 family SoC. | 32 | Select this if ou are using one of Atmel's SAMA5D2 family SoC. |
| @@ -125,6 +126,9 @@ config HAVE_AT91_H32MX | |||
| 125 | config HAVE_AT91_GENERATED_CLK | 126 | config HAVE_AT91_GENERATED_CLK |
| 126 | bool | 127 | bool |
| 127 | 128 | ||
| 129 | config HAVE_AT91_AUDIO_PLL | ||
| 130 | bool | ||
| 131 | |||
| 128 | config SOC_SAM_V4_V5 | 132 | config SOC_SAM_V4_V5 |
| 129 | bool | 133 | bool |
| 130 | 134 | ||
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h index ff97374ca069..71a6f08de8f2 100644 --- a/arch/openrisc/include/asm/pgtable.h +++ b/arch/openrisc/include/asm/pgtable.h | |||
| @@ -414,6 +414,8 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) | |||
| 414 | 414 | ||
| 415 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ | 415 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ |
| 416 | 416 | ||
| 417 | struct vm_area_struct; | ||
| 418 | |||
| 417 | /* | 419 | /* |
| 418 | * or32 doesn't have any external MMU info: the kernel page | 420 | * or32 doesn't have any external MMU info: the kernel page |
| 419 | * tables contain all the necessary information. | 421 | * tables contain all the necessary information. |
diff --git a/block/blk-core.c b/block/blk-core.c index d709c0e3a2ac..aebe676225e6 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -2342,7 +2342,12 @@ blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request * | |||
| 2342 | if (q->mq_ops) { | 2342 | if (q->mq_ops) { |
| 2343 | if (blk_queue_io_stat(q)) | 2343 | if (blk_queue_io_stat(q)) |
| 2344 | blk_account_io_start(rq, true); | 2344 | blk_account_io_start(rq, true); |
| 2345 | blk_mq_sched_insert_request(rq, false, true, false, false); | 2345 | /* |
| 2346 | * Since we have a scheduler attached on the top device, | ||
| 2347 | * bypass a potential scheduler on the bottom device for | ||
| 2348 | * insert. | ||
| 2349 | */ | ||
| 2350 | blk_mq_request_bypass_insert(rq); | ||
| 2346 | return BLK_STS_OK; | 2351 | return BLK_STS_OK; |
| 2347 | } | 2352 | } |
| 2348 | 2353 | ||
diff --git a/block/blk-lib.c b/block/blk-lib.c index e01adb5145b3..62240f8832ca 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
| @@ -269,9 +269,9 @@ static int __blkdev_issue_write_zeroes(struct block_device *bdev, | |||
| 269 | */ | 269 | */ |
| 270 | static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects) | 270 | static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects) |
| 271 | { | 271 | { |
| 272 | sector_t bytes = (nr_sects << 9) + PAGE_SIZE - 1; | 272 | sector_t pages = DIV_ROUND_UP_SECTOR_T(nr_sects, PAGE_SIZE / 512); |
| 273 | 273 | ||
| 274 | return min(bytes >> PAGE_SHIFT, (sector_t)BIO_MAX_PAGES); | 274 | return min(pages, (sector_t)BIO_MAX_PAGES); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | /** | 277 | /** |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 3f18cff80050..98a18609755e 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -1401,6 +1401,22 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, | |||
| 1401 | blk_mq_hctx_mark_pending(hctx, ctx); | 1401 | blk_mq_hctx_mark_pending(hctx, ctx); |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | /* | ||
| 1405 | * Should only be used carefully, when the caller knows we want to | ||
| 1406 | * bypass a potential IO scheduler on the target device. | ||
| 1407 | */ | ||
| 1408 | void blk_mq_request_bypass_insert(struct request *rq) | ||
| 1409 | { | ||
| 1410 | struct blk_mq_ctx *ctx = rq->mq_ctx; | ||
| 1411 | struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, ctx->cpu); | ||
| 1412 | |||
| 1413 | spin_lock(&hctx->lock); | ||
| 1414 | list_add_tail(&rq->queuelist, &hctx->dispatch); | ||
| 1415 | spin_unlock(&hctx->lock); | ||
| 1416 | |||
| 1417 | blk_mq_run_hw_queue(hctx, false); | ||
| 1418 | } | ||
| 1419 | |||
| 1404 | void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, | 1420 | void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, |
| 1405 | struct list_head *list) | 1421 | struct list_head *list) |
| 1406 | 1422 | ||
diff --git a/block/blk-mq.h b/block/blk-mq.h index 98252b79b80b..ef15b3414da5 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h | |||
| @@ -54,6 +54,7 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, | |||
| 54 | */ | 54 | */ |
| 55 | void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, | 55 | void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, |
| 56 | bool at_head); | 56 | bool at_head); |
| 57 | void blk_mq_request_bypass_insert(struct request *rq); | ||
| 57 | void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, | 58 | void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, |
| 58 | struct list_head *list); | 59 | struct list_head *list); |
| 59 | 60 | ||
diff --git a/block/opal_proto.h b/block/opal_proto.h index f40c9acf8895..e20be8258854 100644 --- a/block/opal_proto.h +++ b/block/opal_proto.h | |||
| @@ -46,6 +46,7 @@ enum opal_response_token { | |||
| 46 | #define GENERIC_HOST_SESSION_NUM 0x41 | 46 | #define GENERIC_HOST_SESSION_NUM 0x41 |
| 47 | 47 | ||
| 48 | #define TPER_SYNC_SUPPORTED 0x01 | 48 | #define TPER_SYNC_SUPPORTED 0x01 |
| 49 | #define MBR_ENABLED_MASK 0x10 | ||
| 49 | 50 | ||
| 50 | #define TINY_ATOM_DATA_MASK 0x3F | 51 | #define TINY_ATOM_DATA_MASK 0x3F |
| 51 | #define TINY_ATOM_SIGNED 0x40 | 52 | #define TINY_ATOM_SIGNED 0x40 |
diff --git a/block/sed-opal.c b/block/sed-opal.c index 9b30ae5ab843..9ed51d0c6b1d 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c | |||
| @@ -80,6 +80,7 @@ struct parsed_resp { | |||
| 80 | 80 | ||
| 81 | struct opal_dev { | 81 | struct opal_dev { |
| 82 | bool supported; | 82 | bool supported; |
| 83 | bool mbr_enabled; | ||
| 83 | 84 | ||
| 84 | void *data; | 85 | void *data; |
| 85 | sec_send_recv *send_recv; | 86 | sec_send_recv *send_recv; |
| @@ -283,6 +284,14 @@ static bool check_tper(const void *data) | |||
| 283 | return true; | 284 | return true; |
| 284 | } | 285 | } |
| 285 | 286 | ||
| 287 | static bool check_mbrenabled(const void *data) | ||
| 288 | { | ||
| 289 | const struct d0_locking_features *lfeat = data; | ||
| 290 | u8 sup_feat = lfeat->supported_features; | ||
| 291 | |||
| 292 | return !!(sup_feat & MBR_ENABLED_MASK); | ||
| 293 | } | ||
| 294 | |||
| 286 | static bool check_sum(const void *data) | 295 | static bool check_sum(const void *data) |
| 287 | { | 296 | { |
| 288 | const struct d0_single_user_mode *sum = data; | 297 | const struct d0_single_user_mode *sum = data; |
| @@ -417,6 +426,7 @@ static int opal_discovery0_end(struct opal_dev *dev) | |||
| 417 | u32 hlen = be32_to_cpu(hdr->length); | 426 | u32 hlen = be32_to_cpu(hdr->length); |
| 418 | 427 | ||
| 419 | print_buffer(dev->resp, hlen); | 428 | print_buffer(dev->resp, hlen); |
| 429 | dev->mbr_enabled = false; | ||
| 420 | 430 | ||
| 421 | if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) { | 431 | if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) { |
| 422 | pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n", | 432 | pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n", |
| @@ -442,6 +452,8 @@ static int opal_discovery0_end(struct opal_dev *dev) | |||
| 442 | check_geometry(dev, body); | 452 | check_geometry(dev, body); |
| 443 | break; | 453 | break; |
| 444 | case FC_LOCKING: | 454 | case FC_LOCKING: |
| 455 | dev->mbr_enabled = check_mbrenabled(body->features); | ||
| 456 | break; | ||
| 445 | case FC_ENTERPRISE: | 457 | case FC_ENTERPRISE: |
| 446 | case FC_DATASTORE: | 458 | case FC_DATASTORE: |
| 447 | /* some ignored properties */ | 459 | /* some ignored properties */ |
| @@ -2190,6 +2202,21 @@ static int __opal_lock_unlock(struct opal_dev *dev, | |||
| 2190 | return next(dev); | 2202 | return next(dev); |
| 2191 | } | 2203 | } |
| 2192 | 2204 | ||
| 2205 | static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key) | ||
| 2206 | { | ||
| 2207 | u8 mbr_done_tf = 1; | ||
| 2208 | const struct opal_step mbrdone_step [] = { | ||
| 2209 | { opal_discovery0, }, | ||
| 2210 | { start_admin1LSP_opal_session, key }, | ||
| 2211 | { set_mbr_done, &mbr_done_tf }, | ||
| 2212 | { end_opal_session, }, | ||
| 2213 | { NULL, } | ||
| 2214 | }; | ||
| 2215 | |||
| 2216 | dev->steps = mbrdone_step; | ||
| 2217 | return next(dev); | ||
| 2218 | } | ||
| 2219 | |||
| 2193 | static int opal_lock_unlock(struct opal_dev *dev, | 2220 | static int opal_lock_unlock(struct opal_dev *dev, |
| 2194 | struct opal_lock_unlock *lk_unlk) | 2221 | struct opal_lock_unlock *lk_unlk) |
| 2195 | { | 2222 | { |
| @@ -2345,6 +2372,11 @@ bool opal_unlock_from_suspend(struct opal_dev *dev) | |||
| 2345 | suspend->unlk.session.sum); | 2372 | suspend->unlk.session.sum); |
| 2346 | was_failure = true; | 2373 | was_failure = true; |
| 2347 | } | 2374 | } |
| 2375 | if (dev->mbr_enabled) { | ||
| 2376 | ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key); | ||
| 2377 | if (ret) | ||
| 2378 | pr_debug("Failed to set MBR Done in S3 resume\n"); | ||
| 2379 | } | ||
| 2348 | } | 2380 | } |
| 2349 | mutex_unlock(&dev->dev_lock); | 2381 | mutex_unlock(&dev->dev_lock); |
| 2350 | return was_failure; | 2382 | return was_failure; |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 68ca2d9fcd73..1c4e1aa6767e 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
| @@ -31,6 +31,13 @@ config COMMON_CLK_WM831X | |||
| 31 | 31 | ||
| 32 | source "drivers/clk/versatile/Kconfig" | 32 | source "drivers/clk/versatile/Kconfig" |
| 33 | 33 | ||
| 34 | config CLK_HSDK | ||
| 35 | bool "PLL Driver for HSDK platform" | ||
| 36 | depends on OF || COMPILE_TEST | ||
| 37 | ---help--- | ||
| 38 | This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs | ||
| 39 | control. | ||
| 40 | |||
| 34 | config COMMON_CLK_MAX77686 | 41 | config COMMON_CLK_MAX77686 |
| 35 | tristate "Clock driver for Maxim 77620/77686/77802 MFD" | 42 | tristate "Clock driver for Maxim 77620/77686/77802 MFD" |
| 36 | depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST | 43 | depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST |
| @@ -39,10 +46,10 @@ config COMMON_CLK_MAX77686 | |||
| 39 | clock. | 46 | clock. |
| 40 | 47 | ||
| 41 | config COMMON_CLK_RK808 | 48 | config COMMON_CLK_RK808 |
| 42 | tristate "Clock driver for RK808/RK818" | 49 | tristate "Clock driver for RK805/RK808/RK818" |
| 43 | depends on MFD_RK808 | 50 | depends on MFD_RK808 |
| 44 | ---help--- | 51 | ---help--- |
| 45 | This driver supports RK808 and RK818 crystal oscillator clock. These | 52 | This driver supports RK805, RK808 and RK818 crystal oscillator clock. These |
| 46 | multi-function devices have two fixed-rate oscillators, | 53 | multi-function devices have two fixed-rate oscillators, |
| 47 | clocked at 32KHz each. Clkout1 is always on, Clkout2 can off | 54 | clocked at 32KHz each. Clkout1 is always on, Clkout2 can off |
| 48 | by control register. | 55 | by control register. |
| @@ -210,14 +217,14 @@ config COMMON_CLK_OXNAS | |||
| 210 | Support for the OXNAS SoC Family clocks. | 217 | Support for the OXNAS SoC Family clocks. |
| 211 | 218 | ||
| 212 | config COMMON_CLK_VC5 | 219 | config COMMON_CLK_VC5 |
| 213 | tristate "Clock driver for IDT VersaClock5 devices" | 220 | tristate "Clock driver for IDT VersaClock 5,6 devices" |
| 214 | depends on I2C | 221 | depends on I2C |
| 215 | depends on OF | 222 | depends on OF |
| 216 | select REGMAP_I2C | 223 | select REGMAP_I2C |
| 217 | help | 224 | help |
| 218 | ---help--- | 225 | ---help--- |
| 219 | This driver supports the IDT VersaClock5 programmable clock | 226 | This driver supports the IDT VersaClock 5 and VersaClock 6 |
| 220 | generator. | 227 | programmable clock generators. |
| 221 | 228 | ||
| 222 | source "drivers/clk/bcm/Kconfig" | 229 | source "drivers/clk/bcm/Kconfig" |
| 223 | source "drivers/clk/hisilicon/Kconfig" | 230 | source "drivers/clk/hisilicon/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cd376b3fb47a..c99f363826f0 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
| @@ -27,8 +27,8 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o | |||
| 27 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o | 27 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o |
| 28 | obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o | 28 | obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o |
| 29 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o | 29 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
| 30 | obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o | ||
| 30 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 31 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
| 31 | obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o | ||
| 32 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o | 32 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o |
| 33 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o | 33 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
| 34 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o | 34 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o |
| @@ -44,6 +44,7 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o | |||
| 44 | obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o | 44 | obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o |
| 45 | obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o | 45 | obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o |
| 46 | obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o | 46 | obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o |
| 47 | obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o | ||
| 47 | obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o | 48 | obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o |
| 48 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o | 49 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o |
| 49 | obj-$(CONFIG_ARCH_U300) += clk-u300.o | 50 | obj-$(CONFIG_ARCH_U300) += clk-u300.o |
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 13e67bd35cff..c68947b65a4c 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile | |||
| @@ -6,6 +6,7 @@ obj-y += pmc.o sckc.o | |||
| 6 | obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o | 6 | obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o |
| 7 | obj-y += clk-system.o clk-peripheral.o clk-programmable.o | 7 | obj-y += clk-system.o clk-peripheral.o clk-programmable.o |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_HAVE_AT91_AUDIO_PLL) += clk-audio-pll.o | ||
| 9 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o | 10 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o |
| 10 | obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o | 11 | obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o |
| 11 | obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o | 12 | obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o |
diff --git a/drivers/clk/at91/clk-audio-pll.c b/drivers/clk/at91/clk-audio-pll.c new file mode 100644 index 000000000000..da7bafcfbe70 --- /dev/null +++ b/drivers/clk/at91/clk-audio-pll.c | |||
| @@ -0,0 +1,536 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2016 Atmel Corporation, | ||
| 3 | * Songjun Wu <songjun.wu@atmel.com>, | ||
| 4 | * Nicolas Ferre <nicolas.ferre@atmel.com> | ||
| 5 | * Copyright (C) 2017 Free Electrons, | ||
| 6 | * Quentin Schulz <quentin.schulz@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent | ||
| 14 | * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of | ||
| 15 | * its own parent. PMC and PAD can then divide the FRAC rate to best match the | ||
| 16 | * asked rate. | ||
| 17 | * | ||
| 18 | * Traits of FRAC clock: | ||
| 19 | * enable - clk_enable writes nd, fracr parameters and enables PLL | ||
| 20 | * rate - rate is adjustable. | ||
| 21 | * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22)) | ||
| 22 | * parent - fixed parent. No clk_set_parent support | ||
| 23 | * | ||
| 24 | * Traits of PMC clock: | ||
| 25 | * enable - clk_enable writes qdpmc, and enables PMC output | ||
| 26 | * rate - rate is adjustable. | ||
| 27 | * clk->rate = parent->rate / (qdpmc + 1) | ||
| 28 | * parent - fixed parent. No clk_set_parent support | ||
| 29 | * | ||
| 30 | * Traits of PAD clock: | ||
| 31 | * enable - clk_enable writes divisors and enables PAD output | ||
| 32 | * rate - rate is adjustable. | ||
| 33 | * clk->rate = parent->rate / (qdaudio * div)) | ||
| 34 | * parent - fixed parent. No clk_set_parent support | ||
| 35 | * | ||
| 36 | */ | ||
| 37 | |||
| 38 | #include <linux/clk.h> | ||
| 39 | #include <linux/clk-provider.h> | ||
| 40 | #include <linux/clk/at91_pmc.h> | ||
| 41 | #include <linux/of.h> | ||
| 42 | #include <linux/mfd/syscon.h> | ||
| 43 | #include <linux/regmap.h> | ||
| 44 | #include <linux/slab.h> | ||
| 45 | |||
| 46 | #define AUDIO_PLL_DIV_FRAC BIT(22) | ||
| 47 | #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ | ||
| 48 | AT91_PMC_AUDIO_PLL_ND_OFFSET) | ||
| 49 | |||
| 50 | #define AUDIO_PLL_QDPAD(qd, div) ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \ | ||
| 51 | AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \ | ||
| 52 | (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \ | ||
| 53 | AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK)) | ||
| 54 | |||
| 55 | #define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \ | ||
| 56 | AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | ||
| 57 | |||
| 58 | #define AUDIO_PLL_FOUT_MIN 620000000UL | ||
| 59 | #define AUDIO_PLL_FOUT_MAX 700000000UL | ||
| 60 | |||
| 61 | struct clk_audio_frac { | ||
| 62 | struct clk_hw hw; | ||
| 63 | struct regmap *regmap; | ||
| 64 | u32 fracr; | ||
| 65 | u8 nd; | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct clk_audio_pad { | ||
| 69 | struct clk_hw hw; | ||
| 70 | struct regmap *regmap; | ||
| 71 | u8 qdaudio; | ||
| 72 | u8 div; | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct clk_audio_pmc { | ||
| 76 | struct clk_hw hw; | ||
| 77 | struct regmap *regmap; | ||
| 78 | u8 qdpmc; | ||
| 79 | }; | ||
| 80 | |||
| 81 | #define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw) | ||
| 82 | #define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw) | ||
| 83 | #define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw) | ||
| 84 | |||
| 85 | static int clk_audio_pll_frac_enable(struct clk_hw *hw) | ||
| 86 | { | ||
| 87 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); | ||
| 88 | |||
| 89 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 90 | AT91_PMC_AUDIO_PLL_RESETN, 0); | ||
| 91 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 92 | AT91_PMC_AUDIO_PLL_RESETN, | ||
| 93 | AT91_PMC_AUDIO_PLL_RESETN); | ||
| 94 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL1, | ||
| 95 | AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr); | ||
| 96 | |||
| 97 | /* | ||
| 98 | * reset and enable have to be done in 2 separated writes | ||
| 99 | * for AT91_PMC_AUDIO_PLL0 | ||
| 100 | */ | ||
| 101 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 102 | AT91_PMC_AUDIO_PLL_PLLEN | | ||
| 103 | AT91_PMC_AUDIO_PLL_ND_MASK, | ||
| 104 | AT91_PMC_AUDIO_PLL_PLLEN | | ||
| 105 | AT91_PMC_AUDIO_PLL_ND(frac->nd)); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int clk_audio_pll_pad_enable(struct clk_hw *hw) | ||
| 111 | { | ||
| 112 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | ||
| 113 | |||
| 114 | regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1, | ||
| 115 | AT91_PMC_AUDIO_PLL_QDPAD_MASK, | ||
| 116 | AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); | ||
| 117 | regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 118 | AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN); | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int clk_audio_pll_pmc_enable(struct clk_hw *hw) | ||
| 124 | { | ||
| 125 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | ||
| 126 | |||
| 127 | regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 128 | AT91_PMC_AUDIO_PLL_PMCEN | | ||
| 129 | AT91_PMC_AUDIO_PLL_QDPMC_MASK, | ||
| 130 | AT91_PMC_AUDIO_PLL_PMCEN | | ||
| 131 | AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void clk_audio_pll_frac_disable(struct clk_hw *hw) | ||
| 136 | { | ||
| 137 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); | ||
| 138 | |||
| 139 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 140 | AT91_PMC_AUDIO_PLL_PLLEN, 0); | ||
| 141 | /* do it in 2 separated writes */ | ||
| 142 | regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 143 | AT91_PMC_AUDIO_PLL_RESETN, 0); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void clk_audio_pll_pad_disable(struct clk_hw *hw) | ||
| 147 | { | ||
| 148 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | ||
| 149 | |||
| 150 | regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 151 | AT91_PMC_AUDIO_PLL_PADEN, 0); | ||
| 152 | } | ||
| 153 | |||
| 154 | static void clk_audio_pll_pmc_disable(struct clk_hw *hw) | ||
| 155 | { | ||
| 156 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | ||
| 157 | |||
| 158 | regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, | ||
| 159 | AT91_PMC_AUDIO_PLL_PMCEN, 0); | ||
| 160 | } | ||
| 161 | |||
| 162 | static unsigned long clk_audio_pll_fout(unsigned long parent_rate, | ||
| 163 | unsigned long nd, unsigned long fracr) | ||
| 164 | { | ||
| 165 | unsigned long long fr = (unsigned long long)parent_rate * fracr; | ||
| 166 | |||
| 167 | pr_debug("A PLL: %s, fr = %llu\n", __func__, fr); | ||
| 168 | |||
| 169 | fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC); | ||
| 170 | |||
| 171 | pr_debug("A PLL: %s, fr = %llu\n", __func__, fr); | ||
| 172 | |||
| 173 | return parent_rate * (nd + 1) + fr; | ||
| 174 | } | ||
| 175 | |||
| 176 | static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw, | ||
| 177 | unsigned long parent_rate) | ||
| 178 | { | ||
| 179 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); | ||
| 180 | unsigned long fout; | ||
| 181 | |||
| 182 | fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); | ||
| 183 | |||
| 184 | pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n", __func__, | ||
| 185 | fout, frac->nd, (unsigned long)frac->fracr); | ||
| 186 | |||
| 187 | return fout; | ||
| 188 | } | ||
| 189 | |||
| 190 | static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw, | ||
| 191 | unsigned long parent_rate) | ||
| 192 | { | ||
| 193 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | ||
| 194 | unsigned long apad_rate = 0; | ||
| 195 | |||
| 196 | if (apad_ck->qdaudio && apad_ck->div) | ||
| 197 | apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); | ||
| 198 | |||
| 199 | pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, qdaudio = %u)\n", | ||
| 200 | __func__, apad_rate, apad_ck->div, apad_ck->qdaudio); | ||
| 201 | |||
| 202 | return apad_rate; | ||
| 203 | } | ||
| 204 | |||
| 205 | static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw, | ||
| 206 | unsigned long parent_rate) | ||
| 207 | { | ||
| 208 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | ||
| 209 | unsigned long apmc_rate = 0; | ||
| 210 | |||
| 211 | apmc_rate = parent_rate / (apmc_ck->qdpmc + 1); | ||
| 212 | |||
| 213 | pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n", __func__, | ||
| 214 | apmc_rate, apmc_ck->qdpmc); | ||
| 215 | |||
| 216 | return apmc_rate; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int clk_audio_pll_frac_compute_frac(unsigned long rate, | ||
| 220 | unsigned long parent_rate, | ||
| 221 | unsigned long *nd, | ||
| 222 | unsigned long *fracr) | ||
| 223 | { | ||
| 224 | unsigned long long tmp, rem; | ||
| 225 | |||
| 226 | if (!rate) | ||
| 227 | return -EINVAL; | ||
| 228 | |||
| 229 | tmp = rate; | ||
| 230 | rem = do_div(tmp, parent_rate); | ||
| 231 | if (!tmp || tmp >= AUDIO_PLL_ND_MAX) | ||
| 232 | return -EINVAL; | ||
| 233 | |||
| 234 | *nd = tmp - 1; | ||
| 235 | |||
| 236 | tmp = rem * AUDIO_PLL_DIV_FRAC; | ||
| 237 | tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate); | ||
| 238 | if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK) | ||
| 239 | return -EINVAL; | ||
| 240 | |||
| 241 | /* we can cast here as we verified the bounds just above */ | ||
| 242 | *fracr = (unsigned long)tmp; | ||
| 243 | |||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw, | ||
| 248 | struct clk_rate_request *req) | ||
| 249 | { | ||
| 250 | unsigned long fracr, nd; | ||
| 251 | int ret; | ||
| 252 | |||
| 253 | pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, | ||
| 254 | req->rate, req->best_parent_rate); | ||
| 255 | |||
| 256 | req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX); | ||
| 257 | |||
| 258 | req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN); | ||
| 259 | req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX); | ||
| 260 | |||
| 261 | ret = clk_audio_pll_frac_compute_frac(req->rate, req->best_parent_rate, | ||
| 262 | &nd, &fracr); | ||
| 263 | if (ret) | ||
| 264 | return ret; | ||
| 265 | |||
| 266 | req->rate = clk_audio_pll_fout(req->best_parent_rate, nd, fracr); | ||
| 267 | |||
| 268 | req->best_parent_hw = clk_hw_get_parent(hw); | ||
| 269 | |||
| 270 | pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n", | ||
| 271 | __func__, req->rate, nd, fracr); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 277 | unsigned long *parent_rate) | ||
| 278 | { | ||
| 279 | struct clk_hw *pclk = clk_hw_get_parent(hw); | ||
| 280 | long best_rate = -EINVAL; | ||
| 281 | unsigned long best_parent_rate; | ||
| 282 | unsigned long tmp_qd; | ||
| 283 | u32 div; | ||
| 284 | long tmp_rate; | ||
| 285 | int tmp_diff; | ||
| 286 | int best_diff = -1; | ||
| 287 | |||
| 288 | pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, | ||
| 289 | rate, *parent_rate); | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Rate divisor is actually made of two different divisors, multiplied | ||
| 293 | * between themselves before dividing the rate. | ||
| 294 | * tmp_qd goes from 1 to 31 and div is either 2 or 3. | ||
| 295 | * In order to avoid testing twice the rate divisor (e.g. divisor 12 can | ||
| 296 | * be found with (tmp_qd, div) = (2, 6) or (3, 4)), we remove any loop | ||
| 297 | * for a rate divisor when div is 2 and tmp_qd is a multiple of 3. | ||
| 298 | * We cannot inverse it (condition div is 3 and tmp_qd is even) or we | ||
| 299 | * would miss some rate divisor that aren't reachable with div being 2 | ||
| 300 | * (e.g. rate divisor 90 is made with div = 3 and tmp_qd = 30, thus | ||
| 301 | * tmp_qd is even so we skip it because we think div 2 could make this | ||
| 302 | * rate divisor which isn't possible since tmp_qd has to be <= 31). | ||
| 303 | */ | ||
| 304 | for (tmp_qd = 1; tmp_qd < AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX; tmp_qd++) | ||
| 305 | for (div = 2; div <= 3; div++) { | ||
| 306 | if (div == 2 && tmp_qd % 3 == 0) | ||
| 307 | continue; | ||
| 308 | |||
| 309 | best_parent_rate = clk_hw_round_rate(pclk, | ||
| 310 | rate * tmp_qd * div); | ||
| 311 | tmp_rate = best_parent_rate / (div * tmp_qd); | ||
| 312 | tmp_diff = abs(rate - tmp_rate); | ||
| 313 | |||
| 314 | if (best_diff < 0 || best_diff > tmp_diff) { | ||
| 315 | *parent_rate = best_parent_rate; | ||
| 316 | best_rate = tmp_rate; | ||
| 317 | best_diff = tmp_diff; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n", | ||
| 322 | __func__, best_rate, best_parent_rate); | ||
| 323 | |||
| 324 | return best_rate; | ||
| 325 | } | ||
| 326 | |||
| 327 | static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 328 | unsigned long *parent_rate) | ||
| 329 | { | ||
| 330 | struct clk_hw *pclk = clk_hw_get_parent(hw); | ||
| 331 | long best_rate = -EINVAL; | ||
| 332 | unsigned long best_parent_rate = 0; | ||
| 333 | u32 tmp_qd = 0, div; | ||
| 334 | long tmp_rate; | ||
| 335 | int tmp_diff; | ||
| 336 | int best_diff = -1; | ||
| 337 | |||
| 338 | pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, | ||
| 339 | rate, *parent_rate); | ||
| 340 | |||
| 341 | for (div = 1; div <= AUDIO_PLL_QDPMC_MAX; div++) { | ||
| 342 | best_parent_rate = clk_round_rate(pclk->clk, rate * div); | ||
| 343 | tmp_rate = best_parent_rate / div; | ||
| 344 | tmp_diff = abs(rate - tmp_rate); | ||
| 345 | |||
| 346 | if (best_diff < 0 || best_diff > tmp_diff) { | ||
| 347 | *parent_rate = best_parent_rate; | ||
| 348 | best_rate = tmp_rate; | ||
| 349 | best_diff = tmp_diff; | ||
| 350 | tmp_qd = div; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n", | ||
| 355 | __func__, best_rate, *parent_rate, tmp_qd - 1); | ||
| 356 | |||
| 357 | return best_rate; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 361 | unsigned long parent_rate) | ||
| 362 | { | ||
| 363 | struct clk_audio_frac *frac = to_clk_audio_frac(hw); | ||
| 364 | unsigned long fracr, nd; | ||
| 365 | int ret; | ||
| 366 | |||
| 367 | pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, rate, | ||
| 368 | parent_rate); | ||
| 369 | |||
| 370 | if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) | ||
| 371 | return -EINVAL; | ||
| 372 | |||
| 373 | ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr); | ||
| 374 | if (ret) | ||
| 375 | return ret; | ||
| 376 | |||
| 377 | frac->nd = nd; | ||
| 378 | frac->fracr = fracr; | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 384 | unsigned long parent_rate) | ||
| 385 | { | ||
| 386 | struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | ||
| 387 | u8 tmp_div; | ||
| 388 | |||
| 389 | pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, | ||
| 390 | rate, parent_rate); | ||
| 391 | |||
| 392 | if (!rate) | ||
| 393 | return -EINVAL; | ||
| 394 | |||
| 395 | tmp_div = parent_rate / rate; | ||
| 396 | if (tmp_div % 3 == 0) { | ||
| 397 | apad_ck->qdaudio = tmp_div / 3; | ||
| 398 | apad_ck->div = 3; | ||
| 399 | } else { | ||
| 400 | apad_ck->qdaudio = tmp_div / 2; | ||
| 401 | apad_ck->div = 2; | ||
| 402 | } | ||
| 403 | |||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 408 | unsigned long parent_rate) | ||
| 409 | { | ||
| 410 | struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | ||
| 411 | |||
| 412 | if (!rate) | ||
| 413 | return -EINVAL; | ||
| 414 | |||
| 415 | pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, | ||
| 416 | rate, parent_rate); | ||
| 417 | |||
| 418 | apmc_ck->qdpmc = parent_rate / rate - 1; | ||
| 419 | |||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static const struct clk_ops audio_pll_frac_ops = { | ||
| 424 | .enable = clk_audio_pll_frac_enable, | ||
| 425 | .disable = clk_audio_pll_frac_disable, | ||
| 426 | .recalc_rate = clk_audio_pll_frac_recalc_rate, | ||
| 427 | .determine_rate = clk_audio_pll_frac_determine_rate, | ||
| 428 | .set_rate = clk_audio_pll_frac_set_rate, | ||
| 429 | }; | ||
| 430 | |||
| 431 | static const struct clk_ops audio_pll_pad_ops = { | ||
| 432 | .enable = clk_audio_pll_pad_enable, | ||
| 433 | .disable = clk_audio_pll_pad_disable, | ||
| 434 | .recalc_rate = clk_audio_pll_pad_recalc_rate, | ||
| 435 | .round_rate = clk_audio_pll_pad_round_rate, | ||
| 436 | .set_rate = clk_audio_pll_pad_set_rate, | ||
| 437 | }; | ||
| 438 | |||
| 439 | static const struct clk_ops audio_pll_pmc_ops = { | ||
| 440 | .enable = clk_audio_pll_pmc_enable, | ||
| 441 | .disable = clk_audio_pll_pmc_disable, | ||
| 442 | .recalc_rate = clk_audio_pll_pmc_recalc_rate, | ||
| 443 | .round_rate = clk_audio_pll_pmc_round_rate, | ||
| 444 | .set_rate = clk_audio_pll_pmc_set_rate, | ||
| 445 | }; | ||
| 446 | |||
| 447 | static int of_sama5d2_clk_audio_pll_setup(struct device_node *np, | ||
| 448 | struct clk_init_data *init, | ||
| 449 | struct clk_hw *hw, | ||
| 450 | struct regmap **clk_audio_regmap) | ||
| 451 | { | ||
| 452 | struct regmap *regmap; | ||
| 453 | const char *parent_names[1]; | ||
| 454 | int ret; | ||
| 455 | |||
| 456 | regmap = syscon_node_to_regmap(of_get_parent(np)); | ||
| 457 | if (IS_ERR(regmap)) | ||
| 458 | return PTR_ERR(regmap); | ||
| 459 | |||
| 460 | init->name = np->name; | ||
| 461 | of_clk_parent_fill(np, parent_names, 1); | ||
| 462 | init->parent_names = parent_names; | ||
| 463 | init->num_parents = 1; | ||
| 464 | |||
| 465 | hw->init = init; | ||
| 466 | *clk_audio_regmap = regmap; | ||
| 467 | |||
| 468 | ret = clk_hw_register(NULL, hw); | ||
| 469 | if (ret) | ||
| 470 | return ret; | ||
| 471 | |||
| 472 | return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); | ||
| 473 | } | ||
| 474 | |||
| 475 | static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np) | ||
| 476 | { | ||
| 477 | struct clk_audio_frac *frac_ck; | ||
| 478 | struct clk_init_data init = {}; | ||
| 479 | |||
| 480 | frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL); | ||
| 481 | if (!frac_ck) | ||
| 482 | return; | ||
| 483 | |||
| 484 | init.ops = &audio_pll_frac_ops; | ||
| 485 | init.flags = CLK_SET_RATE_GATE; | ||
| 486 | |||
| 487 | if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw, | ||
| 488 | &frac_ck->regmap)) | ||
| 489 | kfree(frac_ck); | ||
| 490 | } | ||
| 491 | |||
| 492 | static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np) | ||
| 493 | { | ||
| 494 | struct clk_audio_pad *apad_ck; | ||
| 495 | struct clk_init_data init = {}; | ||
| 496 | |||
| 497 | apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL); | ||
| 498 | if (!apad_ck) | ||
| 499 | return; | ||
| 500 | |||
| 501 | init.ops = &audio_pll_pad_ops; | ||
| 502 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | | ||
| 503 | CLK_SET_RATE_PARENT; | ||
| 504 | |||
| 505 | if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw, | ||
| 506 | &apad_ck->regmap)) | ||
| 507 | kfree(apad_ck); | ||
| 508 | } | ||
| 509 | |||
| 510 | static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np) | ||
| 511 | { | ||
| 512 | struct clk_audio_pad *apmc_ck; | ||
| 513 | struct clk_init_data init = {}; | ||
| 514 | |||
| 515 | apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL); | ||
| 516 | if (!apmc_ck) | ||
| 517 | return; | ||
| 518 | |||
| 519 | init.ops = &audio_pll_pmc_ops; | ||
| 520 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | | ||
| 521 | CLK_SET_RATE_PARENT; | ||
| 522 | |||
| 523 | if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw, | ||
| 524 | &apmc_ck->regmap)) | ||
| 525 | kfree(apmc_ck); | ||
| 526 | } | ||
| 527 | |||
| 528 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup, | ||
| 529 | "atmel,sama5d2-clk-audio-pll-frac", | ||
| 530 | of_sama5d2_clk_audio_pll_frac_setup); | ||
| 531 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup, | ||
| 532 | "atmel,sama5d2-clk-audio-pll-pad", | ||
| 533 | of_sama5d2_clk_audio_pll_pad_setup); | ||
| 534 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup, | ||
| 535 | "atmel,sama5d2-clk-audio-pll-pmc", | ||
| 536 | of_sama5d2_clk_audio_pll_pmc_setup); | ||
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index f0b7ae904ce2..33481368740e 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c | |||
| @@ -26,6 +26,13 @@ | |||
| 26 | #define GENERATED_SOURCE_MAX 6 | 26 | #define GENERATED_SOURCE_MAX 6 |
| 27 | #define GENERATED_MAX_DIV 255 | 27 | #define GENERATED_MAX_DIV 255 |
| 28 | 28 | ||
| 29 | #define GCK_ID_SSC0 43 | ||
| 30 | #define GCK_ID_SSC1 44 | ||
| 31 | #define GCK_ID_I2S0 54 | ||
| 32 | #define GCK_ID_I2S1 55 | ||
| 33 | #define GCK_ID_CLASSD 59 | ||
| 34 | #define GCK_INDEX_DT_AUDIO_PLL 5 | ||
| 35 | |||
| 29 | struct clk_generated { | 36 | struct clk_generated { |
| 30 | struct clk_hw hw; | 37 | struct clk_hw hw; |
| 31 | struct regmap *regmap; | 38 | struct regmap *regmap; |
| @@ -34,6 +41,7 @@ struct clk_generated { | |||
| 34 | u32 id; | 41 | u32 id; |
| 35 | u32 gckdiv; | 42 | u32 gckdiv; |
| 36 | u8 parent_id; | 43 | u8 parent_id; |
| 44 | bool audio_pll_allowed; | ||
| 37 | }; | 45 | }; |
| 38 | 46 | ||
| 39 | #define to_clk_generated(hw) \ | 47 | #define to_clk_generated(hw) \ |
| @@ -99,21 +107,41 @@ clk_generated_recalc_rate(struct clk_hw *hw, | |||
| 99 | return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1); | 107 | return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1); |
| 100 | } | 108 | } |
| 101 | 109 | ||
| 110 | static void clk_generated_best_diff(struct clk_rate_request *req, | ||
| 111 | struct clk_hw *parent, | ||
| 112 | unsigned long parent_rate, u32 div, | ||
| 113 | int *best_diff, long *best_rate) | ||
| 114 | { | ||
| 115 | unsigned long tmp_rate; | ||
| 116 | int tmp_diff; | ||
| 117 | |||
| 118 | if (!div) | ||
| 119 | tmp_rate = parent_rate; | ||
| 120 | else | ||
| 121 | tmp_rate = parent_rate / div; | ||
| 122 | tmp_diff = abs(req->rate - tmp_rate); | ||
| 123 | |||
| 124 | if (*best_diff < 0 || *best_diff > tmp_diff) { | ||
| 125 | *best_rate = tmp_rate; | ||
| 126 | *best_diff = tmp_diff; | ||
| 127 | req->best_parent_rate = parent_rate; | ||
| 128 | req->best_parent_hw = parent; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 102 | static int clk_generated_determine_rate(struct clk_hw *hw, | 132 | static int clk_generated_determine_rate(struct clk_hw *hw, |
| 103 | struct clk_rate_request *req) | 133 | struct clk_rate_request *req) |
| 104 | { | 134 | { |
| 105 | struct clk_generated *gck = to_clk_generated(hw); | 135 | struct clk_generated *gck = to_clk_generated(hw); |
| 106 | struct clk_hw *parent = NULL; | 136 | struct clk_hw *parent = NULL; |
| 137 | struct clk_rate_request req_parent = *req; | ||
| 107 | long best_rate = -EINVAL; | 138 | long best_rate = -EINVAL; |
| 108 | unsigned long tmp_rate, min_rate; | 139 | unsigned long min_rate, parent_rate; |
| 109 | int best_diff = -1; | 140 | int best_diff = -1; |
| 110 | int tmp_diff; | ||
| 111 | int i; | 141 | int i; |
| 142 | u32 div; | ||
| 112 | 143 | ||
| 113 | for (i = 0; i < clk_hw_get_num_parents(hw); i++) { | 144 | for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) { |
| 114 | u32 div; | ||
| 115 | unsigned long parent_rate; | ||
| 116 | |||
| 117 | parent = clk_hw_get_parent_by_index(hw, i); | 145 | parent = clk_hw_get_parent_by_index(hw, i); |
| 118 | if (!parent) | 146 | if (!parent) |
| 119 | continue; | 147 | continue; |
| @@ -124,25 +152,43 @@ static int clk_generated_determine_rate(struct clk_hw *hw, | |||
| 124 | (gck->range.max && min_rate > gck->range.max)) | 152 | (gck->range.max && min_rate > gck->range.max)) |
| 125 | continue; | 153 | continue; |
| 126 | 154 | ||
| 127 | for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { | 155 | div = DIV_ROUND_CLOSEST(parent_rate, req->rate); |
| 128 | tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div); | ||
| 129 | tmp_diff = abs(req->rate - tmp_rate); | ||
| 130 | 156 | ||
| 131 | if (best_diff < 0 || best_diff > tmp_diff) { | 157 | clk_generated_best_diff(req, parent, parent_rate, div, |
| 132 | best_rate = tmp_rate; | 158 | &best_diff, &best_rate); |
| 133 | best_diff = tmp_diff; | ||
| 134 | req->best_parent_rate = parent_rate; | ||
| 135 | req->best_parent_hw = parent; | ||
| 136 | } | ||
| 137 | 159 | ||
| 138 | if (!best_diff || tmp_rate < req->rate) | 160 | if (!best_diff) |
| 139 | break; | 161 | break; |
| 140 | } | 162 | } |
| 163 | |||
| 164 | /* | ||
| 165 | * The audio_pll rate can be modified, unlike the five others clocks | ||
| 166 | * that should never be altered. | ||
| 167 | * The audio_pll can technically be used by multiple consumers. However, | ||
| 168 | * with the rate locking, the first consumer to enable to clock will be | ||
| 169 | * the one definitely setting the rate of the clock. | ||
| 170 | * Since audio IPs are most likely to request the same rate, we enforce | ||
| 171 | * that the only clks able to modify gck rate are those of audio IPs. | ||
| 172 | */ | ||
| 173 | |||
| 174 | if (!gck->audio_pll_allowed) | ||
| 175 | goto end; | ||
| 176 | |||
| 177 | parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL); | ||
| 178 | if (!parent) | ||
| 179 | goto end; | ||
| 180 | |||
| 181 | for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { | ||
| 182 | req_parent.rate = req->rate * div; | ||
| 183 | __clk_determine_rate(parent, &req_parent); | ||
| 184 | clk_generated_best_diff(req, parent, req_parent.rate, div, | ||
| 185 | &best_diff, &best_rate); | ||
| 141 | 186 | ||
| 142 | if (!best_diff) | 187 | if (!best_diff) |
| 143 | break; | 188 | break; |
| 144 | } | 189 | } |
| 145 | 190 | ||
| 191 | end: | ||
| 146 | pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n", | 192 | pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n", |
| 147 | __func__, best_rate, | 193 | __func__, best_rate, |
| 148 | __clk_get_name((req->best_parent_hw)->clk), | 194 | __clk_get_name((req->best_parent_hw)->clk), |
| @@ -252,7 +298,8 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, | |||
| 252 | init.ops = &generated_ops; | 298 | init.ops = &generated_ops; |
| 253 | init.parent_names = parent_names; | 299 | init.parent_names = parent_names; |
| 254 | init.num_parents = num_parents; | 300 | init.num_parents = num_parents; |
| 255 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; | 301 | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | |
| 302 | CLK_SET_RATE_PARENT; | ||
| 256 | 303 | ||
| 257 | gck->id = id; | 304 | gck->id = id; |
| 258 | gck->hw.init = &init; | 305 | gck->hw.init = &init; |
| @@ -284,6 +331,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) | |||
| 284 | struct device_node *gcknp; | 331 | struct device_node *gcknp; |
| 285 | struct clk_range range = CLK_RANGE(0, 0); | 332 | struct clk_range range = CLK_RANGE(0, 0); |
| 286 | struct regmap *regmap; | 333 | struct regmap *regmap; |
| 334 | struct clk_generated *gck; | ||
| 287 | 335 | ||
| 288 | num_parents = of_clk_get_parent_count(np); | 336 | num_parents = of_clk_get_parent_count(np); |
| 289 | if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX) | 337 | if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX) |
| @@ -315,6 +363,21 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) | |||
| 315 | hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, | 363 | hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, |
| 316 | parent_names, num_parents, | 364 | parent_names, num_parents, |
| 317 | id, &range); | 365 | id, &range); |
| 366 | |||
| 367 | gck = to_clk_generated(hw); | ||
| 368 | |||
| 369 | if (of_device_is_compatible(np, | ||
| 370 | "atmel,sama5d2-clk-generated")) { | ||
| 371 | if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 || | ||
| 372 | gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 || | ||
| 373 | gck->id == GCK_ID_CLASSD) | ||
| 374 | gck->audio_pll_allowed = true; | ||
| 375 | else | ||
| 376 | gck->audio_pll_allowed = false; | ||
| 377 | } else { | ||
| 378 | gck->audio_pll_allowed = false; | ||
| 379 | } | ||
| 380 | |||
| 318 | if (IS_ERR(hw)) | 381 | if (IS_ERR(hw)) |
| 319 | continue; | 382 | continue; |
| 320 | 383 | ||
diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile index 01996b871b06..d747deafbf1e 100644 --- a/drivers/clk/axs10x/Makefile +++ b/drivers/clk/axs10x/Makefile | |||
| @@ -1 +1,2 @@ | |||
| 1 | obj-y += i2s_pll_clock.o | 1 | obj-y += i2s_pll_clock.o |
| 2 | obj-y += pll_clock.o | ||
diff --git a/drivers/clk/axs10x/pll_clock.c b/drivers/clk/axs10x/pll_clock.c new file mode 100644 index 000000000000..25d8c240ddfb --- /dev/null +++ b/drivers/clk/axs10x/pll_clock.c | |||
| @@ -0,0 +1,346 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys AXS10X SDP Generic PLL clock driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 Synopsys | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2. This program is licensed "as is" without any | ||
| 8 | * warranty of any kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/clk-provider.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/of_address.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | |||
| 22 | /* PLL registers addresses */ | ||
| 23 | #define PLL_REG_IDIV 0x0 | ||
| 24 | #define PLL_REG_FBDIV 0x4 | ||
| 25 | #define PLL_REG_ODIV 0x8 | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Bit fields of the PLL IDIV/FBDIV/ODIV registers: | ||
| 29 | * ________________________________________________________________________ | ||
| 30 | * |31 15| 14 | 13 | 12 |11 6|5 0| | ||
| 31 | * |-------RESRVED------|-NOUPDATE-|-BYPASS-|-EDGE-|--HIGHTIME--|--LOWTIME--| | ||
| 32 | * |____________________|__________|________|______|____________|___________| | ||
| 33 | * | ||
| 34 | * Following macros determine the way of access to these registers | ||
| 35 | * They should be set up only using the macros. | ||
| 36 | * reg should be an u32 variable. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #define PLL_REG_GET_LOW(reg) \ | ||
| 40 | (((reg) & (0x3F << 0)) >> 0) | ||
| 41 | #define PLL_REG_GET_HIGH(reg) \ | ||
| 42 | (((reg) & (0x3F << 6)) >> 6) | ||
| 43 | #define PLL_REG_GET_EDGE(reg) \ | ||
| 44 | (((reg) & (BIT(12))) ? 1 : 0) | ||
| 45 | #define PLL_REG_GET_BYPASS(reg) \ | ||
| 46 | (((reg) & (BIT(13))) ? 1 : 0) | ||
| 47 | #define PLL_REG_GET_NOUPD(reg) \ | ||
| 48 | (((reg) & (BIT(14))) ? 1 : 0) | ||
| 49 | #define PLL_REG_GET_PAD(reg) \ | ||
| 50 | (((reg) & (0x1FFFF << 15)) >> 15) | ||
| 51 | |||
| 52 | #define PLL_REG_SET_LOW(reg, value) \ | ||
| 53 | { reg |= (((value) & 0x3F) << 0); } | ||
| 54 | #define PLL_REG_SET_HIGH(reg, value) \ | ||
| 55 | { reg |= (((value) & 0x3F) << 6); } | ||
| 56 | #define PLL_REG_SET_EDGE(reg, value) \ | ||
| 57 | { reg |= (((value) & 0x01) << 12); } | ||
| 58 | #define PLL_REG_SET_BYPASS(reg, value) \ | ||
| 59 | { reg |= (((value) & 0x01) << 13); } | ||
| 60 | #define PLL_REG_SET_NOUPD(reg, value) \ | ||
| 61 | { reg |= (((value) & 0x01) << 14); } | ||
| 62 | #define PLL_REG_SET_PAD(reg, value) \ | ||
| 63 | { reg |= (((value) & 0x1FFFF) << 15); } | ||
| 64 | |||
| 65 | #define PLL_LOCK BIT(0) | ||
| 66 | #define PLL_ERROR BIT(1) | ||
| 67 | #define PLL_MAX_LOCK_TIME 100 /* 100 us */ | ||
| 68 | |||
| 69 | struct axs10x_pll_cfg { | ||
| 70 | u32 rate; | ||
| 71 | u32 idiv; | ||
| 72 | u32 fbdiv; | ||
| 73 | u32 odiv; | ||
| 74 | }; | ||
| 75 | |||
| 76 | static const struct axs10x_pll_cfg arc_pll_cfg[] = { | ||
| 77 | { 33333333, 1, 1, 1 }, | ||
| 78 | { 50000000, 1, 30, 20 }, | ||
| 79 | { 75000000, 2, 45, 10 }, | ||
| 80 | { 90000000, 2, 54, 10 }, | ||
| 81 | { 100000000, 1, 30, 10 }, | ||
| 82 | { 125000000, 2, 45, 6 }, | ||
| 83 | {} | ||
| 84 | }; | ||
| 85 | |||
| 86 | static const struct axs10x_pll_cfg pgu_pll_cfg[] = { | ||
| 87 | { 25200000, 1, 84, 90 }, | ||
| 88 | { 50000000, 1, 100, 54 }, | ||
| 89 | { 74250000, 1, 44, 16 }, | ||
| 90 | {} | ||
| 91 | }; | ||
| 92 | |||
| 93 | struct axs10x_pll_clk { | ||
| 94 | struct clk_hw hw; | ||
| 95 | void __iomem *base; | ||
| 96 | void __iomem *lock; | ||
| 97 | const struct axs10x_pll_cfg *pll_cfg; | ||
| 98 | struct device *dev; | ||
| 99 | }; | ||
| 100 | |||
| 101 | static inline void axs10x_pll_write(struct axs10x_pll_clk *clk, u32 reg, | ||
| 102 | u32 val) | ||
| 103 | { | ||
| 104 | iowrite32(val, clk->base + reg); | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline u32 axs10x_pll_read(struct axs10x_pll_clk *clk, u32 reg) | ||
| 108 | { | ||
| 109 | return ioread32(clk->base + reg); | ||
| 110 | } | ||
| 111 | |||
| 112 | static inline struct axs10x_pll_clk *to_axs10x_pll_clk(struct clk_hw *hw) | ||
| 113 | { | ||
| 114 | return container_of(hw, struct axs10x_pll_clk, hw); | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline u32 axs10x_div_get_value(u32 reg) | ||
| 118 | { | ||
| 119 | if (PLL_REG_GET_BYPASS(reg)) | ||
| 120 | return 1; | ||
| 121 | |||
| 122 | return PLL_REG_GET_HIGH(reg) + PLL_REG_GET_LOW(reg); | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline u32 axs10x_encode_div(unsigned int id, int upd) | ||
| 126 | { | ||
| 127 | u32 div = 0; | ||
| 128 | |||
| 129 | PLL_REG_SET_LOW(div, (id % 2 == 0) ? id >> 1 : (id >> 1) + 1); | ||
| 130 | PLL_REG_SET_HIGH(div, id >> 1); | ||
| 131 | PLL_REG_SET_EDGE(div, id % 2); | ||
| 132 | PLL_REG_SET_BYPASS(div, id == 1 ? 1 : 0); | ||
| 133 | PLL_REG_SET_NOUPD(div, upd == 0 ? 1 : 0); | ||
| 134 | |||
| 135 | return div; | ||
| 136 | } | ||
| 137 | |||
| 138 | static unsigned long axs10x_pll_recalc_rate(struct clk_hw *hw, | ||
| 139 | unsigned long parent_rate) | ||
| 140 | { | ||
| 141 | u64 rate; | ||
| 142 | u32 idiv, fbdiv, odiv; | ||
| 143 | struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | ||
| 144 | |||
| 145 | idiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_IDIV)); | ||
| 146 | fbdiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_FBDIV)); | ||
| 147 | odiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_ODIV)); | ||
| 148 | |||
| 149 | rate = (u64)parent_rate * fbdiv; | ||
| 150 | do_div(rate, idiv * odiv); | ||
| 151 | |||
| 152 | return rate; | ||
| 153 | } | ||
| 154 | |||
| 155 | static long axs10x_pll_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 156 | unsigned long *prate) | ||
| 157 | { | ||
| 158 | int i; | ||
| 159 | long best_rate; | ||
| 160 | struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | ||
| 161 | const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; | ||
| 162 | |||
| 163 | if (pll_cfg[0].rate == 0) | ||
| 164 | return -EINVAL; | ||
| 165 | |||
| 166 | best_rate = pll_cfg[0].rate; | ||
| 167 | |||
| 168 | for (i = 1; pll_cfg[i].rate != 0; i++) { | ||
| 169 | if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) | ||
| 170 | best_rate = pll_cfg[i].rate; | ||
| 171 | } | ||
| 172 | |||
| 173 | return best_rate; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int axs10x_pll_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 177 | unsigned long parent_rate) | ||
| 178 | { | ||
| 179 | int i; | ||
| 180 | struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | ||
| 181 | const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; | ||
| 182 | |||
| 183 | for (i = 0; pll_cfg[i].rate != 0; i++) { | ||
| 184 | if (pll_cfg[i].rate == rate) { | ||
| 185 | axs10x_pll_write(clk, PLL_REG_IDIV, | ||
| 186 | axs10x_encode_div(pll_cfg[i].idiv, 0)); | ||
| 187 | axs10x_pll_write(clk, PLL_REG_FBDIV, | ||
| 188 | axs10x_encode_div(pll_cfg[i].fbdiv, 0)); | ||
| 189 | axs10x_pll_write(clk, PLL_REG_ODIV, | ||
| 190 | axs10x_encode_div(pll_cfg[i].odiv, 1)); | ||
| 191 | |||
| 192 | /* | ||
| 193 | * Wait until CGU relocks and check error status. | ||
| 194 | * If after timeout CGU is unlocked yet return error | ||
| 195 | */ | ||
| 196 | udelay(PLL_MAX_LOCK_TIME); | ||
| 197 | if (!(ioread32(clk->lock) & PLL_LOCK)) | ||
| 198 | return -ETIMEDOUT; | ||
| 199 | |||
| 200 | if (ioread32(clk->lock) & PLL_ERROR) | ||
| 201 | return -EINVAL; | ||
| 202 | |||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, | ||
| 208 | parent_rate); | ||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | |||
| 212 | static const struct clk_ops axs10x_pll_ops = { | ||
| 213 | .recalc_rate = axs10x_pll_recalc_rate, | ||
| 214 | .round_rate = axs10x_pll_round_rate, | ||
| 215 | .set_rate = axs10x_pll_set_rate, | ||
| 216 | }; | ||
| 217 | |||
| 218 | static int axs10x_pll_clk_probe(struct platform_device *pdev) | ||
| 219 | { | ||
| 220 | struct device *dev = &pdev->dev; | ||
| 221 | const char *parent_name; | ||
| 222 | struct axs10x_pll_clk *pll_clk; | ||
| 223 | struct resource *mem; | ||
| 224 | struct clk_init_data init = { }; | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); | ||
| 228 | if (!pll_clk) | ||
| 229 | return -ENOMEM; | ||
| 230 | |||
| 231 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 232 | pll_clk->base = devm_ioremap_resource(dev, mem); | ||
| 233 | if (IS_ERR(pll_clk->base)) | ||
| 234 | return PTR_ERR(pll_clk->base); | ||
| 235 | |||
| 236 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 237 | pll_clk->lock = devm_ioremap_resource(dev, mem); | ||
| 238 | if (IS_ERR(pll_clk->lock)) | ||
| 239 | return PTR_ERR(pll_clk->lock); | ||
| 240 | |||
| 241 | init.name = dev->of_node->name; | ||
| 242 | init.ops = &axs10x_pll_ops; | ||
| 243 | parent_name = of_clk_get_parent_name(dev->of_node, 0); | ||
| 244 | init.parent_names = &parent_name; | ||
| 245 | init.num_parents = 1; | ||
| 246 | pll_clk->hw.init = &init; | ||
| 247 | pll_clk->dev = dev; | ||
| 248 | pll_clk->pll_cfg = of_device_get_match_data(dev); | ||
| 249 | |||
| 250 | if (!pll_clk->pll_cfg) { | ||
| 251 | dev_err(dev, "No OF match data provided\n"); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | |||
| 255 | ret = devm_clk_hw_register(dev, &pll_clk->hw); | ||
| 256 | if (ret) { | ||
| 257 | dev_err(dev, "failed to register %s clock\n", init.name); | ||
| 258 | return ret; | ||
| 259 | } | ||
| 260 | |||
| 261 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, | ||
| 262 | &pll_clk->hw); | ||
| 263 | } | ||
| 264 | |||
| 265 | static int axs10x_pll_clk_remove(struct platform_device *pdev) | ||
| 266 | { | ||
| 267 | of_clk_del_provider(pdev->dev.of_node); | ||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 271 | static void __init of_axs10x_pll_clk_setup(struct device_node *node) | ||
| 272 | { | ||
| 273 | const char *parent_name; | ||
| 274 | struct axs10x_pll_clk *pll_clk; | ||
| 275 | struct clk_init_data init = { }; | ||
| 276 | int ret; | ||
| 277 | |||
| 278 | pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | ||
| 279 | if (!pll_clk) | ||
| 280 | return; | ||
| 281 | |||
| 282 | pll_clk->base = of_iomap(node, 0); | ||
| 283 | if (!pll_clk->base) { | ||
| 284 | pr_err("failed to map pll div registers\n"); | ||
| 285 | goto err_free_pll_clk; | ||
| 286 | } | ||
| 287 | |||
| 288 | pll_clk->lock = of_iomap(node, 1); | ||
| 289 | if (!pll_clk->lock) { | ||
| 290 | pr_err("failed to map pll lock register\n"); | ||
| 291 | goto err_unmap_base; | ||
| 292 | } | ||
| 293 | |||
| 294 | init.name = node->name; | ||
| 295 | init.ops = &axs10x_pll_ops; | ||
| 296 | parent_name = of_clk_get_parent_name(node, 0); | ||
| 297 | init.parent_names = &parent_name; | ||
| 298 | init.num_parents = parent_name ? 1 : 0; | ||
| 299 | pll_clk->hw.init = &init; | ||
| 300 | pll_clk->pll_cfg = arc_pll_cfg; | ||
| 301 | |||
| 302 | ret = clk_hw_register(NULL, &pll_clk->hw); | ||
| 303 | if (ret) { | ||
| 304 | pr_err("failed to register %s clock\n", node->name); | ||
| 305 | goto err_unmap_lock; | ||
| 306 | } | ||
| 307 | |||
| 308 | ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw); | ||
| 309 | if (ret) { | ||
| 310 | pr_err("failed to add hw provider for %s clock\n", node->name); | ||
| 311 | goto err_unregister_clk; | ||
| 312 | } | ||
| 313 | |||
| 314 | return; | ||
| 315 | |||
| 316 | err_unregister_clk: | ||
| 317 | clk_hw_unregister(&pll_clk->hw); | ||
| 318 | err_unmap_lock: | ||
| 319 | iounmap(pll_clk->lock); | ||
| 320 | err_unmap_base: | ||
| 321 | iounmap(pll_clk->base); | ||
| 322 | err_free_pll_clk: | ||
| 323 | kfree(pll_clk); | ||
| 324 | } | ||
| 325 | CLK_OF_DECLARE(axs10x_pll_clock, "snps,axs10x-arc-pll-clock", | ||
| 326 | of_axs10x_pll_clk_setup); | ||
| 327 | |||
| 328 | static const struct of_device_id axs10x_pll_clk_id[] = { | ||
| 329 | { .compatible = "snps,axs10x-pgu-pll-clock", .data = &pgu_pll_cfg}, | ||
| 330 | { } | ||
| 331 | }; | ||
| 332 | MODULE_DEVICE_TABLE(of, axs10x_pll_clk_id); | ||
| 333 | |||
| 334 | static struct platform_driver axs10x_pll_clk_driver = { | ||
| 335 | .driver = { | ||
| 336 | .name = "axs10x-pll-clock", | ||
| 337 | .of_match_table = axs10x_pll_clk_id, | ||
| 338 | }, | ||
| 339 | .probe = axs10x_pll_clk_probe, | ||
| 340 | .remove = axs10x_pll_clk_remove, | ||
| 341 | }; | ||
| 342 | builtin_platform_driver(axs10x_pll_clk_driver); | ||
| 343 | |||
| 344 | MODULE_AUTHOR("Vlad Zakharov <vzakhar@synopsys.com>"); | ||
| 345 | MODULE_DESCRIPTION("Synopsys AXS10X SDP Generic PLL Clock Driver"); | ||
| 346 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c index 1d99292e2039..e7331ace0337 100644 --- a/drivers/clk/berlin/bg2.c +++ b/drivers/clk/berlin/bg2.c | |||
| @@ -679,8 +679,7 @@ static void __init berlin2_clock_setup(struct device_node *np) | |||
| 679 | if (!IS_ERR(hws[n])) | 679 | if (!IS_ERR(hws[n])) |
| 680 | continue; | 680 | continue; |
| 681 | 681 | ||
| 682 | pr_err("%s: Unable to register leaf clock %d\n", | 682 | pr_err("%pOF: Unable to register leaf clock %d\n", np, n); |
| 683 | np->full_name, n); | ||
| 684 | goto bg2_fail; | 683 | goto bg2_fail; |
| 685 | } | 684 | } |
| 686 | 685 | ||
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c index 3b784b593afd..67c270b143f7 100644 --- a/drivers/clk/berlin/bg2q.c +++ b/drivers/clk/berlin/bg2q.c | |||
| @@ -304,14 +304,14 @@ static void __init berlin2q_clock_setup(struct device_node *np) | |||
| 304 | 304 | ||
| 305 | gbase = of_iomap(parent_np, 0); | 305 | gbase = of_iomap(parent_np, 0); |
| 306 | if (!gbase) { | 306 | if (!gbase) { |
| 307 | pr_err("%s: Unable to map global base\n", np->full_name); | 307 | pr_err("%pOF: Unable to map global base\n", np); |
| 308 | return; | 308 | return; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /* BG2Q CPU PLL is not part of global registers */ | 311 | /* BG2Q CPU PLL is not part of global registers */ |
| 312 | cpupll_base = of_iomap(parent_np, 1); | 312 | cpupll_base = of_iomap(parent_np, 1); |
| 313 | if (!cpupll_base) { | 313 | if (!cpupll_base) { |
| 314 | pr_err("%s: Unable to map cpupll base\n", np->full_name); | 314 | pr_err("%pOF: Unable to map cpupll base\n", np); |
| 315 | iounmap(gbase); | 315 | iounmap(gbase); |
| 316 | return; | 316 | return; |
| 317 | } | 317 | } |
| @@ -376,8 +376,7 @@ static void __init berlin2q_clock_setup(struct device_node *np) | |||
| 376 | if (!IS_ERR(hws[n])) | 376 | if (!IS_ERR(hws[n])) |
| 377 | continue; | 377 | continue; |
| 378 | 378 | ||
| 379 | pr_err("%s: Unable to register leaf clock %d\n", | 379 | pr_err("%pOF: Unable to register leaf clock %d\n", np, n); |
| 380 | np->full_name, n); | ||
| 381 | goto bg2q_fail; | 380 | goto bg2q_fail; |
| 382 | } | 381 | } |
| 383 | 382 | ||
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c index ea8568536193..bf0582cbbf38 100644 --- a/drivers/clk/clk-asm9260.c +++ b/drivers/clk/clk-asm9260.c | |||
| @@ -338,8 +338,8 @@ static void __init asm9260_acc_init(struct device_node *np) | |||
| 338 | if (!IS_ERR(hws[n])) | 338 | if (!IS_ERR(hws[n])) |
| 339 | continue; | 339 | continue; |
| 340 | 340 | ||
| 341 | pr_err("%s: Unable to register leaf clock %d\n", | 341 | pr_err("%pOF: Unable to register leaf clock %d\n", |
| 342 | np->full_name, n); | 342 | np, n); |
| 343 | goto fail; | 343 | goto fail; |
| 344 | } | 344 | } |
| 345 | 345 | ||
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c index 7ec36722f8ab..49819b546134 100644 --- a/drivers/clk/clk-conf.c +++ b/drivers/clk/clk-conf.c | |||
| @@ -23,8 +23,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) | |||
| 23 | num_parents = of_count_phandle_with_args(node, "assigned-clock-parents", | 23 | num_parents = of_count_phandle_with_args(node, "assigned-clock-parents", |
| 24 | "#clock-cells"); | 24 | "#clock-cells"); |
| 25 | if (num_parents == -EINVAL) | 25 | if (num_parents == -EINVAL) |
| 26 | pr_err("clk: invalid value of clock-parents property at %s\n", | 26 | pr_err("clk: invalid value of clock-parents property at %pOF\n", |
| 27 | node->full_name); | 27 | node); |
| 28 | 28 | ||
| 29 | for (index = 0; index < num_parents; index++) { | 29 | for (index = 0; index < num_parents; index++) { |
| 30 | rc = of_parse_phandle_with_args(node, "assigned-clock-parents", | 30 | rc = of_parse_phandle_with_args(node, "assigned-clock-parents", |
| @@ -41,8 +41,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) | |||
| 41 | pclk = of_clk_get_from_provider(&clkspec); | 41 | pclk = of_clk_get_from_provider(&clkspec); |
| 42 | if (IS_ERR(pclk)) { | 42 | if (IS_ERR(pclk)) { |
| 43 | if (PTR_ERR(pclk) != -EPROBE_DEFER) | 43 | if (PTR_ERR(pclk) != -EPROBE_DEFER) |
| 44 | pr_warn("clk: couldn't get parent clock %d for %s\n", | 44 | pr_warn("clk: couldn't get parent clock %d for %pOF\n", |
| 45 | index, node->full_name); | 45 | index, node); |
| 46 | return PTR_ERR(pclk); | 46 | return PTR_ERR(pclk); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| @@ -57,8 +57,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) | |||
| 57 | clk = of_clk_get_from_provider(&clkspec); | 57 | clk = of_clk_get_from_provider(&clkspec); |
| 58 | if (IS_ERR(clk)) { | 58 | if (IS_ERR(clk)) { |
| 59 | if (PTR_ERR(clk) != -EPROBE_DEFER) | 59 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 60 | pr_warn("clk: couldn't get assigned clock %d for %s\n", | 60 | pr_warn("clk: couldn't get assigned clock %d for %pOF\n", |
| 61 | index, node->full_name); | 61 | index, node); |
| 62 | rc = PTR_ERR(clk); | 62 | rc = PTR_ERR(clk); |
| 63 | goto err; | 63 | goto err; |
| 64 | } | 64 | } |
| @@ -102,8 +102,8 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier) | |||
| 102 | clk = of_clk_get_from_provider(&clkspec); | 102 | clk = of_clk_get_from_provider(&clkspec); |
| 103 | if (IS_ERR(clk)) { | 103 | if (IS_ERR(clk)) { |
| 104 | if (PTR_ERR(clk) != -EPROBE_DEFER) | 104 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 105 | pr_warn("clk: couldn't get clock %d for %s\n", | 105 | pr_warn("clk: couldn't get clock %d for %pOF\n", |
| 106 | index, node->full_name); | 106 | index, node); |
| 107 | return PTR_ERR(clk); | 107 | return PTR_ERR(clk); |
| 108 | } | 108 | } |
| 109 | 109 | ||
diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c index c54baede4d68..e8ea81c30f0c 100644 --- a/drivers/clk/clk-cs2000-cp.c +++ b/drivers/clk/clk-cs2000-cp.c | |||
| @@ -343,6 +343,15 @@ static int cs2000_set_rate(struct clk_hw *hw, | |||
| 343 | return __cs2000_set_rate(priv, ch, rate, parent_rate); | 343 | return __cs2000_set_rate(priv, ch, rate, parent_rate); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static int cs2000_set_saved_rate(struct cs2000_priv *priv) | ||
| 347 | { | ||
| 348 | int ch = 0; /* it uses ch0 only at this point */ | ||
| 349 | |||
| 350 | return __cs2000_set_rate(priv, ch, | ||
| 351 | priv->saved_rate, | ||
| 352 | priv->saved_parent_rate); | ||
| 353 | } | ||
| 354 | |||
| 346 | static int cs2000_enable(struct clk_hw *hw) | 355 | static int cs2000_enable(struct clk_hw *hw) |
| 347 | { | 356 | { |
| 348 | struct cs2000_priv *priv = hw_to_priv(hw); | 357 | struct cs2000_priv *priv = hw_to_priv(hw); |
| @@ -535,11 +544,8 @@ probe_err: | |||
| 535 | static int cs2000_resume(struct device *dev) | 544 | static int cs2000_resume(struct device *dev) |
| 536 | { | 545 | { |
| 537 | struct cs2000_priv *priv = dev_get_drvdata(dev); | 546 | struct cs2000_priv *priv = dev_get_drvdata(dev); |
| 538 | int ch = 0; /* it uses ch0 only at this point */ | ||
| 539 | 547 | ||
| 540 | return __cs2000_set_rate(priv, ch, | 548 | return cs2000_set_saved_rate(priv); |
| 541 | priv->saved_rate, | ||
| 542 | priv->saved_parent_rate); | ||
| 543 | } | 549 | } |
| 544 | 550 | ||
| 545 | static const struct dev_pm_ops cs2000_pm_ops = { | 551 | static const struct dev_pm_ops cs2000_pm_ops = { |
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 9bb472cccca6..4ed516cb7276 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
| @@ -385,12 +385,14 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 385 | unsigned long parent_rate) | 385 | unsigned long parent_rate) |
| 386 | { | 386 | { |
| 387 | struct clk_divider *divider = to_clk_divider(hw); | 387 | struct clk_divider *divider = to_clk_divider(hw); |
| 388 | unsigned int value; | 388 | int value; |
| 389 | unsigned long flags = 0; | 389 | unsigned long flags = 0; |
| 390 | u32 val; | 390 | u32 val; |
| 391 | 391 | ||
| 392 | value = divider_get_val(rate, parent_rate, divider->table, | 392 | value = divider_get_val(rate, parent_rate, divider->table, |
| 393 | divider->width, divider->flags); | 393 | divider->width, divider->flags); |
| 394 | if (value < 0) | ||
| 395 | return value; | ||
| 394 | 396 | ||
| 395 | if (divider->lock) | 397 | if (divider->lock) |
| 396 | spin_lock_irqsave(divider->lock, flags); | 398 | spin_lock_irqsave(divider->lock, flags); |
| @@ -403,7 +405,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 403 | val = clk_readl(divider->reg); | 405 | val = clk_readl(divider->reg); |
| 404 | val &= ~(div_mask(divider->width) << divider->shift); | 406 | val &= ~(div_mask(divider->width) << divider->shift); |
| 405 | } | 407 | } |
| 406 | val |= value << divider->shift; | 408 | val |= (u32)value << divider->shift; |
| 407 | clk_writel(val, divider->reg); | 409 | clk_writel(val, divider->reg); |
| 408 | 410 | ||
| 409 | if (divider->lock) | 411 | if (divider->lock) |
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index aab904618eb6..fdf625fb10fa 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c | |||
| @@ -49,16 +49,12 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, | |||
| 49 | return ret; | 49 | return ret; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | 52 | static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate, |
| 53 | unsigned long *parent_rate) | 53 | unsigned long *parent_rate, |
| 54 | unsigned long *m, unsigned long *n) | ||
| 54 | { | 55 | { |
| 55 | struct clk_fractional_divider *fd = to_clk_fd(hw); | 56 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
| 56 | unsigned long scale; | 57 | unsigned long scale; |
| 57 | unsigned long m, n; | ||
| 58 | u64 ret; | ||
| 59 | |||
| 60 | if (!rate || rate >= *parent_rate) | ||
| 61 | return *parent_rate; | ||
| 62 | 58 | ||
| 63 | /* | 59 | /* |
| 64 | * Get rate closer to *parent_rate to guarantee there is no overflow | 60 | * Get rate closer to *parent_rate to guarantee there is no overflow |
| @@ -71,7 +67,23 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 71 | 67 | ||
| 72 | rational_best_approximation(rate, *parent_rate, | 68 | rational_best_approximation(rate, *parent_rate, |
| 73 | GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), | 69 | GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), |
| 74 | &m, &n); | 70 | m, n); |
| 71 | } | ||
| 72 | |||
| 73 | static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 74 | unsigned long *parent_rate) | ||
| 75 | { | ||
| 76 | struct clk_fractional_divider *fd = to_clk_fd(hw); | ||
| 77 | unsigned long m, n; | ||
| 78 | u64 ret; | ||
| 79 | |||
| 80 | if (!rate || rate >= *parent_rate) | ||
| 81 | return *parent_rate; | ||
| 82 | |||
| 83 | if (fd->approximation) | ||
| 84 | fd->approximation(hw, rate, parent_rate, &m, &n); | ||
| 85 | else | ||
| 86 | clk_fd_general_approximation(hw, rate, parent_rate, &m, &n); | ||
| 75 | 87 | ||
| 76 | ret = (u64)*parent_rate * m; | 88 | ret = (u64)*parent_rate * m; |
| 77 | do_div(ret, n); | 89 | do_div(ret, n); |
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 4e0c054a787c..dd82485e09a1 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c | |||
| @@ -86,7 +86,7 @@ static void clk_gate_disable(struct clk_hw *hw) | |||
| 86 | clk_gate_endisable(hw, 0); | 86 | clk_gate_endisable(hw, 0); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | static int clk_gate_is_enabled(struct clk_hw *hw) | 89 | int clk_gate_is_enabled(struct clk_hw *hw) |
| 90 | { | 90 | { |
| 91 | u32 reg; | 91 | u32 reg; |
| 92 | struct clk_gate *gate = to_clk_gate(hw); | 92 | struct clk_gate *gate = to_clk_gate(hw); |
| @@ -101,6 +101,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw) | |||
| 101 | 101 | ||
| 102 | return reg ? 1 : 0; | 102 | return reg ? 1 : 0; |
| 103 | } | 103 | } |
| 104 | EXPORT_SYMBOL_GPL(clk_gate_is_enabled); | ||
| 104 | 105 | ||
| 105 | const struct clk_ops clk_gate_ops = { | 106 | const struct clk_ops clk_gate_ops = { |
| 106 | .enable = clk_gate_enable, | 107 | .enable = clk_gate_enable, |
diff --git a/drivers/clk/clk-gemini.c b/drivers/clk/clk-gemini.c index b4cf2f699a21..f940e5af845b 100644 --- a/drivers/clk/clk-gemini.c +++ b/drivers/clk/clk-gemini.c | |||
| @@ -37,7 +37,6 @@ static DEFINE_SPINLOCK(gemini_clk_lock); | |||
| 37 | 37 | ||
| 38 | #define GEMINI_GLOBAL_MISC_CONTROL 0x30 | 38 | #define GEMINI_GLOBAL_MISC_CONTROL 0x30 |
| 39 | #define PCI_CLK_66MHZ BIT(18) | 39 | #define PCI_CLK_66MHZ BIT(18) |
| 40 | #define PCI_CLK_OE BIT(17) | ||
| 41 | 40 | ||
| 42 | #define GEMINI_GLOBAL_CLOCK_CONTROL 0x34 | 41 | #define GEMINI_GLOBAL_CLOCK_CONTROL 0x34 |
| 43 | #define PCI_CLKRUN_EN BIT(16) | 42 | #define PCI_CLKRUN_EN BIT(16) |
| @@ -159,9 +158,6 @@ static int gemini_pci_enable(struct clk_hw *hw) | |||
| 159 | 158 | ||
| 160 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, | 159 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, |
| 161 | 0, PCI_CLKRUN_EN); | 160 | 0, PCI_CLKRUN_EN); |
| 162 | regmap_update_bits(pciclk->map, | ||
| 163 | GEMINI_GLOBAL_MISC_CONTROL, | ||
| 164 | 0, PCI_CLK_OE); | ||
| 165 | return 0; | 161 | return 0; |
| 166 | } | 162 | } |
| 167 | 163 | ||
| @@ -169,9 +165,6 @@ static void gemini_pci_disable(struct clk_hw *hw) | |||
| 169 | { | 165 | { |
| 170 | struct clk_gemini_pci *pciclk = to_pciclk(hw); | 166 | struct clk_gemini_pci *pciclk = to_pciclk(hw); |
| 171 | 167 | ||
| 172 | regmap_update_bits(pciclk->map, | ||
| 173 | GEMINI_GLOBAL_MISC_CONTROL, | ||
| 174 | PCI_CLK_OE, 0); | ||
| 175 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, | 168 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, |
| 176 | PCI_CLKRUN_EN, 0); | 169 | PCI_CLKRUN_EN, 0); |
| 177 | } | 170 | } |
diff --git a/drivers/clk/clk-hsdk-pll.c b/drivers/clk/clk-hsdk-pll.c new file mode 100644 index 000000000000..bbf237173b37 --- /dev/null +++ b/drivers/clk/clk-hsdk-pll.c | |||
| @@ -0,0 +1,431 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys HSDK SDP Generic PLL clock driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 Synopsys | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2. This program is licensed "as is" without any | ||
| 8 | * warranty of any kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_address.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | |||
| 21 | #define CGU_PLL_CTRL 0x000 /* ARC PLL control register */ | ||
| 22 | #define CGU_PLL_STATUS 0x004 /* ARC PLL status register */ | ||
| 23 | #define CGU_PLL_FMEAS 0x008 /* ARC PLL frequency measurement register */ | ||
| 24 | #define CGU_PLL_MON 0x00C /* ARC PLL monitor register */ | ||
| 25 | |||
| 26 | #define CGU_PLL_CTRL_ODIV_SHIFT 2 | ||
| 27 | #define CGU_PLL_CTRL_IDIV_SHIFT 4 | ||
| 28 | #define CGU_PLL_CTRL_FBDIV_SHIFT 9 | ||
| 29 | #define CGU_PLL_CTRL_BAND_SHIFT 20 | ||
| 30 | |||
| 31 | #define CGU_PLL_CTRL_ODIV_MASK GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT) | ||
| 32 | #define CGU_PLL_CTRL_IDIV_MASK GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT) | ||
| 33 | #define CGU_PLL_CTRL_FBDIV_MASK GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT) | ||
| 34 | |||
| 35 | #define CGU_PLL_CTRL_PD BIT(0) | ||
| 36 | #define CGU_PLL_CTRL_BYPASS BIT(1) | ||
| 37 | |||
| 38 | #define CGU_PLL_STATUS_LOCK BIT(0) | ||
| 39 | #define CGU_PLL_STATUS_ERR BIT(1) | ||
| 40 | |||
| 41 | #define HSDK_PLL_MAX_LOCK_TIME 100 /* 100 us */ | ||
| 42 | |||
| 43 | #define CGU_PLL_SOURCE_MAX 1 | ||
| 44 | |||
| 45 | #define CORE_IF_CLK_THRESHOLD_HZ 500000000 | ||
| 46 | #define CREG_CORE_IF_CLK_DIV_1 0x0 | ||
| 47 | #define CREG_CORE_IF_CLK_DIV_2 0x1 | ||
| 48 | |||
| 49 | struct hsdk_pll_cfg { | ||
| 50 | u32 rate; | ||
| 51 | u32 idiv; | ||
| 52 | u32 fbdiv; | ||
| 53 | u32 odiv; | ||
| 54 | u32 band; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static const struct hsdk_pll_cfg asdt_pll_cfg[] = { | ||
| 58 | { 100000000, 0, 11, 3, 0 }, | ||
| 59 | { 133000000, 0, 15, 3, 0 }, | ||
| 60 | { 200000000, 1, 47, 3, 0 }, | ||
| 61 | { 233000000, 1, 27, 2, 0 }, | ||
| 62 | { 300000000, 1, 35, 2, 0 }, | ||
| 63 | { 333000000, 1, 39, 2, 0 }, | ||
| 64 | { 400000000, 1, 47, 2, 0 }, | ||
| 65 | { 500000000, 0, 14, 1, 0 }, | ||
| 66 | { 600000000, 0, 17, 1, 0 }, | ||
| 67 | { 700000000, 0, 20, 1, 0 }, | ||
| 68 | { 800000000, 0, 23, 1, 0 }, | ||
| 69 | { 900000000, 1, 26, 0, 0 }, | ||
| 70 | { 1000000000, 1, 29, 0, 0 }, | ||
| 71 | { 1100000000, 1, 32, 0, 0 }, | ||
| 72 | { 1200000000, 1, 35, 0, 0 }, | ||
| 73 | { 1300000000, 1, 38, 0, 0 }, | ||
| 74 | { 1400000000, 1, 41, 0, 0 }, | ||
| 75 | { 1500000000, 1, 44, 0, 0 }, | ||
| 76 | { 1600000000, 1, 47, 0, 0 }, | ||
| 77 | {} | ||
| 78 | }; | ||
| 79 | |||
| 80 | static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { | ||
| 81 | { 297000000, 0, 21, 2, 0 }, | ||
| 82 | { 540000000, 0, 19, 1, 0 }, | ||
| 83 | { 594000000, 0, 21, 1, 0 }, | ||
| 84 | {} | ||
| 85 | }; | ||
| 86 | |||
| 87 | struct hsdk_pll_clk { | ||
| 88 | struct clk_hw hw; | ||
| 89 | void __iomem *regs; | ||
| 90 | void __iomem *spec_regs; | ||
| 91 | const struct hsdk_pll_devdata *pll_devdata; | ||
| 92 | struct device *dev; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct hsdk_pll_devdata { | ||
| 96 | const struct hsdk_pll_cfg *pll_cfg; | ||
| 97 | int (*update_rate)(struct hsdk_pll_clk *clk, unsigned long rate, | ||
| 98 | const struct hsdk_pll_cfg *cfg); | ||
| 99 | }; | ||
| 100 | |||
| 101 | static int hsdk_pll_core_update_rate(struct hsdk_pll_clk *, unsigned long, | ||
| 102 | const struct hsdk_pll_cfg *); | ||
| 103 | static int hsdk_pll_comm_update_rate(struct hsdk_pll_clk *, unsigned long, | ||
| 104 | const struct hsdk_pll_cfg *); | ||
| 105 | |||
| 106 | static const struct hsdk_pll_devdata core_pll_devdata = { | ||
| 107 | .pll_cfg = asdt_pll_cfg, | ||
| 108 | .update_rate = hsdk_pll_core_update_rate, | ||
| 109 | }; | ||
| 110 | |||
| 111 | static const struct hsdk_pll_devdata sdt_pll_devdata = { | ||
| 112 | .pll_cfg = asdt_pll_cfg, | ||
| 113 | .update_rate = hsdk_pll_comm_update_rate, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static const struct hsdk_pll_devdata hdmi_pll_devdata = { | ||
| 117 | .pll_cfg = hdmi_pll_cfg, | ||
| 118 | .update_rate = hsdk_pll_comm_update_rate, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static inline void hsdk_pll_write(struct hsdk_pll_clk *clk, u32 reg, u32 val) | ||
| 122 | { | ||
| 123 | iowrite32(val, clk->regs + reg); | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline u32 hsdk_pll_read(struct hsdk_pll_clk *clk, u32 reg) | ||
| 127 | { | ||
| 128 | return ioread32(clk->regs + reg); | ||
| 129 | } | ||
| 130 | |||
| 131 | static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk, | ||
| 132 | const struct hsdk_pll_cfg *cfg) | ||
| 133 | { | ||
| 134 | u32 val = 0; | ||
| 135 | |||
| 136 | /* Powerdown and Bypass bits should be cleared */ | ||
| 137 | val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; | ||
| 138 | val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; | ||
| 139 | val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; | ||
| 140 | val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; | ||
| 141 | |||
| 142 | dev_dbg(clk->dev, "write configurarion: %#x\n", val); | ||
| 143 | |||
| 144 | hsdk_pll_write(clk, CGU_PLL_CTRL, val); | ||
| 145 | } | ||
| 146 | |||
| 147 | static inline bool hsdk_pll_is_locked(struct hsdk_pll_clk *clk) | ||
| 148 | { | ||
| 149 | return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK); | ||
| 150 | } | ||
| 151 | |||
| 152 | static inline bool hsdk_pll_is_err(struct hsdk_pll_clk *clk) | ||
| 153 | { | ||
| 154 | return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR); | ||
| 155 | } | ||
| 156 | |||
| 157 | static inline struct hsdk_pll_clk *to_hsdk_pll_clk(struct clk_hw *hw) | ||
| 158 | { | ||
| 159 | return container_of(hw, struct hsdk_pll_clk, hw); | ||
| 160 | } | ||
| 161 | |||
| 162 | static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw, | ||
| 163 | unsigned long parent_rate) | ||
| 164 | { | ||
| 165 | u32 val; | ||
| 166 | u64 rate; | ||
| 167 | u32 idiv, fbdiv, odiv; | ||
| 168 | struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | ||
| 169 | |||
| 170 | val = hsdk_pll_read(clk, CGU_PLL_CTRL); | ||
| 171 | |||
| 172 | dev_dbg(clk->dev, "current configurarion: %#x\n", val); | ||
| 173 | |||
| 174 | /* Check if PLL is disabled */ | ||
| 175 | if (val & CGU_PLL_CTRL_PD) | ||
| 176 | return 0; | ||
| 177 | |||
| 178 | /* Check if PLL is bypassed */ | ||
| 179 | if (val & CGU_PLL_CTRL_BYPASS) | ||
| 180 | return parent_rate; | ||
| 181 | |||
| 182 | /* input divider = reg.idiv + 1 */ | ||
| 183 | idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT); | ||
| 184 | /* fb divider = 2*(reg.fbdiv + 1) */ | ||
| 185 | fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT)); | ||
| 186 | /* output divider = 2^(reg.odiv) */ | ||
| 187 | odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT); | ||
| 188 | |||
| 189 | rate = (u64)parent_rate * fbdiv; | ||
| 190 | do_div(rate, idiv * odiv); | ||
| 191 | |||
| 192 | return rate; | ||
| 193 | } | ||
| 194 | |||
| 195 | static long hsdk_pll_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 196 | unsigned long *prate) | ||
| 197 | { | ||
| 198 | int i; | ||
| 199 | unsigned long best_rate; | ||
| 200 | struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | ||
| 201 | const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; | ||
| 202 | |||
| 203 | if (pll_cfg[0].rate == 0) | ||
| 204 | return -EINVAL; | ||
| 205 | |||
| 206 | best_rate = pll_cfg[0].rate; | ||
| 207 | |||
| 208 | for (i = 1; pll_cfg[i].rate != 0; i++) { | ||
| 209 | if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) | ||
| 210 | best_rate = pll_cfg[i].rate; | ||
| 211 | } | ||
| 212 | |||
| 213 | dev_dbg(clk->dev, "chosen best rate: %lu\n", best_rate); | ||
| 214 | |||
| 215 | return best_rate; | ||
| 216 | } | ||
| 217 | |||
| 218 | static int hsdk_pll_comm_update_rate(struct hsdk_pll_clk *clk, | ||
| 219 | unsigned long rate, | ||
| 220 | const struct hsdk_pll_cfg *cfg) | ||
| 221 | { | ||
| 222 | hsdk_pll_set_cfg(clk, cfg); | ||
| 223 | |||
| 224 | /* | ||
| 225 | * Wait until CGU relocks and check error status. | ||
| 226 | * If after timeout CGU is unlocked yet return error. | ||
| 227 | */ | ||
| 228 | udelay(HSDK_PLL_MAX_LOCK_TIME); | ||
| 229 | if (!hsdk_pll_is_locked(clk)) | ||
| 230 | return -ETIMEDOUT; | ||
| 231 | |||
| 232 | if (hsdk_pll_is_err(clk)) | ||
| 233 | return -EINVAL; | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int hsdk_pll_core_update_rate(struct hsdk_pll_clk *clk, | ||
| 239 | unsigned long rate, | ||
| 240 | const struct hsdk_pll_cfg *cfg) | ||
| 241 | { | ||
| 242 | /* | ||
| 243 | * When core clock exceeds 500MHz, the divider for the interface | ||
| 244 | * clock must be programmed to div-by-2. | ||
| 245 | */ | ||
| 246 | if (rate > CORE_IF_CLK_THRESHOLD_HZ) | ||
| 247 | iowrite32(CREG_CORE_IF_CLK_DIV_2, clk->spec_regs); | ||
| 248 | |||
| 249 | hsdk_pll_set_cfg(clk, cfg); | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Wait until CGU relocks and check error status. | ||
| 253 | * If after timeout CGU is unlocked yet return error. | ||
| 254 | */ | ||
| 255 | udelay(HSDK_PLL_MAX_LOCK_TIME); | ||
| 256 | if (!hsdk_pll_is_locked(clk)) | ||
| 257 | return -ETIMEDOUT; | ||
| 258 | |||
| 259 | if (hsdk_pll_is_err(clk)) | ||
| 260 | return -EINVAL; | ||
| 261 | |||
| 262 | /* | ||
| 263 | * Program divider to div-by-1 if we succesfuly set core clock below | ||
| 264 | * 500MHz threshold. | ||
| 265 | */ | ||
| 266 | if (rate <= CORE_IF_CLK_THRESHOLD_HZ) | ||
| 267 | iowrite32(CREG_CORE_IF_CLK_DIV_1, clk->spec_regs); | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | static int hsdk_pll_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 273 | unsigned long parent_rate) | ||
| 274 | { | ||
| 275 | int i; | ||
| 276 | struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | ||
| 277 | const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; | ||
| 278 | |||
| 279 | for (i = 0; pll_cfg[i].rate != 0; i++) { | ||
| 280 | if (pll_cfg[i].rate == rate) { | ||
| 281 | return clk->pll_devdata->update_rate(clk, rate, | ||
| 282 | &pll_cfg[i]); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, | ||
| 287 | parent_rate); | ||
| 288 | |||
| 289 | return -EINVAL; | ||
| 290 | } | ||
| 291 | |||
| 292 | static const struct clk_ops hsdk_pll_ops = { | ||
| 293 | .recalc_rate = hsdk_pll_recalc_rate, | ||
| 294 | .round_rate = hsdk_pll_round_rate, | ||
| 295 | .set_rate = hsdk_pll_set_rate, | ||
| 296 | }; | ||
| 297 | |||
| 298 | static int hsdk_pll_clk_probe(struct platform_device *pdev) | ||
| 299 | { | ||
| 300 | int ret; | ||
| 301 | struct resource *mem; | ||
| 302 | const char *parent_name; | ||
| 303 | unsigned int num_parents; | ||
| 304 | struct hsdk_pll_clk *pll_clk; | ||
| 305 | struct clk_init_data init = { }; | ||
| 306 | struct device *dev = &pdev->dev; | ||
| 307 | |||
| 308 | pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); | ||
| 309 | if (!pll_clk) | ||
| 310 | return -ENOMEM; | ||
| 311 | |||
| 312 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 313 | pll_clk->regs = devm_ioremap_resource(dev, mem); | ||
| 314 | if (IS_ERR(pll_clk->regs)) | ||
| 315 | return PTR_ERR(pll_clk->regs); | ||
| 316 | |||
| 317 | init.name = dev->of_node->name; | ||
| 318 | init.ops = &hsdk_pll_ops; | ||
| 319 | parent_name = of_clk_get_parent_name(dev->of_node, 0); | ||
| 320 | init.parent_names = &parent_name; | ||
| 321 | num_parents = of_clk_get_parent_count(dev->of_node); | ||
| 322 | if (num_parents == 0 || num_parents > CGU_PLL_SOURCE_MAX) { | ||
| 323 | dev_err(dev, "wrong clock parents number: %u\n", num_parents); | ||
| 324 | return -EINVAL; | ||
| 325 | } | ||
| 326 | init.num_parents = num_parents; | ||
| 327 | |||
| 328 | pll_clk->hw.init = &init; | ||
| 329 | pll_clk->dev = dev; | ||
| 330 | pll_clk->pll_devdata = of_device_get_match_data(dev); | ||
| 331 | |||
| 332 | if (!pll_clk->pll_devdata) { | ||
| 333 | dev_err(dev, "No OF match data provided\n"); | ||
| 334 | return -EINVAL; | ||
| 335 | } | ||
| 336 | |||
| 337 | ret = devm_clk_hw_register(dev, &pll_clk->hw); | ||
| 338 | if (ret) { | ||
| 339 | dev_err(dev, "failed to register %s clock\n", init.name); | ||
| 340 | return ret; | ||
| 341 | } | ||
| 342 | |||
| 343 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, | ||
| 344 | &pll_clk->hw); | ||
| 345 | } | ||
| 346 | |||
| 347 | static int hsdk_pll_clk_remove(struct platform_device *pdev) | ||
| 348 | { | ||
| 349 | of_clk_del_provider(pdev->dev.of_node); | ||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static void __init of_hsdk_pll_clk_setup(struct device_node *node) | ||
| 354 | { | ||
| 355 | int ret; | ||
| 356 | const char *parent_name; | ||
| 357 | unsigned int num_parents; | ||
| 358 | struct hsdk_pll_clk *pll_clk; | ||
| 359 | struct clk_init_data init = { }; | ||
| 360 | |||
| 361 | pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | ||
| 362 | if (!pll_clk) | ||
| 363 | return; | ||
| 364 | |||
| 365 | pll_clk->regs = of_iomap(node, 0); | ||
| 366 | if (!pll_clk->regs) { | ||
| 367 | pr_err("failed to map pll registers\n"); | ||
| 368 | goto err_free_pll_clk; | ||
| 369 | } | ||
| 370 | |||
| 371 | pll_clk->spec_regs = of_iomap(node, 1); | ||
| 372 | if (!pll_clk->spec_regs) { | ||
| 373 | pr_err("failed to map pll registers\n"); | ||
| 374 | goto err_unmap_comm_regs; | ||
| 375 | } | ||
| 376 | |||
| 377 | init.name = node->name; | ||
| 378 | init.ops = &hsdk_pll_ops; | ||
| 379 | parent_name = of_clk_get_parent_name(node, 0); | ||
| 380 | init.parent_names = &parent_name; | ||
| 381 | num_parents = of_clk_get_parent_count(node); | ||
| 382 | if (num_parents > CGU_PLL_SOURCE_MAX) { | ||
| 383 | pr_err("too much clock parents: %u\n", num_parents); | ||
| 384 | goto err_unmap_spec_regs; | ||
| 385 | } | ||
| 386 | init.num_parents = num_parents; | ||
| 387 | |||
| 388 | pll_clk->hw.init = &init; | ||
| 389 | pll_clk->pll_devdata = &core_pll_devdata; | ||
| 390 | |||
| 391 | ret = clk_hw_register(NULL, &pll_clk->hw); | ||
| 392 | if (ret) { | ||
| 393 | pr_err("failed to register %s clock\n", node->name); | ||
| 394 | goto err_unmap_spec_regs; | ||
| 395 | } | ||
| 396 | |||
| 397 | ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw); | ||
| 398 | if (ret) { | ||
| 399 | pr_err("failed to add hw provider for %s clock\n", node->name); | ||
| 400 | goto err_unmap_spec_regs; | ||
| 401 | } | ||
| 402 | |||
| 403 | return; | ||
| 404 | |||
| 405 | err_unmap_spec_regs: | ||
| 406 | iounmap(pll_clk->spec_regs); | ||
| 407 | err_unmap_comm_regs: | ||
| 408 | iounmap(pll_clk->regs); | ||
| 409 | err_free_pll_clk: | ||
| 410 | kfree(pll_clk); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* Core PLL needed early for ARC cpus timers */ | ||
| 414 | CLK_OF_DECLARE(hsdk_pll_clock, "snps,hsdk-core-pll-clock", | ||
| 415 | of_hsdk_pll_clk_setup); | ||
| 416 | |||
| 417 | static const struct of_device_id hsdk_pll_clk_id[] = { | ||
| 418 | { .compatible = "snps,hsdk-gp-pll-clock", .data = &sdt_pll_devdata}, | ||
| 419 | { .compatible = "snps,hsdk-hdmi-pll-clock", .data = &hdmi_pll_devdata}, | ||
| 420 | { } | ||
| 421 | }; | ||
| 422 | |||
| 423 | static struct platform_driver hsdk_pll_clk_driver = { | ||
| 424 | .driver = { | ||
| 425 | .name = "hsdk-gp-pll-clock", | ||
| 426 | .of_match_table = hsdk_pll_clk_id, | ||
| 427 | }, | ||
| 428 | .probe = hsdk_pll_clk_probe, | ||
| 429 | .remove = hsdk_pll_clk_remove, | ||
| 430 | }; | ||
| 431 | builtin_platform_driver(hsdk_pll_clk_driver); | ||
diff --git a/drivers/clk/clk-mb86s7x.c b/drivers/clk/clk-mb86s7x.c deleted file mode 100644 index 2a83a3ff1d09..000000000000 --- a/drivers/clk/clk-mb86s7x.c +++ /dev/null | |||
| @@ -1,390 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED | ||
| 3 | * Copyright (C) 2015 Linaro Ltd. | ||
| 4 | * | ||
| 5 | * This program is free software: you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation, version 2 of the License. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/clkdev.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/cpu.h> | ||
| 20 | #include <linux/clk-provider.h> | ||
| 21 | #include <linux/spinlock.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/topology.h> | ||
| 24 | #include <linux/mailbox_client.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | |||
| 27 | #include <soc/mb86s7x/scb_mhu.h> | ||
| 28 | |||
| 29 | #define to_crg_clk(p) container_of(p, struct crg_clk, hw) | ||
| 30 | #define to_clc_clk(p) container_of(p, struct cl_clk, hw) | ||
| 31 | |||
| 32 | struct mb86s7x_peri_clk { | ||
| 33 | u32 payload_size; | ||
| 34 | u32 cntrlr; | ||
| 35 | u32 domain; | ||
| 36 | u32 port; | ||
| 37 | u32 en; | ||
| 38 | u64 frequency; | ||
| 39 | } __packed __aligned(4); | ||
| 40 | |||
| 41 | struct hack_rate { | ||
| 42 | unsigned clk_id; | ||
| 43 | unsigned long rate; | ||
| 44 | int gated; | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct crg_clk { | ||
| 48 | struct clk_hw hw; | ||
| 49 | u8 cntrlr, domain, port; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static int crg_gate_control(struct clk_hw *hw, int en) | ||
| 53 | { | ||
| 54 | struct crg_clk *crgclk = to_crg_clk(hw); | ||
| 55 | struct mb86s7x_peri_clk cmd; | ||
| 56 | int ret; | ||
| 57 | |||
| 58 | cmd.payload_size = sizeof(cmd); | ||
| 59 | cmd.cntrlr = crgclk->cntrlr; | ||
| 60 | cmd.domain = crgclk->domain; | ||
| 61 | cmd.port = crgclk->port; | ||
| 62 | cmd.en = en; | ||
| 63 | |||
| 64 | /* Port is UngatedCLK */ | ||
| 65 | if (cmd.port == 8) | ||
| 66 | return en ? 0 : -EINVAL; | ||
| 67 | |||
| 68 | pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u En-%u}\n", | ||
| 69 | __func__, __LINE__, cmd.cntrlr, | ||
| 70 | cmd.domain, cmd.port, cmd.en); | ||
| 71 | |||
| 72 | ret = mb86s7x_send_packet(CMD_PERI_CLOCK_GATE_SET_REQ, | ||
| 73 | &cmd, sizeof(cmd)); | ||
| 74 | if (ret < 0) { | ||
| 75 | pr_err("%s:%d failed!\n", __func__, __LINE__); | ||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u En-%u}\n", | ||
| 80 | __func__, __LINE__, cmd.cntrlr, | ||
| 81 | cmd.domain, cmd.port, cmd.en); | ||
| 82 | |||
| 83 | /* If the request was rejected */ | ||
| 84 | if (cmd.en != en) | ||
| 85 | ret = -EINVAL; | ||
| 86 | else | ||
| 87 | ret = 0; | ||
| 88 | |||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int crg_port_prepare(struct clk_hw *hw) | ||
| 93 | { | ||
| 94 | return crg_gate_control(hw, 1); | ||
| 95 | } | ||
| 96 | |||
| 97 | static void crg_port_unprepare(struct clk_hw *hw) | ||
| 98 | { | ||
| 99 | crg_gate_control(hw, 0); | ||
| 100 | } | ||
| 101 | |||
| 102 | static int | ||
| 103 | crg_rate_control(struct clk_hw *hw, int set, unsigned long *rate) | ||
| 104 | { | ||
| 105 | struct crg_clk *crgclk = to_crg_clk(hw); | ||
| 106 | struct mb86s7x_peri_clk cmd; | ||
| 107 | int code, ret; | ||
| 108 | |||
| 109 | cmd.payload_size = sizeof(cmd); | ||
| 110 | cmd.cntrlr = crgclk->cntrlr; | ||
| 111 | cmd.domain = crgclk->domain; | ||
| 112 | cmd.port = crgclk->port; | ||
| 113 | cmd.frequency = *rate; | ||
| 114 | |||
| 115 | if (set) { | ||
| 116 | code = CMD_PERI_CLOCK_RATE_SET_REQ; | ||
| 117 | pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n", | ||
| 118 | __func__, __LINE__, cmd.cntrlr, | ||
| 119 | cmd.domain, cmd.port, cmd.frequency); | ||
| 120 | } else { | ||
| 121 | code = CMD_PERI_CLOCK_RATE_GET_REQ; | ||
| 122 | pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-GET}\n", | ||
| 123 | __func__, __LINE__, cmd.cntrlr, | ||
| 124 | cmd.domain, cmd.port); | ||
| 125 | } | ||
| 126 | |||
| 127 | ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd)); | ||
| 128 | if (ret < 0) { | ||
| 129 | pr_err("%s:%d failed!\n", __func__, __LINE__); | ||
| 130 | return ret; | ||
| 131 | } | ||
| 132 | |||
| 133 | if (set) | ||
| 134 | pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n", | ||
| 135 | __func__, __LINE__, cmd.cntrlr, | ||
| 136 | cmd.domain, cmd.port, cmd.frequency); | ||
| 137 | else | ||
| 138 | pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-GOT %lluHz}\n", | ||
| 139 | __func__, __LINE__, cmd.cntrlr, | ||
| 140 | cmd.domain, cmd.port, cmd.frequency); | ||
| 141 | |||
| 142 | *rate = cmd.frequency; | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static unsigned long | ||
| 147 | crg_port_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | ||
| 148 | { | ||
| 149 | unsigned long rate; | ||
| 150 | |||
| 151 | crg_rate_control(hw, 0, &rate); | ||
| 152 | |||
| 153 | return rate; | ||
| 154 | } | ||
| 155 | |||
| 156 | static long | ||
| 157 | crg_port_round_rate(struct clk_hw *hw, | ||
| 158 | unsigned long rate, unsigned long *pr) | ||
| 159 | { | ||
| 160 | return rate; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int | ||
| 164 | crg_port_set_rate(struct clk_hw *hw, | ||
| 165 | unsigned long rate, unsigned long parent_rate) | ||
| 166 | { | ||
| 167 | return crg_rate_control(hw, 1, &rate); | ||
| 168 | } | ||
| 169 | |||
| 170 | const struct clk_ops crg_port_ops = { | ||
| 171 | .prepare = crg_port_prepare, | ||
| 172 | .unprepare = crg_port_unprepare, | ||
| 173 | .recalc_rate = crg_port_recalc_rate, | ||
| 174 | .round_rate = crg_port_round_rate, | ||
| 175 | .set_rate = crg_port_set_rate, | ||
| 176 | }; | ||
| 177 | |||
| 178 | struct mb86s70_crg11 { | ||
| 179 | struct mutex lock; /* protects CLK populating and searching */ | ||
| 180 | }; | ||
| 181 | |||
| 182 | static struct clk *crg11_get(struct of_phandle_args *clkspec, void *data) | ||
| 183 | { | ||
| 184 | struct mb86s70_crg11 *crg11 = data; | ||
| 185 | struct clk_init_data init; | ||
| 186 | u32 cntrlr, domain, port; | ||
| 187 | struct crg_clk *crgclk; | ||
| 188 | struct clk *clk; | ||
| 189 | char clkp[20]; | ||
| 190 | |||
| 191 | if (clkspec->args_count != 3) | ||
| 192 | return ERR_PTR(-EINVAL); | ||
| 193 | |||
| 194 | cntrlr = clkspec->args[0]; | ||
| 195 | domain = clkspec->args[1]; | ||
| 196 | port = clkspec->args[2]; | ||
| 197 | |||
| 198 | if (port > 7) | ||
| 199 | snprintf(clkp, 20, "UngatedCLK%d_%X", cntrlr, domain); | ||
| 200 | else | ||
| 201 | snprintf(clkp, 20, "CLK%d_%X_%d", cntrlr, domain, port); | ||
| 202 | |||
| 203 | mutex_lock(&crg11->lock); | ||
| 204 | |||
| 205 | clk = __clk_lookup(clkp); | ||
| 206 | if (clk) { | ||
| 207 | mutex_unlock(&crg11->lock); | ||
| 208 | return clk; | ||
| 209 | } | ||
| 210 | |||
| 211 | crgclk = kzalloc(sizeof(*crgclk), GFP_KERNEL); | ||
| 212 | if (!crgclk) { | ||
| 213 | mutex_unlock(&crg11->lock); | ||
| 214 | return ERR_PTR(-ENOMEM); | ||
| 215 | } | ||
| 216 | |||
| 217 | init.name = clkp; | ||
| 218 | init.num_parents = 0; | ||
| 219 | init.ops = &crg_port_ops; | ||
| 220 | init.flags = 0; | ||
| 221 | crgclk->hw.init = &init; | ||
| 222 | crgclk->cntrlr = cntrlr; | ||
| 223 | crgclk->domain = domain; | ||
| 224 | crgclk->port = port; | ||
| 225 | clk = clk_register(NULL, &crgclk->hw); | ||
| 226 | if (IS_ERR(clk)) | ||
| 227 | pr_err("%s:%d Error!\n", __func__, __LINE__); | ||
| 228 | else | ||
| 229 | pr_debug("Registered %s\n", clkp); | ||
| 230 | |||
| 231 | clk_register_clkdev(clk, clkp, NULL); | ||
| 232 | mutex_unlock(&crg11->lock); | ||
| 233 | return clk; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void __init crg_port_init(struct device_node *node) | ||
| 237 | { | ||
| 238 | struct mb86s70_crg11 *crg11; | ||
| 239 | |||
| 240 | crg11 = kzalloc(sizeof(*crg11), GFP_KERNEL); | ||
| 241 | if (!crg11) | ||
| 242 | return; | ||
| 243 | |||
| 244 | mutex_init(&crg11->lock); | ||
| 245 | |||
| 246 | of_clk_add_provider(node, crg11_get, crg11); | ||
| 247 | } | ||
| 248 | CLK_OF_DECLARE(crg11_gate, "fujitsu,mb86s70-crg11", crg_port_init); | ||
| 249 | |||
| 250 | struct cl_clk { | ||
| 251 | struct clk_hw hw; | ||
| 252 | int cluster; | ||
| 253 | }; | ||
| 254 | |||
| 255 | struct mb86s7x_cpu_freq { | ||
| 256 | u32 payload_size; | ||
| 257 | u32 cluster_class; | ||
| 258 | u32 cluster_id; | ||
| 259 | u32 cpu_id; | ||
| 260 | u64 frequency; | ||
| 261 | }; | ||
| 262 | |||
| 263 | static void mhu_cluster_rate(struct clk_hw *hw, unsigned long *rate, int get) | ||
| 264 | { | ||
| 265 | struct cl_clk *clc = to_clc_clk(hw); | ||
| 266 | struct mb86s7x_cpu_freq cmd; | ||
| 267 | int code, ret; | ||
| 268 | |||
| 269 | cmd.payload_size = sizeof(cmd); | ||
| 270 | cmd.cluster_class = 0; | ||
| 271 | cmd.cluster_id = clc->cluster; | ||
| 272 | cmd.cpu_id = 0; | ||
| 273 | cmd.frequency = *rate; | ||
| 274 | |||
| 275 | if (get) | ||
| 276 | code = CMD_CPU_CLOCK_RATE_GET_REQ; | ||
| 277 | else | ||
| 278 | code = CMD_CPU_CLOCK_RATE_SET_REQ; | ||
| 279 | |||
| 280 | pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n", | ||
| 281 | __func__, __LINE__, cmd.cluster_class, | ||
| 282 | cmd.cluster_id, cmd.cpu_id, cmd.frequency); | ||
| 283 | |||
| 284 | ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd)); | ||
| 285 | if (ret < 0) { | ||
| 286 | pr_err("%s:%d failed!\n", __func__, __LINE__); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | |||
| 290 | pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n", | ||
| 291 | __func__, __LINE__, cmd.cluster_class, | ||
| 292 | cmd.cluster_id, cmd.cpu_id, cmd.frequency); | ||
| 293 | |||
| 294 | *rate = cmd.frequency; | ||
| 295 | } | ||
| 296 | |||
| 297 | static unsigned long | ||
| 298 | clc_recalc_rate(struct clk_hw *hw, unsigned long unused) | ||
| 299 | { | ||
| 300 | unsigned long rate; | ||
| 301 | |||
| 302 | mhu_cluster_rate(hw, &rate, 1); | ||
| 303 | return rate; | ||
| 304 | } | ||
| 305 | |||
| 306 | static long | ||
| 307 | clc_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 308 | unsigned long *unused) | ||
| 309 | { | ||
| 310 | return rate; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int | ||
| 314 | clc_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 315 | unsigned long unused) | ||
| 316 | { | ||
| 317 | unsigned long res = rate; | ||
| 318 | |||
| 319 | mhu_cluster_rate(hw, &res, 0); | ||
| 320 | |||
| 321 | return (res == rate) ? 0 : -EINVAL; | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct clk_ops clk_clc_ops = { | ||
| 325 | .recalc_rate = clc_recalc_rate, | ||
| 326 | .round_rate = clc_round_rate, | ||
| 327 | .set_rate = clc_set_rate, | ||
| 328 | }; | ||
| 329 | |||
| 330 | static struct clk_hw *mb86s7x_clclk_register(struct device *cpu_dev) | ||
| 331 | { | ||
| 332 | struct clk_init_data init; | ||
| 333 | struct cl_clk *clc; | ||
| 334 | int ret; | ||
| 335 | |||
| 336 | clc = kzalloc(sizeof(*clc), GFP_KERNEL); | ||
| 337 | if (!clc) | ||
| 338 | return ERR_PTR(-ENOMEM); | ||
| 339 | |||
| 340 | clc->hw.init = &init; | ||
| 341 | clc->cluster = topology_physical_package_id(cpu_dev->id); | ||
| 342 | |||
| 343 | init.name = dev_name(cpu_dev); | ||
| 344 | init.ops = &clk_clc_ops; | ||
| 345 | init.flags = CLK_GET_RATE_NOCACHE; | ||
| 346 | init.num_parents = 0; | ||
| 347 | |||
| 348 | ret = devm_clk_hw_register(cpu_dev, &clc->hw); | ||
| 349 | if (ret) | ||
| 350 | return ERR_PTR(ret); | ||
| 351 | return &clc->hw; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int mb86s7x_clclk_of_init(void) | ||
| 355 | { | ||
| 356 | int cpu, ret = -ENODEV; | ||
| 357 | struct device_node *np; | ||
| 358 | struct clk_hw *hw; | ||
| 359 | |||
| 360 | np = of_find_compatible_node(NULL, NULL, "fujitsu,mb86s70-scb-1.0"); | ||
| 361 | if (!np || !of_device_is_available(np)) | ||
| 362 | goto exit; | ||
| 363 | |||
| 364 | for_each_possible_cpu(cpu) { | ||
| 365 | struct device *cpu_dev = get_cpu_device(cpu); | ||
| 366 | |||
| 367 | if (!cpu_dev) { | ||
| 368 | pr_err("failed to get cpu%d device\n", cpu); | ||
| 369 | continue; | ||
| 370 | } | ||
| 371 | |||
| 372 | hw = mb86s7x_clclk_register(cpu_dev); | ||
| 373 | if (IS_ERR(hw)) { | ||
| 374 | pr_err("failed to register cpu%d clock\n", cpu); | ||
| 375 | continue; | ||
| 376 | } | ||
| 377 | if (clk_hw_register_clkdev(hw, NULL, dev_name(cpu_dev))) { | ||
| 378 | pr_err("failed to register cpu%d clock lookup\n", cpu); | ||
| 379 | continue; | ||
| 380 | } | ||
| 381 | pr_debug("registered clk for %s\n", dev_name(cpu_dev)); | ||
| 382 | } | ||
| 383 | ret = 0; | ||
| 384 | |||
| 385 | platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0); | ||
| 386 | exit: | ||
| 387 | of_node_put(np); | ||
| 388 | return ret; | ||
| 389 | } | ||
| 390 | module_init(mb86s7x_clclk_of_init); | ||
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c index b86dac851116..58428d0043fd 100644 --- a/drivers/clk/clk-moxart.c +++ b/drivers/clk/clk-moxart.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | static void __init moxart_of_pll_clk_init(struct device_node *node) | 19 | static void __init moxart_of_pll_clk_init(struct device_node *node) |
| 20 | { | 20 | { |
| 21 | static void __iomem *base; | 21 | void __iomem *base; |
| 22 | struct clk_hw *hw; | 22 | struct clk_hw *hw; |
| 23 | struct clk *ref_clk; | 23 | struct clk *ref_clk; |
| 24 | unsigned int mul; | 24 | unsigned int mul; |
| @@ -30,7 +30,7 @@ static void __init moxart_of_pll_clk_init(struct device_node *node) | |||
| 30 | 30 | ||
| 31 | base = of_iomap(node, 0); | 31 | base = of_iomap(node, 0); |
| 32 | if (!base) { | 32 | if (!base) { |
| 33 | pr_err("%s: of_iomap failed\n", node->full_name); | 33 | pr_err("%pOF: of_iomap failed\n", node); |
| 34 | return; | 34 | return; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| @@ -39,13 +39,13 @@ static void __init moxart_of_pll_clk_init(struct device_node *node) | |||
| 39 | 39 | ||
| 40 | ref_clk = of_clk_get(node, 0); | 40 | ref_clk = of_clk_get(node, 0); |
| 41 | if (IS_ERR(ref_clk)) { | 41 | if (IS_ERR(ref_clk)) { |
| 42 | pr_err("%s: of_clk_get failed\n", node->full_name); | 42 | pr_err("%pOF: of_clk_get failed\n", node); |
| 43 | return; | 43 | return; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); | 46 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); |
| 47 | if (IS_ERR(hw)) { | 47 | if (IS_ERR(hw)) { |
| 48 | pr_err("%s: failed to register clock\n", node->full_name); | 48 | pr_err("%pOF: failed to register clock\n", node); |
| 49 | return; | 49 | return; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| @@ -57,7 +57,7 @@ CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", | |||
| 57 | 57 | ||
| 58 | static void __init moxart_of_apb_clk_init(struct device_node *node) | 58 | static void __init moxart_of_apb_clk_init(struct device_node *node) |
| 59 | { | 59 | { |
| 60 | static void __iomem *base; | 60 | void __iomem *base; |
| 61 | struct clk_hw *hw; | 61 | struct clk_hw *hw; |
| 62 | struct clk *pll_clk; | 62 | struct clk *pll_clk; |
| 63 | unsigned int div, val; | 63 | unsigned int div, val; |
| @@ -70,7 +70,7 @@ static void __init moxart_of_apb_clk_init(struct device_node *node) | |||
| 70 | 70 | ||
| 71 | base = of_iomap(node, 0); | 71 | base = of_iomap(node, 0); |
| 72 | if (!base) { | 72 | if (!base) { |
| 73 | pr_err("%s: of_iomap failed\n", node->full_name); | 73 | pr_err("%pOF: of_iomap failed\n", node); |
| 74 | return; | 74 | return; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| @@ -83,13 +83,13 @@ static void __init moxart_of_apb_clk_init(struct device_node *node) | |||
| 83 | 83 | ||
| 84 | pll_clk = of_clk_get(node, 0); | 84 | pll_clk = of_clk_get(node, 0); |
| 85 | if (IS_ERR(pll_clk)) { | 85 | if (IS_ERR(pll_clk)) { |
| 86 | pr_err("%s: of_clk_get failed\n", node->full_name); | 86 | pr_err("%pOF: of_clk_get failed\n", node); |
| 87 | return; | 87 | return; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div); | 90 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div); |
| 91 | if (IS_ERR(hw)) { | 91 | if (IS_ERR(hw)) { |
| 92 | pr_err("%s: failed to register clock\n", node->full_name); | 92 | pr_err("%pOF: failed to register clock\n", node); |
| 93 | return; | 93 | return; |
| 94 | } | 94 | } |
| 95 | 95 | ||
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index f3931e38fac0..b0ea753b8709 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
| 14 | #include <linux/clk-provider.h> | 14 | #include <linux/clk-provider.h> |
| 15 | #include <linux/clkdev.h> | ||
| 15 | #include <linux/fsl/guts.h> | 16 | #include <linux/fsl/guts.h> |
| 16 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| @@ -537,6 +538,17 @@ static const struct clockgen_chipinfo chipinfo[] = { | |||
| 537 | .flags = CG_PLL_8BIT, | 538 | .flags = CG_PLL_8BIT, |
| 538 | }, | 539 | }, |
| 539 | { | 540 | { |
| 541 | .compat = "fsl,ls1088a-clockgen", | ||
| 542 | .cmux_groups = { | ||
| 543 | &clockgen2_cmux_cga12 | ||
| 544 | }, | ||
| 545 | .cmux_to_group = { | ||
| 546 | 0, 0, -1 | ||
| 547 | }, | ||
| 548 | .pll_mask = 0x07, | ||
| 549 | .flags = CG_VER3 | CG_LITTLE_ENDIAN, | ||
| 550 | }, | ||
| 551 | { | ||
| 540 | .compat = "fsl,ls1012a-clockgen", | 552 | .compat = "fsl,ls1012a-clockgen", |
| 541 | .cmux_groups = { | 553 | .cmux_groups = { |
| 542 | &ls1012a_cmux | 554 | &ls1012a_cmux |
| @@ -1113,6 +1125,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx) | |||
| 1113 | 1125 | ||
| 1114 | for (i = 0; i < ARRAY_SIZE(pll->div); i++) { | 1126 | for (i = 0; i < ARRAY_SIZE(pll->div); i++) { |
| 1115 | struct clk *clk; | 1127 | struct clk *clk; |
| 1128 | int ret; | ||
| 1116 | 1129 | ||
| 1117 | snprintf(pll->div[i].name, sizeof(pll->div[i].name), | 1130 | snprintf(pll->div[i].name, sizeof(pll->div[i].name), |
| 1118 | "cg-pll%d-div%d", idx, i + 1); | 1131 | "cg-pll%d-div%d", idx, i + 1); |
| @@ -1126,6 +1139,11 @@ static void __init create_one_pll(struct clockgen *cg, int idx) | |||
| 1126 | } | 1139 | } |
| 1127 | 1140 | ||
| 1128 | pll->div[i].clk = clk; | 1141 | pll->div[i].clk = clk; |
| 1142 | ret = clk_register_clkdev(clk, pll->div[i].name, NULL); | ||
| 1143 | if (ret != 0) | ||
| 1144 | pr_err("%s: %s: register to lookup table failed %ld\n", | ||
| 1145 | __func__, pll->div[i].name, PTR_ERR(clk)); | ||
| 1146 | |||
| 1129 | } | 1147 | } |
| 1130 | } | 1148 | } |
| 1131 | 1149 | ||
| @@ -1348,8 +1366,7 @@ static void __init clockgen_init(struct device_node *np) | |||
| 1348 | } | 1366 | } |
| 1349 | 1367 | ||
| 1350 | if (i == ARRAY_SIZE(chipinfo)) { | 1368 | if (i == ARRAY_SIZE(chipinfo)) { |
| 1351 | pr_err("%s: unknown clockgen node %s\n", __func__, | 1369 | pr_err("%s: unknown clockgen node %pOF\n", __func__, np); |
| 1352 | np->full_name); | ||
| 1353 | goto err; | 1370 | goto err; |
| 1354 | } | 1371 | } |
| 1355 | clockgen.info = chipinfo[i]; | 1372 | clockgen.info = chipinfo[i]; |
| @@ -1362,8 +1379,8 @@ static void __init clockgen_init(struct device_node *np) | |||
| 1362 | if (guts) { | 1379 | if (guts) { |
| 1363 | clockgen.guts = of_iomap(guts, 0); | 1380 | clockgen.guts = of_iomap(guts, 0); |
| 1364 | if (!clockgen.guts) { | 1381 | if (!clockgen.guts) { |
| 1365 | pr_err("%s: Couldn't map %s regs\n", __func__, | 1382 | pr_err("%s: Couldn't map %pOF regs\n", __func__, |
| 1366 | guts->full_name); | 1383 | guts); |
| 1367 | } | 1384 | } |
| 1368 | } | 1385 | } |
| 1369 | 1386 | ||
| @@ -1398,6 +1415,7 @@ CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init); | |||
| 1398 | CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); | 1415 | CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); |
| 1399 | CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); | 1416 | CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); |
| 1400 | CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init); | 1417 | CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init); |
| 1418 | CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init); | ||
| 1401 | CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); | 1419 | CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); |
| 1402 | 1420 | ||
| 1403 | /* Legacy nodes */ | 1421 | /* Legacy nodes */ |
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 2492442eea77..20d90769cced 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c | |||
| @@ -519,6 +519,11 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 519 | SI5351_CLK_INTEGER_MODE, | 519 | SI5351_CLK_INTEGER_MODE, |
| 520 | (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0); | 520 | (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0); |
| 521 | 521 | ||
| 522 | /* Do a pll soft reset on the affected pll */ | ||
| 523 | si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET, | ||
| 524 | hwdata->num == 0 ? SI5351_PLL_RESET_A : | ||
| 525 | SI5351_PLL_RESET_B); | ||
| 526 | |||
| 522 | dev_dbg(&hwdata->drvdata->client->dev, | 527 | dev_dbg(&hwdata->drvdata->client->dev, |
| 523 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", | 528 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", |
| 524 | __func__, clk_hw_get_name(hw), | 529 | __func__, clk_hw_get_name(hw), |
| @@ -1091,13 +1096,6 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 1091 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, | 1096 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, |
| 1092 | SI5351_CLK_POWERDOWN, 0); | 1097 | SI5351_CLK_POWERDOWN, 0); |
| 1093 | 1098 | ||
| 1094 | /* | ||
| 1095 | * Do a pll soft reset on both plls, needed in some cases to get | ||
| 1096 | * all outputs running. | ||
| 1097 | */ | ||
| 1098 | si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET, | ||
| 1099 | SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); | ||
| 1100 | |||
| 1101 | dev_dbg(&hwdata->drvdata->client->dev, | 1099 | dev_dbg(&hwdata->drvdata->client->dev, |
| 1102 | "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", | 1100 | "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", |
| 1103 | __func__, clk_hw_get_name(hw), (1 << rdiv), | 1101 | __func__, clk_hw_get_name(hw), (1 << rdiv), |
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index 68e2a4e499f1..96c6b6bc8f0e 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c | |||
| @@ -1541,8 +1541,8 @@ static void __init stm32f4_rcc_init(struct device_node *np) | |||
| 1541 | base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); | 1541 | base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); |
| 1542 | 1542 | ||
| 1543 | if (IS_ERR(clks[idx])) { | 1543 | if (IS_ERR(clks[idx])) { |
| 1544 | pr_err("%s: Unable to register leaf clock %s\n", | 1544 | pr_err("%pOF: Unable to register leaf clock %s\n", |
| 1545 | np->full_name, gd->name); | 1545 | np, gd->name); |
| 1546 | goto fail; | 1546 | goto fail; |
| 1547 | } | 1547 | } |
| 1548 | } | 1548 | } |
diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c new file mode 100644 index 000000000000..a94c3f56c590 --- /dev/null +++ b/drivers/clk/clk-stm32h7.c | |||
| @@ -0,0 +1,1410 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Gabriel Fernandez 2017 | ||
| 3 | * Author: Gabriel Fernandez <gabriel.fernandez@st.com> | ||
| 4 | * | ||
| 5 | * License terms: GPL V2.0. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms and conditions of the GNU General Public License, | ||
| 9 | * version 2, as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/clk-provider.h> | ||
| 22 | #include <linux/err.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/mfd/syscon.h> | ||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/of_address.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/spinlock.h> | ||
| 29 | #include <linux/regmap.h> | ||
| 30 | |||
| 31 | #include <dt-bindings/clock/stm32h7-clks.h> | ||
| 32 | |||
| 33 | /* Reset Clock Control Registers */ | ||
| 34 | #define RCC_CR 0x00 | ||
| 35 | #define RCC_CFGR 0x10 | ||
| 36 | #define RCC_D1CFGR 0x18 | ||
| 37 | #define RCC_D2CFGR 0x1C | ||
| 38 | #define RCC_D3CFGR 0x20 | ||
| 39 | #define RCC_PLLCKSELR 0x28 | ||
| 40 | #define RCC_PLLCFGR 0x2C | ||
| 41 | #define RCC_PLL1DIVR 0x30 | ||
| 42 | #define RCC_PLL1FRACR 0x34 | ||
| 43 | #define RCC_PLL2DIVR 0x38 | ||
| 44 | #define RCC_PLL2FRACR 0x3C | ||
| 45 | #define RCC_PLL3DIVR 0x40 | ||
| 46 | #define RCC_PLL3FRACR 0x44 | ||
| 47 | #define RCC_D1CCIPR 0x4C | ||
| 48 | #define RCC_D2CCIP1R 0x50 | ||
| 49 | #define RCC_D2CCIP2R 0x54 | ||
| 50 | #define RCC_D3CCIPR 0x58 | ||
| 51 | #define RCC_BDCR 0x70 | ||
| 52 | #define RCC_CSR 0x74 | ||
| 53 | #define RCC_AHB3ENR 0xD4 | ||
| 54 | #define RCC_AHB1ENR 0xD8 | ||
| 55 | #define RCC_AHB2ENR 0xDC | ||
| 56 | #define RCC_AHB4ENR 0xE0 | ||
| 57 | #define RCC_APB3ENR 0xE4 | ||
| 58 | #define RCC_APB1LENR 0xE8 | ||
| 59 | #define RCC_APB1HENR 0xEC | ||
| 60 | #define RCC_APB2ENR 0xF0 | ||
| 61 | #define RCC_APB4ENR 0xF4 | ||
| 62 | |||
| 63 | static DEFINE_SPINLOCK(stm32rcc_lock); | ||
| 64 | |||
| 65 | static void __iomem *base; | ||
| 66 | static struct clk_hw **hws; | ||
| 67 | |||
| 68 | /* System clock parent */ | ||
| 69 | static const char * const sys_src[] = { | ||
| 70 | "hsi_ck", "csi_ck", "hse_ck", "pll1_p" }; | ||
| 71 | |||
| 72 | static const char * const tracein_src[] = { | ||
| 73 | "hsi_ck", "csi_ck", "hse_ck", "pll1_r" }; | ||
| 74 | |||
| 75 | static const char * const per_src[] = { | ||
| 76 | "hsi_ker", "csi_ker", "hse_ck", "disabled" }; | ||
| 77 | |||
| 78 | static const char * const pll_src[] = { | ||
| 79 | "hsi_ck", "csi_ck", "hse_ck", "no clock" }; | ||
| 80 | |||
| 81 | static const char * const sdmmc_src[] = { "pll1_q", "pll2_r" }; | ||
| 82 | |||
| 83 | static const char * const dsi_src[] = { "ck_dsi_phy", "pll2_q" }; | ||
| 84 | |||
| 85 | static const char * const qspi_src[] = { | ||
| 86 | "hclk", "pll1_q", "pll2_r", "per_ck" }; | ||
| 87 | |||
| 88 | static const char * const fmc_src[] = { | ||
| 89 | "hclk", "pll1_q", "pll2_r", "per_ck" }; | ||
| 90 | |||
| 91 | /* Kernel clock parent */ | ||
| 92 | static const char * const swp_src[] = { "pclk1", "hsi_ker" }; | ||
| 93 | |||
| 94 | static const char * const fdcan_src[] = { "hse_ck", "pll1_q", "pll2_q" }; | ||
| 95 | |||
| 96 | static const char * const dfsdm1_src[] = { "pclk2", "sys_ck" }; | ||
| 97 | |||
| 98 | static const char * const spdifrx_src[] = { | ||
| 99 | "pll1_q", "pll2_r", "pll3_r", "hsi_ker" }; | ||
| 100 | |||
| 101 | static const char *spi_src1[5] = { | ||
| 102 | "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; | ||
| 103 | |||
| 104 | static const char * const spi_src2[] = { | ||
| 105 | "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; | ||
| 106 | |||
| 107 | static const char * const spi_src3[] = { | ||
| 108 | "pclk4", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; | ||
| 109 | |||
| 110 | static const char * const lptim_src1[] = { | ||
| 111 | "pclk1", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; | ||
| 112 | |||
| 113 | static const char * const lptim_src2[] = { | ||
| 114 | "pclk4", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; | ||
| 115 | |||
| 116 | static const char * const cec_src[] = {"lse_ck", "lsi_ck", "csi_ker_div122" }; | ||
| 117 | |||
| 118 | static const char * const usbotg_src[] = {"pll1_q", "pll3_q", "rc48_ck" }; | ||
| 119 | |||
| 120 | /* i2c 1,2,3 src */ | ||
| 121 | static const char * const i2c_src1[] = { | ||
| 122 | "pclk1", "pll3_r", "hsi_ker", "csi_ker" }; | ||
| 123 | |||
| 124 | static const char * const i2c_src2[] = { | ||
| 125 | "pclk4", "pll3_r", "hsi_ker", "csi_ker" }; | ||
| 126 | |||
| 127 | static const char * const rng_src[] = { | ||
| 128 | "rc48_ck", "pll1_q", "lse_ck", "lsi_ck" }; | ||
| 129 | |||
| 130 | /* usart 1,6 src */ | ||
| 131 | static const char * const usart_src1[] = { | ||
| 132 | "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; | ||
| 133 | |||
| 134 | /* usart 2,3,4,5,7,8 src */ | ||
| 135 | static const char * const usart_src2[] = { | ||
| 136 | "pclk1", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; | ||
| 137 | |||
| 138 | static const char *sai_src[5] = { | ||
| 139 | "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; | ||
| 140 | |||
| 141 | static const char * const adc_src[] = { "pll2_p", "pll3_r", "per_ck" }; | ||
| 142 | |||
| 143 | /* lptim 2,3,4,5 src */ | ||
| 144 | static const char * const lpuart1_src[] = { | ||
| 145 | "pclk3", "pll2_q", "pll3_q", "csi_ker", "lse_ck" }; | ||
| 146 | |||
| 147 | static const char * const hrtim_src[] = { "tim2_ker", "d1cpre" }; | ||
| 148 | |||
| 149 | /* RTC clock parent */ | ||
| 150 | static const char * const rtc_src[] = { "off", "lse_ck", "lsi_ck", "hse_1M" }; | ||
| 151 | |||
| 152 | /* Micro-controller output clock parent */ | ||
| 153 | static const char * const mco_src1[] = { | ||
| 154 | "hsi_ck", "lse_ck", "hse_ck", "pll1_q", "rc48_ck" }; | ||
| 155 | |||
| 156 | static const char * const mco_src2[] = { | ||
| 157 | "sys_ck", "pll2_p", "hse_ck", "pll1_p", "csi_ck", "lsi_ck" }; | ||
| 158 | |||
| 159 | /* LCD clock */ | ||
| 160 | static const char * const ltdc_src[] = {"pll3_r"}; | ||
| 161 | |||
| 162 | /* Gate clock with ready bit and backup domain management */ | ||
| 163 | struct stm32_ready_gate { | ||
| 164 | struct clk_gate gate; | ||
| 165 | u8 bit_rdy; | ||
| 166 | }; | ||
| 167 | |||
| 168 | #define to_ready_gate_clk(_rgate) container_of(_rgate, struct stm32_ready_gate,\ | ||
| 169 | gate) | ||
| 170 | |||
| 171 | #define RGATE_TIMEOUT 10000 | ||
| 172 | |||
| 173 | static int ready_gate_clk_enable(struct clk_hw *hw) | ||
| 174 | { | ||
| 175 | struct clk_gate *gate = to_clk_gate(hw); | ||
| 176 | struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); | ||
| 177 | int bit_status; | ||
| 178 | unsigned int timeout = RGATE_TIMEOUT; | ||
| 179 | |||
| 180 | if (clk_gate_ops.is_enabled(hw)) | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | clk_gate_ops.enable(hw); | ||
| 184 | |||
| 185 | /* We can't use readl_poll_timeout() because we can blocked if | ||
| 186 | * someone enables this clock before clocksource changes. | ||
| 187 | * Only jiffies counter is available. Jiffies are incremented by | ||
| 188 | * interruptions and enable op does not allow to be interrupted. | ||
| 189 | */ | ||
| 190 | do { | ||
| 191 | bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy)); | ||
| 192 | |||
| 193 | if (bit_status) | ||
| 194 | udelay(100); | ||
| 195 | |||
| 196 | } while (bit_status && --timeout); | ||
| 197 | |||
| 198 | return bit_status; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void ready_gate_clk_disable(struct clk_hw *hw) | ||
| 202 | { | ||
| 203 | struct clk_gate *gate = to_clk_gate(hw); | ||
| 204 | struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); | ||
| 205 | int bit_status; | ||
| 206 | unsigned int timeout = RGATE_TIMEOUT; | ||
| 207 | |||
| 208 | if (!clk_gate_ops.is_enabled(hw)) | ||
| 209 | return; | ||
| 210 | |||
| 211 | clk_gate_ops.disable(hw); | ||
| 212 | |||
| 213 | do { | ||
| 214 | bit_status = !!(readl(gate->reg) & BIT(rgate->bit_rdy)); | ||
| 215 | |||
| 216 | if (bit_status) | ||
| 217 | udelay(100); | ||
| 218 | |||
| 219 | } while (bit_status && --timeout); | ||
| 220 | } | ||
| 221 | |||
| 222 | static const struct clk_ops ready_gate_clk_ops = { | ||
| 223 | .enable = ready_gate_clk_enable, | ||
| 224 | .disable = ready_gate_clk_disable, | ||
| 225 | .is_enabled = clk_gate_is_enabled, | ||
| 226 | }; | ||
| 227 | |||
| 228 | static struct clk_hw *clk_register_ready_gate(struct device *dev, | ||
| 229 | const char *name, const char *parent_name, | ||
| 230 | void __iomem *reg, u8 bit_idx, u8 bit_rdy, | ||
| 231 | unsigned long flags, spinlock_t *lock) | ||
| 232 | { | ||
| 233 | struct stm32_ready_gate *rgate; | ||
| 234 | struct clk_init_data init = { NULL }; | ||
| 235 | struct clk_hw *hw; | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | rgate = kzalloc(sizeof(*rgate), GFP_KERNEL); | ||
| 239 | if (!rgate) | ||
| 240 | return ERR_PTR(-ENOMEM); | ||
| 241 | |||
| 242 | init.name = name; | ||
| 243 | init.ops = &ready_gate_clk_ops; | ||
| 244 | init.flags = flags; | ||
| 245 | init.parent_names = &parent_name; | ||
| 246 | init.num_parents = 1; | ||
| 247 | |||
| 248 | rgate->bit_rdy = bit_rdy; | ||
| 249 | rgate->gate.lock = lock; | ||
| 250 | rgate->gate.reg = reg; | ||
| 251 | rgate->gate.bit_idx = bit_idx; | ||
| 252 | rgate->gate.hw.init = &init; | ||
| 253 | |||
| 254 | hw = &rgate->gate.hw; | ||
| 255 | ret = clk_hw_register(dev, hw); | ||
| 256 | if (ret) { | ||
| 257 | kfree(rgate); | ||
| 258 | hw = ERR_PTR(ret); | ||
| 259 | } | ||
| 260 | |||
| 261 | return hw; | ||
| 262 | } | ||
| 263 | |||
| 264 | struct gate_cfg { | ||
| 265 | u32 offset; | ||
| 266 | u8 bit_idx; | ||
| 267 | }; | ||
| 268 | |||
| 269 | struct muxdiv_cfg { | ||
| 270 | u32 offset; | ||
| 271 | u8 shift; | ||
| 272 | u8 width; | ||
| 273 | }; | ||
| 274 | |||
| 275 | struct composite_clk_cfg { | ||
| 276 | struct gate_cfg *gate; | ||
| 277 | struct muxdiv_cfg *mux; | ||
| 278 | struct muxdiv_cfg *div; | ||
| 279 | const char *name; | ||
| 280 | const char * const *parent_name; | ||
| 281 | int num_parents; | ||
| 282 | u32 flags; | ||
| 283 | }; | ||
| 284 | |||
| 285 | struct composite_clk_gcfg_t { | ||
| 286 | u8 flags; | ||
| 287 | const struct clk_ops *ops; | ||
| 288 | }; | ||
| 289 | |||
| 290 | /* | ||
| 291 | * General config definition of a composite clock (only clock diviser for rate) | ||
| 292 | */ | ||
| 293 | struct composite_clk_gcfg { | ||
| 294 | struct composite_clk_gcfg_t *mux; | ||
| 295 | struct composite_clk_gcfg_t *div; | ||
| 296 | struct composite_clk_gcfg_t *gate; | ||
| 297 | }; | ||
| 298 | |||
| 299 | #define M_CFG_MUX(_mux_ops, _mux_flags)\ | ||
| 300 | .mux = &(struct composite_clk_gcfg_t) { _mux_flags, _mux_ops} | ||
| 301 | |||
| 302 | #define M_CFG_DIV(_rate_ops, _rate_flags)\ | ||
| 303 | .div = &(struct composite_clk_gcfg_t) {_rate_flags, _rate_ops} | ||
| 304 | |||
| 305 | #define M_CFG_GATE(_gate_ops, _gate_flags)\ | ||
| 306 | .gate = &(struct composite_clk_gcfg_t) { _gate_flags, _gate_ops} | ||
| 307 | |||
| 308 | static struct clk_mux *_get_cmux(void __iomem *reg, u8 shift, u8 width, | ||
| 309 | u32 flags, spinlock_t *lock) | ||
| 310 | { | ||
| 311 | struct clk_mux *mux; | ||
| 312 | |||
| 313 | mux = kzalloc(sizeof(*mux), GFP_KERNEL); | ||
| 314 | if (!mux) | ||
| 315 | return ERR_PTR(-ENOMEM); | ||
| 316 | |||
| 317 | mux->reg = reg; | ||
| 318 | mux->shift = shift; | ||
| 319 | mux->mask = (1 << width) - 1; | ||
| 320 | mux->flags = flags; | ||
| 321 | mux->lock = lock; | ||
| 322 | |||
| 323 | return mux; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct clk_divider *_get_cdiv(void __iomem *reg, u8 shift, u8 width, | ||
| 327 | u32 flags, spinlock_t *lock) | ||
| 328 | { | ||
| 329 | struct clk_divider *div; | ||
| 330 | |||
| 331 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
| 332 | |||
| 333 | if (!div) | ||
| 334 | return ERR_PTR(-ENOMEM); | ||
| 335 | |||
| 336 | div->reg = reg; | ||
| 337 | div->shift = shift; | ||
| 338 | div->width = width; | ||
| 339 | div->flags = flags; | ||
| 340 | div->lock = lock; | ||
| 341 | |||
| 342 | return div; | ||
| 343 | } | ||
| 344 | |||
| 345 | static struct clk_gate *_get_cgate(void __iomem *reg, u8 bit_idx, u32 flags, | ||
| 346 | spinlock_t *lock) | ||
| 347 | { | ||
| 348 | struct clk_gate *gate; | ||
| 349 | |||
| 350 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
| 351 | if (!gate) | ||
| 352 | return ERR_PTR(-ENOMEM); | ||
| 353 | |||
| 354 | gate->reg = reg; | ||
| 355 | gate->bit_idx = bit_idx; | ||
| 356 | gate->flags = flags; | ||
| 357 | gate->lock = lock; | ||
| 358 | |||
| 359 | return gate; | ||
| 360 | } | ||
| 361 | |||
| 362 | struct composite_cfg { | ||
| 363 | struct clk_hw *mux_hw; | ||
| 364 | struct clk_hw *div_hw; | ||
| 365 | struct clk_hw *gate_hw; | ||
| 366 | |||
| 367 | const struct clk_ops *mux_ops; | ||
| 368 | const struct clk_ops *div_ops; | ||
| 369 | const struct clk_ops *gate_ops; | ||
| 370 | }; | ||
| 371 | |||
| 372 | static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg, | ||
| 373 | const struct composite_clk_cfg *cfg, | ||
| 374 | struct composite_cfg *composite, spinlock_t *lock) | ||
| 375 | { | ||
| 376 | struct clk_mux *mux = NULL; | ||
| 377 | struct clk_divider *div = NULL; | ||
| 378 | struct clk_gate *gate = NULL; | ||
| 379 | const struct clk_ops *mux_ops, *div_ops, *gate_ops; | ||
| 380 | struct clk_hw *mux_hw; | ||
| 381 | struct clk_hw *div_hw; | ||
| 382 | struct clk_hw *gate_hw; | ||
| 383 | |||
| 384 | mux_ops = div_ops = gate_ops = NULL; | ||
| 385 | mux_hw = div_hw = gate_hw = NULL; | ||
| 386 | |||
| 387 | if (gcfg->mux && gcfg->mux) { | ||
| 388 | mux = _get_cmux(base + cfg->mux->offset, | ||
| 389 | cfg->mux->shift, | ||
| 390 | cfg->mux->width, | ||
| 391 | gcfg->mux->flags, lock); | ||
| 392 | |||
| 393 | if (!IS_ERR(mux)) { | ||
| 394 | mux_hw = &mux->hw; | ||
| 395 | mux_ops = gcfg->mux->ops ? | ||
| 396 | gcfg->mux->ops : &clk_mux_ops; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | if (gcfg->div && cfg->div) { | ||
| 401 | div = _get_cdiv(base + cfg->div->offset, | ||
| 402 | cfg->div->shift, | ||
| 403 | cfg->div->width, | ||
| 404 | gcfg->div->flags, lock); | ||
| 405 | |||
| 406 | if (!IS_ERR(div)) { | ||
| 407 | div_hw = &div->hw; | ||
| 408 | div_ops = gcfg->div->ops ? | ||
| 409 | gcfg->div->ops : &clk_divider_ops; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | if (gcfg->gate && gcfg->gate) { | ||
| 414 | gate = _get_cgate(base + cfg->gate->offset, | ||
| 415 | cfg->gate->bit_idx, | ||
| 416 | gcfg->gate->flags, lock); | ||
| 417 | |||
| 418 | if (!IS_ERR(gate)) { | ||
| 419 | gate_hw = &gate->hw; | ||
| 420 | gate_ops = gcfg->gate->ops ? | ||
| 421 | gcfg->gate->ops : &clk_gate_ops; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | composite->mux_hw = mux_hw; | ||
| 426 | composite->mux_ops = mux_ops; | ||
| 427 | |||
| 428 | composite->div_hw = div_hw; | ||
| 429 | composite->div_ops = div_ops; | ||
| 430 | |||
| 431 | composite->gate_hw = gate_hw; | ||
| 432 | composite->gate_ops = gate_ops; | ||
| 433 | } | ||
| 434 | |||
| 435 | /* Kernel Timer */ | ||
| 436 | struct timer_ker { | ||
| 437 | u8 dppre_shift; | ||
| 438 | struct clk_hw hw; | ||
| 439 | spinlock_t *lock; | ||
| 440 | }; | ||
| 441 | |||
| 442 | #define to_timer_ker(_hw) container_of(_hw, struct timer_ker, hw) | ||
| 443 | |||
| 444 | static unsigned long timer_ker_recalc_rate(struct clk_hw *hw, | ||
| 445 | unsigned long parent_rate) | ||
| 446 | { | ||
| 447 | struct timer_ker *clk_elem = to_timer_ker(hw); | ||
| 448 | u32 timpre; | ||
| 449 | u32 dppre_shift = clk_elem->dppre_shift; | ||
| 450 | u32 prescaler; | ||
| 451 | u32 mul; | ||
| 452 | |||
| 453 | timpre = (readl(base + RCC_CFGR) >> 15) & 0x01; | ||
| 454 | |||
| 455 | prescaler = (readl(base + RCC_D2CFGR) >> dppre_shift) & 0x03; | ||
| 456 | |||
| 457 | mul = 2; | ||
| 458 | |||
| 459 | if (prescaler < 4) | ||
| 460 | mul = 1; | ||
| 461 | |||
| 462 | else if (timpre && prescaler > 4) | ||
| 463 | mul = 4; | ||
| 464 | |||
| 465 | return parent_rate * mul; | ||
| 466 | } | ||
| 467 | |||
| 468 | static const struct clk_ops timer_ker_ops = { | ||
| 469 | .recalc_rate = timer_ker_recalc_rate, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static struct clk_hw *clk_register_stm32_timer_ker(struct device *dev, | ||
| 473 | const char *name, const char *parent_name, | ||
| 474 | unsigned long flags, | ||
| 475 | u8 dppre_shift, | ||
| 476 | spinlock_t *lock) | ||
| 477 | { | ||
| 478 | struct timer_ker *element; | ||
| 479 | struct clk_init_data init; | ||
| 480 | struct clk_hw *hw; | ||
| 481 | int err; | ||
| 482 | |||
| 483 | element = kzalloc(sizeof(*element), GFP_KERNEL); | ||
| 484 | if (!element) | ||
| 485 | return ERR_PTR(-ENOMEM); | ||
| 486 | |||
| 487 | init.name = name; | ||
| 488 | init.ops = &timer_ker_ops; | ||
| 489 | init.flags = flags; | ||
| 490 | init.parent_names = &parent_name; | ||
| 491 | init.num_parents = 1; | ||
| 492 | |||
| 493 | element->hw.init = &init; | ||
| 494 | element->lock = lock; | ||
| 495 | element->dppre_shift = dppre_shift; | ||
| 496 | |||
| 497 | hw = &element->hw; | ||
| 498 | err = clk_hw_register(dev, hw); | ||
| 499 | |||
| 500 | if (err) { | ||
| 501 | kfree(element); | ||
| 502 | return ERR_PTR(err); | ||
| 503 | } | ||
| 504 | |||
| 505 | return hw; | ||
| 506 | } | ||
| 507 | |||
| 508 | static const struct clk_div_table d1cpre_div_table[] = { | ||
| 509 | { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, | ||
| 510 | { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1}, | ||
| 511 | { 8, 2 }, { 9, 4 }, { 10, 8 }, { 11, 16 }, | ||
| 512 | { 12, 64 }, { 13, 128 }, { 14, 256 }, | ||
| 513 | { 15, 512 }, | ||
| 514 | { 0 }, | ||
| 515 | }; | ||
| 516 | |||
| 517 | static const struct clk_div_table ppre_div_table[] = { | ||
| 518 | { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, | ||
| 519 | { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 }, | ||
| 520 | { 0 }, | ||
| 521 | }; | ||
| 522 | |||
| 523 | static void register_core_and_bus_clocks(void) | ||
| 524 | { | ||
| 525 | /* CORE AND BUS */ | ||
| 526 | hws[SYS_D1CPRE] = clk_hw_register_divider_table(NULL, "d1cpre", | ||
| 527 | "sys_ck", CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 8, 4, 0, | ||
| 528 | d1cpre_div_table, &stm32rcc_lock); | ||
| 529 | |||
| 530 | hws[HCLK] = clk_hw_register_divider_table(NULL, "hclk", "d1cpre", | ||
| 531 | CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 0, 4, 0, | ||
| 532 | d1cpre_div_table, &stm32rcc_lock); | ||
| 533 | |||
| 534 | /* D1 DOMAIN */ | ||
| 535 | /* * CPU Systick */ | ||
| 536 | hws[CPU_SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", | ||
| 537 | "d1cpre", 0, 1, 8); | ||
| 538 | |||
| 539 | /* * APB3 peripheral */ | ||
| 540 | hws[PCLK3] = clk_hw_register_divider_table(NULL, "pclk3", "hclk", 0, | ||
| 541 | base + RCC_D1CFGR, 4, 3, 0, | ||
| 542 | ppre_div_table, &stm32rcc_lock); | ||
| 543 | |||
| 544 | /* D2 DOMAIN */ | ||
| 545 | /* * APB1 peripheral */ | ||
| 546 | hws[PCLK1] = clk_hw_register_divider_table(NULL, "pclk1", "hclk", 0, | ||
| 547 | base + RCC_D2CFGR, 4, 3, 0, | ||
| 548 | ppre_div_table, &stm32rcc_lock); | ||
| 549 | |||
| 550 | /* Timers prescaler clocks */ | ||
| 551 | clk_register_stm32_timer_ker(NULL, "tim1_ker", "pclk1", 0, | ||
| 552 | 4, &stm32rcc_lock); | ||
| 553 | |||
| 554 | /* * APB2 peripheral */ | ||
| 555 | hws[PCLK2] = clk_hw_register_divider_table(NULL, "pclk2", "hclk", 0, | ||
| 556 | base + RCC_D2CFGR, 8, 3, 0, ppre_div_table, | ||
| 557 | &stm32rcc_lock); | ||
| 558 | |||
| 559 | clk_register_stm32_timer_ker(NULL, "tim2_ker", "pclk2", 0, 8, | ||
| 560 | &stm32rcc_lock); | ||
| 561 | |||
| 562 | /* D3 DOMAIN */ | ||
| 563 | /* * APB4 peripheral */ | ||
| 564 | hws[PCLK4] = clk_hw_register_divider_table(NULL, "pclk4", "hclk", 0, | ||
| 565 | base + RCC_D3CFGR, 4, 3, 0, | ||
| 566 | ppre_div_table, &stm32rcc_lock); | ||
| 567 | } | ||
| 568 | |||
| 569 | /* MUX clock configuration */ | ||
| 570 | struct stm32_mux_clk { | ||
| 571 | const char *name; | ||
| 572 | const char * const *parents; | ||
| 573 | u8 num_parents; | ||
| 574 | u32 offset; | ||
| 575 | u8 shift; | ||
| 576 | u8 width; | ||
| 577 | u32 flags; | ||
| 578 | }; | ||
| 579 | |||
| 580 | #define M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, _flags)\ | ||
| 581 | {\ | ||
| 582 | .name = _name,\ | ||
| 583 | .parents = _parents,\ | ||
| 584 | .num_parents = ARRAY_SIZE(_parents),\ | ||
| 585 | .offset = _mux_offset,\ | ||
| 586 | .shift = _mux_shift,\ | ||
| 587 | .width = _mux_width,\ | ||
| 588 | .flags = _flags,\ | ||
| 589 | } | ||
| 590 | |||
| 591 | #define M_MCLOC(_name, _parents, _mux_offset, _mux_shift, _mux_width)\ | ||
| 592 | M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, 0)\ | ||
| 593 | |||
| 594 | static const struct stm32_mux_clk stm32_mclk[] __initconst = { | ||
| 595 | M_MCLOC("per_ck", per_src, RCC_D1CCIPR, 28, 3), | ||
| 596 | M_MCLOC("pllsrc", pll_src, RCC_PLLCKSELR, 0, 3), | ||
| 597 | M_MCLOC("sys_ck", sys_src, RCC_CFGR, 0, 3), | ||
| 598 | M_MCLOC("tracein_ck", tracein_src, RCC_CFGR, 0, 3), | ||
| 599 | }; | ||
| 600 | |||
| 601 | /* Oscillary clock configuration */ | ||
| 602 | struct stm32_osc_clk { | ||
| 603 | const char *name; | ||
| 604 | const char *parent; | ||
| 605 | u32 gate_offset; | ||
| 606 | u8 bit_idx; | ||
| 607 | u8 bit_rdy; | ||
| 608 | u32 flags; | ||
| 609 | }; | ||
| 610 | |||
| 611 | #define OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, _flags)\ | ||
| 612 | {\ | ||
| 613 | .name = _name,\ | ||
| 614 | .parent = _parent,\ | ||
| 615 | .gate_offset = _gate_offset,\ | ||
| 616 | .bit_idx = _bit_idx,\ | ||
| 617 | .bit_rdy = _bit_rdy,\ | ||
| 618 | .flags = _flags,\ | ||
| 619 | } | ||
| 620 | |||
| 621 | #define OSC_CLK(_name, _parent, _gate_offset, _bit_idx, _bit_rdy)\ | ||
| 622 | OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, 0) | ||
| 623 | |||
| 624 | static const struct stm32_osc_clk stm32_oclk[] __initconst = { | ||
| 625 | OSC_CLKF("hsi_ck", "hsidiv", RCC_CR, 0, 2, CLK_IGNORE_UNUSED), | ||
| 626 | OSC_CLKF("hsi_ker", "hsidiv", RCC_CR, 1, 2, CLK_IGNORE_UNUSED), | ||
| 627 | OSC_CLKF("csi_ck", "clk-csi", RCC_CR, 7, 8, CLK_IGNORE_UNUSED), | ||
| 628 | OSC_CLKF("csi_ker", "clk-csi", RCC_CR, 9, 8, CLK_IGNORE_UNUSED), | ||
| 629 | OSC_CLKF("rc48_ck", "clk-rc48", RCC_CR, 12, 13, CLK_IGNORE_UNUSED), | ||
| 630 | OSC_CLKF("lsi_ck", "clk-lsi", RCC_CSR, 0, 1, CLK_IGNORE_UNUSED), | ||
| 631 | }; | ||
| 632 | |||
| 633 | /* PLL configuration */ | ||
| 634 | struct st32h7_pll_cfg { | ||
| 635 | u8 bit_idx; | ||
| 636 | u32 offset_divr; | ||
| 637 | u8 bit_frac_en; | ||
| 638 | u32 offset_frac; | ||
| 639 | u8 divm; | ||
| 640 | }; | ||
| 641 | |||
| 642 | struct stm32_pll_data { | ||
| 643 | const char *name; | ||
| 644 | const char *parent_name; | ||
| 645 | unsigned long flags; | ||
| 646 | const struct st32h7_pll_cfg *cfg; | ||
| 647 | }; | ||
| 648 | |||
| 649 | static const struct st32h7_pll_cfg stm32h7_pll1 = { | ||
| 650 | .bit_idx = 24, | ||
| 651 | .offset_divr = RCC_PLL1DIVR, | ||
| 652 | .bit_frac_en = 0, | ||
| 653 | .offset_frac = RCC_PLL1FRACR, | ||
| 654 | .divm = 4, | ||
| 655 | }; | ||
| 656 | |||
| 657 | static const struct st32h7_pll_cfg stm32h7_pll2 = { | ||
| 658 | .bit_idx = 26, | ||
| 659 | .offset_divr = RCC_PLL2DIVR, | ||
| 660 | .bit_frac_en = 4, | ||
| 661 | .offset_frac = RCC_PLL2FRACR, | ||
| 662 | .divm = 12, | ||
| 663 | }; | ||
| 664 | |||
| 665 | static const struct st32h7_pll_cfg stm32h7_pll3 = { | ||
| 666 | .bit_idx = 28, | ||
| 667 | .offset_divr = RCC_PLL3DIVR, | ||
| 668 | .bit_frac_en = 8, | ||
| 669 | .offset_frac = RCC_PLL3FRACR, | ||
| 670 | .divm = 20, | ||
| 671 | }; | ||
| 672 | |||
| 673 | static const struct stm32_pll_data stm32_pll[] = { | ||
| 674 | { "vco1", "pllsrc", CLK_IGNORE_UNUSED, &stm32h7_pll1 }, | ||
| 675 | { "vco2", "pllsrc", 0, &stm32h7_pll2 }, | ||
| 676 | { "vco3", "pllsrc", 0, &stm32h7_pll3 }, | ||
| 677 | }; | ||
| 678 | |||
| 679 | struct stm32_fractional_divider { | ||
| 680 | void __iomem *mreg; | ||
| 681 | u8 mshift; | ||
| 682 | u8 mwidth; | ||
| 683 | u32 mmask; | ||
| 684 | |||
| 685 | void __iomem *nreg; | ||
| 686 | u8 nshift; | ||
| 687 | u8 nwidth; | ||
| 688 | |||
| 689 | void __iomem *freg_status; | ||
| 690 | u8 freg_bit; | ||
| 691 | void __iomem *freg_value; | ||
| 692 | u8 fshift; | ||
| 693 | u8 fwidth; | ||
| 694 | |||
| 695 | u8 flags; | ||
| 696 | struct clk_hw hw; | ||
| 697 | spinlock_t *lock; | ||
| 698 | }; | ||
| 699 | |||
| 700 | struct stm32_pll_obj { | ||
| 701 | spinlock_t *lock; | ||
| 702 | struct stm32_fractional_divider div; | ||
| 703 | struct stm32_ready_gate rgate; | ||
| 704 | struct clk_hw hw; | ||
| 705 | }; | ||
| 706 | |||
| 707 | #define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) | ||
| 708 | |||
| 709 | static int pll_is_enabled(struct clk_hw *hw) | ||
| 710 | { | ||
| 711 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 712 | struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | ||
| 713 | |||
| 714 | __clk_hw_set_clk(_hw, hw); | ||
| 715 | |||
| 716 | return ready_gate_clk_ops.is_enabled(_hw); | ||
| 717 | } | ||
| 718 | |||
| 719 | static int pll_enable(struct clk_hw *hw) | ||
| 720 | { | ||
| 721 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 722 | struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | ||
| 723 | |||
| 724 | __clk_hw_set_clk(_hw, hw); | ||
| 725 | |||
| 726 | return ready_gate_clk_ops.enable(_hw); | ||
| 727 | } | ||
| 728 | |||
| 729 | static void pll_disable(struct clk_hw *hw) | ||
| 730 | { | ||
| 731 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 732 | struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | ||
| 733 | |||
| 734 | __clk_hw_set_clk(_hw, hw); | ||
| 735 | |||
| 736 | ready_gate_clk_ops.disable(_hw); | ||
| 737 | } | ||
| 738 | |||
| 739 | static int pll_frac_is_enabled(struct clk_hw *hw) | ||
| 740 | { | ||
| 741 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 742 | struct stm32_fractional_divider *fd = &clk_elem->div; | ||
| 743 | |||
| 744 | return (readl(fd->freg_status) >> fd->freg_bit) & 0x01; | ||
| 745 | } | ||
| 746 | |||
| 747 | static unsigned long pll_read_frac(struct clk_hw *hw) | ||
| 748 | { | ||
| 749 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 750 | struct stm32_fractional_divider *fd = &clk_elem->div; | ||
| 751 | |||
| 752 | return (readl(fd->freg_value) >> fd->fshift) & | ||
| 753 | GENMASK(fd->fwidth - 1, 0); | ||
| 754 | } | ||
| 755 | |||
| 756 | static unsigned long pll_fd_recalc_rate(struct clk_hw *hw, | ||
| 757 | unsigned long parent_rate) | ||
| 758 | { | ||
| 759 | struct stm32_pll_obj *clk_elem = to_pll(hw); | ||
| 760 | struct stm32_fractional_divider *fd = &clk_elem->div; | ||
| 761 | unsigned long m, n; | ||
| 762 | u32 val, mask; | ||
| 763 | u64 rate, rate1 = 0; | ||
| 764 | |||
| 765 | val = readl(fd->mreg); | ||
| 766 | mask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; | ||
| 767 | m = (val & mask) >> fd->mshift; | ||
| 768 | |||
| 769 | val = readl(fd->nreg); | ||
| 770 | mask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; | ||
| 771 | n = ((val & mask) >> fd->nshift) + 1; | ||
| 772 | |||
| 773 | if (!n || !m) | ||
| 774 | return parent_rate; | ||
| 775 | |||
| 776 | rate = (u64)parent_rate * n; | ||
| 777 | do_div(rate, m); | ||
| 778 | |||
| 779 | if (pll_frac_is_enabled(hw)) { | ||
| 780 | val = pll_read_frac(hw); | ||
| 781 | rate1 = (u64)parent_rate * (u64)val; | ||
| 782 | do_div(rate1, (m * 8191)); | ||
| 783 | } | ||
| 784 | |||
| 785 | return rate + rate1; | ||
| 786 | } | ||
| 787 | |||
| 788 | static const struct clk_ops pll_ops = { | ||
| 789 | .enable = pll_enable, | ||
| 790 | .disable = pll_disable, | ||
| 791 | .is_enabled = pll_is_enabled, | ||
| 792 | .recalc_rate = pll_fd_recalc_rate, | ||
| 793 | }; | ||
| 794 | |||
| 795 | static struct clk_hw *clk_register_stm32_pll(struct device *dev, | ||
| 796 | const char *name, | ||
| 797 | const char *parent, | ||
| 798 | unsigned long flags, | ||
| 799 | const struct st32h7_pll_cfg *cfg, | ||
| 800 | spinlock_t *lock) | ||
| 801 | { | ||
| 802 | struct stm32_pll_obj *pll; | ||
| 803 | struct clk_init_data init = { NULL }; | ||
| 804 | struct clk_hw *hw; | ||
| 805 | int ret; | ||
| 806 | struct stm32_fractional_divider *div = NULL; | ||
| 807 | struct stm32_ready_gate *rgate; | ||
| 808 | |||
| 809 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
| 810 | if (!pll) | ||
| 811 | return ERR_PTR(-ENOMEM); | ||
| 812 | |||
| 813 | init.name = name; | ||
| 814 | init.ops = &pll_ops; | ||
| 815 | init.flags = flags; | ||
| 816 | init.parent_names = &parent; | ||
| 817 | init.num_parents = 1; | ||
| 818 | pll->hw.init = &init; | ||
| 819 | |||
| 820 | hw = &pll->hw; | ||
| 821 | rgate = &pll->rgate; | ||
| 822 | |||
| 823 | rgate->bit_rdy = cfg->bit_idx + 1; | ||
| 824 | rgate->gate.lock = lock; | ||
| 825 | rgate->gate.reg = base + RCC_CR; | ||
| 826 | rgate->gate.bit_idx = cfg->bit_idx; | ||
| 827 | |||
| 828 | div = &pll->div; | ||
| 829 | div->flags = 0; | ||
| 830 | div->mreg = base + RCC_PLLCKSELR; | ||
| 831 | div->mshift = cfg->divm; | ||
| 832 | div->mwidth = 6; | ||
| 833 | div->nreg = base + cfg->offset_divr; | ||
| 834 | div->nshift = 0; | ||
| 835 | div->nwidth = 9; | ||
| 836 | |||
| 837 | div->freg_status = base + RCC_PLLCFGR; | ||
| 838 | div->freg_bit = cfg->bit_frac_en; | ||
| 839 | div->freg_value = base + cfg->offset_frac; | ||
| 840 | div->fshift = 3; | ||
| 841 | div->fwidth = 13; | ||
| 842 | |||
| 843 | div->lock = lock; | ||
| 844 | |||
| 845 | ret = clk_hw_register(dev, hw); | ||
| 846 | if (ret) { | ||
| 847 | kfree(pll); | ||
| 848 | hw = ERR_PTR(ret); | ||
| 849 | } | ||
| 850 | |||
| 851 | return hw; | ||
| 852 | } | ||
| 853 | |||
| 854 | /* ODF CLOCKS */ | ||
| 855 | static unsigned long odf_divider_recalc_rate(struct clk_hw *hw, | ||
| 856 | unsigned long parent_rate) | ||
| 857 | { | ||
| 858 | return clk_divider_ops.recalc_rate(hw, parent_rate); | ||
| 859 | } | ||
| 860 | |||
| 861 | static long odf_divider_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 862 | unsigned long *prate) | ||
| 863 | { | ||
| 864 | return clk_divider_ops.round_rate(hw, rate, prate); | ||
| 865 | } | ||
| 866 | |||
| 867 | static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 868 | unsigned long parent_rate) | ||
| 869 | { | ||
| 870 | struct clk_hw *hwp; | ||
| 871 | int pll_status; | ||
| 872 | int ret; | ||
| 873 | |||
| 874 | hwp = clk_hw_get_parent(hw); | ||
| 875 | |||
| 876 | pll_status = pll_is_enabled(hwp); | ||
| 877 | |||
| 878 | if (pll_status) | ||
| 879 | pll_disable(hwp); | ||
| 880 | |||
| 881 | ret = clk_divider_ops.set_rate(hw, rate, parent_rate); | ||
| 882 | |||
| 883 | if (pll_status) | ||
| 884 | pll_enable(hwp); | ||
| 885 | |||
| 886 | return ret; | ||
| 887 | } | ||
| 888 | |||
| 889 | static const struct clk_ops odf_divider_ops = { | ||
| 890 | .recalc_rate = odf_divider_recalc_rate, | ||
| 891 | .round_rate = odf_divider_round_rate, | ||
| 892 | .set_rate = odf_divider_set_rate, | ||
| 893 | }; | ||
| 894 | |||
| 895 | static int odf_gate_enable(struct clk_hw *hw) | ||
| 896 | { | ||
| 897 | struct clk_hw *hwp; | ||
| 898 | int pll_status; | ||
| 899 | int ret; | ||
| 900 | |||
| 901 | if (clk_gate_ops.is_enabled(hw)) | ||
| 902 | return 0; | ||
| 903 | |||
| 904 | hwp = clk_hw_get_parent(hw); | ||
| 905 | |||
| 906 | pll_status = pll_is_enabled(hwp); | ||
| 907 | |||
| 908 | if (pll_status) | ||
| 909 | pll_disable(hwp); | ||
| 910 | |||
| 911 | ret = clk_gate_ops.enable(hw); | ||
| 912 | |||
| 913 | if (pll_status) | ||
| 914 | pll_enable(hwp); | ||
| 915 | |||
| 916 | return ret; | ||
| 917 | } | ||
| 918 | |||
| 919 | static void odf_gate_disable(struct clk_hw *hw) | ||
| 920 | { | ||
| 921 | struct clk_hw *hwp; | ||
| 922 | int pll_status; | ||
| 923 | |||
| 924 | if (!clk_gate_ops.is_enabled(hw)) | ||
| 925 | return; | ||
| 926 | |||
| 927 | hwp = clk_hw_get_parent(hw); | ||
| 928 | |||
| 929 | pll_status = pll_is_enabled(hwp); | ||
| 930 | |||
| 931 | if (pll_status) | ||
| 932 | pll_disable(hwp); | ||
| 933 | |||
| 934 | clk_gate_ops.disable(hw); | ||
| 935 | |||
| 936 | if (pll_status) | ||
| 937 | pll_enable(hwp); | ||
| 938 | } | ||
| 939 | |||
| 940 | static const struct clk_ops odf_gate_ops = { | ||
| 941 | .enable = odf_gate_enable, | ||
| 942 | .disable = odf_gate_disable, | ||
| 943 | .is_enabled = clk_gate_is_enabled, | ||
| 944 | }; | ||
| 945 | |||
| 946 | static struct composite_clk_gcfg odf_clk_gcfg = { | ||
| 947 | M_CFG_DIV(&odf_divider_ops, 0), | ||
| 948 | M_CFG_GATE(&odf_gate_ops, 0), | ||
| 949 | }; | ||
| 950 | |||
| 951 | #define M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | ||
| 952 | _rate_shift, _rate_width, _flags)\ | ||
| 953 | {\ | ||
| 954 | .mux = NULL,\ | ||
| 955 | .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ | ||
| 956 | .gate = &(struct gate_cfg) {_gate_offset, _bit_idx },\ | ||
| 957 | .name = _name,\ | ||
| 958 | .parent_name = &(const char *) {_parent},\ | ||
| 959 | .num_parents = 1,\ | ||
| 960 | .flags = _flags,\ | ||
| 961 | } | ||
| 962 | |||
| 963 | #define M_ODF(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | ||
| 964 | _rate_shift, _rate_width)\ | ||
| 965 | M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | ||
| 966 | _rate_shift, _rate_width, 0)\ | ||
| 967 | |||
| 968 | static const struct composite_clk_cfg stm32_odf[3][3] = { | ||
| 969 | { | ||
| 970 | M_ODF_F("pll1_p", "vco1", RCC_PLLCFGR, 16, RCC_PLL1DIVR, 9, 7, | ||
| 971 | CLK_IGNORE_UNUSED), | ||
| 972 | M_ODF_F("pll1_q", "vco1", RCC_PLLCFGR, 17, RCC_PLL1DIVR, 16, 7, | ||
| 973 | CLK_IGNORE_UNUSED), | ||
| 974 | M_ODF_F("pll1_r", "vco1", RCC_PLLCFGR, 18, RCC_PLL1DIVR, 24, 7, | ||
| 975 | CLK_IGNORE_UNUSED), | ||
| 976 | }, | ||
| 977 | |||
| 978 | { | ||
| 979 | M_ODF("pll2_p", "vco2", RCC_PLLCFGR, 19, RCC_PLL2DIVR, 9, 7), | ||
| 980 | M_ODF("pll2_q", "vco2", RCC_PLLCFGR, 20, RCC_PLL2DIVR, 16, 7), | ||
| 981 | M_ODF("pll2_r", "vco2", RCC_PLLCFGR, 21, RCC_PLL2DIVR, 24, 7), | ||
| 982 | }, | ||
| 983 | { | ||
| 984 | M_ODF("pll3_p", "vco3", RCC_PLLCFGR, 22, RCC_PLL3DIVR, 9, 7), | ||
| 985 | M_ODF("pll3_q", "vco3", RCC_PLLCFGR, 23, RCC_PLL3DIVR, 16, 7), | ||
| 986 | M_ODF("pll3_r", "vco3", RCC_PLLCFGR, 24, RCC_PLL3DIVR, 24, 7), | ||
| 987 | } | ||
| 988 | }; | ||
| 989 | |||
| 990 | /* PERIF CLOCKS */ | ||
| 991 | struct pclk_t { | ||
| 992 | u32 gate_offset; | ||
| 993 | u8 bit_idx; | ||
| 994 | const char *name; | ||
| 995 | const char *parent; | ||
| 996 | u32 flags; | ||
| 997 | }; | ||
| 998 | |||
| 999 | #define PER_CLKF(_gate_offset, _bit_idx, _name, _parent, _flags)\ | ||
| 1000 | {\ | ||
| 1001 | .gate_offset = _gate_offset,\ | ||
| 1002 | .bit_idx = _bit_idx,\ | ||
| 1003 | .name = _name,\ | ||
| 1004 | .parent = _parent,\ | ||
| 1005 | .flags = _flags,\ | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | #define PER_CLK(_gate_offset, _bit_idx, _name, _parent)\ | ||
| 1009 | PER_CLKF(_gate_offset, _bit_idx, _name, _parent, 0) | ||
| 1010 | |||
| 1011 | static const struct pclk_t pclk[] = { | ||
| 1012 | PER_CLK(RCC_AHB3ENR, 31, "d1sram1", "hclk"), | ||
| 1013 | PER_CLK(RCC_AHB3ENR, 30, "itcm", "hclk"), | ||
| 1014 | PER_CLK(RCC_AHB3ENR, 29, "dtcm2", "hclk"), | ||
| 1015 | PER_CLK(RCC_AHB3ENR, 28, "dtcm1", "hclk"), | ||
| 1016 | PER_CLK(RCC_AHB3ENR, 8, "flitf", "hclk"), | ||
| 1017 | PER_CLK(RCC_AHB3ENR, 5, "jpgdec", "hclk"), | ||
| 1018 | PER_CLK(RCC_AHB3ENR, 4, "dma2d", "hclk"), | ||
| 1019 | PER_CLK(RCC_AHB3ENR, 0, "mdma", "hclk"), | ||
| 1020 | PER_CLK(RCC_AHB1ENR, 28, "usb2ulpi", "hclk"), | ||
| 1021 | PER_CLK(RCC_AHB1ENR, 26, "usb1ulpi", "hclk"), | ||
| 1022 | PER_CLK(RCC_AHB1ENR, 17, "eth1rx", "hclk"), | ||
| 1023 | PER_CLK(RCC_AHB1ENR, 16, "eth1tx", "hclk"), | ||
| 1024 | PER_CLK(RCC_AHB1ENR, 15, "eth1mac", "hclk"), | ||
| 1025 | PER_CLK(RCC_AHB1ENR, 14, "art", "hclk"), | ||
| 1026 | PER_CLK(RCC_AHB1ENR, 1, "dma2", "hclk"), | ||
| 1027 | PER_CLK(RCC_AHB1ENR, 0, "dma1", "hclk"), | ||
| 1028 | PER_CLK(RCC_AHB2ENR, 31, "d2sram3", "hclk"), | ||
| 1029 | PER_CLK(RCC_AHB2ENR, 30, "d2sram2", "hclk"), | ||
| 1030 | PER_CLK(RCC_AHB2ENR, 29, "d2sram1", "hclk"), | ||
| 1031 | PER_CLK(RCC_AHB2ENR, 5, "hash", "hclk"), | ||
| 1032 | PER_CLK(RCC_AHB2ENR, 4, "crypt", "hclk"), | ||
| 1033 | PER_CLK(RCC_AHB2ENR, 0, "camitf", "hclk"), | ||
| 1034 | PER_CLK(RCC_AHB4ENR, 28, "bkpram", "hclk"), | ||
| 1035 | PER_CLK(RCC_AHB4ENR, 25, "hsem", "hclk"), | ||
| 1036 | PER_CLK(RCC_AHB4ENR, 21, "bdma", "hclk"), | ||
| 1037 | PER_CLK(RCC_AHB4ENR, 19, "crc", "hclk"), | ||
| 1038 | PER_CLK(RCC_AHB4ENR, 10, "gpiok", "hclk"), | ||
| 1039 | PER_CLK(RCC_AHB4ENR, 9, "gpioj", "hclk"), | ||
| 1040 | PER_CLK(RCC_AHB4ENR, 8, "gpioi", "hclk"), | ||
| 1041 | PER_CLK(RCC_AHB4ENR, 7, "gpioh", "hclk"), | ||
| 1042 | PER_CLK(RCC_AHB4ENR, 6, "gpiog", "hclk"), | ||
| 1043 | PER_CLK(RCC_AHB4ENR, 5, "gpiof", "hclk"), | ||
| 1044 | PER_CLK(RCC_AHB4ENR, 4, "gpioe", "hclk"), | ||
| 1045 | PER_CLK(RCC_AHB4ENR, 3, "gpiod", "hclk"), | ||
| 1046 | PER_CLK(RCC_AHB4ENR, 2, "gpioc", "hclk"), | ||
| 1047 | PER_CLK(RCC_AHB4ENR, 1, "gpiob", "hclk"), | ||
| 1048 | PER_CLK(RCC_AHB4ENR, 0, "gpioa", "hclk"), | ||
| 1049 | PER_CLK(RCC_APB3ENR, 6, "wwdg1", "pclk3"), | ||
| 1050 | PER_CLK(RCC_APB1LENR, 29, "dac12", "pclk1"), | ||
| 1051 | PER_CLK(RCC_APB1LENR, 11, "wwdg2", "pclk1"), | ||
| 1052 | PER_CLK(RCC_APB1LENR, 8, "tim14", "tim1_ker"), | ||
| 1053 | PER_CLK(RCC_APB1LENR, 7, "tim13", "tim1_ker"), | ||
| 1054 | PER_CLK(RCC_APB1LENR, 6, "tim12", "tim1_ker"), | ||
| 1055 | PER_CLK(RCC_APB1LENR, 5, "tim7", "tim1_ker"), | ||
| 1056 | PER_CLK(RCC_APB1LENR, 4, "tim6", "tim1_ker"), | ||
| 1057 | PER_CLK(RCC_APB1LENR, 3, "tim5", "tim1_ker"), | ||
| 1058 | PER_CLK(RCC_APB1LENR, 2, "tim4", "tim1_ker"), | ||
| 1059 | PER_CLK(RCC_APB1LENR, 1, "tim3", "tim1_ker"), | ||
| 1060 | PER_CLK(RCC_APB1LENR, 0, "tim2", "tim1_ker"), | ||
| 1061 | PER_CLK(RCC_APB1HENR, 5, "mdios", "pclk1"), | ||
| 1062 | PER_CLK(RCC_APB1HENR, 4, "opamp", "pclk1"), | ||
| 1063 | PER_CLK(RCC_APB1HENR, 1, "crs", "pclk1"), | ||
| 1064 | PER_CLK(RCC_APB2ENR, 18, "tim17", "tim2_ker"), | ||
| 1065 | PER_CLK(RCC_APB2ENR, 17, "tim16", "tim2_ker"), | ||
| 1066 | PER_CLK(RCC_APB2ENR, 16, "tim15", "tim2_ker"), | ||
| 1067 | PER_CLK(RCC_APB2ENR, 1, "tim8", "tim2_ker"), | ||
| 1068 | PER_CLK(RCC_APB2ENR, 0, "tim1", "tim2_ker"), | ||
| 1069 | PER_CLK(RCC_APB4ENR, 26, "tmpsens", "pclk4"), | ||
| 1070 | PER_CLK(RCC_APB4ENR, 16, "rtcapb", "pclk4"), | ||
| 1071 | PER_CLK(RCC_APB4ENR, 15, "vref", "pclk4"), | ||
| 1072 | PER_CLK(RCC_APB4ENR, 14, "comp12", "pclk4"), | ||
| 1073 | PER_CLK(RCC_APB4ENR, 1, "syscfg", "pclk4"), | ||
| 1074 | }; | ||
| 1075 | |||
| 1076 | /* KERNEL CLOCKS */ | ||
| 1077 | #define KER_CLKF(_gate_offset, _bit_idx,\ | ||
| 1078 | _mux_offset, _mux_shift, _mux_width,\ | ||
| 1079 | _name, _parent_name,\ | ||
| 1080 | _flags) \ | ||
| 1081 | { \ | ||
| 1082 | .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ | ||
| 1083 | .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ | ||
| 1084 | .name = _name, \ | ||
| 1085 | .parent_name = _parent_name, \ | ||
| 1086 | .num_parents = ARRAY_SIZE(_parent_name),\ | ||
| 1087 | .flags = _flags,\ | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | #define KER_CLK(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ | ||
| 1091 | _name, _parent_name) \ | ||
| 1092 | KER_CLKF(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ | ||
| 1093 | _name, _parent_name, 0)\ | ||
| 1094 | |||
| 1095 | #define KER_CLKF_NOMUX(_gate_offset, _bit_idx,\ | ||
| 1096 | _name, _parent_name,\ | ||
| 1097 | _flags) \ | ||
| 1098 | { \ | ||
| 1099 | .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ | ||
| 1100 | .mux = NULL,\ | ||
| 1101 | .name = _name, \ | ||
| 1102 | .parent_name = _parent_name, \ | ||
| 1103 | .num_parents = 1,\ | ||
| 1104 | .flags = _flags,\ | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | static const struct composite_clk_cfg kclk[] = { | ||
| 1108 | KER_CLK(RCC_AHB3ENR, 16, RCC_D1CCIPR, 16, 1, "sdmmc1", sdmmc_src), | ||
| 1109 | KER_CLKF(RCC_AHB3ENR, 14, RCC_D1CCIPR, 4, 2, "quadspi", qspi_src, | ||
| 1110 | CLK_IGNORE_UNUSED), | ||
| 1111 | KER_CLKF(RCC_AHB3ENR, 12, RCC_D1CCIPR, 0, 2, "fmc", fmc_src, | ||
| 1112 | CLK_IGNORE_UNUSED), | ||
| 1113 | KER_CLK(RCC_AHB1ENR, 27, RCC_D2CCIP2R, 20, 2, "usb2otg", usbotg_src), | ||
| 1114 | KER_CLK(RCC_AHB1ENR, 25, RCC_D2CCIP2R, 20, 2, "usb1otg", usbotg_src), | ||
| 1115 | KER_CLK(RCC_AHB1ENR, 5, RCC_D3CCIPR, 16, 2, "adc12", adc_src), | ||
| 1116 | KER_CLK(RCC_AHB2ENR, 9, RCC_D1CCIPR, 16, 1, "sdmmc2", sdmmc_src), | ||
| 1117 | KER_CLK(RCC_AHB2ENR, 6, RCC_D2CCIP2R, 8, 2, "rng", rng_src), | ||
| 1118 | KER_CLK(RCC_AHB4ENR, 24, RCC_D3CCIPR, 16, 2, "adc3", adc_src), | ||
| 1119 | KER_CLKF(RCC_APB3ENR, 4, RCC_D1CCIPR, 8, 1, "dsi", dsi_src, | ||
| 1120 | CLK_SET_RATE_PARENT), | ||
| 1121 | KER_CLKF_NOMUX(RCC_APB3ENR, 3, "ltdc", ltdc_src, CLK_SET_RATE_PARENT), | ||
| 1122 | KER_CLK(RCC_APB1LENR, 31, RCC_D2CCIP2R, 0, 3, "usart8", usart_src2), | ||
| 1123 | KER_CLK(RCC_APB1LENR, 30, RCC_D2CCIP2R, 0, 3, "usart7", usart_src2), | ||
| 1124 | KER_CLK(RCC_APB1LENR, 27, RCC_D2CCIP2R, 22, 2, "hdmicec", cec_src), | ||
| 1125 | KER_CLK(RCC_APB1LENR, 23, RCC_D2CCIP2R, 12, 2, "i2c3", i2c_src1), | ||
| 1126 | KER_CLK(RCC_APB1LENR, 22, RCC_D2CCIP2R, 12, 2, "i2c2", i2c_src1), | ||
| 1127 | KER_CLK(RCC_APB1LENR, 21, RCC_D2CCIP2R, 12, 2, "i2c1", i2c_src1), | ||
| 1128 | KER_CLK(RCC_APB1LENR, 20, RCC_D2CCIP2R, 0, 3, "uart5", usart_src2), | ||
| 1129 | KER_CLK(RCC_APB1LENR, 19, RCC_D2CCIP2R, 0, 3, "uart4", usart_src2), | ||
| 1130 | KER_CLK(RCC_APB1LENR, 18, RCC_D2CCIP2R, 0, 3, "usart3", usart_src2), | ||
| 1131 | KER_CLK(RCC_APB1LENR, 17, RCC_D2CCIP2R, 0, 3, "usart2", usart_src2), | ||
| 1132 | KER_CLK(RCC_APB1LENR, 16, RCC_D2CCIP1R, 20, 2, "spdifrx", spdifrx_src), | ||
| 1133 | KER_CLK(RCC_APB1LENR, 15, RCC_D2CCIP1R, 16, 3, "spi3", spi_src1), | ||
| 1134 | KER_CLK(RCC_APB1LENR, 14, RCC_D2CCIP1R, 16, 3, "spi2", spi_src1), | ||
| 1135 | KER_CLK(RCC_APB1LENR, 9, RCC_D2CCIP2R, 28, 3, "lptim1", lptim_src1), | ||
| 1136 | KER_CLK(RCC_APB1HENR, 8, RCC_D2CCIP1R, 28, 2, "fdcan", fdcan_src), | ||
| 1137 | KER_CLK(RCC_APB1HENR, 2, RCC_D2CCIP1R, 31, 1, "swp", swp_src), | ||
| 1138 | KER_CLK(RCC_APB2ENR, 29, RCC_CFGR, 14, 1, "hrtim", hrtim_src), | ||
| 1139 | KER_CLK(RCC_APB2ENR, 28, RCC_D2CCIP1R, 24, 1, "dfsdm1", dfsdm1_src), | ||
| 1140 | KER_CLKF(RCC_APB2ENR, 24, RCC_D2CCIP1R, 6, 3, "sai3", sai_src, | ||
| 1141 | CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | ||
| 1142 | KER_CLKF(RCC_APB2ENR, 23, RCC_D2CCIP1R, 6, 3, "sai2", sai_src, | ||
| 1143 | CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | ||
| 1144 | KER_CLKF(RCC_APB2ENR, 22, RCC_D2CCIP1R, 0, 3, "sai1", sai_src, | ||
| 1145 | CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | ||
| 1146 | KER_CLK(RCC_APB2ENR, 20, RCC_D2CCIP1R, 16, 3, "spi5", spi_src2), | ||
| 1147 | KER_CLK(RCC_APB2ENR, 13, RCC_D2CCIP1R, 16, 3, "spi4", spi_src2), | ||
| 1148 | KER_CLK(RCC_APB2ENR, 12, RCC_D2CCIP1R, 16, 3, "spi1", spi_src1), | ||
| 1149 | KER_CLK(RCC_APB2ENR, 5, RCC_D2CCIP2R, 3, 3, "usart6", usart_src1), | ||
| 1150 | KER_CLK(RCC_APB2ENR, 4, RCC_D2CCIP2R, 3, 3, "usart1", usart_src1), | ||
| 1151 | KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 24, 3, "sai4b", sai_src), | ||
| 1152 | KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 21, 3, "sai4a", sai_src), | ||
| 1153 | KER_CLK(RCC_APB4ENR, 12, RCC_D3CCIPR, 13, 3, "lptim5", lptim_src2), | ||
| 1154 | KER_CLK(RCC_APB4ENR, 11, RCC_D3CCIPR, 13, 3, "lptim4", lptim_src2), | ||
| 1155 | KER_CLK(RCC_APB4ENR, 10, RCC_D3CCIPR, 13, 3, "lptim3", lptim_src2), | ||
| 1156 | KER_CLK(RCC_APB4ENR, 9, RCC_D3CCIPR, 10, 3, "lptim2", lptim_src2), | ||
| 1157 | KER_CLK(RCC_APB4ENR, 7, RCC_D3CCIPR, 8, 2, "i2c4", i2c_src2), | ||
| 1158 | KER_CLK(RCC_APB4ENR, 5, RCC_D3CCIPR, 28, 3, "spi6", spi_src3), | ||
| 1159 | KER_CLK(RCC_APB4ENR, 3, RCC_D3CCIPR, 0, 3, "lpuart1", lpuart1_src), | ||
| 1160 | }; | ||
| 1161 | |||
| 1162 | static struct composite_clk_gcfg kernel_clk_cfg = { | ||
| 1163 | M_CFG_MUX(NULL, 0), | ||
| 1164 | M_CFG_GATE(NULL, 0), | ||
| 1165 | }; | ||
| 1166 | |||
| 1167 | /* RTC clock */ | ||
| 1168 | /* | ||
| 1169 | * RTC & LSE registers are protected against parasitic write access. | ||
| 1170 | * PWR_CR_DBP bit must be set to enable write access to RTC registers. | ||
| 1171 | */ | ||
| 1172 | /* STM32_PWR_CR */ | ||
| 1173 | #define PWR_CR 0x00 | ||
| 1174 | /* STM32_PWR_CR bit field */ | ||
| 1175 | #define PWR_CR_DBP BIT(8) | ||
| 1176 | |||
| 1177 | static struct composite_clk_gcfg rtc_clk_cfg = { | ||
| 1178 | M_CFG_MUX(NULL, 0), | ||
| 1179 | M_CFG_GATE(NULL, 0), | ||
| 1180 | }; | ||
| 1181 | |||
| 1182 | static const struct composite_clk_cfg rtc_clk = | ||
| 1183 | KER_CLK(RCC_BDCR, 15, RCC_BDCR, 8, 2, "rtc_ck", rtc_src); | ||
| 1184 | |||
| 1185 | /* Micro-controller output clock */ | ||
| 1186 | static struct composite_clk_gcfg mco_clk_cfg = { | ||
| 1187 | M_CFG_MUX(NULL, 0), | ||
| 1188 | M_CFG_DIV(NULL, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), | ||
| 1189 | }; | ||
| 1190 | |||
| 1191 | #define M_MCO_F(_name, _parents, _mux_offset, _mux_shift, _mux_width,\ | ||
| 1192 | _rate_offset, _rate_shift, _rate_width,\ | ||
| 1193 | _flags)\ | ||
| 1194 | {\ | ||
| 1195 | .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ | ||
| 1196 | .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ | ||
| 1197 | .gate = NULL,\ | ||
| 1198 | .name = _name,\ | ||
| 1199 | .parent_name = _parents,\ | ||
| 1200 | .num_parents = ARRAY_SIZE(_parents),\ | ||
| 1201 | .flags = _flags,\ | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | static const struct composite_clk_cfg mco_clk[] = { | ||
| 1205 | M_MCO_F("mco1", mco_src1, RCC_CFGR, 22, 4, RCC_CFGR, 18, 4, 0), | ||
| 1206 | M_MCO_F("mco2", mco_src2, RCC_CFGR, 29, 3, RCC_CFGR, 25, 4, 0), | ||
| 1207 | }; | ||
| 1208 | |||
| 1209 | static void __init stm32h7_rcc_init(struct device_node *np) | ||
| 1210 | { | ||
| 1211 | struct clk_hw_onecell_data *clk_data; | ||
| 1212 | struct composite_cfg c_cfg; | ||
| 1213 | int n; | ||
| 1214 | const char *hse_clk, *lse_clk, *i2s_clk; | ||
| 1215 | struct regmap *pdrm; | ||
| 1216 | |||
| 1217 | clk_data = kzalloc(sizeof(*clk_data) + | ||
| 1218 | sizeof(*clk_data->hws) * STM32H7_MAX_CLKS, | ||
| 1219 | GFP_KERNEL); | ||
| 1220 | if (!clk_data) | ||
| 1221 | return; | ||
| 1222 | |||
| 1223 | clk_data->num = STM32H7_MAX_CLKS; | ||
| 1224 | |||
| 1225 | hws = clk_data->hws; | ||
| 1226 | |||
| 1227 | for (n = 0; n < STM32H7_MAX_CLKS; n++) | ||
| 1228 | hws[n] = ERR_PTR(-ENOENT); | ||
| 1229 | |||
| 1230 | /* get RCC base @ from DT */ | ||
| 1231 | base = of_iomap(np, 0); | ||
| 1232 | if (!base) { | ||
| 1233 | pr_err("%s: unable to map resource", np->name); | ||
| 1234 | goto err_free_clks; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
| 1238 | if (IS_ERR(pdrm)) | ||
| 1239 | pr_warn("%s: Unable to get syscfg\n", __func__); | ||
| 1240 | else | ||
| 1241 | /* In any case disable backup domain write protection | ||
| 1242 | * and will never be enabled. | ||
| 1243 | * Needed by LSE & RTC clocks. | ||
| 1244 | */ | ||
| 1245 | regmap_update_bits(pdrm, PWR_CR, PWR_CR_DBP, PWR_CR_DBP); | ||
| 1246 | |||
| 1247 | /* Put parent names from DT */ | ||
| 1248 | hse_clk = of_clk_get_parent_name(np, 0); | ||
| 1249 | lse_clk = of_clk_get_parent_name(np, 1); | ||
| 1250 | i2s_clk = of_clk_get_parent_name(np, 2); | ||
| 1251 | |||
| 1252 | sai_src[3] = i2s_clk; | ||
| 1253 | spi_src1[3] = i2s_clk; | ||
| 1254 | |||
| 1255 | /* Register Internal oscillators */ | ||
| 1256 | clk_hw_register_fixed_rate(NULL, "clk-hsi", NULL, 0, 64000000); | ||
| 1257 | clk_hw_register_fixed_rate(NULL, "clk-csi", NULL, 0, 4000000); | ||
| 1258 | clk_hw_register_fixed_rate(NULL, "clk-lsi", NULL, 0, 32000); | ||
| 1259 | clk_hw_register_fixed_rate(NULL, "clk-rc48", NULL, 0, 48000); | ||
| 1260 | |||
| 1261 | /* This clock is coming from outside. Frequencies unknown */ | ||
| 1262 | hws[CK_DSI_PHY] = clk_hw_register_fixed_rate(NULL, "ck_dsi_phy", NULL, | ||
| 1263 | 0, 0); | ||
| 1264 | |||
| 1265 | hws[HSI_DIV] = clk_hw_register_divider(NULL, "hsidiv", "clk-hsi", 0, | ||
| 1266 | base + RCC_CR, 3, 2, CLK_DIVIDER_POWER_OF_TWO, | ||
| 1267 | &stm32rcc_lock); | ||
| 1268 | |||
| 1269 | hws[HSE_1M] = clk_hw_register_divider(NULL, "hse_1M", "hse_ck", 0, | ||
| 1270 | base + RCC_CFGR, 8, 6, CLK_DIVIDER_ONE_BASED | | ||
| 1271 | CLK_DIVIDER_ALLOW_ZERO, | ||
| 1272 | &stm32rcc_lock); | ||
| 1273 | |||
| 1274 | /* Mux system clocks */ | ||
| 1275 | for (n = 0; n < ARRAY_SIZE(stm32_mclk); n++) | ||
| 1276 | hws[MCLK_BANK + n] = clk_hw_register_mux(NULL, | ||
| 1277 | stm32_mclk[n].name, | ||
| 1278 | stm32_mclk[n].parents, | ||
| 1279 | stm32_mclk[n].num_parents, | ||
| 1280 | stm32_mclk[n].flags, | ||
| 1281 | stm32_mclk[n].offset + base, | ||
| 1282 | stm32_mclk[n].shift, | ||
| 1283 | stm32_mclk[n].width, | ||
| 1284 | 0, | ||
| 1285 | &stm32rcc_lock); | ||
| 1286 | |||
| 1287 | register_core_and_bus_clocks(); | ||
| 1288 | |||
| 1289 | /* Oscillary clocks */ | ||
| 1290 | for (n = 0; n < ARRAY_SIZE(stm32_oclk); n++) | ||
| 1291 | hws[OSC_BANK + n] = clk_register_ready_gate(NULL, | ||
| 1292 | stm32_oclk[n].name, | ||
| 1293 | stm32_oclk[n].parent, | ||
| 1294 | stm32_oclk[n].gate_offset + base, | ||
| 1295 | stm32_oclk[n].bit_idx, | ||
| 1296 | stm32_oclk[n].bit_rdy, | ||
| 1297 | stm32_oclk[n].flags, | ||
| 1298 | &stm32rcc_lock); | ||
| 1299 | |||
| 1300 | hws[HSE_CK] = clk_register_ready_gate(NULL, | ||
| 1301 | "hse_ck", | ||
| 1302 | hse_clk, | ||
| 1303 | RCC_CR + base, | ||
| 1304 | 16, 17, | ||
| 1305 | 0, | ||
| 1306 | &stm32rcc_lock); | ||
| 1307 | |||
| 1308 | hws[LSE_CK] = clk_register_ready_gate(NULL, | ||
| 1309 | "lse_ck", | ||
| 1310 | lse_clk, | ||
| 1311 | RCC_BDCR + base, | ||
| 1312 | 0, 1, | ||
| 1313 | 0, | ||
| 1314 | &stm32rcc_lock); | ||
| 1315 | |||
| 1316 | hws[CSI_KER_DIV122 + n] = clk_hw_register_fixed_factor(NULL, | ||
| 1317 | "csi_ker_div122", "csi_ker", 0, 1, 122); | ||
| 1318 | |||
| 1319 | /* PLLs */ | ||
| 1320 | for (n = 0; n < ARRAY_SIZE(stm32_pll); n++) { | ||
| 1321 | int odf; | ||
| 1322 | |||
| 1323 | /* Register the VCO */ | ||
| 1324 | clk_register_stm32_pll(NULL, stm32_pll[n].name, | ||
| 1325 | stm32_pll[n].parent_name, stm32_pll[n].flags, | ||
| 1326 | stm32_pll[n].cfg, | ||
| 1327 | &stm32rcc_lock); | ||
| 1328 | |||
| 1329 | /* Register the 3 output dividers */ | ||
| 1330 | for (odf = 0; odf < 3; odf++) { | ||
| 1331 | int idx = n * 3 + odf; | ||
| 1332 | |||
| 1333 | get_cfg_composite_div(&odf_clk_gcfg, &stm32_odf[n][odf], | ||
| 1334 | &c_cfg, &stm32rcc_lock); | ||
| 1335 | |||
| 1336 | hws[ODF_BANK + idx] = clk_hw_register_composite(NULL, | ||
| 1337 | stm32_odf[n][odf].name, | ||
| 1338 | stm32_odf[n][odf].parent_name, | ||
| 1339 | stm32_odf[n][odf].num_parents, | ||
| 1340 | c_cfg.mux_hw, c_cfg.mux_ops, | ||
| 1341 | c_cfg.div_hw, c_cfg.div_ops, | ||
| 1342 | c_cfg.gate_hw, c_cfg.gate_ops, | ||
| 1343 | stm32_odf[n][odf].flags); | ||
| 1344 | } | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | /* Peripheral clocks */ | ||
| 1348 | for (n = 0; n < ARRAY_SIZE(pclk); n++) | ||
| 1349 | hws[PERIF_BANK + n] = clk_hw_register_gate(NULL, pclk[n].name, | ||
| 1350 | pclk[n].parent, | ||
| 1351 | pclk[n].flags, base + pclk[n].gate_offset, | ||
| 1352 | pclk[n].bit_idx, pclk[n].flags, &stm32rcc_lock); | ||
| 1353 | |||
| 1354 | /* Kernel clocks */ | ||
| 1355 | for (n = 0; n < ARRAY_SIZE(kclk); n++) { | ||
| 1356 | get_cfg_composite_div(&kernel_clk_cfg, &kclk[n], &c_cfg, | ||
| 1357 | &stm32rcc_lock); | ||
| 1358 | |||
| 1359 | hws[KERN_BANK + n] = clk_hw_register_composite(NULL, | ||
| 1360 | kclk[n].name, | ||
| 1361 | kclk[n].parent_name, | ||
| 1362 | kclk[n].num_parents, | ||
| 1363 | c_cfg.mux_hw, c_cfg.mux_ops, | ||
| 1364 | c_cfg.div_hw, c_cfg.div_ops, | ||
| 1365 | c_cfg.gate_hw, c_cfg.gate_ops, | ||
| 1366 | kclk[n].flags); | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | /* RTC clock (default state is off) */ | ||
| 1370 | clk_hw_register_fixed_rate(NULL, "off", NULL, 0, 0); | ||
| 1371 | |||
| 1372 | get_cfg_composite_div(&rtc_clk_cfg, &rtc_clk, &c_cfg, &stm32rcc_lock); | ||
| 1373 | |||
| 1374 | hws[RTC_CK] = clk_hw_register_composite(NULL, | ||
| 1375 | rtc_clk.name, | ||
| 1376 | rtc_clk.parent_name, | ||
| 1377 | rtc_clk.num_parents, | ||
| 1378 | c_cfg.mux_hw, c_cfg.mux_ops, | ||
| 1379 | c_cfg.div_hw, c_cfg.div_ops, | ||
| 1380 | c_cfg.gate_hw, c_cfg.gate_ops, | ||
| 1381 | rtc_clk.flags); | ||
| 1382 | |||
| 1383 | /* Micro-controller clocks */ | ||
| 1384 | for (n = 0; n < ARRAY_SIZE(mco_clk); n++) { | ||
| 1385 | get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg, | ||
| 1386 | &stm32rcc_lock); | ||
| 1387 | |||
| 1388 | hws[MCO_BANK + n] = clk_hw_register_composite(NULL, | ||
| 1389 | mco_clk[n].name, | ||
| 1390 | mco_clk[n].parent_name, | ||
| 1391 | mco_clk[n].num_parents, | ||
| 1392 | c_cfg.mux_hw, c_cfg.mux_ops, | ||
| 1393 | c_cfg.div_hw, c_cfg.div_ops, | ||
| 1394 | c_cfg.gate_hw, c_cfg.gate_ops, | ||
| 1395 | mco_clk[n].flags); | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); | ||
| 1399 | |||
| 1400 | return; | ||
| 1401 | |||
| 1402 | err_free_clks: | ||
| 1403 | kfree(clk_data); | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | /* The RCC node is a clock and reset controller, and these | ||
| 1407 | * functionalities are supported by different drivers that | ||
| 1408 | * matches the same compatible strings. | ||
| 1409 | */ | ||
| 1410 | CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init); | ||
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index ea7d552a2f2b..decffb3826ec 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #define VC5_PRIM_SRC_SHDN 0x10 | 57 | #define VC5_PRIM_SRC_SHDN 0x10 |
| 58 | #define VC5_PRIM_SRC_SHDN_EN_XTAL BIT(7) | 58 | #define VC5_PRIM_SRC_SHDN_EN_XTAL BIT(7) |
| 59 | #define VC5_PRIM_SRC_SHDN_EN_CLKIN BIT(6) | 59 | #define VC5_PRIM_SRC_SHDN_EN_CLKIN BIT(6) |
| 60 | #define VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ BIT(3) | ||
| 60 | #define VC5_PRIM_SRC_SHDN_SP BIT(1) | 61 | #define VC5_PRIM_SRC_SHDN_SP BIT(1) |
| 61 | #define VC5_PRIM_SRC_SHDN_EN_GBL_SHDN BIT(0) | 62 | #define VC5_PRIM_SRC_SHDN_EN_GBL_SHDN BIT(0) |
| 62 | 63 | ||
| @@ -122,12 +123,16 @@ | |||
| 122 | /* flags to describe chip features */ | 123 | /* flags to describe chip features */ |
| 123 | /* chip has built-in oscilator */ | 124 | /* chip has built-in oscilator */ |
| 124 | #define VC5_HAS_INTERNAL_XTAL BIT(0) | 125 | #define VC5_HAS_INTERNAL_XTAL BIT(0) |
| 126 | /* chip has PFD requency doubler */ | ||
| 127 | #define VC5_HAS_PFD_FREQ_DBL BIT(1) | ||
| 125 | 128 | ||
| 126 | /* Supported IDT VC5 models. */ | 129 | /* Supported IDT VC5 models. */ |
| 127 | enum vc5_model { | 130 | enum vc5_model { |
| 128 | IDT_VC5_5P49V5923, | 131 | IDT_VC5_5P49V5923, |
| 132 | IDT_VC5_5P49V5925, | ||
| 129 | IDT_VC5_5P49V5933, | 133 | IDT_VC5_5P49V5933, |
| 130 | IDT_VC5_5P49V5935, | 134 | IDT_VC5_5P49V5935, |
| 135 | IDT_VC6_5P49V6901, | ||
| 131 | }; | 136 | }; |
| 132 | 137 | ||
| 133 | /* Structure to describe features of a particular VC5 model */ | 138 | /* Structure to describe features of a particular VC5 model */ |
| @@ -157,6 +162,8 @@ struct vc5_driver_data { | |||
| 157 | struct clk *pin_clkin; | 162 | struct clk *pin_clkin; |
| 158 | unsigned char clk_mux_ins; | 163 | unsigned char clk_mux_ins; |
| 159 | struct clk_hw clk_mux; | 164 | struct clk_hw clk_mux; |
| 165 | struct clk_hw clk_mul; | ||
| 166 | struct clk_hw clk_pfd; | ||
| 160 | struct vc5_hw_data clk_pll; | 167 | struct vc5_hw_data clk_pll; |
| 161 | struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; | 168 | struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; |
| 162 | struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; | 169 | struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; |
| @@ -166,6 +173,14 @@ static const char * const vc5_mux_names[] = { | |||
| 166 | "mux" | 173 | "mux" |
| 167 | }; | 174 | }; |
| 168 | 175 | ||
| 176 | static const char * const vc5_dbl_names[] = { | ||
| 177 | "dbl" | ||
| 178 | }; | ||
| 179 | |||
| 180 | static const char * const vc5_pfd_names[] = { | ||
| 181 | "pfd" | ||
| 182 | }; | ||
| 183 | |||
| 169 | static const char * const vc5_pll_names[] = { | 184 | static const char * const vc5_pll_names[] = { |
| 170 | "pll" | 185 | "pll" |
| 171 | }; | 186 | }; |
| @@ -254,11 +269,64 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index) | |||
| 254 | return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src); | 269 | return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src); |
| 255 | } | 270 | } |
| 256 | 271 | ||
| 257 | static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, | 272 | static const struct clk_ops vc5_mux_ops = { |
| 273 | .set_parent = vc5_mux_set_parent, | ||
| 274 | .get_parent = vc5_mux_get_parent, | ||
| 275 | }; | ||
| 276 | |||
| 277 | static unsigned long vc5_dbl_recalc_rate(struct clk_hw *hw, | ||
| 258 | unsigned long parent_rate) | 278 | unsigned long parent_rate) |
| 259 | { | 279 | { |
| 260 | struct vc5_driver_data *vc5 = | 280 | struct vc5_driver_data *vc5 = |
| 261 | container_of(hw, struct vc5_driver_data, clk_mux); | 281 | container_of(hw, struct vc5_driver_data, clk_mul); |
| 282 | unsigned int premul; | ||
| 283 | |||
| 284 | regmap_read(vc5->regmap, VC5_PRIM_SRC_SHDN, &premul); | ||
| 285 | if (premul & VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ) | ||
| 286 | parent_rate *= 2; | ||
| 287 | |||
| 288 | return parent_rate; | ||
| 289 | } | ||
| 290 | |||
| 291 | static long vc5_dbl_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 292 | unsigned long *parent_rate) | ||
| 293 | { | ||
| 294 | if ((*parent_rate == rate) || ((*parent_rate * 2) == rate)) | ||
| 295 | return rate; | ||
| 296 | else | ||
| 297 | return -EINVAL; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int vc5_dbl_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 301 | unsigned long parent_rate) | ||
| 302 | { | ||
| 303 | struct vc5_driver_data *vc5 = | ||
| 304 | container_of(hw, struct vc5_driver_data, clk_mul); | ||
| 305 | u32 mask; | ||
| 306 | |||
| 307 | if ((parent_rate * 2) == rate) | ||
| 308 | mask = VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ; | ||
| 309 | else | ||
| 310 | mask = 0; | ||
| 311 | |||
| 312 | regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, | ||
| 313 | VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ, | ||
| 314 | mask); | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | static const struct clk_ops vc5_dbl_ops = { | ||
| 320 | .recalc_rate = vc5_dbl_recalc_rate, | ||
| 321 | .round_rate = vc5_dbl_round_rate, | ||
| 322 | .set_rate = vc5_dbl_set_rate, | ||
| 323 | }; | ||
| 324 | |||
| 325 | static unsigned long vc5_pfd_recalc_rate(struct clk_hw *hw, | ||
| 326 | unsigned long parent_rate) | ||
| 327 | { | ||
| 328 | struct vc5_driver_data *vc5 = | ||
| 329 | container_of(hw, struct vc5_driver_data, clk_pfd); | ||
| 262 | unsigned int prediv, div; | 330 | unsigned int prediv, div; |
| 263 | 331 | ||
| 264 | regmap_read(vc5->regmap, VC5_VCO_CTRL_AND_PREDIV, &prediv); | 332 | regmap_read(vc5->regmap, VC5_VCO_CTRL_AND_PREDIV, &prediv); |
| @@ -276,7 +344,7 @@ static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, | |||
| 276 | return parent_rate / VC5_REF_DIVIDER_REF_DIV(div); | 344 | return parent_rate / VC5_REF_DIVIDER_REF_DIV(div); |
| 277 | } | 345 | } |
| 278 | 346 | ||
| 279 | static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, | 347 | static long vc5_pfd_round_rate(struct clk_hw *hw, unsigned long rate, |
| 280 | unsigned long *parent_rate) | 348 | unsigned long *parent_rate) |
| 281 | { | 349 | { |
| 282 | unsigned long idiv; | 350 | unsigned long idiv; |
| @@ -296,11 +364,11 @@ static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 296 | return *parent_rate / idiv; | 364 | return *parent_rate / idiv; |
| 297 | } | 365 | } |
| 298 | 366 | ||
| 299 | static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, | 367 | static int vc5_pfd_set_rate(struct clk_hw *hw, unsigned long rate, |
| 300 | unsigned long parent_rate) | 368 | unsigned long parent_rate) |
| 301 | { | 369 | { |
| 302 | struct vc5_driver_data *vc5 = | 370 | struct vc5_driver_data *vc5 = |
| 303 | container_of(hw, struct vc5_driver_data, clk_mux); | 371 | container_of(hw, struct vc5_driver_data, clk_pfd); |
| 304 | unsigned long idiv; | 372 | unsigned long idiv; |
| 305 | u8 div; | 373 | u8 div; |
| 306 | 374 | ||
| @@ -328,12 +396,10 @@ static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 328 | return 0; | 396 | return 0; |
| 329 | } | 397 | } |
| 330 | 398 | ||
| 331 | static const struct clk_ops vc5_mux_ops = { | 399 | static const struct clk_ops vc5_pfd_ops = { |
| 332 | .set_parent = vc5_mux_set_parent, | 400 | .recalc_rate = vc5_pfd_recalc_rate, |
| 333 | .get_parent = vc5_mux_get_parent, | 401 | .round_rate = vc5_pfd_round_rate, |
| 334 | .recalc_rate = vc5_mux_recalc_rate, | 402 | .set_rate = vc5_pfd_set_rate, |
| 335 | .round_rate = vc5_mux_round_rate, | ||
| 336 | .set_rate = vc5_mux_set_rate, | ||
| 337 | }; | 403 | }; |
| 338 | 404 | ||
| 339 | /* | 405 | /* |
| @@ -426,6 +492,10 @@ static unsigned long vc5_fod_recalc_rate(struct clk_hw *hw, | |||
| 426 | div_frc = (od_frc[0] << 22) | (od_frc[1] << 14) | | 492 | div_frc = (od_frc[0] << 22) | (od_frc[1] << 14) | |
| 427 | (od_frc[2] << 6) | (od_frc[3] >> 2); | 493 | (od_frc[2] << 6) | (od_frc[3] >> 2); |
| 428 | 494 | ||
| 495 | /* Avoid division by zero if the output is not configured. */ | ||
| 496 | if (div_int == 0 && div_frc == 0) | ||
| 497 | return 0; | ||
| 498 | |||
| 429 | /* The PLL divider has 12 integer bits and 30 fractional bits */ | 499 | /* The PLL divider has 12 integer bits and 30 fractional bits */ |
| 430 | return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc); | 500 | return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc); |
| 431 | } | 501 | } |
| @@ -503,6 +573,25 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) | |||
| 503 | { | 573 | { |
| 504 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); | 574 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); |
| 505 | struct vc5_driver_data *vc5 = hwdata->vc5; | 575 | struct vc5_driver_data *vc5 = hwdata->vc5; |
| 576 | const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM | | ||
| 577 | VC5_OUT_DIV_CONTROL_SEL_EXT | | ||
| 578 | VC5_OUT_DIV_CONTROL_EN_FOD; | ||
| 579 | unsigned int src; | ||
| 580 | int ret; | ||
| 581 | |||
| 582 | /* | ||
| 583 | * If the input mux is disabled, enable it first and | ||
| 584 | * select source from matching FOD. | ||
| 585 | */ | ||
| 586 | regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); | ||
| 587 | if ((src & mask) == 0) { | ||
| 588 | src = VC5_OUT_DIV_CONTROL_RESET | VC5_OUT_DIV_CONTROL_EN_FOD; | ||
| 589 | ret = regmap_update_bits(vc5->regmap, | ||
| 590 | VC5_OUT_DIV_CONTROL(hwdata->num), | ||
| 591 | mask | VC5_OUT_DIV_CONTROL_RESET, src); | ||
| 592 | if (ret) | ||
| 593 | return ret; | ||
| 594 | } | ||
| 506 | 595 | ||
| 507 | /* Enable the clock buffer */ | 596 | /* Enable the clock buffer */ |
| 508 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), | 597 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), |
| @@ -516,7 +605,7 @@ static void vc5_clk_out_unprepare(struct clk_hw *hw) | |||
| 516 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); | 605 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); |
| 517 | struct vc5_driver_data *vc5 = hwdata->vc5; | 606 | struct vc5_driver_data *vc5 = hwdata->vc5; |
| 518 | 607 | ||
| 519 | /* Enable the clock buffer */ | 608 | /* Disable the clock buffer */ |
| 520 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), | 609 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), |
| 521 | VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, 0); | 610 | VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, 0); |
| 522 | } | 611 | } |
| @@ -537,6 +626,9 @@ static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) | |||
| 537 | regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); | 626 | regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); |
| 538 | src &= mask; | 627 | src &= mask; |
| 539 | 628 | ||
| 629 | if (src == 0) /* Input mux set to DISABLED */ | ||
| 630 | return 0; | ||
| 631 | |||
| 540 | if ((src & fodclkmask) == VC5_OUT_DIV_CONTROL_EN_FOD) | 632 | if ((src & fodclkmask) == VC5_OUT_DIV_CONTROL_EN_FOD) |
| 541 | return 0; | 633 | return 0; |
| 542 | 634 | ||
| @@ -595,7 +687,9 @@ static int vc5_map_index_to_output(const enum vc5_model model, | |||
| 595 | case IDT_VC5_5P49V5933: | 687 | case IDT_VC5_5P49V5933: |
| 596 | return (n == 0) ? 0 : 3; | 688 | return (n == 0) ? 0 : 3; |
| 597 | case IDT_VC5_5P49V5923: | 689 | case IDT_VC5_5P49V5923: |
| 690 | case IDT_VC5_5P49V5925: | ||
| 598 | case IDT_VC5_5P49V5935: | 691 | case IDT_VC5_5P49V5935: |
| 692 | case IDT_VC6_5P49V6901: | ||
| 599 | default: | 693 | default: |
| 600 | return n; | 694 | return n; |
| 601 | } | 695 | } |
| @@ -672,12 +766,46 @@ static int vc5_probe(struct i2c_client *client, | |||
| 672 | goto err_clk; | 766 | goto err_clk; |
| 673 | } | 767 | } |
| 674 | 768 | ||
| 769 | if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { | ||
| 770 | /* Register frequency doubler */ | ||
| 771 | memset(&init, 0, sizeof(init)); | ||
| 772 | init.name = vc5_dbl_names[0]; | ||
| 773 | init.ops = &vc5_dbl_ops; | ||
| 774 | init.flags = CLK_SET_RATE_PARENT; | ||
| 775 | init.parent_names = vc5_mux_names; | ||
| 776 | init.num_parents = 1; | ||
| 777 | vc5->clk_mul.init = &init; | ||
| 778 | ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); | ||
| 779 | if (ret) { | ||
| 780 | dev_err(&client->dev, "unable to register %s\n", | ||
| 781 | init.name); | ||
| 782 | goto err_clk; | ||
| 783 | } | ||
| 784 | } | ||
| 785 | |||
| 786 | /* Register PFD */ | ||
| 787 | memset(&init, 0, sizeof(init)); | ||
| 788 | init.name = vc5_pfd_names[0]; | ||
| 789 | init.ops = &vc5_pfd_ops; | ||
| 790 | init.flags = CLK_SET_RATE_PARENT; | ||
| 791 | if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) | ||
| 792 | init.parent_names = vc5_dbl_names; | ||
| 793 | else | ||
| 794 | init.parent_names = vc5_mux_names; | ||
| 795 | init.num_parents = 1; | ||
| 796 | vc5->clk_pfd.init = &init; | ||
| 797 | ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); | ||
| 798 | if (ret) { | ||
| 799 | dev_err(&client->dev, "unable to register %s\n", init.name); | ||
| 800 | goto err_clk; | ||
| 801 | } | ||
| 802 | |||
| 675 | /* Register PLL */ | 803 | /* Register PLL */ |
| 676 | memset(&init, 0, sizeof(init)); | 804 | memset(&init, 0, sizeof(init)); |
| 677 | init.name = vc5_pll_names[0]; | 805 | init.name = vc5_pll_names[0]; |
| 678 | init.ops = &vc5_pll_ops; | 806 | init.ops = &vc5_pll_ops; |
| 679 | init.flags = CLK_SET_RATE_PARENT; | 807 | init.flags = CLK_SET_RATE_PARENT; |
| 680 | init.parent_names = vc5_mux_names; | 808 | init.parent_names = vc5_pfd_names; |
| 681 | init.num_parents = 1; | 809 | init.num_parents = 1; |
| 682 | vc5->clk_pll.num = 0; | 810 | vc5->clk_pll.num = 0; |
| 683 | vc5->clk_pll.vc5 = vc5; | 811 | vc5->clk_pll.vc5 = vc5; |
| @@ -785,6 +913,13 @@ static const struct vc5_chip_info idt_5p49v5923_info = { | |||
| 785 | .flags = 0, | 913 | .flags = 0, |
| 786 | }; | 914 | }; |
| 787 | 915 | ||
| 916 | static const struct vc5_chip_info idt_5p49v5925_info = { | ||
| 917 | .model = IDT_VC5_5P49V5925, | ||
| 918 | .clk_fod_cnt = 4, | ||
| 919 | .clk_out_cnt = 5, | ||
| 920 | .flags = 0, | ||
| 921 | }; | ||
| 922 | |||
| 788 | static const struct vc5_chip_info idt_5p49v5933_info = { | 923 | static const struct vc5_chip_info idt_5p49v5933_info = { |
| 789 | .model = IDT_VC5_5P49V5933, | 924 | .model = IDT_VC5_5P49V5933, |
| 790 | .clk_fod_cnt = 2, | 925 | .clk_fod_cnt = 2, |
| @@ -799,18 +934,29 @@ static const struct vc5_chip_info idt_5p49v5935_info = { | |||
| 799 | .flags = VC5_HAS_INTERNAL_XTAL, | 934 | .flags = VC5_HAS_INTERNAL_XTAL, |
| 800 | }; | 935 | }; |
| 801 | 936 | ||
| 937 | static const struct vc5_chip_info idt_5p49v6901_info = { | ||
| 938 | .model = IDT_VC6_5P49V6901, | ||
| 939 | .clk_fod_cnt = 4, | ||
| 940 | .clk_out_cnt = 5, | ||
| 941 | .flags = VC5_HAS_PFD_FREQ_DBL, | ||
| 942 | }; | ||
| 943 | |||
| 802 | static const struct i2c_device_id vc5_id[] = { | 944 | static const struct i2c_device_id vc5_id[] = { |
| 803 | { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, | 945 | { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, |
| 946 | { "5p49v5925", .driver_data = IDT_VC5_5P49V5925 }, | ||
| 804 | { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, | 947 | { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, |
| 805 | { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, | 948 | { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, |
| 949 | { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 }, | ||
| 806 | { } | 950 | { } |
| 807 | }; | 951 | }; |
| 808 | MODULE_DEVICE_TABLE(i2c, vc5_id); | 952 | MODULE_DEVICE_TABLE(i2c, vc5_id); |
| 809 | 953 | ||
| 810 | static const struct of_device_id clk_vc5_of_match[] = { | 954 | static const struct of_device_id clk_vc5_of_match[] = { |
| 811 | { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info }, | 955 | { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info }, |
| 956 | { .compatible = "idt,5p49v5925", .data = &idt_5p49v5925_info }, | ||
| 812 | { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info }, | 957 | { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info }, |
| 813 | { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info }, | 958 | { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info }, |
| 959 | { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info }, | ||
| 814 | { }, | 960 | { }, |
| 815 | }; | 961 | }; |
| 816 | MODULE_DEVICE_TABLE(of, clk_vc5_of_match); | 962 | MODULE_DEVICE_TABLE(of, clk_vc5_of_match); |
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index bc37030e38ba..4c75821a3933 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c | |||
| @@ -192,7 +192,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty | |||
| 192 | 192 | ||
| 193 | reg = of_iomap(np, 0); | 193 | reg = of_iomap(np, 0); |
| 194 | if (reg == NULL) { | 194 | if (reg == NULL) { |
| 195 | pr_err("Unable to map CSR register for %s\n", np->full_name); | 195 | pr_err("Unable to map CSR register for %pOF\n", np); |
| 196 | return; | 196 | return; |
| 197 | } | 197 | } |
| 198 | of_property_read_string(np, "clock-output-names", &clk_name); | 198 | of_property_read_string(np, "clock-output-names", &clk_name); |
| @@ -409,12 +409,12 @@ static void xgene_pmdclk_init(struct device_node *np) | |||
| 409 | /* Parse the DTS register for resource */ | 409 | /* Parse the DTS register for resource */ |
| 410 | rc = of_address_to_resource(np, 0, &res); | 410 | rc = of_address_to_resource(np, 0, &res); |
| 411 | if (rc != 0) { | 411 | if (rc != 0) { |
| 412 | pr_err("no DTS register for %s\n", np->full_name); | 412 | pr_err("no DTS register for %pOF\n", np); |
| 413 | return; | 413 | return; |
| 414 | } | 414 | } |
| 415 | csr_reg = of_iomap(np, 0); | 415 | csr_reg = of_iomap(np, 0); |
| 416 | if (!csr_reg) { | 416 | if (!csr_reg) { |
| 417 | pr_err("Unable to map resource for %s\n", np->full_name); | 417 | pr_err("Unable to map resource for %pOF\n", np); |
| 418 | return; | 418 | return; |
| 419 | } | 419 | } |
| 420 | of_property_read_string(np, "clock-output-names", &clk_name); | 420 | of_property_read_string(np, "clock-output-names", &clk_name); |
| @@ -703,16 +703,14 @@ static void __init xgene_devclk_init(struct device_node *np) | |||
| 703 | rc = of_address_to_resource(np, i, &res); | 703 | rc = of_address_to_resource(np, i, &res); |
| 704 | if (rc != 0) { | 704 | if (rc != 0) { |
| 705 | if (i == 0) { | 705 | if (i == 0) { |
| 706 | pr_err("no DTS register for %s\n", | 706 | pr_err("no DTS register for %pOF\n", np); |
| 707 | np->full_name); | ||
| 708 | return; | 707 | return; |
| 709 | } | 708 | } |
| 710 | break; | 709 | break; |
| 711 | } | 710 | } |
| 712 | map_res = of_iomap(np, i); | 711 | map_res = of_iomap(np, i); |
| 713 | if (map_res == NULL) { | 712 | if (map_res == NULL) { |
| 714 | pr_err("Unable to map resource %d for %s\n", | 713 | pr_err("Unable to map resource %d for %pOF\n", i, np); |
| 715 | i, np->full_name); | ||
| 716 | goto err; | 714 | goto err; |
| 717 | } | 715 | } |
| 718 | if (strcmp(res.name, "div-reg") == 0) | 716 | if (strcmp(res.name, "div-reg") == 0) |
| @@ -747,8 +745,7 @@ static void __init xgene_devclk_init(struct device_node *np) | |||
| 747 | pr_debug("Add %s clock\n", clk_name); | 745 | pr_debug("Add %s clock\n", clk_name); |
| 748 | rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); | 746 | rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); |
| 749 | if (rc != 0) | 747 | if (rc != 0) |
| 750 | pr_err("%s: could register provider clk %s\n", __func__, | 748 | pr_err("%s: could register provider clk %pOF\n", __func__, np); |
| 751 | np->full_name); | ||
| 752 | 749 | ||
| 753 | return; | 750 | return; |
| 754 | 751 | ||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fc58c52a26b4..c8d83acda006 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -3132,7 +3132,7 @@ int of_clk_add_provider(struct device_node *np, | |||
| 3132 | mutex_lock(&of_clk_mutex); | 3132 | mutex_lock(&of_clk_mutex); |
| 3133 | list_add(&cp->link, &of_clk_providers); | 3133 | list_add(&cp->link, &of_clk_providers); |
| 3134 | mutex_unlock(&of_clk_mutex); | 3134 | mutex_unlock(&of_clk_mutex); |
| 3135 | pr_debug("Added clock from %s\n", np->full_name); | 3135 | pr_debug("Added clock from %pOF\n", np); |
| 3136 | 3136 | ||
| 3137 | ret = of_clk_set_defaults(np, true); | 3137 | ret = of_clk_set_defaults(np, true); |
| 3138 | if (ret < 0) | 3138 | if (ret < 0) |
| @@ -3167,7 +3167,7 @@ int of_clk_add_hw_provider(struct device_node *np, | |||
| 3167 | mutex_lock(&of_clk_mutex); | 3167 | mutex_lock(&of_clk_mutex); |
| 3168 | list_add(&cp->link, &of_clk_providers); | 3168 | list_add(&cp->link, &of_clk_providers); |
| 3169 | mutex_unlock(&of_clk_mutex); | 3169 | mutex_unlock(&of_clk_mutex); |
| 3170 | pr_debug("Added clk_hw provider from %s\n", np->full_name); | 3170 | pr_debug("Added clk_hw provider from %pOF\n", np); |
| 3171 | 3171 | ||
| 3172 | ret = of_clk_set_defaults(np, true); | 3172 | ret = of_clk_set_defaults(np, true); |
| 3173 | if (ret < 0) | 3173 | if (ret < 0) |
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index bb8a77a5985f..6b2f29df3f70 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
| @@ -77,8 +77,8 @@ static struct clk *__of_clk_get_by_name(struct device_node *np, | |||
| 77 | break; | 77 | break; |
| 78 | } else if (name && index >= 0) { | 78 | } else if (name && index >= 0) { |
| 79 | if (PTR_ERR(clk) != -EPROBE_DEFER) | 79 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 80 | pr_err("ERROR: could not get clock %s:%s(%i)\n", | 80 | pr_err("ERROR: could not get clock %pOF:%s(%i)\n", |
| 81 | np->full_name, name ? name : "", index); | 81 | np, name ? name : "", index); |
| 82 | return clk; | 82 | return clk; |
| 83 | } | 83 | } |
| 84 | 84 | ||
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index 4181b6808545..e786d717f75d 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c | |||
| @@ -55,9 +55,9 @@ static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = { | |||
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { | 57 | static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { |
| 58 | { HI6220_WDT0_PCLK, "wdt0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, }, | 58 | { HI6220_WDT0_PCLK, "wdt0_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, }, |
| 59 | { HI6220_WDT1_PCLK, "wdt1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, }, | 59 | { HI6220_WDT1_PCLK, "wdt1_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, }, |
| 60 | { HI6220_WDT2_PCLK, "wdt2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, }, | 60 | { HI6220_WDT2_PCLK, "wdt2_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, }, |
| 61 | { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, }, | 61 | { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, }, |
| 62 | { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, }, | 62 | { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, }, |
| 63 | { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, }, | 63 | { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, }, |
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c index 1e3c9ea5f9dc..7bcaf270db11 100644 --- a/drivers/clk/imx/clk-imx51-imx53.c +++ b/drivers/clk/imx/clk-imx51-imx53.c | |||
| @@ -416,10 +416,10 @@ static void __init mx51_clocks_init(struct device_node *np) | |||
| 416 | 416 | ||
| 417 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, | 417 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, |
| 418 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); | 418 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); |
| 419 | clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, | 419 | clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, |
| 420 | mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); | 420 | mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel), CLK_SET_RATE_PARENT); |
| 421 | clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, | 421 | clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, |
| 422 | mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); | 422 | mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel), CLK_SET_RATE_PARENT); |
| 423 | clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, | 423 | clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, |
| 424 | mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); | 424 | mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); |
| 425 | clk[IMX5_CLK_TVE_SEL] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, | 425 | clk[IMX5_CLK_TVE_SEL] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, |
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c index 5fd4ddac1bf1..9642cdf0fb88 100644 --- a/drivers/clk/imx/clk-imx6sl.c +++ b/drivers/clk/imx/clk-imx6sl.c | |||
| @@ -71,7 +71,7 @@ static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; | |||
| 71 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; | 71 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; |
| 72 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; | 72 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; |
| 73 | 73 | ||
| 74 | static struct clk_div_table clk_enet_ref_table[] = { | 74 | static const struct clk_div_table clk_enet_ref_table[] = { |
| 75 | { .val = 0, .div = 20, }, | 75 | { .val = 0, .div = 20, }, |
| 76 | { .val = 1, .div = 10, }, | 76 | { .val = 1, .div = 10, }, |
| 77 | { .val = 2, .div = 5, }, | 77 | { .val = 2, .div = 5, }, |
| @@ -79,14 +79,14 @@ static struct clk_div_table clk_enet_ref_table[] = { | |||
| 79 | { } | 79 | { } |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | static struct clk_div_table post_div_table[] = { | 82 | static const struct clk_div_table post_div_table[] = { |
| 83 | { .val = 2, .div = 1, }, | 83 | { .val = 2, .div = 1, }, |
| 84 | { .val = 1, .div = 2, }, | 84 | { .val = 1, .div = 2, }, |
| 85 | { .val = 0, .div = 4, }, | 85 | { .val = 0, .div = 4, }, |
| 86 | { } | 86 | { } |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | static struct clk_div_table video_div_table[] = { | 89 | static const struct clk_div_table video_div_table[] = { |
| 90 | { .val = 0, .div = 1, }, | 90 | { .val = 0, .div = 1, }, |
| 91 | { .val = 1, .div = 2, }, | 91 | { .val = 1, .div = 2, }, |
| 92 | { .val = 2, .div = 1, }, | 92 | { .val = 2, .div = 1, }, |
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index b5c96de41ccf..e6d389e333d7 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c | |||
| @@ -105,7 +105,7 @@ static int const clks_init_on[] __initconst = { | |||
| 105 | IMX6SX_CLK_EPIT2, | 105 | IMX6SX_CLK_EPIT2, |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | static struct clk_div_table clk_enet_ref_table[] = { | 108 | static const struct clk_div_table clk_enet_ref_table[] = { |
| 109 | { .val = 0, .div = 20, }, | 109 | { .val = 0, .div = 20, }, |
| 110 | { .val = 1, .div = 10, }, | 110 | { .val = 1, .div = 10, }, |
| 111 | { .val = 2, .div = 5, }, | 111 | { .val = 2, .div = 5, }, |
| @@ -113,14 +113,14 @@ static struct clk_div_table clk_enet_ref_table[] = { | |||
| 113 | { } | 113 | { } |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
| 116 | static struct clk_div_table post_div_table[] = { | 116 | static const struct clk_div_table post_div_table[] = { |
| 117 | { .val = 2, .div = 1, }, | 117 | { .val = 2, .div = 1, }, |
| 118 | { .val = 1, .div = 2, }, | 118 | { .val = 1, .div = 2, }, |
| 119 | { .val = 0, .div = 4, }, | 119 | { .val = 0, .div = 4, }, |
| 120 | { } | 120 | { } |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | static struct clk_div_table video_div_table[] = { | 123 | static const struct clk_div_table video_div_table[] = { |
| 124 | { .val = 0, .div = 1, }, | 124 | { .val = 0, .div = 1, }, |
| 125 | { .val = 1, .div = 2, }, | 125 | { .val = 1, .div = 2, }, |
| 126 | { .val = 2, .div = 1, }, | 126 | { .val = 2, .div = 1, }, |
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index b4e0dff3c8c2..5e8c18afce9a 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c | |||
| @@ -78,7 +78,7 @@ static int const clks_init_on[] __initconst = { | |||
| 78 | IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG, | 78 | IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG, |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | static struct clk_div_table clk_enet_ref_table[] = { | 81 | static const struct clk_div_table clk_enet_ref_table[] = { |
| 82 | { .val = 0, .div = 20, }, | 82 | { .val = 0, .div = 20, }, |
| 83 | { .val = 1, .div = 10, }, | 83 | { .val = 1, .div = 10, }, |
| 84 | { .val = 2, .div = 5, }, | 84 | { .val = 2, .div = 5, }, |
| @@ -86,14 +86,14 @@ static struct clk_div_table clk_enet_ref_table[] = { | |||
| 86 | { } | 86 | { } |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | static struct clk_div_table post_div_table[] = { | 89 | static const struct clk_div_table post_div_table[] = { |
| 90 | { .val = 2, .div = 1, }, | 90 | { .val = 2, .div = 1, }, |
| 91 | { .val = 1, .div = 2, }, | 91 | { .val = 1, .div = 2, }, |
| 92 | { .val = 0, .div = 4, }, | 92 | { .val = 0, .div = 4, }, |
| 93 | { } | 93 | { } |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | static struct clk_div_table video_div_table[] = { | 96 | static const struct clk_div_table video_div_table[] = { |
| 97 | { .val = 0, .div = 1, }, | 97 | { .val = 0, .div = 1, }, |
| 98 | { .val = 1, .div = 2, }, | 98 | { .val = 1, .div = 2, }, |
| 99 | { .val = 2, .div = 1, }, | 99 | { .val = 2, .div = 1, }, |
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 3da121826b1b..2305699db467 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c | |||
| @@ -27,7 +27,7 @@ static u32 share_count_sai2; | |||
| 27 | static u32 share_count_sai3; | 27 | static u32 share_count_sai3; |
| 28 | static u32 share_count_nand; | 28 | static u32 share_count_nand; |
| 29 | 29 | ||
| 30 | static struct clk_div_table test_div_table[] = { | 30 | static const struct clk_div_table test_div_table[] = { |
| 31 | { .val = 3, .div = 1, }, | 31 | { .val = 3, .div = 1, }, |
| 32 | { .val = 2, .div = 1, }, | 32 | { .val = 2, .div = 1, }, |
| 33 | { .val = 1, .div = 2, }, | 33 | { .val = 1, .div = 2, }, |
| @@ -35,7 +35,7 @@ static struct clk_div_table test_div_table[] = { | |||
| 35 | { } | 35 | { } |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static struct clk_div_table post_div_table[] = { | 38 | static const struct clk_div_table post_div_table[] = { |
| 39 | { .val = 3, .div = 4, }, | 39 | { .val = 3, .div = 4, }, |
| 40 | { .val = 2, .div = 1, }, | 40 | { .val = 2, .div = 1, }, |
| 41 | { .val = 1, .div = 2, }, | 41 | { .val = 1, .div = 2, }, |
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 59b1863deb88..6dae54325a91 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c | |||
| @@ -102,7 +102,7 @@ static const char *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ | |||
| 102 | static const char *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; | 102 | static const char *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; |
| 103 | 103 | ||
| 104 | 104 | ||
| 105 | static struct clk_div_table pll4_audio_div_table[] = { | 105 | static const struct clk_div_table pll4_audio_div_table[] = { |
| 106 | { .val = 0, .div = 1 }, | 106 | { .val = 0, .div = 1 }, |
| 107 | { .val = 1, .div = 2 }, | 107 | { .val = 1, .div = 2 }, |
| 108 | { .val = 2, .div = 6 }, | 108 | { .val = 2, .div = 6 }, |
diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c index edd8e6918050..16e56772d280 100644 --- a/drivers/clk/mediatek/clk-cpumux.c +++ b/drivers/clk/mediatek/clk-cpumux.c | |||
| @@ -27,7 +27,6 @@ static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw) | |||
| 27 | static u8 clk_cpumux_get_parent(struct clk_hw *hw) | 27 | static u8 clk_cpumux_get_parent(struct clk_hw *hw) |
| 28 | { | 28 | { |
| 29 | struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); | 29 | struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); |
| 30 | int num_parents = clk_hw_get_num_parents(hw); | ||
| 31 | unsigned int val; | 30 | unsigned int val; |
| 32 | 31 | ||
| 33 | regmap_read(mux->regmap, mux->reg, &val); | 32 | regmap_read(mux->regmap, mux->reg, &val); |
| @@ -35,9 +34,6 @@ static u8 clk_cpumux_get_parent(struct clk_hw *hw) | |||
| 35 | val >>= mux->shift; | 34 | val >>= mux->shift; |
| 36 | val &= mux->mask; | 35 | val &= mux->mask; |
| 37 | 36 | ||
| 38 | if (val >= num_parents) | ||
| 39 | return -EINVAL; | ||
| 40 | |||
| 41 | return val; | 37 | return val; |
| 42 | } | 38 | } |
| 43 | 39 | ||
| @@ -98,7 +94,7 @@ int __init mtk_clk_register_cpumuxes(struct device_node *node, | |||
| 98 | 94 | ||
| 99 | regmap = syscon_node_to_regmap(node); | 95 | regmap = syscon_node_to_regmap(node); |
| 100 | if (IS_ERR(regmap)) { | 96 | if (IS_ERR(regmap)) { |
| 101 | pr_err("Cannot find regmap for %s: %ld\n", node->full_name, | 97 | pr_err("Cannot find regmap for %pOF: %ld\n", node, |
| 102 | PTR_ERR(regmap)); | 98 | PTR_ERR(regmap)); |
| 103 | return PTR_ERR(regmap); | 99 | return PTR_ERR(regmap); |
| 104 | } | 100 | } |
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 0541df78141c..9c0ae4278a94 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c | |||
| @@ -114,7 +114,7 @@ int mtk_clk_register_gates(struct device_node *node, | |||
| 114 | 114 | ||
| 115 | regmap = syscon_node_to_regmap(node); | 115 | regmap = syscon_node_to_regmap(node); |
| 116 | if (IS_ERR(regmap)) { | 116 | if (IS_ERR(regmap)) { |
| 117 | pr_err("Cannot find regmap for %s: %ld\n", node->full_name, | 117 | pr_err("Cannot find regmap for %pOF: %ld\n", node, |
| 118 | PTR_ERR(regmap)); | 118 | PTR_ERR(regmap)); |
| 119 | return PTR_ERR(regmap); | 119 | return PTR_ERR(regmap); |
| 120 | } | 120 | } |
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index 309049d41f1b..d3551d5efef2 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c | |||
| @@ -72,7 +72,7 @@ void mtk_register_reset_controller(struct device_node *np, | |||
| 72 | 72 | ||
| 73 | regmap = syscon_node_to_regmap(np); | 73 | regmap = syscon_node_to_regmap(np); |
| 74 | if (IS_ERR(regmap)) { | 74 | if (IS_ERR(regmap)) { |
| 75 | pr_err("Cannot find regmap for %s: %ld\n", np->full_name, | 75 | pr_err("Cannot find regmap for %pOF: %ld\n", np, |
| 76 | PTR_ERR(regmap)); | 76 | PTR_ERR(regmap)); |
| 77 | return; | 77 | return; |
| 78 | } | 78 | } |
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 5588f75a8414..d2d0174a6eca 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig | |||
| @@ -6,6 +6,7 @@ config COMMON_CLK_AMLOGIC | |||
| 6 | config COMMON_CLK_MESON8B | 6 | config COMMON_CLK_MESON8B |
| 7 | bool | 7 | bool |
| 8 | depends on COMMON_CLK_AMLOGIC | 8 | depends on COMMON_CLK_AMLOGIC |
| 9 | select RESET_CONTROLLER | ||
| 9 | help | 10 | help |
| 10 | Support for the clock controller on AmLogic S802 (Meson8), | 11 | Support for the clock controller on AmLogic S802 (Meson8), |
| 11 | S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you | 12 | S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you |
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 83b6d9d65aa1..b139d41b25da 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile | |||
| @@ -4,4 +4,4 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o | 5 | obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o |
| 6 | obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o | 6 | obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o |
| 7 | obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o | 7 | obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o |
diff --git a/drivers/clk/meson/gxbb-aoclk-32k.c b/drivers/clk/meson/gxbb-aoclk-32k.c new file mode 100644 index 000000000000..491634dbc985 --- /dev/null +++ b/drivers/clk/meson/gxbb-aoclk-32k.c | |||
| @@ -0,0 +1,194 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2017 BayLibre, SAS. | ||
| 3 | * Author: Neil Armstrong <narmstrong@baylibre.com> | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0+ | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/clk-provider.h> | ||
| 9 | #include <linux/bitfield.h> | ||
| 10 | #include <linux/regmap.h> | ||
| 11 | #include "gxbb-aoclk.h" | ||
| 12 | |||
| 13 | /* | ||
| 14 | * The AO Domain embeds a dual/divider to generate a more precise | ||
| 15 | * 32,768KHz clock for low-power suspend mode and CEC. | ||
| 16 | * ______ ______ | ||
| 17 | * | | | | | ||
| 18 | * ______ | Div1 |-| Cnt1 | ______ | ||
| 19 | * | | /|______| |______|\ | | | ||
| 20 | * Xtal-->| Gate |---| ______ ______ X-X--| Gate |--> | ||
| 21 | * |______| | \| | | |/ | |______| | ||
| 22 | * | | Div2 |-| Cnt2 | | | ||
| 23 | * | |______| |______| | | ||
| 24 | * |_______________________| | ||
| 25 | * | ||
| 26 | * The dividing can be switched to single or dual, with a counter | ||
| 27 | * for each divider to set when the switching is done. | ||
| 28 | * The entire dividing mechanism can be also bypassed. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define CLK_CNTL0_N1_MASK GENMASK(11, 0) | ||
| 32 | #define CLK_CNTL0_N2_MASK GENMASK(23, 12) | ||
| 33 | #define CLK_CNTL0_DUALDIV_EN BIT(28) | ||
| 34 | #define CLK_CNTL0_OUT_GATE_EN BIT(30) | ||
| 35 | #define CLK_CNTL0_IN_GATE_EN BIT(31) | ||
| 36 | |||
| 37 | #define CLK_CNTL1_M1_MASK GENMASK(11, 0) | ||
| 38 | #define CLK_CNTL1_M2_MASK GENMASK(23, 12) | ||
| 39 | #define CLK_CNTL1_BYPASS_EN BIT(24) | ||
| 40 | #define CLK_CNTL1_SELECT_OSC BIT(27) | ||
| 41 | |||
| 42 | #define PWR_CNTL_ALT_32K_SEL GENMASK(13, 10) | ||
| 43 | |||
| 44 | struct cec_32k_freq_table { | ||
| 45 | unsigned long parent_rate; | ||
| 46 | unsigned long target_rate; | ||
| 47 | bool dualdiv; | ||
| 48 | unsigned int n1; | ||
| 49 | unsigned int n2; | ||
| 50 | unsigned int m1; | ||
| 51 | unsigned int m2; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static const struct cec_32k_freq_table aoclk_cec_32k_table[] = { | ||
| 55 | [0] = { | ||
| 56 | .parent_rate = 24000000, | ||
| 57 | .target_rate = 32768, | ||
| 58 | .dualdiv = true, | ||
| 59 | .n1 = 733, | ||
| 60 | .n2 = 732, | ||
| 61 | .m1 = 8, | ||
| 62 | .m2 = 11, | ||
| 63 | }, | ||
| 64 | }; | ||
| 65 | |||
| 66 | /* | ||
| 67 | * If CLK_CNTL0_DUALDIV_EN == 0 | ||
| 68 | * - will use N1 divider only | ||
| 69 | * If CLK_CNTL0_DUALDIV_EN == 1 | ||
| 70 | * - hold M1 cycles of N1 divider then changes to N2 | ||
| 71 | * - hold M2 cycles of N2 divider then changes to N1 | ||
| 72 | * Then we can get more accurate division. | ||
| 73 | */ | ||
| 74 | static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw, | ||
| 75 | unsigned long parent_rate) | ||
| 76 | { | ||
| 77 | struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); | ||
| 78 | unsigned long n1; | ||
| 79 | u32 reg0, reg1; | ||
| 80 | |||
| 81 | regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, ®0); | ||
| 82 | regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, ®1); | ||
| 83 | |||
| 84 | if (reg1 & CLK_CNTL1_BYPASS_EN) | ||
| 85 | return parent_rate; | ||
| 86 | |||
| 87 | if (reg0 & CLK_CNTL0_DUALDIV_EN) { | ||
| 88 | unsigned long n2, m1, m2, f1, f2, p1, p2; | ||
| 89 | |||
| 90 | n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; | ||
| 91 | n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1; | ||
| 92 | |||
| 93 | m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1; | ||
| 94 | m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1; | ||
| 95 | |||
| 96 | f1 = DIV_ROUND_CLOSEST(parent_rate, n1); | ||
| 97 | f2 = DIV_ROUND_CLOSEST(parent_rate, n2); | ||
| 98 | |||
| 99 | p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2)); | ||
| 100 | p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2)); | ||
| 101 | |||
| 102 | return DIV_ROUND_UP(100000000, p1 + p2); | ||
| 103 | } | ||
| 104 | |||
| 105 | n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; | ||
| 106 | |||
| 107 | return DIV_ROUND_CLOSEST(parent_rate, n1); | ||
| 108 | } | ||
| 109 | |||
| 110 | static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate, | ||
| 111 | unsigned long prate) | ||
| 112 | { | ||
| 113 | int i; | ||
| 114 | |||
| 115 | for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i) | ||
| 116 | if (aoclk_cec_32k_table[i].parent_rate == prate && | ||
| 117 | aoclk_cec_32k_table[i].target_rate == rate) | ||
| 118 | return &aoclk_cec_32k_table[i]; | ||
| 119 | |||
| 120 | return NULL; | ||
| 121 | } | ||
| 122 | |||
| 123 | static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 124 | unsigned long *prate) | ||
| 125 | { | ||
| 126 | const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, | ||
| 127 | *prate); | ||
| 128 | |||
| 129 | /* If invalid return first one */ | ||
| 130 | if (!freq) | ||
| 131 | return aoclk_cec_32k_table[0].target_rate; | ||
| 132 | |||
| 133 | return freq->target_rate; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | ||
| 137 | * From the Amlogic init procedure, the IN and OUT gates needs to be handled | ||
| 138 | * in the init procedure to avoid any glitches. | ||
| 139 | */ | ||
| 140 | |||
| 141 | static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 142 | unsigned long parent_rate) | ||
| 143 | { | ||
| 144 | const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, | ||
| 145 | parent_rate); | ||
| 146 | struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); | ||
| 147 | u32 reg = 0; | ||
| 148 | |||
| 149 | if (!freq) | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | /* Disable clock */ | ||
| 153 | regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | ||
| 154 | CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN, 0); | ||
| 155 | |||
| 156 | reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1); | ||
| 157 | if (freq->dualdiv) | ||
| 158 | reg |= CLK_CNTL0_DUALDIV_EN | | ||
| 159 | FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1); | ||
| 160 | |||
| 161 | regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, reg); | ||
| 162 | |||
| 163 | reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1); | ||
| 164 | if (freq->dualdiv) | ||
| 165 | reg |= FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1); | ||
| 166 | |||
| 167 | regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, reg); | ||
| 168 | |||
| 169 | /* Enable clock */ | ||
| 170 | regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | ||
| 171 | CLK_CNTL0_IN_GATE_EN, CLK_CNTL0_IN_GATE_EN); | ||
| 172 | |||
| 173 | udelay(200); | ||
| 174 | |||
| 175 | regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | ||
| 176 | CLK_CNTL0_OUT_GATE_EN, CLK_CNTL0_OUT_GATE_EN); | ||
| 177 | |||
| 178 | regmap_update_bits(cec_32k->regmap, AO_CRT_CLK_CNTL1, | ||
| 179 | CLK_CNTL1_SELECT_OSC, CLK_CNTL1_SELECT_OSC); | ||
| 180 | |||
| 181 | /* Select 32k from XTAL */ | ||
| 182 | regmap_update_bits(cec_32k->regmap, | ||
| 183 | AO_RTI_PWR_CNTL_REG0, | ||
| 184 | PWR_CNTL_ALT_32K_SEL, | ||
| 185 | FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4)); | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | const struct clk_ops meson_aoclk_cec_32k_ops = { | ||
| 191 | .recalc_rate = aoclk_cec_32k_recalc_rate, | ||
| 192 | .round_rate = aoclk_cec_32k_round_rate, | ||
| 193 | .set_rate = aoclk_cec_32k_set_rate, | ||
| 194 | }; | ||
diff --git a/drivers/clk/meson/gxbb-aoclk-regmap.c b/drivers/clk/meson/gxbb-aoclk-regmap.c new file mode 100644 index 000000000000..2515fbfa0467 --- /dev/null +++ b/drivers/clk/meson/gxbb-aoclk-regmap.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2017 BayLibre, SAS. | ||
| 3 | * Author: Neil Armstrong <narmstrong@baylibre.com> | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0+ | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/clk-provider.h> | ||
| 9 | #include <linux/bitfield.h> | ||
| 10 | #include <linux/regmap.h> | ||
| 11 | #include "gxbb-aoclk.h" | ||
| 12 | |||
| 13 | static int aoclk_gate_regmap_enable(struct clk_hw *hw) | ||
| 14 | { | ||
| 15 | struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | ||
| 16 | |||
| 17 | return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, | ||
| 18 | BIT(gate->bit_idx), BIT(gate->bit_idx)); | ||
| 19 | } | ||
| 20 | |||
| 21 | static void aoclk_gate_regmap_disable(struct clk_hw *hw) | ||
| 22 | { | ||
| 23 | struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | ||
| 24 | |||
| 25 | regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, | ||
| 26 | BIT(gate->bit_idx), 0); | ||
| 27 | } | ||
| 28 | |||
| 29 | static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw) | ||
| 30 | { | ||
| 31 | struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | ||
| 32 | unsigned int val; | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val); | ||
| 36 | if (ret) | ||
| 37 | return ret; | ||
| 38 | |||
| 39 | return (val & BIT(gate->bit_idx)) != 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | const struct clk_ops meson_aoclk_gate_regmap_ops = { | ||
| 43 | .enable = aoclk_gate_regmap_enable, | ||
| 44 | .disable = aoclk_gate_regmap_disable, | ||
| 45 | .is_enabled = aoclk_gate_regmap_is_enabled, | ||
| 46 | }; | ||
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index b45c5fba7e35..6c161e0a8e59 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c | |||
| @@ -56,16 +56,20 @@ | |||
| 56 | #include <linux/of_address.h> | 56 | #include <linux/of_address.h> |
| 57 | #include <linux/platform_device.h> | 57 | #include <linux/platform_device.h> |
| 58 | #include <linux/reset-controller.h> | 58 | #include <linux/reset-controller.h> |
| 59 | #include <linux/mfd/syscon.h> | ||
| 60 | #include <linux/regmap.h> | ||
| 59 | #include <linux/init.h> | 61 | #include <linux/init.h> |
| 62 | #include <linux/delay.h> | ||
| 60 | #include <dt-bindings/clock/gxbb-aoclkc.h> | 63 | #include <dt-bindings/clock/gxbb-aoclkc.h> |
| 61 | #include <dt-bindings/reset/gxbb-aoclkc.h> | 64 | #include <dt-bindings/reset/gxbb-aoclkc.h> |
| 65 | #include "gxbb-aoclk.h" | ||
| 62 | 66 | ||
| 63 | static DEFINE_SPINLOCK(gxbb_aoclk_lock); | 67 | static DEFINE_SPINLOCK(gxbb_aoclk_lock); |
| 64 | 68 | ||
| 65 | struct gxbb_aoclk_reset_controller { | 69 | struct gxbb_aoclk_reset_controller { |
| 66 | struct reset_controller_dev reset; | 70 | struct reset_controller_dev reset; |
| 67 | unsigned int *data; | 71 | unsigned int *data; |
| 68 | void __iomem *base; | 72 | struct regmap *regmap; |
| 69 | }; | 73 | }; |
| 70 | 74 | ||
| 71 | static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, | 75 | static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, |
| @@ -74,9 +78,8 @@ static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, | |||
| 74 | struct gxbb_aoclk_reset_controller *reset = | 78 | struct gxbb_aoclk_reset_controller *reset = |
| 75 | container_of(rcdev, struct gxbb_aoclk_reset_controller, reset); | 79 | container_of(rcdev, struct gxbb_aoclk_reset_controller, reset); |
| 76 | 80 | ||
| 77 | writel(BIT(reset->data[id]), reset->base); | 81 | return regmap_write(reset->regmap, AO_RTI_GEN_CNTL_REG0, |
| 78 | 82 | BIT(reset->data[id])); | |
| 79 | return 0; | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | static const struct reset_control_ops gxbb_aoclk_reset_ops = { | 85 | static const struct reset_control_ops gxbb_aoclk_reset_ops = { |
| @@ -84,13 +87,12 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = { | |||
| 84 | }; | 87 | }; |
| 85 | 88 | ||
| 86 | #define GXBB_AO_GATE(_name, _bit) \ | 89 | #define GXBB_AO_GATE(_name, _bit) \ |
| 87 | static struct clk_gate _name##_ao = { \ | 90 | static struct aoclk_gate_regmap _name##_ao = { \ |
| 88 | .reg = (void __iomem *)0, \ | ||
| 89 | .bit_idx = (_bit), \ | 91 | .bit_idx = (_bit), \ |
| 90 | .lock = &gxbb_aoclk_lock, \ | 92 | .lock = &gxbb_aoclk_lock, \ |
| 91 | .hw.init = &(struct clk_init_data) { \ | 93 | .hw.init = &(struct clk_init_data) { \ |
| 92 | .name = #_name "_ao", \ | 94 | .name = #_name "_ao", \ |
| 93 | .ops = &clk_gate_ops, \ | 95 | .ops = &meson_aoclk_gate_regmap_ops, \ |
| 94 | .parent_names = (const char *[]){ "clk81" }, \ | 96 | .parent_names = (const char *[]){ "clk81" }, \ |
| 95 | .num_parents = 1, \ | 97 | .num_parents = 1, \ |
| 96 | .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ | 98 | .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ |
| @@ -104,6 +106,17 @@ GXBB_AO_GATE(uart1, 3); | |||
| 104 | GXBB_AO_GATE(uart2, 5); | 106 | GXBB_AO_GATE(uart2, 5); |
| 105 | GXBB_AO_GATE(ir_blaster, 6); | 107 | GXBB_AO_GATE(ir_blaster, 6); |
| 106 | 108 | ||
| 109 | static struct aoclk_cec_32k cec_32k_ao = { | ||
| 110 | .lock = &gxbb_aoclk_lock, | ||
| 111 | .hw.init = &(struct clk_init_data) { | ||
| 112 | .name = "cec_32k_ao", | ||
| 113 | .ops = &meson_aoclk_cec_32k_ops, | ||
| 114 | .parent_names = (const char *[]){ "xtal" }, | ||
| 115 | .num_parents = 1, | ||
| 116 | .flags = CLK_IGNORE_UNUSED, | ||
| 117 | }, | ||
| 118 | }; | ||
| 119 | |||
| 107 | static unsigned int gxbb_aoclk_reset[] = { | 120 | static unsigned int gxbb_aoclk_reset[] = { |
| 108 | [RESET_AO_REMOTE] = 16, | 121 | [RESET_AO_REMOTE] = 16, |
| 109 | [RESET_AO_I2C_MASTER] = 18, | 122 | [RESET_AO_I2C_MASTER] = 18, |
| @@ -113,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = { | |||
| 113 | [RESET_AO_IR_BLASTER] = 23, | 126 | [RESET_AO_IR_BLASTER] = 23, |
| 114 | }; | 127 | }; |
| 115 | 128 | ||
| 116 | static struct clk_gate *gxbb_aoclk_gate[] = { | 129 | static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { |
| 117 | [CLKID_AO_REMOTE] = &remote_ao, | 130 | [CLKID_AO_REMOTE] = &remote_ao, |
| 118 | [CLKID_AO_I2C_MASTER] = &i2c_master_ao, | 131 | [CLKID_AO_I2C_MASTER] = &i2c_master_ao, |
| 119 | [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, | 132 | [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, |
| @@ -130,30 +143,30 @@ static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { | |||
| 130 | [CLKID_AO_UART1] = &uart1_ao.hw, | 143 | [CLKID_AO_UART1] = &uart1_ao.hw, |
| 131 | [CLKID_AO_UART2] = &uart2_ao.hw, | 144 | [CLKID_AO_UART2] = &uart2_ao.hw, |
| 132 | [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, | 145 | [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, |
| 146 | [CLKID_AO_CEC_32K] = &cec_32k_ao.hw, | ||
| 133 | }, | 147 | }, |
| 134 | .num = ARRAY_SIZE(gxbb_aoclk_gate), | 148 | .num = 7, |
| 135 | }; | 149 | }; |
| 136 | 150 | ||
| 137 | static int gxbb_aoclkc_probe(struct platform_device *pdev) | 151 | static int gxbb_aoclkc_probe(struct platform_device *pdev) |
| 138 | { | 152 | { |
| 139 | struct resource *res; | ||
| 140 | void __iomem *base; | ||
| 141 | int ret, clkid; | ||
| 142 | struct device *dev = &pdev->dev; | ||
| 143 | struct gxbb_aoclk_reset_controller *rstc; | 153 | struct gxbb_aoclk_reset_controller *rstc; |
| 154 | struct device *dev = &pdev->dev; | ||
| 155 | struct regmap *regmap; | ||
| 156 | int ret, clkid; | ||
| 144 | 157 | ||
| 145 | rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); | 158 | rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); |
| 146 | if (!rstc) | 159 | if (!rstc) |
| 147 | return -ENOMEM; | 160 | return -ENOMEM; |
| 148 | 161 | ||
| 149 | /* Generic clocks */ | 162 | regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); |
| 150 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 163 | if (IS_ERR(regmap)) { |
| 151 | base = devm_ioremap_resource(dev, res); | 164 | dev_err(dev, "failed to get regmap\n"); |
| 152 | if (IS_ERR(base)) | 165 | return -ENODEV; |
| 153 | return PTR_ERR(base); | 166 | } |
| 154 | 167 | ||
| 155 | /* Reset Controller */ | 168 | /* Reset Controller */ |
| 156 | rstc->base = base; | 169 | rstc->regmap = regmap; |
| 157 | rstc->data = gxbb_aoclk_reset; | 170 | rstc->data = gxbb_aoclk_reset; |
| 158 | rstc->reset.ops = &gxbb_aoclk_reset_ops; | 171 | rstc->reset.ops = &gxbb_aoclk_reset_ops; |
| 159 | rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset); | 172 | rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset); |
| @@ -161,10 +174,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev) | |||
| 161 | ret = devm_reset_controller_register(dev, &rstc->reset); | 174 | ret = devm_reset_controller_register(dev, &rstc->reset); |
| 162 | 175 | ||
| 163 | /* | 176 | /* |
| 164 | * Populate base address and register all clks | 177 | * Populate regmap and register all clks |
| 165 | */ | 178 | */ |
| 166 | for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) { | 179 | for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { |
| 167 | gxbb_aoclk_gate[clkid]->reg = base; | 180 | gxbb_aoclk_gate[clkid]->regmap = regmap; |
| 168 | 181 | ||
| 169 | ret = devm_clk_hw_register(dev, | 182 | ret = devm_clk_hw_register(dev, |
| 170 | gxbb_aoclk_onecell_data.hws[clkid]); | 183 | gxbb_aoclk_onecell_data.hws[clkid]); |
| @@ -172,12 +185,18 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev) | |||
| 172 | return ret; | 185 | return ret; |
| 173 | } | 186 | } |
| 174 | 187 | ||
| 188 | /* Specific clocks */ | ||
| 189 | cec_32k_ao.regmap = regmap; | ||
| 190 | ret = devm_clk_hw_register(dev, &cec_32k_ao.hw); | ||
| 191 | if (ret) | ||
| 192 | return ret; | ||
| 193 | |||
| 175 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, | 194 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, |
| 176 | &gxbb_aoclk_onecell_data); | 195 | &gxbb_aoclk_onecell_data); |
| 177 | } | 196 | } |
| 178 | 197 | ||
| 179 | static const struct of_device_id gxbb_aoclkc_match_table[] = { | 198 | static const struct of_device_id gxbb_aoclkc_match_table[] = { |
| 180 | { .compatible = "amlogic,gxbb-aoclkc" }, | 199 | { .compatible = "amlogic,meson-gx-aoclkc" }, |
| 181 | { } | 200 | { } |
| 182 | }; | 201 | }; |
| 183 | 202 | ||
diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h new file mode 100644 index 000000000000..e8604c8f7eee --- /dev/null +++ b/drivers/clk/meson/gxbb-aoclk.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2017 BayLibre, SAS | ||
| 3 | * Author: Neil Armstrong <narmstrong@baylibre.com> | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0+ | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef __GXBB_AOCLKC_H | ||
| 9 | #define __GXBB_AOCLKC_H | ||
| 10 | |||
| 11 | /* AO Configuration Clock registers offsets */ | ||
| 12 | #define AO_RTI_PWR_CNTL_REG1 0x0c | ||
| 13 | #define AO_RTI_PWR_CNTL_REG0 0x10 | ||
| 14 | #define AO_RTI_GEN_CNTL_REG0 0x40 | ||
| 15 | #define AO_OSCIN_CNTL 0x58 | ||
| 16 | #define AO_CRT_CLK_CNTL1 0x68 | ||
| 17 | #define AO_RTC_ALT_CLK_CNTL0 0x94 | ||
| 18 | #define AO_RTC_ALT_CLK_CNTL1 0x98 | ||
| 19 | |||
| 20 | struct aoclk_gate_regmap { | ||
| 21 | struct clk_hw hw; | ||
| 22 | unsigned bit_idx; | ||
| 23 | struct regmap *regmap; | ||
| 24 | spinlock_t *lock; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #define to_aoclk_gate_regmap(_hw) \ | ||
| 28 | container_of(_hw, struct aoclk_gate_regmap, hw) | ||
| 29 | |||
| 30 | extern const struct clk_ops meson_aoclk_gate_regmap_ops; | ||
| 31 | |||
| 32 | struct aoclk_cec_32k { | ||
| 33 | struct clk_hw hw; | ||
| 34 | struct regmap *regmap; | ||
| 35 | spinlock_t *lock; | ||
| 36 | }; | ||
| 37 | |||
| 38 | #define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw) | ||
| 39 | |||
| 40 | extern const struct clk_ops meson_aoclk_cec_32k_ops; | ||
| 41 | |||
| 42 | #endif /* __GXBB_AOCLKC_H */ | ||
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 964489b39f6a..b2d1e8ed7152 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c | |||
| @@ -850,13 +850,14 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = { | |||
| 850 | .shift = 0, | 850 | .shift = 0, |
| 851 | .width = 8, | 851 | .width = 8, |
| 852 | }, | 852 | }, |
| 853 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
| 853 | .lock = &clk_lock, | 854 | .lock = &clk_lock, |
| 854 | .hw.init = &(struct clk_init_data){ | 855 | .hw.init = &(struct clk_init_data){ |
| 855 | .name = "cts_amclk_div", | 856 | .name = "cts_amclk_div", |
| 856 | .ops = &meson_clk_audio_divider_ops, | 857 | .ops = &meson_clk_audio_divider_ops, |
| 857 | .parent_names = (const char *[]){ "cts_amclk_sel" }, | 858 | .parent_names = (const char *[]){ "cts_amclk_sel" }, |
| 858 | .num_parents = 1, | 859 | .num_parents = 1, |
| 859 | .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, | 860 | .flags = CLK_SET_RATE_PARENT, |
| 860 | }, | 861 | }, |
| 861 | }; | 862 | }; |
| 862 | 863 | ||
| @@ -880,7 +881,7 @@ static struct clk_mux gxbb_cts_mclk_i958_sel = { | |||
| 880 | /* Default parent unknown (register reset value: 0) */ | 881 | /* Default parent unknown (register reset value: 0) */ |
| 881 | .table = (u32[]){ 1, 2, 3 }, | 882 | .table = (u32[]){ 1, 2, 3 }, |
| 882 | .lock = &clk_lock, | 883 | .lock = &clk_lock, |
| 883 | .hw.init = &(struct clk_init_data){ | 884 | .hw.init = &(struct clk_init_data) { |
| 884 | .name = "cts_mclk_i958_sel", | 885 | .name = "cts_mclk_i958_sel", |
| 885 | .ops = &clk_mux_ops, | 886 | .ops = &clk_mux_ops, |
| 886 | .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, | 887 | .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, |
| @@ -894,12 +895,13 @@ static struct clk_divider gxbb_cts_mclk_i958_div = { | |||
| 894 | .shift = 16, | 895 | .shift = 16, |
| 895 | .width = 8, | 896 | .width = 8, |
| 896 | .lock = &clk_lock, | 897 | .lock = &clk_lock, |
| 897 | .hw.init = &(struct clk_init_data){ | 898 | .flags = CLK_DIVIDER_ROUND_CLOSEST, |
| 899 | .hw.init = &(struct clk_init_data) { | ||
| 898 | .name = "cts_mclk_i958_div", | 900 | .name = "cts_mclk_i958_div", |
| 899 | .ops = &clk_divider_ops, | 901 | .ops = &clk_divider_ops, |
| 900 | .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, | 902 | .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, |
| 901 | .num_parents = 1, | 903 | .num_parents = 1, |
| 902 | .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, | 904 | .flags = CLK_SET_RATE_PARENT, |
| 903 | }, | 905 | }, |
| 904 | }; | 906 | }; |
| 905 | 907 | ||
| @@ -979,6 +981,156 @@ static struct clk_mux gxbb_32k_clk_sel = { | |||
| 979 | }, | 981 | }, |
| 980 | }; | 982 | }; |
| 981 | 983 | ||
| 984 | static const char * const gxbb_sd_emmc_clk0_parent_names[] = { | ||
| 985 | "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", | ||
| 986 | |||
| 987 | /* | ||
| 988 | * Following these parent clocks, we should also have had mpll2, mpll3 | ||
| 989 | * and gp0_pll but these clocks are too precious to be used here. All | ||
| 990 | * the necessary rates for MMC and NAND operation can be acheived using | ||
| 991 | * xtal or fclk_div clocks | ||
| 992 | */ | ||
| 993 | }; | ||
| 994 | |||
| 995 | /* SDIO clock */ | ||
| 996 | static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { | ||
| 997 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 998 | .mask = 0x7, | ||
| 999 | .shift = 9, | ||
| 1000 | .lock = &clk_lock, | ||
| 1001 | .hw.init = &(struct clk_init_data) { | ||
| 1002 | .name = "sd_emmc_a_clk0_sel", | ||
| 1003 | .ops = &clk_mux_ops, | ||
| 1004 | .parent_names = gxbb_sd_emmc_clk0_parent_names, | ||
| 1005 | .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | ||
| 1006 | .flags = CLK_SET_RATE_PARENT, | ||
| 1007 | }, | ||
| 1008 | }; | ||
| 1009 | |||
| 1010 | static struct clk_divider gxbb_sd_emmc_a_clk0_div = { | ||
| 1011 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 1012 | .shift = 0, | ||
| 1013 | .width = 7, | ||
| 1014 | .lock = &clk_lock, | ||
| 1015 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
| 1016 | .hw.init = &(struct clk_init_data) { | ||
| 1017 | .name = "sd_emmc_a_clk0_div", | ||
| 1018 | .ops = &clk_divider_ops, | ||
| 1019 | .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, | ||
| 1020 | .num_parents = 1, | ||
| 1021 | .flags = CLK_SET_RATE_PARENT, | ||
| 1022 | }, | ||
| 1023 | }; | ||
| 1024 | |||
| 1025 | static struct clk_gate gxbb_sd_emmc_a_clk0 = { | ||
| 1026 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 1027 | .bit_idx = 7, | ||
| 1028 | .lock = &clk_lock, | ||
| 1029 | .hw.init = &(struct clk_init_data){ | ||
| 1030 | .name = "sd_emmc_a_clk0", | ||
| 1031 | .ops = &clk_gate_ops, | ||
| 1032 | .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, | ||
| 1033 | .num_parents = 1, | ||
| 1034 | |||
| 1035 | /* | ||
| 1036 | * FIXME: | ||
| 1037 | * We need CLK_IGNORE_UNUSED because mmc DT node point to xtal | ||
| 1038 | * instead of this clock. CCF would gate this on boot, killing | ||
| 1039 | * the mmc controller. Please remove this flag once DT properly | ||
| 1040 | * point to this clock instead of xtal | ||
| 1041 | * | ||
| 1042 | * Same goes for emmc B and C clocks | ||
| 1043 | */ | ||
| 1044 | .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | ||
| 1045 | }, | ||
| 1046 | }; | ||
| 1047 | |||
| 1048 | /* SDcard clock */ | ||
| 1049 | static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { | ||
| 1050 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 1051 | .mask = 0x7, | ||
| 1052 | .shift = 25, | ||
| 1053 | .lock = &clk_lock, | ||
| 1054 | .hw.init = &(struct clk_init_data) { | ||
| 1055 | .name = "sd_emmc_b_clk0_sel", | ||
| 1056 | .ops = &clk_mux_ops, | ||
| 1057 | .parent_names = gxbb_sd_emmc_clk0_parent_names, | ||
| 1058 | .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | ||
| 1059 | .flags = CLK_SET_RATE_PARENT, | ||
| 1060 | }, | ||
| 1061 | }; | ||
| 1062 | |||
| 1063 | static struct clk_divider gxbb_sd_emmc_b_clk0_div = { | ||
| 1064 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 1065 | .shift = 16, | ||
| 1066 | .width = 7, | ||
| 1067 | .lock = &clk_lock, | ||
| 1068 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
| 1069 | .hw.init = &(struct clk_init_data) { | ||
| 1070 | .name = "sd_emmc_b_clk0_div", | ||
| 1071 | .ops = &clk_divider_ops, | ||
| 1072 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, | ||
| 1073 | .num_parents = 1, | ||
| 1074 | .flags = CLK_SET_RATE_PARENT, | ||
| 1075 | }, | ||
| 1076 | }; | ||
| 1077 | |||
| 1078 | static struct clk_gate gxbb_sd_emmc_b_clk0 = { | ||
| 1079 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | ||
| 1080 | .bit_idx = 23, | ||
| 1081 | .lock = &clk_lock, | ||
| 1082 | .hw.init = &(struct clk_init_data){ | ||
| 1083 | .name = "sd_emmc_b_clk0", | ||
| 1084 | .ops = &clk_gate_ops, | ||
| 1085 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, | ||
| 1086 | .num_parents = 1, | ||
| 1087 | .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | ||
| 1088 | }, | ||
| 1089 | }; | ||
| 1090 | |||
| 1091 | /* EMMC/NAND clock */ | ||
| 1092 | static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { | ||
| 1093 | .reg = (void *)HHI_NAND_CLK_CNTL, | ||
| 1094 | .mask = 0x7, | ||
| 1095 | .shift = 9, | ||
| 1096 | .lock = &clk_lock, | ||
| 1097 | .hw.init = &(struct clk_init_data) { | ||
| 1098 | .name = "sd_emmc_c_clk0_sel", | ||
| 1099 | .ops = &clk_mux_ops, | ||
| 1100 | .parent_names = gxbb_sd_emmc_clk0_parent_names, | ||
| 1101 | .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | ||
| 1102 | .flags = CLK_SET_RATE_PARENT, | ||
| 1103 | }, | ||
| 1104 | }; | ||
| 1105 | |||
| 1106 | static struct clk_divider gxbb_sd_emmc_c_clk0_div = { | ||
| 1107 | .reg = (void *)HHI_NAND_CLK_CNTL, | ||
| 1108 | .shift = 0, | ||
| 1109 | .width = 7, | ||
| 1110 | .lock = &clk_lock, | ||
| 1111 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
| 1112 | .hw.init = &(struct clk_init_data) { | ||
| 1113 | .name = "sd_emmc_c_clk0_div", | ||
| 1114 | .ops = &clk_divider_ops, | ||
| 1115 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, | ||
| 1116 | .num_parents = 1, | ||
| 1117 | .flags = CLK_SET_RATE_PARENT, | ||
| 1118 | }, | ||
| 1119 | }; | ||
| 1120 | |||
| 1121 | static struct clk_gate gxbb_sd_emmc_c_clk0 = { | ||
| 1122 | .reg = (void *)HHI_NAND_CLK_CNTL, | ||
| 1123 | .bit_idx = 7, | ||
| 1124 | .lock = &clk_lock, | ||
| 1125 | .hw.init = &(struct clk_init_data){ | ||
| 1126 | .name = "sd_emmc_c_clk0", | ||
| 1127 | .ops = &clk_gate_ops, | ||
| 1128 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, | ||
| 1129 | .num_parents = 1, | ||
| 1130 | .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | ||
| 1131 | }, | ||
| 1132 | }; | ||
| 1133 | |||
| 982 | /* Everything Else (EE) domain gates */ | 1134 | /* Everything Else (EE) domain gates */ |
| 983 | static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); | 1135 | static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); |
| 984 | static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); | 1136 | static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); |
| @@ -1188,6 +1340,15 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { | |||
| 1188 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, | 1340 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, |
| 1189 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, | 1341 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, |
| 1190 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, | 1342 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, |
| 1343 | [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, | ||
| 1344 | [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, | ||
| 1345 | [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, | ||
| 1346 | [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, | ||
| 1347 | [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, | ||
| 1348 | [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, | ||
| 1349 | [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, | ||
| 1350 | [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, | ||
| 1351 | [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, | ||
| 1191 | [NR_CLKS] = NULL, | 1352 | [NR_CLKS] = NULL, |
| 1192 | }, | 1353 | }, |
| 1193 | .num = NR_CLKS, | 1354 | .num = NR_CLKS, |
| @@ -1311,6 +1472,15 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { | |||
| 1311 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, | 1472 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, |
| 1312 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, | 1473 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, |
| 1313 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, | 1474 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, |
| 1475 | [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, | ||
| 1476 | [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, | ||
| 1477 | [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, | ||
| 1478 | [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, | ||
| 1479 | [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, | ||
| 1480 | [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, | ||
| 1481 | [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, | ||
| 1482 | [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, | ||
| 1483 | [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, | ||
| 1314 | [NR_CLKS] = NULL, | 1484 | [NR_CLKS] = NULL, |
| 1315 | }, | 1485 | }, |
| 1316 | .num = NR_CLKS, | 1486 | .num = NR_CLKS, |
| @@ -1427,6 +1597,9 @@ static struct clk_gate *const gxbb_clk_gates[] = { | |||
| 1427 | &gxbb_cts_amclk, | 1597 | &gxbb_cts_amclk, |
| 1428 | &gxbb_cts_mclk_i958, | 1598 | &gxbb_cts_mclk_i958, |
| 1429 | &gxbb_32k_clk, | 1599 | &gxbb_32k_clk, |
| 1600 | &gxbb_sd_emmc_a_clk0, | ||
| 1601 | &gxbb_sd_emmc_b_clk0, | ||
| 1602 | &gxbb_sd_emmc_c_clk0, | ||
| 1430 | }; | 1603 | }; |
| 1431 | 1604 | ||
| 1432 | static struct clk_mux *const gxbb_clk_muxes[] = { | 1605 | static struct clk_mux *const gxbb_clk_muxes[] = { |
| @@ -1439,6 +1612,9 @@ static struct clk_mux *const gxbb_clk_muxes[] = { | |||
| 1439 | &gxbb_cts_mclk_i958_sel, | 1612 | &gxbb_cts_mclk_i958_sel, |
| 1440 | &gxbb_cts_i958, | 1613 | &gxbb_cts_i958, |
| 1441 | &gxbb_32k_clk_sel, | 1614 | &gxbb_32k_clk_sel, |
| 1615 | &gxbb_sd_emmc_a_clk0_sel, | ||
| 1616 | &gxbb_sd_emmc_b_clk0_sel, | ||
| 1617 | &gxbb_sd_emmc_c_clk0_sel, | ||
| 1442 | }; | 1618 | }; |
| 1443 | 1619 | ||
| 1444 | static struct clk_divider *const gxbb_clk_dividers[] = { | 1620 | static struct clk_divider *const gxbb_clk_dividers[] = { |
| @@ -1448,6 +1624,9 @@ static struct clk_divider *const gxbb_clk_dividers[] = { | |||
| 1448 | &gxbb_mali_1_div, | 1624 | &gxbb_mali_1_div, |
| 1449 | &gxbb_cts_mclk_i958_div, | 1625 | &gxbb_cts_mclk_i958_div, |
| 1450 | &gxbb_32k_clk_div, | 1626 | &gxbb_32k_clk_div, |
| 1627 | &gxbb_sd_emmc_a_clk0_div, | ||
| 1628 | &gxbb_sd_emmc_b_clk0_div, | ||
| 1629 | &gxbb_sd_emmc_c_clk0_div, | ||
| 1451 | }; | 1630 | }; |
| 1452 | 1631 | ||
| 1453 | static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { | 1632 | static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { |
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index cb60a516ca82..20ab7190d328 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/clk-provider.h> | 25 | #include <linux/clk-provider.h> |
| 26 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
| 27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/reset-controller.h> | ||
| 29 | #include <linux/slab.h> | ||
| 28 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 29 | 31 | ||
| 30 | #include "clkc.h" | 32 | #include "clkc.h" |
| @@ -32,6 +34,13 @@ | |||
| 32 | 34 | ||
| 33 | static DEFINE_SPINLOCK(clk_lock); | 35 | static DEFINE_SPINLOCK(clk_lock); |
| 34 | 36 | ||
| 37 | static void __iomem *clk_base; | ||
| 38 | |||
| 39 | struct meson8b_clk_reset { | ||
| 40 | struct reset_controller_dev reset; | ||
| 41 | void __iomem *base; | ||
| 42 | }; | ||
| 43 | |||
| 35 | static const struct pll_rate_table sys_pll_rate_table[] = { | 44 | static const struct pll_rate_table sys_pll_rate_table[] = { |
| 36 | PLL_RATE(312000000, 52, 1, 2), | 45 | PLL_RATE(312000000, 52, 1, 2), |
| 37 | PLL_RATE(336000000, 56, 1, 2), | 46 | PLL_RATE(336000000, 56, 1, 2), |
| @@ -696,20 +705,114 @@ static struct clk_divider *const meson8b_clk_dividers[] = { | |||
| 696 | &meson8b_mpeg_clk_div, | 705 | &meson8b_mpeg_clk_div, |
| 697 | }; | 706 | }; |
| 698 | 707 | ||
| 708 | static const struct meson8b_clk_reset_line { | ||
| 709 | u32 reg; | ||
| 710 | u8 bit_idx; | ||
| 711 | } meson8b_clk_reset_bits[] = { | ||
| 712 | [CLKC_RESET_L2_CACHE_SOFT_RESET] = { | ||
| 713 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30 | ||
| 714 | }, | ||
| 715 | [CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = { | ||
| 716 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29 | ||
| 717 | }, | ||
| 718 | [CLKC_RESET_SCU_SOFT_RESET] = { | ||
| 719 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28 | ||
| 720 | }, | ||
| 721 | [CLKC_RESET_CPU3_SOFT_RESET] = { | ||
| 722 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27 | ||
| 723 | }, | ||
| 724 | [CLKC_RESET_CPU2_SOFT_RESET] = { | ||
| 725 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26 | ||
| 726 | }, | ||
| 727 | [CLKC_RESET_CPU1_SOFT_RESET] = { | ||
| 728 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25 | ||
| 729 | }, | ||
| 730 | [CLKC_RESET_CPU0_SOFT_RESET] = { | ||
| 731 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24 | ||
| 732 | }, | ||
| 733 | [CLKC_RESET_A5_GLOBAL_RESET] = { | ||
| 734 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18 | ||
| 735 | }, | ||
| 736 | [CLKC_RESET_A5_AXI_SOFT_RESET] = { | ||
| 737 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17 | ||
| 738 | }, | ||
| 739 | [CLKC_RESET_A5_ABP_SOFT_RESET] = { | ||
| 740 | .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16 | ||
| 741 | }, | ||
| 742 | [CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = { | ||
| 743 | .reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30 | ||
| 744 | }, | ||
| 745 | [CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = { | ||
| 746 | .reg = HHI_VID_CLK_CNTL, .bit_idx = 15 | ||
| 747 | }, | ||
| 748 | [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = { | ||
| 749 | .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7 | ||
| 750 | }, | ||
| 751 | [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = { | ||
| 752 | .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3 | ||
| 753 | }, | ||
| 754 | [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = { | ||
| 755 | .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1 | ||
| 756 | }, | ||
| 757 | [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = { | ||
| 758 | .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0 | ||
| 759 | }, | ||
| 760 | }; | ||
| 761 | |||
| 762 | static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev, | ||
| 763 | unsigned long id, bool assert) | ||
| 764 | { | ||
| 765 | struct meson8b_clk_reset *meson8b_clk_reset = | ||
| 766 | container_of(rcdev, struct meson8b_clk_reset, reset); | ||
| 767 | unsigned long flags; | ||
| 768 | const struct meson8b_clk_reset_line *reset; | ||
| 769 | u32 val; | ||
| 770 | |||
| 771 | if (id >= ARRAY_SIZE(meson8b_clk_reset_bits)) | ||
| 772 | return -EINVAL; | ||
| 773 | |||
| 774 | reset = &meson8b_clk_reset_bits[id]; | ||
| 775 | |||
| 776 | spin_lock_irqsave(&clk_lock, flags); | ||
| 777 | |||
| 778 | val = readl(meson8b_clk_reset->base + reset->reg); | ||
| 779 | if (assert) | ||
| 780 | val |= BIT(reset->bit_idx); | ||
| 781 | else | ||
| 782 | val &= ~BIT(reset->bit_idx); | ||
| 783 | writel(val, meson8b_clk_reset->base + reset->reg); | ||
| 784 | |||
| 785 | spin_unlock_irqrestore(&clk_lock, flags); | ||
| 786 | |||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | |||
| 790 | static int meson8b_clk_reset_assert(struct reset_controller_dev *rcdev, | ||
| 791 | unsigned long id) | ||
| 792 | { | ||
| 793 | return meson8b_clk_reset_update(rcdev, id, true); | ||
| 794 | } | ||
| 795 | |||
| 796 | static int meson8b_clk_reset_deassert(struct reset_controller_dev *rcdev, | ||
| 797 | unsigned long id) | ||
| 798 | { | ||
| 799 | return meson8b_clk_reset_update(rcdev, id, false); | ||
| 800 | } | ||
| 801 | |||
| 802 | static const struct reset_control_ops meson8b_clk_reset_ops = { | ||
| 803 | .assert = meson8b_clk_reset_assert, | ||
| 804 | .deassert = meson8b_clk_reset_deassert, | ||
| 805 | }; | ||
| 806 | |||
| 699 | static int meson8b_clkc_probe(struct platform_device *pdev) | 807 | static int meson8b_clkc_probe(struct platform_device *pdev) |
| 700 | { | 808 | { |
| 701 | void __iomem *clk_base; | ||
| 702 | int ret, clkid, i; | 809 | int ret, clkid, i; |
| 703 | struct clk_hw *parent_hw; | 810 | struct clk_hw *parent_hw; |
| 704 | struct clk *parent_clk; | 811 | struct clk *parent_clk; |
| 705 | struct device *dev = &pdev->dev; | 812 | struct device *dev = &pdev->dev; |
| 706 | 813 | ||
| 707 | /* Generic clocks and PLLs */ | 814 | if (!clk_base) |
| 708 | clk_base = of_iomap(dev->of_node, 1); | ||
| 709 | if (!clk_base) { | ||
| 710 | pr_err("%s: Unable to map clk base\n", __func__); | ||
| 711 | return -ENXIO; | 815 | return -ENXIO; |
| 712 | } | ||
| 713 | 816 | ||
| 714 | /* Populate base address for PLLs */ | 817 | /* Populate base address for PLLs */ |
| 715 | for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) | 818 | for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) |
| @@ -749,7 +852,7 @@ static int meson8b_clkc_probe(struct platform_device *pdev) | |||
| 749 | /* FIXME convert to devm_clk_register */ | 852 | /* FIXME convert to devm_clk_register */ |
| 750 | ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); | 853 | ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); |
| 751 | if (ret) | 854 | if (ret) |
| 752 | goto iounmap; | 855 | return ret; |
| 753 | } | 856 | } |
| 754 | 857 | ||
| 755 | /* | 858 | /* |
| @@ -772,15 +875,11 @@ static int meson8b_clkc_probe(struct platform_device *pdev) | |||
| 772 | if (ret) { | 875 | if (ret) { |
| 773 | pr_err("%s: failed to register clock notifier for cpu_clk\n", | 876 | pr_err("%s: failed to register clock notifier for cpu_clk\n", |
| 774 | __func__); | 877 | __func__); |
| 775 | goto iounmap; | 878 | return ret; |
| 776 | } | 879 | } |
| 777 | 880 | ||
| 778 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, | 881 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, |
| 779 | &meson8b_hw_onecell_data); | 882 | &meson8b_hw_onecell_data); |
| 780 | |||
| 781 | iounmap: | ||
| 782 | iounmap(clk_base); | ||
| 783 | return ret; | ||
| 784 | } | 883 | } |
| 785 | 884 | ||
| 786 | static const struct of_device_id meson8b_clkc_match_table[] = { | 885 | static const struct of_device_id meson8b_clkc_match_table[] = { |
| @@ -799,3 +898,39 @@ static struct platform_driver meson8b_driver = { | |||
| 799 | }; | 898 | }; |
| 800 | 899 | ||
| 801 | builtin_platform_driver(meson8b_driver); | 900 | builtin_platform_driver(meson8b_driver); |
| 901 | |||
| 902 | static void __init meson8b_clkc_reset_init(struct device_node *np) | ||
| 903 | { | ||
| 904 | struct meson8b_clk_reset *rstc; | ||
| 905 | int ret; | ||
| 906 | |||
| 907 | /* Generic clocks, PLLs and some of the reset-bits */ | ||
| 908 | clk_base = of_iomap(np, 1); | ||
| 909 | if (!clk_base) { | ||
| 910 | pr_err("%s: Unable to map clk base\n", __func__); | ||
| 911 | return; | ||
| 912 | } | ||
| 913 | |||
| 914 | rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); | ||
| 915 | if (!rstc) | ||
| 916 | return; | ||
| 917 | |||
| 918 | /* Reset Controller */ | ||
| 919 | rstc->base = clk_base; | ||
| 920 | rstc->reset.ops = &meson8b_clk_reset_ops; | ||
| 921 | rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); | ||
| 922 | rstc->reset.of_node = np; | ||
| 923 | ret = reset_controller_register(&rstc->reset); | ||
| 924 | if (ret) { | ||
| 925 | pr_err("%s: Failed to register clkc reset controller: %d\n", | ||
| 926 | __func__, ret); | ||
| 927 | return; | ||
| 928 | } | ||
| 929 | } | ||
| 930 | |||
| 931 | CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", | ||
| 932 | meson8b_clkc_reset_init); | ||
| 933 | CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", | ||
| 934 | meson8b_clkc_reset_init); | ||
| 935 | CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", | ||
| 936 | meson8b_clkc_reset_init); | ||
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index c139bb3273ca..2eaf8a52e7dd 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h | |||
| @@ -37,6 +37,9 @@ | |||
| 37 | #define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ | 37 | #define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ |
| 38 | #define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */ | 38 | #define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */ |
| 39 | #define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ | 39 | #define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ |
| 40 | #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ | ||
| 41 | #define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */ | ||
| 42 | #define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ | ||
| 40 | #define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ | 43 | #define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ |
| 41 | #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ | 44 | #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ |
| 42 | #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ | 45 | #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ |
| @@ -68,7 +71,11 @@ | |||
| 68 | 71 | ||
| 69 | #define CLK_NR_CLKS 96 | 72 | #define CLK_NR_CLKS 96 |
| 70 | 73 | ||
| 71 | /* include the CLKIDs that have been made part of the stable DT binding */ | 74 | /* |
| 75 | * include the CLKID and RESETID that have | ||
| 76 | * been made part of the stable DT binding | ||
| 77 | */ | ||
| 72 | #include <dt-bindings/clock/meson8b-clkc.h> | 78 | #include <dt-bindings/clock/meson8b-clkc.h> |
| 79 | #include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h> | ||
| 73 | 80 | ||
| 74 | #endif /* __MESON8B_H */ | 81 | #endif /* __MESON8B_H */ |
diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c index 61893fe73251..089927e4cda2 100644 --- a/drivers/clk/mmp/clk.c +++ b/drivers/clk/mmp/clk.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, | 9 | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, |
| 10 | int nr_clks) | 10 | int nr_clks) |
| 11 | { | 11 | { |
| 12 | static struct clk **clk_table; | 12 | struct clk **clk_table; |
| 13 | 13 | ||
| 14 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); | 14 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); |
| 15 | if (!clk_table) | 15 | if (!clk_table) |
diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 5b98ff9076f3..7b359afd620e 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c | |||
| @@ -885,7 +885,7 @@ static const struct clk_ops clk_usb_i2c_ops = { | |||
| 885 | .recalc_rate = clk_usb_i2c_recalc_rate, | 885 | .recalc_rate = clk_usb_i2c_recalc_rate, |
| 886 | }; | 886 | }; |
| 887 | 887 | ||
| 888 | static int clk_gate_enable(struct clk_hw *hw) | 888 | static int lpc32xx_clk_gate_enable(struct clk_hw *hw) |
| 889 | { | 889 | { |
| 890 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); | 890 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 891 | u32 mask = BIT(clk->bit_idx); | 891 | u32 mask = BIT(clk->bit_idx); |
| @@ -894,7 +894,7 @@ static int clk_gate_enable(struct clk_hw *hw) | |||
| 894 | return regmap_update_bits(clk_regmap, clk->reg, mask, val); | 894 | return regmap_update_bits(clk_regmap, clk->reg, mask, val); |
| 895 | } | 895 | } |
| 896 | 896 | ||
| 897 | static void clk_gate_disable(struct clk_hw *hw) | 897 | static void lpc32xx_clk_gate_disable(struct clk_hw *hw) |
| 898 | { | 898 | { |
| 899 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); | 899 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 900 | u32 mask = BIT(clk->bit_idx); | 900 | u32 mask = BIT(clk->bit_idx); |
| @@ -903,7 +903,7 @@ static void clk_gate_disable(struct clk_hw *hw) | |||
| 903 | regmap_update_bits(clk_regmap, clk->reg, mask, val); | 903 | regmap_update_bits(clk_regmap, clk->reg, mask, val); |
| 904 | } | 904 | } |
| 905 | 905 | ||
| 906 | static int clk_gate_is_enabled(struct clk_hw *hw) | 906 | static int lpc32xx_clk_gate_is_enabled(struct clk_hw *hw) |
| 907 | { | 907 | { |
| 908 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); | 908 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 909 | u32 val; | 909 | u32 val; |
| @@ -916,9 +916,9 @@ static int clk_gate_is_enabled(struct clk_hw *hw) | |||
| 916 | } | 916 | } |
| 917 | 917 | ||
| 918 | static const struct clk_ops lpc32xx_clk_gate_ops = { | 918 | static const struct clk_ops lpc32xx_clk_gate_ops = { |
| 919 | .enable = clk_gate_enable, | 919 | .enable = lpc32xx_clk_gate_enable, |
| 920 | .disable = clk_gate_disable, | 920 | .disable = lpc32xx_clk_gate_disable, |
| 921 | .is_enabled = clk_gate_is_enabled, | 921 | .is_enabled = lpc32xx_clk_gate_is_enabled, |
| 922 | }; | 922 | }; |
| 923 | 923 | ||
| 924 | #define div_mask(width) ((1 << (width)) - 1) | 924 | #define div_mask(width) ((1 << (width)) - 1) |
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index d990fe44aef3..cc03d5508627 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c | |||
| @@ -412,8 +412,6 @@ static const struct clk_ops clk_smd_rpm_ops = { | |||
| 412 | static const struct clk_ops clk_smd_rpm_branch_ops = { | 412 | static const struct clk_ops clk_smd_rpm_branch_ops = { |
| 413 | .prepare = clk_smd_rpm_prepare, | 413 | .prepare = clk_smd_rpm_prepare, |
| 414 | .unprepare = clk_smd_rpm_unprepare, | 414 | .unprepare = clk_smd_rpm_unprepare, |
| 415 | .round_rate = clk_smd_rpm_round_rate, | ||
| 416 | .recalc_rate = clk_smd_rpm_recalc_rate, | ||
| 417 | }; | 415 | }; |
| 418 | 416 | ||
| 419 | /* msm8916 */ | 417 | /* msm8916 */ |
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index 2cfe7000fc60..3410ee68d4bc 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c | |||
| @@ -1176,7 +1176,7 @@ static struct clk_rcg2 bimc_gpu_clk_src = { | |||
| 1176 | .parent_names = gcc_xo_gpll0_bimc, | 1176 | .parent_names = gcc_xo_gpll0_bimc, |
| 1177 | .num_parents = 3, | 1177 | .num_parents = 3, |
| 1178 | .flags = CLK_GET_RATE_NOCACHE, | 1178 | .flags = CLK_GET_RATE_NOCACHE, |
| 1179 | .ops = &clk_rcg2_shared_ops, | 1179 | .ops = &clk_rcg2_ops, |
| 1180 | }, | 1180 | }, |
| 1181 | }; | 1181 | }; |
| 1182 | 1182 | ||
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 8abc200d4fd3..7ddec886fcd3 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c | |||
| @@ -2730,6 +2730,32 @@ static struct clk_fixed_factor ufs_rx_cfg_clk_src = { | |||
| 2730 | }, | 2730 | }, |
| 2731 | }; | 2731 | }; |
| 2732 | 2732 | ||
| 2733 | static struct clk_branch gcc_hlos1_vote_lpass_core_smmu_clk = { | ||
| 2734 | .halt_reg = 0x7d010, | ||
| 2735 | .halt_check = BRANCH_HALT_VOTED, | ||
| 2736 | .clkr = { | ||
| 2737 | .enable_reg = 0x7d010, | ||
| 2738 | .enable_mask = BIT(0), | ||
| 2739 | .hw.init = &(struct clk_init_data){ | ||
| 2740 | .name = "hlos1_vote_lpass_core_smmu_clk", | ||
| 2741 | .ops = &clk_branch2_ops, | ||
| 2742 | }, | ||
| 2743 | }, | ||
| 2744 | }; | ||
| 2745 | |||
| 2746 | static struct clk_branch gcc_hlos1_vote_lpass_adsp_smmu_clk = { | ||
| 2747 | .halt_reg = 0x7d014, | ||
| 2748 | .halt_check = BRANCH_HALT_VOTED, | ||
| 2749 | .clkr = { | ||
| 2750 | .enable_reg = 0x7d014, | ||
| 2751 | .enable_mask = BIT(0), | ||
| 2752 | .hw.init = &(struct clk_init_data){ | ||
| 2753 | .name = "hlos1_vote_lpass_adsp_smmu_clk", | ||
| 2754 | .ops = &clk_branch2_ops, | ||
| 2755 | }, | ||
| 2756 | }, | ||
| 2757 | }; | ||
| 2758 | |||
| 2733 | static struct clk_branch gcc_ufs_rx_cfg_clk = { | 2759 | static struct clk_branch gcc_ufs_rx_cfg_clk = { |
| 2734 | .halt_reg = 0x75014, | 2760 | .halt_reg = 0x75014, |
| 2735 | .clkr = { | 2761 | .clkr = { |
| @@ -3307,6 +3333,8 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { | |||
| 3307 | [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, | 3333 | [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, |
| 3308 | [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, | 3334 | [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, |
| 3309 | [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, | 3335 | [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, |
| 3336 | [GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &gcc_hlos1_vote_lpass_core_smmu_clk.clkr, | ||
| 3337 | [GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &gcc_hlos1_vote_lpass_adsp_smmu_clk.clkr, | ||
| 3310 | [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, | 3338 | [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, |
| 3311 | [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, | 3339 | [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, |
| 3312 | [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, | 3340 | [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, |
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 78d1df9112ba..acbb38151ba1 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig | |||
| @@ -15,6 +15,7 @@ config CLK_RENESAS | |||
| 15 | select CLK_R8A7794 if ARCH_R8A7794 | 15 | select CLK_R8A7794 if ARCH_R8A7794 |
| 16 | select CLK_R8A7795 if ARCH_R8A7795 | 16 | select CLK_R8A7795 if ARCH_R8A7795 |
| 17 | select CLK_R8A7796 if ARCH_R8A7796 | 17 | select CLK_R8A7796 if ARCH_R8A7796 |
| 18 | select CLK_R8A77995 if ARCH_R8A77995 | ||
| 18 | select CLK_SH73A0 if ARCH_SH73A0 | 19 | select CLK_SH73A0 if ARCH_SH73A0 |
| 19 | 20 | ||
| 20 | if CLK_RENESAS | 21 | if CLK_RENESAS |
| @@ -34,94 +35,103 @@ config CLK_EMEV2 | |||
| 34 | bool "Emma Mobile EV2 clock support" if COMPILE_TEST | 35 | bool "Emma Mobile EV2 clock support" if COMPILE_TEST |
| 35 | 36 | ||
| 36 | config CLK_RZA1 | 37 | config CLK_RZA1 |
| 37 | bool | 38 | bool "RZ/A1H clock support" if COMPILE_TEST |
| 38 | select CLK_RENESAS_CPG_MSTP | 39 | select CLK_RENESAS_CPG_MSTP |
| 39 | 40 | ||
| 40 | config CLK_R8A73A4 | 41 | config CLK_R8A73A4 |
| 41 | bool | 42 | bool "R-Mobile APE6 clock support" if COMPILE_TEST |
| 42 | select CLK_RENESAS_CPG_MSTP | 43 | select CLK_RENESAS_CPG_MSTP |
| 43 | select CLK_RENESAS_DIV6 | 44 | select CLK_RENESAS_DIV6 |
| 44 | 45 | ||
| 45 | config CLK_R8A7740 | 46 | config CLK_R8A7740 |
| 46 | bool | 47 | bool "R-Mobile A1 clock support" if COMPILE_TEST |
| 47 | select CLK_RENESAS_CPG_MSTP | 48 | select CLK_RENESAS_CPG_MSTP |
| 48 | select CLK_RENESAS_DIV6 | 49 | select CLK_RENESAS_DIV6 |
| 49 | 50 | ||
| 50 | config CLK_R8A7743 | 51 | config CLK_R8A7743 |
| 51 | bool | 52 | bool "RZ/G1M clock support" if COMPILE_TEST |
| 52 | select CLK_RCAR_GEN2_CPG | 53 | select CLK_RCAR_GEN2_CPG |
| 53 | 54 | ||
| 54 | config CLK_R8A7745 | 55 | config CLK_R8A7745 |
| 55 | bool | 56 | bool "RZ/G1E clock support" if COMPILE_TEST |
| 56 | select CLK_RCAR_GEN2_CPG | 57 | select CLK_RCAR_GEN2_CPG |
| 57 | 58 | ||
| 58 | config CLK_R8A7778 | 59 | config CLK_R8A7778 |
| 59 | bool | 60 | bool "R-Car M1A clock support" if COMPILE_TEST |
| 60 | select CLK_RENESAS_CPG_MSTP | 61 | select CLK_RENESAS_CPG_MSTP |
| 61 | 62 | ||
| 62 | config CLK_R8A7779 | 63 | config CLK_R8A7779 |
| 63 | bool | 64 | bool "R-Car H1 clock support" if COMPILE_TEST |
| 64 | select CLK_RENESAS_CPG_MSTP | 65 | select CLK_RENESAS_CPG_MSTP |
| 65 | 66 | ||
| 66 | config CLK_R8A7790 | 67 | config CLK_R8A7790 |
| 67 | bool | 68 | bool "R-Car H2 clock support" if COMPILE_TEST |
| 68 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY | 69 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 69 | select CLK_RCAR_GEN2_CPG | 70 | select CLK_RCAR_GEN2_CPG |
| 70 | select CLK_RENESAS_DIV6 | 71 | select CLK_RENESAS_DIV6 |
| 71 | 72 | ||
| 72 | config CLK_R8A7791 | 73 | config CLK_R8A7791 |
| 73 | bool | 74 | bool "R-Car M2-W/N clock support" if COMPILE_TEST |
| 74 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY | 75 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 75 | select CLK_RCAR_GEN2_CPG | 76 | select CLK_RCAR_GEN2_CPG |
| 76 | select CLK_RENESAS_DIV6 | 77 | select CLK_RENESAS_DIV6 |
| 77 | 78 | ||
| 78 | config CLK_R8A7792 | 79 | config CLK_R8A7792 |
| 79 | bool | 80 | bool "R-Car V2H clock support" if COMPILE_TEST |
| 80 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY | 81 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 81 | select CLK_RCAR_GEN2_CPG | 82 | select CLK_RCAR_GEN2_CPG |
| 82 | 83 | ||
| 83 | config CLK_R8A7794 | 84 | config CLK_R8A7794 |
| 84 | bool | 85 | bool "R-Car E2 clock support" if COMPILE_TEST |
| 85 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY | 86 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 86 | select CLK_RCAR_GEN2_CPG | 87 | select CLK_RCAR_GEN2_CPG |
| 87 | select CLK_RENESAS_DIV6 | 88 | select CLK_RENESAS_DIV6 |
| 88 | 89 | ||
| 89 | config CLK_R8A7795 | 90 | config CLK_R8A7795 |
| 90 | bool | 91 | bool "R-Car H3 clock support" if COMPILE_TEST |
| 91 | select CLK_RCAR_GEN3_CPG | 92 | select CLK_RCAR_GEN3_CPG |
| 92 | 93 | ||
| 93 | config CLK_R8A7796 | 94 | config CLK_R8A7796 |
| 94 | bool | 95 | bool "R-Car M3-W clock support" if COMPILE_TEST |
| 96 | select CLK_RCAR_GEN3_CPG | ||
| 97 | |||
| 98 | config CLK_R8A77995 | ||
| 99 | bool "R-Car D3 clock support" if COMPILE_TEST | ||
| 95 | select CLK_RCAR_GEN3_CPG | 100 | select CLK_RCAR_GEN3_CPG |
| 96 | 101 | ||
| 97 | config CLK_SH73A0 | 102 | config CLK_SH73A0 |
| 98 | bool | 103 | bool "SH-Mobile AG5 clock support" if COMPILE_TEST |
| 99 | select CLK_RENESAS_CPG_MSTP | 104 | select CLK_RENESAS_CPG_MSTP |
| 100 | select CLK_RENESAS_DIV6 | 105 | select CLK_RENESAS_DIV6 |
| 101 | 106 | ||
| 102 | 107 | ||
| 103 | # Family | 108 | # Family |
| 104 | config CLK_RCAR_GEN2 | 109 | config CLK_RCAR_GEN2 |
| 105 | bool | 110 | bool "R-Car Gen2 legacy clock support" if COMPILE_TEST |
| 106 | select CLK_RENESAS_CPG_MSTP | 111 | select CLK_RENESAS_CPG_MSTP |
| 107 | select CLK_RENESAS_DIV6 | 112 | select CLK_RENESAS_DIV6 |
| 108 | 113 | ||
| 109 | config CLK_RCAR_GEN2_CPG | 114 | config CLK_RCAR_GEN2_CPG |
| 110 | bool | 115 | bool "R-Car Gen2 CPG clock support" if COMPILE_TEST |
| 111 | select CLK_RENESAS_CPG_MSSR | 116 | select CLK_RENESAS_CPG_MSSR |
| 112 | 117 | ||
| 113 | config CLK_RCAR_GEN3_CPG | 118 | config CLK_RCAR_GEN3_CPG |
| 114 | bool | 119 | bool "R-Car Gen3 CPG clock support" if COMPILE_TEST |
| 115 | select CLK_RENESAS_CPG_MSSR | 120 | select CLK_RENESAS_CPG_MSSR |
| 116 | 121 | ||
| 122 | config CLK_RCAR_USB2_CLOCK_SEL | ||
| 123 | bool "Renesas R-Car USB2 clock selector support" | ||
| 124 | depends on ARCH_RENESAS || COMPILE_TEST | ||
| 125 | help | ||
| 126 | This is a driver for R-Car USB2 clock selector | ||
| 117 | 127 | ||
| 118 | # Generic | 128 | # Generic |
| 119 | config CLK_RENESAS_CPG_MSSR | 129 | config CLK_RENESAS_CPG_MSSR |
| 120 | bool | 130 | bool "CPG/MSSR clock support" if COMPILE_TEST |
| 121 | select CLK_RENESAS_DIV6 | 131 | select CLK_RENESAS_DIV6 |
| 122 | 132 | ||
| 123 | config CLK_RENESAS_CPG_MSTP | 133 | config CLK_RENESAS_CPG_MSTP |
| 124 | bool | 134 | bool "MSTP clock support" if COMPILE_TEST |
| 125 | 135 | ||
| 126 | config CLK_RENESAS_DIV6 | 136 | config CLK_RENESAS_DIV6 |
| 127 | bool "DIV6 clock support" if COMPILE_TEST | 137 | bool "DIV6 clock support" if COMPILE_TEST |
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 02d04124371f..9bda3ec5b199 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile | |||
| @@ -13,12 +13,14 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o | |||
| 13 | obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o | 13 | obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o |
| 14 | obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o | 14 | obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o |
| 15 | obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o | 15 | obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o |
| 16 | obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o | ||
| 16 | obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o | 17 | obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o |
| 17 | 18 | ||
| 18 | # Family | 19 | # Family |
| 19 | obj-$(CONFIG_CLK_RCAR_GEN2) += clk-rcar-gen2.o | 20 | obj-$(CONFIG_CLK_RCAR_GEN2) += clk-rcar-gen2.o |
| 20 | obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o | 21 | obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o |
| 21 | obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o | 22 | obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o |
| 23 | obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o | ||
| 22 | 24 | ||
| 23 | # Generic | 25 | # Generic |
| 24 | obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o | 26 | obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o |
diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 0627860233cb..3e0040c0ac87 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c | |||
| @@ -29,6 +29,9 @@ | |||
| 29 | * @hw: handle between common and hardware-specific interfaces | 29 | * @hw: handle between common and hardware-specific interfaces |
| 30 | * @reg: IO-remapped register | 30 | * @reg: IO-remapped register |
| 31 | * @div: divisor value (1-64) | 31 | * @div: divisor value (1-64) |
| 32 | * @src_shift: Shift to access the register bits to select the parent clock | ||
| 33 | * @src_width: Number of register bits to select the parent clock (may be 0) | ||
| 34 | * @parents: Array to map from valid parent clocks indices to hardware indices | ||
| 32 | */ | 35 | */ |
| 33 | struct div6_clock { | 36 | struct div6_clock { |
| 34 | struct clk_hw hw; | 37 | struct clk_hw hw; |
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index f1617dd044cb..500a9e4e03c4 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c | |||
| @@ -335,7 +335,7 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) | |||
| 335 | u32 ncells; | 335 | u32 ncells; |
| 336 | 336 | ||
| 337 | if (of_property_read_u32(np, "#power-domain-cells", &ncells)) { | 337 | if (of_property_read_u32(np, "#power-domain-cells", &ncells)) { |
| 338 | pr_warn("%s lacks #power-domain-cells\n", np->full_name); | 338 | pr_warn("%pOF lacks #power-domain-cells\n", np); |
| 339 | return; | 339 | return; |
| 340 | } | 340 | } |
| 341 | 341 | ||
diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 51a2479ed5d7..0b2e56d0d94b 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c | |||
| @@ -407,8 +407,7 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) | |||
| 407 | 407 | ||
| 408 | if (rcar_rst_read_mode_pins(&cpg_mode)) { | 408 | if (rcar_rst_read_mode_pins(&cpg_mode)) { |
| 409 | /* Backward-compatibility with old DT */ | 409 | /* Backward-compatibility with old DT */ |
| 410 | pr_warn("%s: failed to obtain mode pins from RST\n", | 410 | pr_warn("%pOF: failed to obtain mode pins from RST\n", np); |
| 411 | np->full_name); | ||
| 412 | cpg_mode = rcar_gen2_read_mode_pins(); | 411 | cpg_mode = rcar_gen2_read_mode_pins(); |
| 413 | } | 412 | } |
| 414 | 413 | ||
diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c index a832b9b6f7b0..7f85bbf20bf7 100644 --- a/drivers/clk/renesas/r8a7792-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c | |||
| @@ -118,6 +118,13 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = { | |||
| 118 | DEF_MOD("vin1", 810, R8A7792_CLK_ZG), | 118 | DEF_MOD("vin1", 810, R8A7792_CLK_ZG), |
| 119 | DEF_MOD("vin0", 811, R8A7792_CLK_ZG), | 119 | DEF_MOD("vin0", 811, R8A7792_CLK_ZG), |
| 120 | DEF_MOD("etheravb", 812, R8A7792_CLK_HP), | 120 | DEF_MOD("etheravb", 812, R8A7792_CLK_HP), |
| 121 | DEF_MOD("imr-lx3", 821, R8A7792_CLK_ZG), | ||
| 122 | DEF_MOD("imr-lsx3-1", 822, R8A7792_CLK_ZG), | ||
| 123 | DEF_MOD("imr-lsx3-0", 823, R8A7792_CLK_ZG), | ||
| 124 | DEF_MOD("imr-lsx3-5", 825, R8A7792_CLK_ZG), | ||
| 125 | DEF_MOD("imr-lsx3-4", 826, R8A7792_CLK_ZG), | ||
| 126 | DEF_MOD("imr-lsx3-3", 827, R8A7792_CLK_ZG), | ||
| 127 | DEF_MOD("imr-lsx3-2", 828, R8A7792_CLK_ZG), | ||
| 121 | DEF_MOD("gyro-adc", 901, R8A7792_CLK_P), | 128 | DEF_MOD("gyro-adc", 901, R8A7792_CLK_P), |
| 122 | DEF_MOD("gpio7", 904, R8A7792_CLK_CP), | 129 | DEF_MOD("gpio7", 904, R8A7792_CLK_CP), |
| 123 | DEF_MOD("gpio6", 905, R8A7792_CLK_CP), | 130 | DEF_MOD("gpio6", 905, R8A7792_CLK_CP), |
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index c091a8e024b8..762b2f8824f1 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c | |||
| @@ -305,23 +305,23 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = { | |||
| 305 | (((md) & BIT(17)) >> 17)) | 305 | (((md) & BIT(17)) >> 17)) |
| 306 | 306 | ||
| 307 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { | 307 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { |
| 308 | /* EXTAL div PLL1 mult PLL3 mult */ | 308 | /* EXTAL div PLL1 mult/div PLL3 mult/div */ |
| 309 | { 1, 192, 192, }, | 309 | { 1, 192, 1, 192, 1, }, |
| 310 | { 1, 192, 128, }, | 310 | { 1, 192, 1, 128, 1, }, |
| 311 | { 0, /* Prohibited setting */ }, | 311 | { 0, /* Prohibited setting */ }, |
| 312 | { 1, 192, 192, }, | 312 | { 1, 192, 1, 192, 1, }, |
| 313 | { 1, 160, 160, }, | 313 | { 1, 160, 1, 160, 1, }, |
| 314 | { 1, 160, 106, }, | 314 | { 1, 160, 1, 106, 1, }, |
| 315 | { 0, /* Prohibited setting */ }, | 315 | { 0, /* Prohibited setting */ }, |
| 316 | { 1, 160, 160, }, | 316 | { 1, 160, 1, 160, 1, }, |
| 317 | { 1, 128, 128, }, | 317 | { 1, 128, 1, 128, 1, }, |
| 318 | { 1, 128, 84, }, | 318 | { 1, 128, 1, 84, 1, }, |
| 319 | { 0, /* Prohibited setting */ }, | 319 | { 0, /* Prohibited setting */ }, |
| 320 | { 1, 128, 128, }, | 320 | { 1, 128, 1, 128, 1, }, |
| 321 | { 2, 192, 192, }, | 321 | { 2, 192, 1, 192, 1, }, |
| 322 | { 2, 192, 128, }, | 322 | { 2, 192, 1, 128, 1, }, |
| 323 | { 0, /* Prohibited setting */ }, | 323 | { 0, /* Prohibited setting */ }, |
| 324 | { 2, 192, 192, }, | 324 | { 2, 192, 1, 192, 1, }, |
| 325 | }; | 325 | }; |
| 326 | 326 | ||
| 327 | static const struct soc_device_attribute r8a7795es1[] __initconst = { | 327 | static const struct soc_device_attribute r8a7795es1[] __initconst = { |
diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index acc6d0f153e1..e5e7fb212288 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c | |||
| @@ -138,6 +138,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { | |||
| 138 | DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), | 138 | DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), |
| 139 | DEF_MOD("pcie1", 318, R8A7796_CLK_S3D1), | 139 | DEF_MOD("pcie1", 318, R8A7796_CLK_S3D1), |
| 140 | DEF_MOD("pcie0", 319, R8A7796_CLK_S3D1), | 140 | DEF_MOD("pcie0", 319, R8A7796_CLK_S3D1), |
| 141 | DEF_MOD("usb3-if0", 328, R8A7796_CLK_S3D1), | ||
| 141 | DEF_MOD("usb-dmac0", 330, R8A7796_CLK_S3D1), | 142 | DEF_MOD("usb-dmac0", 330, R8A7796_CLK_S3D1), |
| 142 | DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1), | 143 | DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1), |
| 143 | DEF_MOD("rwdt", 402, R8A7796_CLK_R), | 144 | DEF_MOD("rwdt", 402, R8A7796_CLK_R), |
| @@ -277,23 +278,23 @@ static const unsigned int r8a7796_crit_mod_clks[] __initconst = { | |||
| 277 | (((md) & BIT(17)) >> 17)) | 278 | (((md) & BIT(17)) >> 17)) |
| 278 | 279 | ||
| 279 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { | 280 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { |
| 280 | /* EXTAL div PLL1 mult PLL3 mult */ | 281 | /* EXTAL div PLL1 mult/div PLL3 mult/div */ |
| 281 | { 1, 192, 192, }, | 282 | { 1, 192, 1, 192, 1, }, |
| 282 | { 1, 192, 128, }, | 283 | { 1, 192, 1, 128, 1, }, |
| 283 | { 0, /* Prohibited setting */ }, | 284 | { 0, /* Prohibited setting */ }, |
| 284 | { 1, 192, 192, }, | 285 | { 1, 192, 1, 192, 1, }, |
| 285 | { 1, 160, 160, }, | 286 | { 1, 160, 1, 160, 1, }, |
| 286 | { 1, 160, 106, }, | 287 | { 1, 160, 1, 106, 1, }, |
| 287 | { 0, /* Prohibited setting */ }, | 288 | { 0, /* Prohibited setting */ }, |
| 288 | { 1, 160, 160, }, | 289 | { 1, 160, 1, 160, 1, }, |
| 289 | { 1, 128, 128, }, | 290 | { 1, 128, 1, 128, 1, }, |
| 290 | { 1, 128, 84, }, | 291 | { 1, 128, 1, 84, 1, }, |
| 291 | { 0, /* Prohibited setting */ }, | 292 | { 0, /* Prohibited setting */ }, |
| 292 | { 1, 128, 128, }, | 293 | { 1, 128, 1, 128, 1, }, |
| 293 | { 2, 192, 192, }, | 294 | { 2, 192, 1, 192, 1, }, |
| 294 | { 2, 192, 128, }, | 295 | { 2, 192, 1, 128, 1, }, |
| 295 | { 0, /* Prohibited setting */ }, | 296 | { 0, /* Prohibited setting */ }, |
| 296 | { 2, 192, 192, }, | 297 | { 2, 192, 1, 192, 1, }, |
| 297 | }; | 298 | }; |
| 298 | 299 | ||
| 299 | static int __init r8a7796_cpg_mssr_init(struct device *dev) | 300 | static int __init r8a7796_cpg_mssr_init(struct device *dev) |
diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c new file mode 100644 index 000000000000..e594cf8ee63b --- /dev/null +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c | |||
| @@ -0,0 +1,236 @@ | |||
| 1 | /* | ||
| 2 | * r8a77995 Clock Pulse Generator / Module Standby and Software Reset | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 Glider bvba | ||
| 5 | * | ||
| 6 | * Based on r8a7795-cpg-mssr.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 2015 Glider bvba | ||
| 9 | * Copyright (C) 2015 Renesas Electronics Corp. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; version 2 of the License. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/soc/renesas/rcar-rst.h> | ||
| 20 | |||
| 21 | #include <dt-bindings/clock/r8a77995-cpg-mssr.h> | ||
| 22 | |||
| 23 | #include "renesas-cpg-mssr.h" | ||
| 24 | #include "rcar-gen3-cpg.h" | ||
| 25 | |||
| 26 | enum clk_ids { | ||
| 27 | /* Core Clock Outputs exported to DT */ | ||
| 28 | LAST_DT_CORE_CLK = R8A77995_CLK_CP, | ||
| 29 | |||
| 30 | /* External Input Clocks */ | ||
| 31 | CLK_EXTAL, | ||
| 32 | |||
| 33 | /* Internal Core Clocks */ | ||
| 34 | CLK_MAIN, | ||
| 35 | CLK_PLL0, | ||
| 36 | CLK_PLL1, | ||
| 37 | CLK_PLL3, | ||
| 38 | CLK_PLL0D2, | ||
| 39 | CLK_PLL0D3, | ||
| 40 | CLK_PLL0D5, | ||
| 41 | CLK_PLL1D2, | ||
| 42 | CLK_PE, | ||
| 43 | CLK_S0, | ||
| 44 | CLK_S1, | ||
| 45 | CLK_S2, | ||
| 46 | CLK_S3, | ||
| 47 | CLK_SDSRC, | ||
| 48 | CLK_SSPSRC, | ||
| 49 | |||
| 50 | /* Module Clocks */ | ||
| 51 | MOD_CLK_BASE | ||
| 52 | }; | ||
| 53 | |||
| 54 | static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { | ||
| 55 | /* External Clock Inputs */ | ||
| 56 | DEF_INPUT("extal", CLK_EXTAL), | ||
| 57 | |||
| 58 | /* Internal Core Clocks */ | ||
| 59 | DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), | ||
| 60 | DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), | ||
| 61 | DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), | ||
| 62 | |||
| 63 | DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 4, 250), | ||
| 64 | DEF_FIXED(".pll0d2", CLK_PLL0D2, CLK_PLL0, 2, 1), | ||
| 65 | DEF_FIXED(".pll0d3", CLK_PLL0D3, CLK_PLL0, 3, 1), | ||
| 66 | DEF_FIXED(".pll0d5", CLK_PLL0D5, CLK_PLL0, 5, 1), | ||
| 67 | DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1), | ||
| 68 | DEF_FIXED(".pe", CLK_PE, CLK_PLL0D3, 4, 1), | ||
| 69 | DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1), | ||
| 70 | DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1), | ||
| 71 | DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1), | ||
| 72 | DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), | ||
| 73 | DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), | ||
| 74 | |||
| 75 | /* Core Clock Outputs */ | ||
| 76 | DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), | ||
| 77 | DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), | ||
| 78 | DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1), | ||
| 79 | DEF_FIXED("zx", R8A77995_CLK_ZX, CLK_PLL1, 3, 1), | ||
| 80 | DEF_FIXED("s0d1", R8A77995_CLK_S0D1, CLK_S0, 1, 1), | ||
| 81 | DEF_FIXED("s1d1", R8A77995_CLK_S1D1, CLK_S1, 1, 1), | ||
| 82 | DEF_FIXED("s1d2", R8A77995_CLK_S1D2, CLK_S1, 2, 1), | ||
| 83 | DEF_FIXED("s1d4", R8A77995_CLK_S1D4, CLK_S1, 4, 1), | ||
| 84 | DEF_FIXED("s2d1", R8A77995_CLK_S2D1, CLK_S2, 1, 1), | ||
| 85 | DEF_FIXED("s2d2", R8A77995_CLK_S2D2, CLK_S2, 2, 1), | ||
| 86 | DEF_FIXED("s2d4", R8A77995_CLK_S2D4, CLK_S2, 4, 1), | ||
| 87 | DEF_FIXED("s3d1", R8A77995_CLK_S3D1, CLK_S3, 1, 1), | ||
| 88 | DEF_FIXED("s3d2", R8A77995_CLK_S3D2, CLK_S3, 2, 1), | ||
| 89 | DEF_FIXED("s3d4", R8A77995_CLK_S3D4, CLK_S3, 4, 1), | ||
| 90 | |||
| 91 | DEF_FIXED("cl", R8A77995_CLK_CL, CLK_PLL1, 48, 1), | ||
| 92 | DEF_FIXED("cp", R8A77995_CLK_CP, CLK_EXTAL, 2, 1), | ||
| 93 | DEF_FIXED("osc", R8A77995_CLK_OSC, CLK_EXTAL, 384, 1), | ||
| 94 | DEF_FIXED("r", R8A77995_CLK_R, CLK_EXTAL, 1536, 1), | ||
| 95 | |||
| 96 | DEF_GEN3_PE("s1d4c", R8A77995_CLK_S1D4C, CLK_S1, 4, CLK_PE, 2), | ||
| 97 | DEF_GEN3_PE("s3d1c", R8A77995_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1), | ||
| 98 | DEF_GEN3_PE("s3d2c", R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2), | ||
| 99 | DEF_GEN3_PE("s3d4c", R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4), | ||
| 100 | |||
| 101 | DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, CLK_SDSRC, 0x268), | ||
| 102 | |||
| 103 | DEF_DIV6P1("canfd", R8A77995_CLK_CANFD, CLK_PLL0D3, 0x244), | ||
| 104 | DEF_DIV6P1("mso", R8A77995_CLK_MSO, CLK_PLL1D2, 0x014), | ||
| 105 | }; | ||
| 106 | |||
| 107 | static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { | ||
| 108 | DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C), | ||
| 109 | DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C), | ||
| 110 | DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C), | ||
| 111 | DEF_MOD("scif1", 206, R8A77995_CLK_S3D4C), | ||
| 112 | DEF_MOD("scif0", 207, R8A77995_CLK_S3D4C), | ||
| 113 | DEF_MOD("msiof3", 208, R8A77995_CLK_MSO), | ||
| 114 | DEF_MOD("msiof2", 209, R8A77995_CLK_MSO), | ||
| 115 | DEF_MOD("msiof1", 210, R8A77995_CLK_MSO), | ||
| 116 | DEF_MOD("msiof0", 211, R8A77995_CLK_MSO), | ||
| 117 | DEF_MOD("sys-dmac2", 217, R8A77995_CLK_S3D1), | ||
| 118 | DEF_MOD("sys-dmac1", 218, R8A77995_CLK_S3D1), | ||
| 119 | DEF_MOD("sys-dmac0", 219, R8A77995_CLK_S3D1), | ||
| 120 | DEF_MOD("cmt3", 300, R8A77995_CLK_R), | ||
| 121 | DEF_MOD("cmt2", 301, R8A77995_CLK_R), | ||
| 122 | DEF_MOD("cmt1", 302, R8A77995_CLK_R), | ||
| 123 | DEF_MOD("cmt0", 303, R8A77995_CLK_R), | ||
| 124 | DEF_MOD("scif2", 310, R8A77995_CLK_S3D4C), | ||
| 125 | DEF_MOD("emmc0", 312, R8A77995_CLK_SD0), | ||
| 126 | DEF_MOD("usb-dmac0", 330, R8A77995_CLK_S3D1), | ||
| 127 | DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1), | ||
| 128 | DEF_MOD("rwdt", 402, R8A77995_CLK_R), | ||
| 129 | DEF_MOD("intc-ex", 407, R8A77995_CLK_CP), | ||
| 130 | DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1), | ||
| 131 | DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1), | ||
| 132 | DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C), | ||
| 133 | DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C), | ||
| 134 | DEF_MOD("thermal", 522, R8A77995_CLK_CP), | ||
| 135 | DEF_MOD("pwm", 523, R8A77995_CLK_S3D4C), | ||
| 136 | DEF_MOD("fcpvd1", 602, R8A77995_CLK_S1D2), | ||
| 137 | DEF_MOD("fcpvd0", 603, R8A77995_CLK_S1D2), | ||
| 138 | DEF_MOD("fcpvbs", 607, R8A77995_CLK_S0D1), | ||
| 139 | DEF_MOD("vspd1", 622, R8A77995_CLK_S1D2), | ||
| 140 | DEF_MOD("vspd0", 623, R8A77995_CLK_S1D2), | ||
| 141 | DEF_MOD("vspbs", 627, R8A77995_CLK_S0D1), | ||
| 142 | DEF_MOD("ehci0", 703, R8A77995_CLK_S3D2), | ||
| 143 | DEF_MOD("hsusb", 704, R8A77995_CLK_S3D2), | ||
| 144 | DEF_MOD("du1", 723, R8A77995_CLK_S2D1), | ||
| 145 | DEF_MOD("du0", 724, R8A77995_CLK_S2D1), | ||
| 146 | DEF_MOD("lvds", 727, R8A77995_CLK_S2D1), | ||
| 147 | DEF_MOD("vin7", 804, R8A77995_CLK_S1D2), | ||
| 148 | DEF_MOD("vin6", 805, R8A77995_CLK_S1D2), | ||
| 149 | DEF_MOD("vin5", 806, R8A77995_CLK_S1D2), | ||
| 150 | DEF_MOD("vin4", 807, R8A77995_CLK_S1D2), | ||
| 151 | DEF_MOD("etheravb", 812, R8A77995_CLK_S3D2), | ||
| 152 | DEF_MOD("imr0", 823, R8A77995_CLK_S1D2), | ||
| 153 | DEF_MOD("gpio6", 906, R8A77995_CLK_S3D4), | ||
| 154 | DEF_MOD("gpio5", 907, R8A77995_CLK_S3D4), | ||
| 155 | DEF_MOD("gpio4", 908, R8A77995_CLK_S3D4), | ||
| 156 | DEF_MOD("gpio3", 909, R8A77995_CLK_S3D4), | ||
| 157 | DEF_MOD("gpio2", 910, R8A77995_CLK_S3D4), | ||
| 158 | DEF_MOD("gpio1", 911, R8A77995_CLK_S3D4), | ||
| 159 | DEF_MOD("gpio0", 912, R8A77995_CLK_S3D4), | ||
| 160 | DEF_MOD("can-fd", 914, R8A77995_CLK_S3D2), | ||
| 161 | DEF_MOD("can-if1", 915, R8A77995_CLK_S3D4), | ||
| 162 | DEF_MOD("can-if0", 916, R8A77995_CLK_S3D4), | ||
| 163 | DEF_MOD("i2c3", 928, R8A77995_CLK_S3D2), | ||
| 164 | DEF_MOD("i2c2", 929, R8A77995_CLK_S3D2), | ||
| 165 | DEF_MOD("i2c1", 930, R8A77995_CLK_S3D2), | ||
| 166 | DEF_MOD("i2c0", 931, R8A77995_CLK_S3D2), | ||
| 167 | DEF_MOD("ssi-all", 1005, R8A77995_CLK_S3D4), | ||
| 168 | DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), | ||
| 169 | DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), | ||
| 170 | DEF_MOD("scu-all", 1017, R8A77995_CLK_S3D4), | ||
| 171 | DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), | ||
| 172 | DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), | ||
| 173 | DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), | ||
| 174 | DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), | ||
| 175 | DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), | ||
| 176 | DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), | ||
| 177 | }; | ||
| 178 | |||
| 179 | static const unsigned int r8a77995_crit_mod_clks[] __initconst = { | ||
| 180 | MOD_CLK_ID(408), /* INTC-AP (GIC) */ | ||
| 181 | }; | ||
| 182 | |||
| 183 | |||
| 184 | /* | ||
| 185 | * CPG Clock Data | ||
| 186 | */ | ||
| 187 | |||
| 188 | /* | ||
| 189 | * MD19 EXTAL (MHz) PLL0 PLL1 PLL3 | ||
| 190 | *-------------------------------------------------------------------- | ||
| 191 | * 0 48 x 1 x250/4 x100/3 x100/3 | ||
| 192 | * 1 48 x 1 x250/4 x100/3 x116/6 | ||
| 193 | */ | ||
| 194 | #define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19) | ||
| 195 | |||
| 196 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = { | ||
| 197 | /* EXTAL div PLL1 mult/div PLL3 mult/div */ | ||
| 198 | { 1, 100, 3, 100, 3, }, | ||
| 199 | { 1, 100, 3, 116, 6, }, | ||
| 200 | }; | ||
| 201 | |||
| 202 | static int __init r8a77995_cpg_mssr_init(struct device *dev) | ||
| 203 | { | ||
| 204 | const struct rcar_gen3_cpg_pll_config *cpg_pll_config; | ||
| 205 | u32 cpg_mode; | ||
| 206 | int error; | ||
| 207 | |||
| 208 | error = rcar_rst_read_mode_pins(&cpg_mode); | ||
| 209 | if (error) | ||
| 210 | return error; | ||
| 211 | |||
| 212 | cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; | ||
| 213 | |||
| 214 | return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode); | ||
| 215 | } | ||
| 216 | |||
| 217 | const struct cpg_mssr_info r8a77995_cpg_mssr_info __initconst = { | ||
| 218 | /* Core Clocks */ | ||
| 219 | .core_clks = r8a77995_core_clks, | ||
| 220 | .num_core_clks = ARRAY_SIZE(r8a77995_core_clks), | ||
| 221 | .last_dt_core_clk = LAST_DT_CORE_CLK, | ||
| 222 | .num_total_core_clks = MOD_CLK_BASE, | ||
| 223 | |||
| 224 | /* Module Clocks */ | ||
| 225 | .mod_clks = r8a77995_mod_clks, | ||
| 226 | .num_mod_clks = ARRAY_SIZE(r8a77995_mod_clks), | ||
| 227 | .num_hw_mod_clks = 12 * 32, | ||
| 228 | |||
| 229 | /* Critical Module Clocks */ | ||
| 230 | .crit_mod_clks = r8a77995_crit_mod_clks, | ||
| 231 | .num_crit_mod_clks = ARRAY_SIZE(r8a77995_crit_mod_clks), | ||
| 232 | |||
| 233 | /* Callbacks */ | ||
| 234 | .init = r8a77995_cpg_mssr_init, | ||
| 235 | .cpg_clk_register = rcar_gen3_cpg_clk_register, | ||
| 236 | }; | ||
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 3dee900522b7..951105816547 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c | |||
| @@ -60,6 +60,7 @@ struct sd_clock { | |||
| 60 | unsigned int div_num; | 60 | unsigned int div_num; |
| 61 | unsigned int div_min; | 61 | unsigned int div_min; |
| 62 | unsigned int div_max; | 62 | unsigned int div_max; |
| 63 | unsigned int cur_div_idx; | ||
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | /* SDn divider | 66 | /* SDn divider |
| @@ -96,21 +97,10 @@ static const struct sd_div_table cpg_sd_div_table[] = { | |||
| 96 | static int cpg_sd_clock_enable(struct clk_hw *hw) | 97 | static int cpg_sd_clock_enable(struct clk_hw *hw) |
| 97 | { | 98 | { |
| 98 | struct sd_clock *clock = to_sd_clock(hw); | 99 | struct sd_clock *clock = to_sd_clock(hw); |
| 99 | u32 val, sd_fc; | 100 | u32 val = readl(clock->reg); |
| 100 | unsigned int i; | ||
| 101 | |||
| 102 | val = readl(clock->reg); | ||
| 103 | |||
| 104 | sd_fc = val & CPG_SD_FC_MASK; | ||
| 105 | for (i = 0; i < clock->div_num; i++) | ||
| 106 | if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | ||
| 107 | break; | ||
| 108 | |||
| 109 | if (i >= clock->div_num) | ||
| 110 | return -EINVAL; | ||
| 111 | 101 | ||
| 112 | val &= ~(CPG_SD_STP_MASK); | 102 | val &= ~(CPG_SD_STP_MASK); |
| 113 | val |= clock->div_table[i].val & CPG_SD_STP_MASK; | 103 | val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK; |
| 114 | 104 | ||
| 115 | writel(val, clock->reg); | 105 | writel(val, clock->reg); |
| 116 | 106 | ||
| @@ -135,21 +125,9 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, | |||
| 135 | unsigned long parent_rate) | 125 | unsigned long parent_rate) |
| 136 | { | 126 | { |
| 137 | struct sd_clock *clock = to_sd_clock(hw); | 127 | struct sd_clock *clock = to_sd_clock(hw); |
| 138 | unsigned long rate = parent_rate; | ||
| 139 | u32 val, sd_fc; | ||
| 140 | unsigned int i; | ||
| 141 | 128 | ||
| 142 | val = readl(clock->reg); | 129 | return DIV_ROUND_CLOSEST(parent_rate, |
| 143 | 130 | clock->div_table[clock->cur_div_idx].div); | |
| 144 | sd_fc = val & CPG_SD_FC_MASK; | ||
| 145 | for (i = 0; i < clock->div_num; i++) | ||
| 146 | if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | ||
| 147 | break; | ||
| 148 | |||
| 149 | if (i >= clock->div_num) | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); | ||
| 153 | } | 131 | } |
| 154 | 132 | ||
| 155 | static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, | 133 | static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, |
| @@ -190,6 +168,8 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 190 | if (i >= clock->div_num) | 168 | if (i >= clock->div_num) |
| 191 | return -EINVAL; | 169 | return -EINVAL; |
| 192 | 170 | ||
| 171 | clock->cur_div_idx = i; | ||
| 172 | |||
| 193 | val = readl(clock->reg); | 173 | val = readl(clock->reg); |
| 194 | val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); | 174 | val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); |
| 195 | val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); | 175 | val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); |
| @@ -215,6 +195,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, | |||
| 215 | struct sd_clock *clock; | 195 | struct sd_clock *clock; |
| 216 | struct clk *clk; | 196 | struct clk *clk; |
| 217 | unsigned int i; | 197 | unsigned int i; |
| 198 | u32 sd_fc; | ||
| 218 | 199 | ||
| 219 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); | 200 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); |
| 220 | if (!clock) | 201 | if (!clock) |
| @@ -231,6 +212,18 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, | |||
| 231 | clock->div_table = cpg_sd_div_table; | 212 | clock->div_table = cpg_sd_div_table; |
| 232 | clock->div_num = ARRAY_SIZE(cpg_sd_div_table); | 213 | clock->div_num = ARRAY_SIZE(cpg_sd_div_table); |
| 233 | 214 | ||
| 215 | sd_fc = readl(clock->reg) & CPG_SD_FC_MASK; | ||
| 216 | for (i = 0; i < clock->div_num; i++) | ||
| 217 | if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | ||
| 218 | break; | ||
| 219 | |||
| 220 | if (WARN_ON(i >= clock->div_num)) { | ||
| 221 | kfree(clock); | ||
| 222 | return ERR_PTR(-EINVAL); | ||
| 223 | } | ||
| 224 | |||
| 225 | clock->cur_div_idx = i; | ||
| 226 | |||
| 234 | clock->div_max = clock->div_table[0].div; | 227 | clock->div_max = clock->div_table[0].div; |
| 235 | clock->div_min = clock->div_max; | 228 | clock->div_min = clock->div_max; |
| 236 | for (i = 1; i < clock->div_num; i++) { | 229 | for (i = 1; i < clock->div_num; i++) { |
| @@ -279,7 +272,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, | |||
| 279 | unsigned int div = 1; | 272 | unsigned int div = 1; |
| 280 | u32 value; | 273 | u32 value; |
| 281 | 274 | ||
| 282 | parent = clks[core->parent]; | 275 | parent = clks[core->parent & 0xffff]; /* CLK_TYPE_PE uses high bits */ |
| 283 | if (IS_ERR(parent)) | 276 | if (IS_ERR(parent)) |
| 284 | return ERR_CAST(parent); | 277 | return ERR_CAST(parent); |
| 285 | 278 | ||
| @@ -303,6 +296,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, | |||
| 303 | 296 | ||
| 304 | case CLK_TYPE_GEN3_PLL1: | 297 | case CLK_TYPE_GEN3_PLL1: |
| 305 | mult = cpg_pll_config->pll1_mult; | 298 | mult = cpg_pll_config->pll1_mult; |
| 299 | div = cpg_pll_config->pll1_div; | ||
| 306 | break; | 300 | break; |
| 307 | 301 | ||
| 308 | case CLK_TYPE_GEN3_PLL2: | 302 | case CLK_TYPE_GEN3_PLL2: |
| @@ -320,6 +314,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, | |||
| 320 | 314 | ||
| 321 | case CLK_TYPE_GEN3_PLL3: | 315 | case CLK_TYPE_GEN3_PLL3: |
| 322 | mult = cpg_pll_config->pll3_mult; | 316 | mult = cpg_pll_config->pll3_mult; |
| 317 | div = cpg_pll_config->pll3_div; | ||
| 323 | break; | 318 | break; |
| 324 | 319 | ||
| 325 | case CLK_TYPE_GEN3_PLL4: | 320 | case CLK_TYPE_GEN3_PLL4: |
| @@ -360,6 +355,24 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, | |||
| 360 | parent = clks[cpg_clk_extalr]; | 355 | parent = clks[cpg_clk_extalr]; |
| 361 | break; | 356 | break; |
| 362 | 357 | ||
| 358 | case CLK_TYPE_GEN3_PE: | ||
| 359 | /* | ||
| 360 | * Peripheral clock with a fixed divider, selectable between | ||
| 361 | * clean and spread spectrum parents using MD12 | ||
| 362 | */ | ||
| 363 | if (cpg_mode & BIT(12)) { | ||
| 364 | /* Clean */ | ||
| 365 | div = core->div & 0xffff; | ||
| 366 | } else { | ||
| 367 | /* SCCG */ | ||
| 368 | parent = clks[core->parent >> 16]; | ||
| 369 | if (IS_ERR(parent)) | ||
| 370 | return ERR_CAST(parent); | ||
| 371 | div = core->div >> 16; | ||
| 372 | } | ||
| 373 | mult = 1; | ||
| 374 | break; | ||
| 375 | |||
| 363 | default: | 376 | default: |
| 364 | return ERR_PTR(-EINVAL); | 377 | return ERR_PTR(-EINVAL); |
| 365 | } | 378 | } |
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index 073be54b5d03..d756ef8b78eb 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h | |||
| @@ -20,15 +20,24 @@ enum rcar_gen3_clk_types { | |||
| 20 | CLK_TYPE_GEN3_PLL4, | 20 | CLK_TYPE_GEN3_PLL4, |
| 21 | CLK_TYPE_GEN3_SD, | 21 | CLK_TYPE_GEN3_SD, |
| 22 | CLK_TYPE_GEN3_R, | 22 | CLK_TYPE_GEN3_R, |
| 23 | CLK_TYPE_GEN3_PE, | ||
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ | 26 | #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ |
| 26 | DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) | 27 | DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) |
| 27 | 28 | ||
| 29 | #define DEF_GEN3_PE(_name, _id, _parent_sscg, _div_sscg, _parent_clean, \ | ||
| 30 | _div_clean) \ | ||
| 31 | DEF_BASE(_name, _id, CLK_TYPE_GEN3_PE, \ | ||
| 32 | (_parent_sscg) << 16 | (_parent_clean), \ | ||
| 33 | .div = (_div_sscg) << 16 | (_div_clean)) | ||
| 34 | |||
| 28 | struct rcar_gen3_cpg_pll_config { | 35 | struct rcar_gen3_cpg_pll_config { |
| 29 | unsigned int extal_div; | 36 | u8 extal_div; |
| 30 | unsigned int pll1_mult; | 37 | u8 pll1_mult; |
| 31 | unsigned int pll3_mult; | 38 | u8 pll1_div; |
| 39 | u8 pll3_mult; | ||
| 40 | u8 pll3_div; | ||
| 32 | }; | 41 | }; |
| 33 | 42 | ||
| 34 | #define CPG_RCKCR 0x240 | 43 | #define CPG_RCKCR 0x240 |
diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c new file mode 100644 index 000000000000..6cd030a58964 --- /dev/null +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car USB2.0 clock selector | ||
| 3 | * | ||
| 4 | * Copyright (C) 2017 Renesas Electronics Corp. | ||
| 5 | * | ||
| 6 | * Based on renesas-cpg-mssr.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 2015 Glider bvba | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; version 2 of the License. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/clk-provider.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/pm.h> | ||
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | |||
| 26 | #define USB20_CLKSET0 0x00 | ||
| 27 | #define CLKSET0_INTCLK_EN BIT(11) | ||
| 28 | #define CLKSET0_PRIVATE BIT(0) | ||
| 29 | #define CLKSET0_EXTAL_ONLY (CLKSET0_INTCLK_EN | CLKSET0_PRIVATE) | ||
| 30 | |||
| 31 | struct usb2_clock_sel_priv { | ||
| 32 | void __iomem *base; | ||
| 33 | struct clk_hw hw; | ||
| 34 | bool extal; | ||
| 35 | bool xtal; | ||
| 36 | }; | ||
| 37 | #define to_priv(_hw) container_of(_hw, struct usb2_clock_sel_priv, hw) | ||
| 38 | |||
| 39 | static void usb2_clock_sel_enable_extal_only(struct usb2_clock_sel_priv *priv) | ||
| 40 | { | ||
| 41 | u16 val = readw(priv->base + USB20_CLKSET0); | ||
| 42 | |||
| 43 | pr_debug("%s: enter %d %d %x\n", __func__, | ||
| 44 | priv->extal, priv->xtal, val); | ||
| 45 | |||
| 46 | if (priv->extal && !priv->xtal && val != CLKSET0_EXTAL_ONLY) | ||
| 47 | writew(CLKSET0_EXTAL_ONLY, priv->base + USB20_CLKSET0); | ||
| 48 | } | ||
| 49 | |||
| 50 | static void usb2_clock_sel_disable_extal_only(struct usb2_clock_sel_priv *priv) | ||
| 51 | { | ||
| 52 | if (priv->extal && !priv->xtal) | ||
| 53 | writew(CLKSET0_PRIVATE, priv->base + USB20_CLKSET0); | ||
| 54 | } | ||
| 55 | |||
| 56 | static int usb2_clock_sel_enable(struct clk_hw *hw) | ||
| 57 | { | ||
| 58 | usb2_clock_sel_enable_extal_only(to_priv(hw)); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void usb2_clock_sel_disable(struct clk_hw *hw) | ||
| 64 | { | ||
| 65 | usb2_clock_sel_disable_extal_only(to_priv(hw)); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * This module seems a mux, but this driver assumes a gate because | ||
| 70 | * ehci/ohci platform drivers don't support clk_set_parent() for now. | ||
| 71 | * If this driver acts as a gate, ehci/ohci-platform drivers don't need | ||
| 72 | * any modification. | ||
| 73 | */ | ||
| 74 | static const struct clk_ops usb2_clock_sel_clock_ops = { | ||
| 75 | .enable = usb2_clock_sel_enable, | ||
| 76 | .disable = usb2_clock_sel_disable, | ||
| 77 | }; | ||
| 78 | |||
| 79 | static const struct of_device_id rcar_usb2_clock_sel_match[] = { | ||
| 80 | { .compatible = "renesas,rcar-gen3-usb2-clock-sel" }, | ||
| 81 | { } | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int rcar_usb2_clock_sel_suspend(struct device *dev) | ||
| 85 | { | ||
| 86 | struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev); | ||
| 87 | |||
| 88 | usb2_clock_sel_disable_extal_only(priv); | ||
| 89 | pm_runtime_put(dev); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int rcar_usb2_clock_sel_resume(struct device *dev) | ||
| 95 | { | ||
| 96 | struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev); | ||
| 97 | |||
| 98 | pm_runtime_get_sync(dev); | ||
| 99 | usb2_clock_sel_enable_extal_only(priv); | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) | ||
| 105 | { | ||
| 106 | struct device *dev = &pdev->dev; | ||
| 107 | struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev); | ||
| 108 | |||
| 109 | of_clk_del_provider(dev->of_node); | ||
| 110 | clk_hw_unregister(&priv->hw); | ||
| 111 | pm_runtime_put(dev); | ||
| 112 | pm_runtime_disable(dev); | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) | ||
| 118 | { | ||
| 119 | struct device *dev = &pdev->dev; | ||
| 120 | struct device_node *np = dev->of_node; | ||
| 121 | struct usb2_clock_sel_priv *priv; | ||
| 122 | struct resource *res; | ||
| 123 | struct clk *clk; | ||
| 124 | struct clk_init_data init; | ||
| 125 | |||
| 126 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 127 | if (!priv) | ||
| 128 | return -ENOMEM; | ||
| 129 | |||
| 130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 131 | priv->base = devm_ioremap_resource(dev, res); | ||
| 132 | if (IS_ERR(priv->base)) | ||
| 133 | return PTR_ERR(priv->base); | ||
| 134 | |||
| 135 | pm_runtime_enable(dev); | ||
| 136 | pm_runtime_get_sync(dev); | ||
| 137 | |||
| 138 | clk = devm_clk_get(dev, "usb_extal"); | ||
| 139 | if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { | ||
| 140 | priv->extal = !!clk_get_rate(clk); | ||
| 141 | clk_disable_unprepare(clk); | ||
| 142 | } | ||
| 143 | clk = devm_clk_get(dev, "usb_xtal"); | ||
| 144 | if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { | ||
| 145 | priv->xtal = !!clk_get_rate(clk); | ||
| 146 | clk_disable_unprepare(clk); | ||
| 147 | } | ||
| 148 | |||
| 149 | if (!priv->extal && !priv->xtal) { | ||
| 150 | dev_err(dev, "This driver needs usb_extal or usb_xtal\n"); | ||
| 151 | return -ENOENT; | ||
| 152 | } | ||
| 153 | |||
| 154 | platform_set_drvdata(pdev, priv); | ||
| 155 | dev_set_drvdata(dev, priv); | ||
| 156 | |||
| 157 | init.name = "rcar_usb2_clock_sel"; | ||
| 158 | init.ops = &usb2_clock_sel_clock_ops; | ||
| 159 | init.flags = 0; | ||
| 160 | init.parent_names = NULL; | ||
| 161 | init.num_parents = 0; | ||
| 162 | priv->hw.init = &init; | ||
| 163 | |||
| 164 | clk = clk_register(NULL, &priv->hw); | ||
| 165 | if (IS_ERR(clk)) | ||
| 166 | return PTR_ERR(clk); | ||
| 167 | |||
| 168 | return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); | ||
| 169 | } | ||
| 170 | |||
| 171 | static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = { | ||
| 172 | .suspend = rcar_usb2_clock_sel_suspend, | ||
| 173 | .resume = rcar_usb2_clock_sel_resume, | ||
| 174 | }; | ||
| 175 | |||
| 176 | static struct platform_driver rcar_usb2_clock_sel_driver = { | ||
| 177 | .driver = { | ||
| 178 | .name = "rcar-usb2-clock-sel", | ||
| 179 | .of_match_table = rcar_usb2_clock_sel_match, | ||
| 180 | .pm = &rcar_usb2_clock_sel_pm_ops, | ||
| 181 | }, | ||
| 182 | .probe = rcar_usb2_clock_sel_probe, | ||
| 183 | .remove = rcar_usb2_clock_sel_remove, | ||
| 184 | }; | ||
| 185 | builtin_platform_driver(rcar_usb2_clock_sel_driver); | ||
| 186 | |||
| 187 | MODULE_DESCRIPTION("Renesas R-Car USB2 clock selector Driver"); | ||
| 188 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1f607c806f9b..e580a5e6346c 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c | |||
| @@ -680,6 +680,12 @@ static const struct of_device_id cpg_mssr_match[] = { | |||
| 680 | .data = &r8a7796_cpg_mssr_info, | 680 | .data = &r8a7796_cpg_mssr_info, |
| 681 | }, | 681 | }, |
| 682 | #endif | 682 | #endif |
| 683 | #ifdef CONFIG_CLK_R8A77995 | ||
| 684 | { | ||
| 685 | .compatible = "renesas,r8a77995-cpg-mssr", | ||
| 686 | .data = &r8a77995_cpg_mssr_info, | ||
| 687 | }, | ||
| 688 | #endif | ||
| 683 | { /* sentinel */ } | 689 | { /* sentinel */ } |
| 684 | }; | 690 | }; |
| 685 | 691 | ||
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 43d7c7f6832d..94b9071d1061 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h | |||
| @@ -138,6 +138,7 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; | |||
| 138 | extern const struct cpg_mssr_info r8a7794_cpg_mssr_info; | 138 | extern const struct cpg_mssr_info r8a7794_cpg_mssr_info; |
| 139 | extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; | 139 | extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; |
| 140 | extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; | 140 | extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; |
| 141 | extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; | ||
| 141 | 142 | ||
| 142 | 143 | ||
| 143 | /* | 144 | /* |
diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c index e243f2eae68f..62d7854e4b87 100644 --- a/drivers/clk/rockchip/clk-rk3128.c +++ b/drivers/clk/rockchip/clk-rk3128.c | |||
| @@ -201,7 +201,7 @@ static struct rockchip_clk_branch rk3128_uart2_fracmux __initdata = | |||
| 201 | MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, | 201 | MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, |
| 202 | RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); | 202 | RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); |
| 203 | 203 | ||
| 204 | static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | 204 | static struct rockchip_clk_branch common_clk_branches[] __initdata = { |
| 205 | /* | 205 | /* |
| 206 | * Clock-Architecture Diagram 1 | 206 | * Clock-Architecture Diagram 1 |
| 207 | */ | 207 | */ |
| @@ -459,10 +459,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |||
| 459 | RK2928_CLKSEL_CON(2), 14, 2, MFLAGS, 8, 5, DFLAGS, | 459 | RK2928_CLKSEL_CON(2), 14, 2, MFLAGS, 8, 5, DFLAGS, |
| 460 | RK2928_CLKGATE_CON(10), 15, GFLAGS), | 460 | RK2928_CLKGATE_CON(10), 15, GFLAGS), |
| 461 | 461 | ||
| 462 | COMPOSITE(SCLK_SFC, "sclk_sfc", mux_sclk_sfc_src_p, 0, | ||
| 463 | RK2928_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 464 | RK2928_CLKGATE_CON(3), 15, GFLAGS), | ||
| 465 | |||
| 466 | COMPOSITE_NOMUX(PCLK_PMU_PRE, "pclk_pmu_pre", "cpll", 0, | 462 | COMPOSITE_NOMUX(PCLK_PMU_PRE, "pclk_pmu_pre", "cpll", 0, |
| 467 | RK2928_CLKSEL_CON(29), 8, 6, DFLAGS, | 463 | RK2928_CLKSEL_CON(29), 8, 6, DFLAGS, |
| 468 | RK2928_CLKGATE_CON(1), 0, GFLAGS), | 464 | RK2928_CLKGATE_CON(1), 0, GFLAGS), |
| @@ -495,7 +491,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |||
| 495 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), | 491 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), |
| 496 | GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS), | 492 | GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS), |
| 497 | GATE(0, "aclk_cpu_to_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), | 493 | GATE(0, "aclk_cpu_to_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), |
| 498 | GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), | ||
| 499 | 494 | ||
| 500 | GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), | 495 | GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), |
| 501 | GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), | 496 | GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), |
| @@ -541,7 +536,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |||
| 541 | GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS), | 536 | GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS), |
| 542 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), | 537 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), |
| 543 | 538 | ||
| 544 | GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), | ||
| 545 | GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS), | 539 | GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS), |
| 546 | GATE(0, "pclk_ddrupctl", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 7, GFLAGS), | 540 | GATE(0, "pclk_ddrupctl", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 7, GFLAGS), |
| 547 | GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), | 541 | GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), |
| @@ -561,6 +555,21 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |||
| 561 | MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), | 555 | MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), |
| 562 | }; | 556 | }; |
| 563 | 557 | ||
| 558 | static struct rockchip_clk_branch rk3126_clk_branches[] __initdata = { | ||
| 559 | GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS), | ||
| 560 | GATE(0, "pclk_s_efuse", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), | ||
| 561 | GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 8, GFLAGS), | ||
| 562 | }; | ||
| 563 | |||
| 564 | static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | ||
| 565 | COMPOSITE(SCLK_SFC, "sclk_sfc", mux_sclk_sfc_src_p, 0, | ||
| 566 | RK2928_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 567 | RK2928_CLKGATE_CON(3), 15, GFLAGS), | ||
| 568 | |||
| 569 | GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), | ||
| 570 | GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), | ||
| 571 | }; | ||
| 572 | |||
| 564 | static const char *const rk3128_critical_clocks[] __initconst = { | 573 | static const char *const rk3128_critical_clocks[] __initconst = { |
| 565 | "aclk_cpu", | 574 | "aclk_cpu", |
| 566 | "hclk_cpu", | 575 | "hclk_cpu", |
| @@ -570,7 +579,7 @@ static const char *const rk3128_critical_clocks[] __initconst = { | |||
| 570 | "pclk_peri", | 579 | "pclk_peri", |
| 571 | }; | 580 | }; |
| 572 | 581 | ||
| 573 | static void __init rk3128_clk_init(struct device_node *np) | 582 | static struct rockchip_clk_provider *__init rk3128_common_clk_init(struct device_node *np) |
| 574 | { | 583 | { |
| 575 | struct rockchip_clk_provider *ctx; | 584 | struct rockchip_clk_provider *ctx; |
| 576 | void __iomem *reg_base; | 585 | void __iomem *reg_base; |
| @@ -578,23 +587,21 @@ static void __init rk3128_clk_init(struct device_node *np) | |||
| 578 | reg_base = of_iomap(np, 0); | 587 | reg_base = of_iomap(np, 0); |
| 579 | if (!reg_base) { | 588 | if (!reg_base) { |
| 580 | pr_err("%s: could not map cru region\n", __func__); | 589 | pr_err("%s: could not map cru region\n", __func__); |
| 581 | return; | 590 | return ERR_PTR(-ENOMEM); |
| 582 | } | 591 | } |
| 583 | 592 | ||
| 584 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 593 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
| 585 | if (IS_ERR(ctx)) { | 594 | if (IS_ERR(ctx)) { |
| 586 | pr_err("%s: rockchip clk init failed\n", __func__); | 595 | pr_err("%s: rockchip clk init failed\n", __func__); |
| 587 | iounmap(reg_base); | 596 | iounmap(reg_base); |
| 588 | return; | 597 | return ERR_PTR(-ENOMEM); |
| 589 | } | 598 | } |
| 590 | 599 | ||
| 591 | rockchip_clk_register_plls(ctx, rk3128_pll_clks, | 600 | rockchip_clk_register_plls(ctx, rk3128_pll_clks, |
| 592 | ARRAY_SIZE(rk3128_pll_clks), | 601 | ARRAY_SIZE(rk3128_pll_clks), |
| 593 | RK3128_GRF_SOC_STATUS0); | 602 | RK3128_GRF_SOC_STATUS0); |
| 594 | rockchip_clk_register_branches(ctx, rk3128_clk_branches, | 603 | rockchip_clk_register_branches(ctx, common_clk_branches, |
| 595 | ARRAY_SIZE(rk3128_clk_branches)); | 604 | ARRAY_SIZE(common_clk_branches)); |
| 596 | rockchip_clk_protect_critical(rk3128_critical_clocks, | ||
| 597 | ARRAY_SIZE(rk3128_critical_clocks)); | ||
| 598 | 605 | ||
| 599 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", | 606 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
| 600 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 607 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
| @@ -606,6 +613,40 @@ static void __init rk3128_clk_init(struct device_node *np) | |||
| 606 | 613 | ||
| 607 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); | 614 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
| 608 | 615 | ||
| 616 | return ctx; | ||
| 617 | } | ||
| 618 | |||
| 619 | static void __init rk3126_clk_init(struct device_node *np) | ||
| 620 | { | ||
| 621 | struct rockchip_clk_provider *ctx; | ||
| 622 | |||
| 623 | ctx = rk3128_common_clk_init(np); | ||
| 624 | if (IS_ERR(ctx)) | ||
| 625 | return; | ||
| 626 | |||
| 627 | rockchip_clk_register_branches(ctx, rk3126_clk_branches, | ||
| 628 | ARRAY_SIZE(rk3126_clk_branches)); | ||
| 629 | rockchip_clk_protect_critical(rk3128_critical_clocks, | ||
| 630 | ARRAY_SIZE(rk3128_critical_clocks)); | ||
| 631 | |||
| 632 | rockchip_clk_of_add_provider(np, ctx); | ||
| 633 | } | ||
| 634 | |||
| 635 | CLK_OF_DECLARE(rk3126_cru, "rockchip,rk3126-cru", rk3126_clk_init); | ||
| 636 | |||
| 637 | static void __init rk3128_clk_init(struct device_node *np) | ||
| 638 | { | ||
| 639 | struct rockchip_clk_provider *ctx; | ||
| 640 | |||
| 641 | ctx = rk3128_common_clk_init(np); | ||
| 642 | if (IS_ERR(ctx)) | ||
| 643 | return; | ||
| 644 | |||
| 645 | rockchip_clk_register_branches(ctx, rk3128_clk_branches, | ||
| 646 | ARRAY_SIZE(rk3128_clk_branches)); | ||
| 647 | rockchip_clk_protect_critical(rk3128_critical_clocks, | ||
| 648 | ARRAY_SIZE(rk3128_critical_clocks)); | ||
| 649 | |||
| 609 | rockchip_clk_of_add_provider(np, ctx); | 650 | rockchip_clk_of_add_provider(np, ctx); |
| 610 | } | 651 | } |
| 611 | 652 | ||
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index bb405d9044a3..11e7f2d1c054 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c | |||
| @@ -391,7 +391,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { | |||
| 391 | RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS, | 391 | RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS, |
| 392 | RK2928_CLKGATE_CON(2), 11, GFLAGS), | 392 | RK2928_CLKGATE_CON(2), 11, GFLAGS), |
| 393 | 393 | ||
| 394 | COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, | 394 | COMPOSITE_NODIV(SCLK_SDIO_SRC, "sclk_sdio_src", mux_mmc_src_p, 0, |
| 395 | RK2928_CLKSEL_CON(11), 10, 2, MFLAGS, | 395 | RK2928_CLKSEL_CON(11), 10, 2, MFLAGS, |
| 396 | RK2928_CLKGATE_CON(2), 13, GFLAGS), | 396 | RK2928_CLKGATE_CON(2), 13, GFLAGS), |
| 397 | DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, | 397 | DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, |
diff --git a/drivers/clk/rockchip/clk-rv1108.c b/drivers/clk/rockchip/clk-rv1108.c index 7c05ab366348..089cb17925e5 100644 --- a/drivers/clk/rockchip/clk-rv1108.c +++ b/drivers/clk/rockchip/clk-rv1108.c | |||
| @@ -93,9 +93,24 @@ static struct rockchip_pll_rate_table rv1108_pll_rates[] = { | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = { | 95 | static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = { |
| 96 | RV1108_CPUCLK_RATE(816000000, 4), | 96 | RV1108_CPUCLK_RATE(1608000000, 7), |
| 97 | RV1108_CPUCLK_RATE(600000000, 4), | 97 | RV1108_CPUCLK_RATE(1512000000, 7), |
| 98 | RV1108_CPUCLK_RATE(312000000, 4), | 98 | RV1108_CPUCLK_RATE(1488000000, 5), |
| 99 | RV1108_CPUCLK_RATE(1416000000, 5), | ||
| 100 | RV1108_CPUCLK_RATE(1392000000, 5), | ||
| 101 | RV1108_CPUCLK_RATE(1296000000, 5), | ||
| 102 | RV1108_CPUCLK_RATE(1200000000, 5), | ||
| 103 | RV1108_CPUCLK_RATE(1104000000, 5), | ||
| 104 | RV1108_CPUCLK_RATE(1008000000, 5), | ||
| 105 | RV1108_CPUCLK_RATE(912000000, 5), | ||
| 106 | RV1108_CPUCLK_RATE(816000000, 3), | ||
| 107 | RV1108_CPUCLK_RATE(696000000, 3), | ||
| 108 | RV1108_CPUCLK_RATE(600000000, 3), | ||
| 109 | RV1108_CPUCLK_RATE(500000000, 3), | ||
| 110 | RV1108_CPUCLK_RATE(408000000, 1), | ||
| 111 | RV1108_CPUCLK_RATE(312000000, 1), | ||
| 112 | RV1108_CPUCLK_RATE(216000000, 1), | ||
| 113 | RV1108_CPUCLK_RATE(96000000, 1), | ||
| 99 | }; | 114 | }; |
| 100 | 115 | ||
| 101 | static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { | 116 | static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { |
| @@ -105,7 +120,7 @@ static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { | |||
| 105 | .mux_core_alt = 1, | 120 | .mux_core_alt = 1, |
| 106 | .mux_core_main = 0, | 121 | .mux_core_main = 0, |
| 107 | .mux_core_shift = 8, | 122 | .mux_core_shift = 8, |
| 108 | .mux_core_mask = 0x1, | 123 | .mux_core_mask = 0x3, |
| 109 | }; | 124 | }; |
| 110 | 125 | ||
| 111 | PNAME(mux_pll_p) = { "xin24m", "xin24m"}; | 126 | PNAME(mux_pll_p) = { "xin24m", "xin24m"}; |
| @@ -114,30 +129,42 @@ PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; | |||
| 114 | PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; | 129 | PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; |
| 115 | PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; | 130 | PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; |
| 116 | PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; | 131 | PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; |
| 117 | PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" }; | 132 | PNAME(mux_pll_src_4plls_p) = { "dpll", "gpll", "hdmiphy", "usb480m" }; |
| 118 | PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; | 133 | PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; |
| 119 | PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; | 134 | PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; |
| 120 | PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; | 135 | PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; |
| 121 | PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" }; | 136 | PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_gpll", "aclk_peri_src_dpll" }; |
| 122 | PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; | 137 | PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; |
| 123 | PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; | 138 | PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; |
| 124 | PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; | 139 | PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; |
| 125 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; | 140 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; |
| 126 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; | 141 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; |
| 127 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; | 142 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; |
| 128 | PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" }; | 143 | PNAME(mux_sclk_mac_p) = { "sclk_mac_pre", "ext_gmac" }; |
| 129 | PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; | 144 | PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; |
| 130 | PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; | 145 | PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; |
| 131 | PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; | 146 | PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "dummy", "xin12m" }; |
| 132 | PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; | 147 | PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "dummy", "xin12m" }; |
| 148 | PNAME(mux_wifi_src_p) = { "gpll", "xin24m" }; | ||
| 149 | PNAME(mux_cifout_src_p) = { "hdmiphy", "gpll" }; | ||
| 150 | PNAME(mux_cifout_p) = { "sclk_cifout_src", "xin24m" }; | ||
| 151 | PNAME(mux_sclk_cif0_src_p) = { "pclk_vip", "clk_cif0_chn_out", "pclkin_cvbs2cif" }; | ||
| 152 | PNAME(mux_sclk_cif1_src_p) = { "pclk_vip", "clk_cif1_chn_out", "pclkin_cvbs2cif" }; | ||
| 153 | PNAME(mux_sclk_cif2_src_p) = { "pclk_vip", "clk_cif2_chn_out", "pclkin_cvbs2cif" }; | ||
| 154 | PNAME(mux_sclk_cif3_src_p) = { "pclk_vip", "clk_cif3_chn_out", "pclkin_cvbs2cif" }; | ||
| 155 | PNAME(mux_dsp_src_p) = { "dpll", "gpll", "apll", "usb480m" }; | ||
| 156 | PNAME(mux_dclk_hdmiphy_p) = { "hdmiphy", "xin24m" }; | ||
| 157 | PNAME(mux_dclk_vop_p) = { "dclk_hdmiphy", "dclk_vop_src" }; | ||
| 158 | PNAME(mux_hdmi_cec_src_p) = { "dpll", "gpll", "xin24m" }; | ||
| 159 | PNAME(mux_cvbs_src_p) = { "apll", "io_cvbs_clkin", "hdmiphy", "gpll" }; | ||
| 133 | 160 | ||
| 134 | static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = { | 161 | static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = { |
| 135 | [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0), | 162 | [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0), |
| 136 | RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates), | 163 | RV1108_PLL_CON(3), 8, 0, 0, rv1108_pll_rates), |
| 137 | [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8), | 164 | [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8), |
| 138 | RV1108_PLL_CON(11), 8, 31, 0, NULL), | 165 | RV1108_PLL_CON(11), 8, 1, 0, NULL), |
| 139 | [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16), | 166 | [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16), |
| 140 | RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates), | 167 | RV1108_PLL_CON(19), 8, 2, 0, rv1108_pll_rates), |
| 141 | }; | 168 | }; |
| 142 | 169 | ||
| 143 | #define MFLAGS CLK_MUX_HIWORD_MASK | 170 | #define MFLAGS CLK_MUX_HIWORD_MASK |
| @@ -170,10 +197,10 @@ static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata = | |||
| 170 | RV1108_CLKSEL_CON(7), 12, 2, MFLAGS); | 197 | RV1108_CLKSEL_CON(7), 12, 2, MFLAGS); |
| 171 | 198 | ||
| 172 | static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | 199 | static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { |
| 173 | MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, | 200 | MUX(0, "hdmiphy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, |
| 174 | RV1108_MISC_CON, 13, 2, MFLAGS), | 201 | RV1108_MISC_CON, 13, 1, MFLAGS), |
| 175 | MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, | 202 | MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, |
| 176 | RV1108_MISC_CON, 15, 2, MFLAGS), | 203 | RV1108_MISC_CON, 15, 1, MFLAGS), |
| 177 | /* | 204 | /* |
| 178 | * Clock-Architecture Diagram 2 | 205 | * Clock-Architecture Diagram 2 |
| 179 | */ | 206 | */ |
| @@ -197,50 +224,212 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 197 | RV1108_CLKGATE_CON(11), 1, GFLAGS), | 224 | RV1108_CLKGATE_CON(11), 1, GFLAGS), |
| 198 | 225 | ||
| 199 | /* PD_RKVENC */ | 226 | /* PD_RKVENC */ |
| 227 | COMPOSITE(0, "aclk_rkvenc_pre", mux_pll_src_4plls_p, 0, | ||
| 228 | RV1108_CLKSEL_CON(37), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
| 229 | RV1108_CLKGATE_CON(8), 8, GFLAGS), | ||
| 230 | FACTOR_GATE(0, "hclk_rkvenc_pre", "aclk_rkvenc_pre", 0, 1, 4, | ||
| 231 | RV1108_CLKGATE_CON(8), 10, GFLAGS), | ||
| 232 | COMPOSITE(SCLK_VENC_CORE, "clk_venc_core", mux_pll_src_4plls_p, 0, | ||
| 233 | RV1108_CLKSEL_CON(37), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 234 | RV1108_CLKGATE_CON(8), 9, GFLAGS), | ||
| 235 | GATE(ACLK_RKVENC, "aclk_rkvenc", "aclk_rkvenc_pre", 0, | ||
| 236 | RV1108_CLKGATE_CON(19), 8, GFLAGS), | ||
| 237 | GATE(HCLK_RKVENC, "hclk_rkvenc", "hclk_rkvenc_pre", 0, | ||
| 238 | RV1108_CLKGATE_CON(19), 9, GFLAGS), | ||
| 239 | GATE(0, "aclk_rkvenc_niu", "aclk_rkvenc_pre", CLK_IGNORE_UNUSED, | ||
| 240 | RV1108_CLKGATE_CON(19), 11, GFLAGS), | ||
| 241 | GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc_pre", CLK_IGNORE_UNUSED, | ||
| 242 | RV1108_CLKGATE_CON(19), 10, GFLAGS), | ||
| 200 | 243 | ||
| 201 | /* PD_RKVDEC */ | 244 | /* PD_RKVDEC */ |
| 245 | COMPOSITE(SCLK_HEVC_CORE, "sclk_hevc_core", mux_pll_src_4plls_p, 0, | ||
| 246 | RV1108_CLKSEL_CON(36), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
| 247 | RV1108_CLKGATE_CON(8), 2, GFLAGS), | ||
| 248 | FACTOR_GATE(0, "hclk_rkvdec_pre", "sclk_hevc_core", 0, 1, 4, | ||
| 249 | RV1108_CLKGATE_CON(8), 10, GFLAGS), | ||
| 250 | COMPOSITE(SCLK_HEVC_CABAC, "clk_hevc_cabac", mux_pll_src_4plls_p, 0, | ||
| 251 | RV1108_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 252 | RV1108_CLKGATE_CON(8), 1, GFLAGS), | ||
| 253 | |||
| 254 | COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0, | ||
| 255 | RV1108_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
| 256 | RV1108_CLKGATE_CON(8), 0, GFLAGS), | ||
| 257 | COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0, | ||
| 258 | RV1108_CLKSEL_CON(36), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 259 | RV1108_CLKGATE_CON(8), 3, GFLAGS), | ||
| 260 | GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, | ||
| 261 | RV1108_CLKGATE_CON(19), 0, GFLAGS), | ||
| 262 | GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, | ||
| 263 | RV1108_CLKGATE_CON(19), 1, GFLAGS), | ||
| 264 | GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, | ||
| 265 | RV1108_CLKGATE_CON(19), 2, GFLAGS), | ||
| 266 | GATE(HCLK_VPU, "hclk_vpu", "hclk_rkvdec_pre", 0, | ||
| 267 | RV1108_CLKGATE_CON(19), 3, GFLAGS), | ||
| 268 | GATE(0, "aclk_rkvdec_niu", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, | ||
| 269 | RV1108_CLKGATE_CON(19), 4, GFLAGS), | ||
| 270 | GATE(0, "hclk_rkvdec_niu", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, | ||
| 271 | RV1108_CLKGATE_CON(19), 5, GFLAGS), | ||
| 272 | GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", CLK_IGNORE_UNUSED, | ||
| 273 | RV1108_CLKGATE_CON(19), 6, GFLAGS), | ||
| 202 | 274 | ||
| 203 | /* PD_PMU_wrapper */ | 275 | /* PD_PMU_wrapper */ |
| 204 | COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, | 276 | COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, |
| 205 | RV1108_CLKSEL_CON(38), 0, 5, DFLAGS, | 277 | RV1108_CLKSEL_CON(38), 0, 5, DFLAGS, |
| 206 | RV1108_CLKGATE_CON(8), 12, GFLAGS), | 278 | RV1108_CLKGATE_CON(8), 12, GFLAGS), |
| 207 | GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 279 | GATE(0, "pclk_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, |
| 208 | RV1108_CLKGATE_CON(10), 0, GFLAGS), | 280 | RV1108_CLKGATE_CON(10), 0, GFLAGS), |
| 209 | GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 281 | GATE(0, "pclk_intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, |
| 210 | RV1108_CLKGATE_CON(10), 1, GFLAGS), | 282 | RV1108_CLKGATE_CON(10), 1, GFLAGS), |
| 211 | GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 283 | GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pmu_24m_ena", 0, |
| 212 | RV1108_CLKGATE_CON(10), 2, GFLAGS), | 284 | RV1108_CLKGATE_CON(10), 2, GFLAGS), |
| 213 | GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 285 | GATE(0, "pclk_pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, |
| 214 | RV1108_CLKGATE_CON(10), 3, GFLAGS), | 286 | RV1108_CLKGATE_CON(10), 3, GFLAGS), |
| 215 | GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 287 | GATE(0, "pclk_pmu_niu", "pmu_24m_ena", CLK_IGNORE_UNUSED, |
| 216 | RV1108_CLKGATE_CON(10), 4, GFLAGS), | 288 | RV1108_CLKGATE_CON(10), 4, GFLAGS), |
| 217 | GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 289 | GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pmu_24m_ena", 0, |
| 218 | RV1108_CLKGATE_CON(10), 5, GFLAGS), | 290 | RV1108_CLKGATE_CON(10), 5, GFLAGS), |
| 219 | GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, | 291 | GATE(PCLK_PWM0_PMU, "pclk_pwm0_pmu", "pmu_24m_ena", 0, |
| 220 | RV1108_CLKGATE_CON(10), 6, GFLAGS), | 292 | RV1108_CLKGATE_CON(10), 6, GFLAGS), |
| 221 | COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 293 | COMPOSITE(SCLK_PWM0_PMU, "sclk_pwm0_pmu", mux_pll_src_2plls_p, 0, |
| 222 | RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, | 294 | RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 223 | RV1108_CLKGATE_CON(8), 15, GFLAGS), | 295 | RV1108_CLKGATE_CON(8), 15, GFLAGS), |
| 224 | COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 296 | COMPOSITE(SCLK_I2C0_PMU, "sclk_i2c0_pmu", mux_pll_src_2plls_p, 0, |
| 225 | RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, | 297 | RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 226 | RV1108_CLKGATE_CON(8), 14, GFLAGS), | 298 | RV1108_CLKGATE_CON(8), 14, GFLAGS), |
| 227 | GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, | 299 | GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, |
| 228 | RV1108_CLKGATE_CON(8), 13, GFLAGS), | 300 | RV1108_CLKGATE_CON(8), 13, GFLAGS), |
| 229 | 301 | ||
| 230 | /* | 302 | /* |
| 303 | * Clock-Architecture Diagram 3 | ||
| 304 | */ | ||
| 305 | COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_wifi_src_p, 0, | ||
| 306 | RV1108_CLKSEL_CON(28), 15, 1, MFLAGS, 8, 6, DFLAGS, | ||
| 307 | RV1108_CLKGATE_CON(9), 8, GFLAGS), | ||
| 308 | COMPOSITE_NODIV(0, "sclk_cifout_src", mux_cifout_src_p, 0, | ||
| 309 | RV1108_CLKSEL_CON(40), 8, 1, MFLAGS, | ||
| 310 | RV1108_CLKGATE_CON(9), 11, GFLAGS), | ||
| 311 | COMPOSITE_NOGATE(SCLK_CIFOUT, "sclk_cifout", mux_cifout_p, 0, | ||
| 312 | RV1108_CLKSEL_CON(40), 12, 1, MFLAGS, 0, 5, DFLAGS), | ||
| 313 | COMPOSITE_NOMUX(SCLK_MIPI_CSI_OUT, "sclk_mipi_csi_out", "xin24m", 0, | ||
| 314 | RV1108_CLKSEL_CON(41), 0, 5, DFLAGS, | ||
| 315 | RV1108_CLKGATE_CON(9), 12, GFLAGS), | ||
| 316 | |||
| 317 | GATE(0, "pclk_acodecphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | ||
| 318 | RV1108_CLKGATE_CON(14), 6, GFLAGS), | ||
| 319 | GATE(0, "pclk_usbgrf", "pclk_top_pre", CLK_IGNORE_UNUSED, | ||
| 320 | RV1108_CLKGATE_CON(14), 14, GFLAGS), | ||
| 321 | |||
| 322 | GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio1_pre", 0, | ||
| 323 | RV1108_CLKGATE_CON(18), 10, GFLAGS), | ||
| 324 | GATE(HCLK_CIF0, "hclk_cif0", "hclk_vio_pre", 0, | ||
| 325 | RV1108_CLKGATE_CON(18), 10, GFLAGS), | ||
| 326 | COMPOSITE_NODIV(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_src_p, 0, | ||
| 327 | RV1108_CLKSEL_CON(31), 0, 2, MFLAGS, | ||
| 328 | RV1108_CLKGATE_CON(7), 9, GFLAGS), | ||
| 329 | GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1_pre", 0, | ||
| 330 | RV1108_CLKGATE_CON(17), 6, GFLAGS), | ||
| 331 | GATE(HCLK_CIF1, "hclk_cif1", "hclk_vio_pre", 0, | ||
| 332 | RV1108_CLKGATE_CON(17), 7, GFLAGS), | ||
| 333 | COMPOSITE_NODIV(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_src_p, 0, | ||
| 334 | RV1108_CLKSEL_CON(31), 2, 2, MFLAGS, | ||
| 335 | RV1108_CLKGATE_CON(7), 10, GFLAGS), | ||
| 336 | GATE(ACLK_CIF2, "aclk_cif2", "aclk_vio1_pre", 0, | ||
| 337 | RV1108_CLKGATE_CON(17), 8, GFLAGS), | ||
| 338 | GATE(HCLK_CIF2, "hclk_cif2", "hclk_vio_pre", 0, | ||
| 339 | RV1108_CLKGATE_CON(17), 9, GFLAGS), | ||
| 340 | COMPOSITE_NODIV(SCLK_CIF2, "sclk_cif2", mux_sclk_cif2_src_p, 0, | ||
| 341 | RV1108_CLKSEL_CON(31), 4, 2, MFLAGS, | ||
| 342 | RV1108_CLKGATE_CON(7), 11, GFLAGS), | ||
| 343 | GATE(ACLK_CIF3, "aclk_cif3", "aclk_vio1_pre", 0, | ||
| 344 | RV1108_CLKGATE_CON(17), 10, GFLAGS), | ||
| 345 | GATE(HCLK_CIF3, "hclk_cif3", "hclk_vio_pre", 0, | ||
| 346 | RV1108_CLKGATE_CON(17), 11, GFLAGS), | ||
| 347 | COMPOSITE_NODIV(SCLK_CIF3, "sclk_cif3", mux_sclk_cif3_src_p, 0, | ||
| 348 | RV1108_CLKSEL_CON(31), 6, 2, MFLAGS, | ||
| 349 | RV1108_CLKGATE_CON(7), 12, GFLAGS), | ||
| 350 | GATE(0, "pclk_cif1to4", "pclk_vip", CLK_IGNORE_UNUSED, | ||
| 351 | RV1108_CLKGATE_CON(7), 8, GFLAGS), | ||
| 352 | |||
| 353 | /* PD_DSP_wrapper */ | ||
| 354 | COMPOSITE(SCLK_DSP, "sclk_dsp", mux_dsp_src_p, 0, | ||
| 355 | RV1108_CLKSEL_CON(42), 8, 2, MFLAGS, 0, 5, DFLAGS, | ||
| 356 | RV1108_CLKGATE_CON(9), 0, GFLAGS), | ||
| 357 | GATE(0, "clk_dsp_sys_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 358 | RV1108_CLKGATE_CON(16), 0, GFLAGS), | ||
| 359 | GATE(0, "clk_dsp_epp_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 360 | RV1108_CLKGATE_CON(16), 1, GFLAGS), | ||
| 361 | GATE(0, "clk_dsp_edp_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 362 | RV1108_CLKGATE_CON(16), 2, GFLAGS), | ||
| 363 | GATE(0, "clk_dsp_iop_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 364 | RV1108_CLKGATE_CON(16), 3, GFLAGS), | ||
| 365 | GATE(0, "clk_dsp_free", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 366 | RV1108_CLKGATE_CON(16), 13, GFLAGS), | ||
| 367 | COMPOSITE_NOMUX(SCLK_DSP_IOP, "sclk_dsp_iop", "sclk_dsp", 0, | ||
| 368 | RV1108_CLKSEL_CON(44), 0, 5, DFLAGS, | ||
| 369 | RV1108_CLKGATE_CON(9), 1, GFLAGS), | ||
| 370 | COMPOSITE_NOMUX(SCLK_DSP_EPP, "sclk_dsp_epp", "sclk_dsp", 0, | ||
| 371 | RV1108_CLKSEL_CON(44), 8, 5, DFLAGS, | ||
| 372 | RV1108_CLKGATE_CON(9), 2, GFLAGS), | ||
| 373 | COMPOSITE_NOMUX(SCLK_DSP_EDP, "sclk_dsp_edp", "sclk_dsp", 0, | ||
| 374 | RV1108_CLKSEL_CON(45), 0, 5, DFLAGS, | ||
| 375 | RV1108_CLKGATE_CON(9), 3, GFLAGS), | ||
| 376 | COMPOSITE_NOMUX(SCLK_DSP_EDAP, "sclk_dsp_edap", "sclk_dsp", 0, | ||
| 377 | RV1108_CLKSEL_CON(45), 8, 5, DFLAGS, | ||
| 378 | RV1108_CLKGATE_CON(9), 4, GFLAGS), | ||
| 379 | GATE(0, "pclk_dsp_iop_niu", "sclk_dsp_iop", CLK_IGNORE_UNUSED, | ||
| 380 | RV1108_CLKGATE_CON(16), 4, GFLAGS), | ||
| 381 | GATE(0, "aclk_dsp_epp_niu", "sclk_dsp_epp", CLK_IGNORE_UNUSED, | ||
| 382 | RV1108_CLKGATE_CON(16), 5, GFLAGS), | ||
| 383 | GATE(0, "aclk_dsp_edp_niu", "sclk_dsp_edp", CLK_IGNORE_UNUSED, | ||
| 384 | RV1108_CLKGATE_CON(16), 6, GFLAGS), | ||
| 385 | GATE(0, "pclk_dsp_dbg_niu", "sclk_dsp", CLK_IGNORE_UNUSED, | ||
| 386 | RV1108_CLKGATE_CON(16), 7, GFLAGS), | ||
| 387 | GATE(0, "aclk_dsp_edap_niu", "sclk_dsp_edap", CLK_IGNORE_UNUSED, | ||
| 388 | RV1108_CLKGATE_CON(16), 14, GFLAGS), | ||
| 389 | COMPOSITE_NOMUX(SCLK_DSP_PFM, "sclk_dsp_pfm", "sclk_dsp", 0, | ||
| 390 | RV1108_CLKSEL_CON(43), 0, 5, DFLAGS, | ||
| 391 | RV1108_CLKGATE_CON(9), 5, GFLAGS), | ||
| 392 | COMPOSITE_NOMUX(PCLK_DSP_CFG, "pclk_dsp_cfg", "sclk_dsp", 0, | ||
| 393 | RV1108_CLKSEL_CON(43), 8, 5, DFLAGS, | ||
| 394 | RV1108_CLKGATE_CON(9), 6, GFLAGS), | ||
| 395 | GATE(0, "pclk_dsp_cfg_niu", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | ||
| 396 | RV1108_CLKGATE_CON(16), 8, GFLAGS), | ||
| 397 | GATE(0, "pclk_dsp_pfm_mon", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | ||
| 398 | RV1108_CLKGATE_CON(16), 9, GFLAGS), | ||
| 399 | GATE(0, "pclk_intc", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | ||
| 400 | RV1108_CLKGATE_CON(16), 10, GFLAGS), | ||
| 401 | GATE(0, "pclk_dsp_grf", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | ||
| 402 | RV1108_CLKGATE_CON(16), 11, GFLAGS), | ||
| 403 | GATE(0, "pclk_mailbox", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | ||
| 404 | RV1108_CLKGATE_CON(16), 12, GFLAGS), | ||
| 405 | GATE(0, "aclk_dsp_epp_perf", "sclk_dsp_epp", CLK_IGNORE_UNUSED, | ||
| 406 | RV1108_CLKGATE_CON(16), 15, GFLAGS), | ||
| 407 | GATE(0, "aclk_dsp_edp_perf", "sclk_dsp_edp", CLK_IGNORE_UNUSED, | ||
| 408 | RV1108_CLKGATE_CON(11), 8, GFLAGS), | ||
| 409 | |||
| 410 | /* | ||
| 231 | * Clock-Architecture Diagram 4 | 411 | * Clock-Architecture Diagram 4 |
| 232 | */ | 412 | */ |
| 233 | COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, | 413 | COMPOSITE(0, "aclk_vio0_pre", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, |
| 234 | RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, | 414 | RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, |
| 235 | RV1108_CLKGATE_CON(6), 0, GFLAGS), | 415 | RV1108_CLKGATE_CON(6), 0, GFLAGS), |
| 236 | GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, | 416 | GATE(ACLK_VIO0, "aclk_vio0", "aclk_vio0_pre", 0, |
| 237 | RV1108_CLKGATE_CON(17), 0, GFLAGS), | 417 | RV1108_CLKGATE_CON(17), 0, GFLAGS), |
| 238 | COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, | 418 | COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, |
| 239 | RV1108_CLKSEL_CON(29), 0, 5, DFLAGS, | 419 | RV1108_CLKSEL_CON(29), 0, 5, DFLAGS, |
| 240 | RV1108_CLKGATE_CON(7), 2, GFLAGS), | 420 | RV1108_CLKGATE_CON(7), 2, GFLAGS), |
| 421 | GATE(HCLK_VIO, "hclk_vio", "hclk_vio_pre", 0, | ||
| 422 | RV1108_CLKGATE_CON(17), 2, GFLAGS), | ||
| 241 | COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, | 423 | COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, |
| 242 | RV1108_CLKSEL_CON(29), 8, 5, DFLAGS, | 424 | RV1108_CLKSEL_CON(29), 8, 5, DFLAGS, |
| 243 | RV1108_CLKGATE_CON(7), 3, GFLAGS), | 425 | RV1108_CLKGATE_CON(7), 3, GFLAGS), |
| 426 | GATE(PCLK_VIO, "pclk_vio", "pclk_vio_pre", 0, | ||
| 427 | RV1108_CLKGATE_CON(17), 3, GFLAGS), | ||
| 428 | COMPOSITE(0, "aclk_vio1_pre", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, | ||
| 429 | RV1108_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 430 | RV1108_CLKGATE_CON(6), 1, GFLAGS), | ||
| 431 | GATE(ACLK_VIO1, "aclk_vio1", "aclk_vio1_pre", 0, | ||
| 432 | RV1108_CLKGATE_CON(17), 1, GFLAGS), | ||
| 244 | 433 | ||
| 245 | INVERTER(0, "pclk_vip", "ext_vip", | 434 | INVERTER(0, "pclk_vip", "ext_vip", |
| 246 | RV1108_CLKSEL_CON(31), 8, IFLAGS), | 435 | RV1108_CLKSEL_CON(31), 8, IFLAGS), |
| @@ -252,8 +441,63 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 252 | RV1108_CLKGATE_CON(6), 5, GFLAGS), | 441 | RV1108_CLKGATE_CON(6), 5, GFLAGS), |
| 253 | GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, | 442 | GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, |
| 254 | RV1108_CLKGATE_CON(6), 4, GFLAGS), | 443 | RV1108_CLKGATE_CON(6), 4, GFLAGS), |
| 255 | COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, | 444 | COMPOSITE_NOGATE(0, "dclk_hdmiphy_pre", mux_dclk_hdmiphy_pre_p, 0, |
| 256 | RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), | 445 | RV1108_CLKSEL_CON(32), 6, 1, MFLAGS, 8, 6, DFLAGS), |
| 446 | COMPOSITE_NOGATE(DCLK_VOP_SRC, "dclk_vop_src", mux_dclk_hdmiphy_pre_p, 0, | ||
| 447 | RV1108_CLKSEL_CON(32), 6, 1, MFLAGS, 0, 6, DFLAGS), | ||
| 448 | MUX(DCLK_HDMIPHY, "dclk_hdmiphy", mux_dclk_hdmiphy_p, CLK_SET_RATE_PARENT, | ||
| 449 | RV1108_CLKSEL_CON(32), 15, 1, MFLAGS), | ||
| 450 | MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT, | ||
| 451 | RV1108_CLKSEL_CON(32), 7, 1, MFLAGS), | ||
| 452 | GATE(ACLK_VOP, "aclk_vop", "aclk_vio0_pre", 0, | ||
| 453 | RV1108_CLKGATE_CON(18), 0, GFLAGS), | ||
| 454 | GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, | ||
| 455 | RV1108_CLKGATE_CON(18), 1, GFLAGS), | ||
| 456 | GATE(ACLK_IEP, "aclk_iep", "aclk_vio0_pre", 0, | ||
| 457 | RV1108_CLKGATE_CON(18), 2, GFLAGS), | ||
| 458 | GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, | ||
| 459 | RV1108_CLKGATE_CON(18), 3, GFLAGS), | ||
| 460 | |||
| 461 | GATE(ACLK_RGA, "aclk_rga", "aclk_vio1_pre", 0, | ||
| 462 | RV1108_CLKGATE_CON(18), 4, GFLAGS), | ||
| 463 | GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, | ||
| 464 | RV1108_CLKGATE_CON(18), 5, GFLAGS), | ||
| 465 | COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_4plls_p, 0, | ||
| 466 | RV1108_CLKSEL_CON(33), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
| 467 | RV1108_CLKGATE_CON(6), 6, GFLAGS), | ||
| 468 | |||
| 469 | COMPOSITE(SCLK_CVBS_HOST, "sclk_cvbs_host", mux_cvbs_src_p, 0, | ||
| 470 | RV1108_CLKSEL_CON(33), 13, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 471 | RV1108_CLKGATE_CON(6), 7, GFLAGS), | ||
| 472 | FACTOR(0, "sclk_cvbs_27m", "sclk_cvbs_host", 0, 1, 2), | ||
| 473 | |||
| 474 | GATE(SCLK_HDMI_SFR, "sclk_hdmi_sfr", "xin24m", 0, | ||
| 475 | RV1108_CLKGATE_CON(6), 8, GFLAGS), | ||
| 476 | |||
| 477 | COMPOSITE(SCLK_HDMI_CEC, "sclk_hdmi_cec", mux_hdmi_cec_src_p, 0, | ||
| 478 | RV1108_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 14, DFLAGS, | ||
| 479 | RV1108_CLKGATE_CON(6), 9, GFLAGS), | ||
| 480 | GATE(PCLK_MIPI_DSI, "pclk_mipi_dsi", "pclk_vio_pre", 0, | ||
| 481 | RV1108_CLKGATE_CON(18), 8, GFLAGS), | ||
| 482 | GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_vio_pre", 0, | ||
| 483 | RV1108_CLKGATE_CON(18), 9, GFLAGS), | ||
| 484 | |||
| 485 | GATE(ACLK_ISP, "aclk_isp", "aclk_vio1_pre", 0, | ||
| 486 | RV1108_CLKGATE_CON(18), 12, GFLAGS), | ||
| 487 | GATE(HCLK_ISP, "hclk_isp", "hclk_vio_pre", 0, | ||
| 488 | RV1108_CLKGATE_CON(18), 11, GFLAGS), | ||
| 489 | COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_4plls_p, 0, | ||
| 490 | RV1108_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
| 491 | RV1108_CLKGATE_CON(6), 3, GFLAGS), | ||
| 492 | |||
| 493 | GATE(0, "clk_dsiphy24m", "xin24m", CLK_IGNORE_UNUSED, | ||
| 494 | RV1108_CLKGATE_CON(9), 10, GFLAGS), | ||
| 495 | GATE(0, "pclk_vdacphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | ||
| 496 | RV1108_CLKGATE_CON(14), 9, GFLAGS), | ||
| 497 | GATE(0, "pclk_mipi_dsiphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | ||
| 498 | RV1108_CLKGATE_CON(14), 11, GFLAGS), | ||
| 499 | GATE(0, "pclk_mipi_csiphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | ||
| 500 | RV1108_CLKGATE_CON(14), 12, GFLAGS), | ||
| 257 | 501 | ||
| 258 | /* | 502 | /* |
| 259 | * Clock-Architecture Diagram 5 | 503 | * Clock-Architecture Diagram 5 |
| @@ -261,10 +505,11 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 261 | 505 | ||
| 262 | FACTOR(0, "xin12m", "xin24m", 0, 1, 2), | 506 | FACTOR(0, "xin12m", "xin24m", 0, 1, 2), |
| 263 | 507 | ||
| 264 | COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, | 508 | |
| 509 | COMPOSITE(SCLK_I2S0_SRC, "i2s0_src", mux_pll_src_2plls_p, 0, | ||
| 265 | RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, | 510 | RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 266 | RV1108_CLKGATE_CON(2), 0, GFLAGS), | 511 | RV1108_CLKGATE_CON(2), 0, GFLAGS), |
| 267 | COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, | 512 | COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, |
| 268 | RV1108_CLKSEL_CON(8), 0, | 513 | RV1108_CLKSEL_CON(8), 0, |
| 269 | RV1108_CLKGATE_CON(2), 1, GFLAGS, | 514 | RV1108_CLKGATE_CON(2), 1, GFLAGS, |
| 270 | &rv1108_i2s0_fracmux), | 515 | &rv1108_i2s0_fracmux), |
| @@ -274,7 +519,7 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 274 | RV1108_CLKSEL_CON(5), 15, 1, MFLAGS, | 519 | RV1108_CLKSEL_CON(5), 15, 1, MFLAGS, |
| 275 | RV1108_CLKGATE_CON(2), 3, GFLAGS), | 520 | RV1108_CLKGATE_CON(2), 3, GFLAGS), |
| 276 | 521 | ||
| 277 | COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, | 522 | COMPOSITE(SCLK_I2S1_SRC, "i2s1_src", mux_pll_src_2plls_p, 0, |
| 278 | RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, | 523 | RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 279 | RV1108_CLKGATE_CON(2), 4, GFLAGS), | 524 | RV1108_CLKGATE_CON(2), 4, GFLAGS), |
| 280 | COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, | 525 | COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, |
| @@ -284,7 +529,7 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 284 | GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, | 529 | GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, |
| 285 | RV1108_CLKGATE_CON(2), 6, GFLAGS), | 530 | RV1108_CLKGATE_CON(2), 6, GFLAGS), |
| 286 | 531 | ||
| 287 | COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, | 532 | COMPOSITE(SCLK_I2S2_SRC, "i2s2_src", mux_pll_src_2plls_p, 0, |
| 288 | RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, | 533 | RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 289 | RV1108_CLKGATE_CON(3), 8, GFLAGS), | 534 | RV1108_CLKGATE_CON(3), 8, GFLAGS), |
| 290 | COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, | 535 | COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, |
| @@ -303,32 +548,53 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 303 | RV1108_CLKGATE_CON(1), 2, GFLAGS), | 548 | RV1108_CLKGATE_CON(1), 2, GFLAGS), |
| 304 | COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, | 549 | COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, |
| 305 | RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), | 550 | RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), |
| 306 | COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, | 551 | COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus_pre", "aclk_bus_pre", 0, |
| 307 | RV1108_CLKSEL_CON(3), 0, 5, DFLAGS, | 552 | RV1108_CLKSEL_CON(3), 0, 5, DFLAGS, |
| 308 | RV1108_CLKGATE_CON(1), 4, GFLAGS), | 553 | RV1108_CLKGATE_CON(1), 4, GFLAGS), |
| 309 | COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, | 554 | COMPOSITE_NOMUX(0, "pclk_bus_pre", "aclk_bus_pre", 0, |
| 310 | RV1108_CLKSEL_CON(3), 8, 5, DFLAGS, | 555 | RV1108_CLKSEL_CON(3), 8, 5, DFLAGS, |
| 311 | RV1108_CLKGATE_CON(1), 5, GFLAGS), | 556 | RV1108_CLKGATE_CON(1), 5, GFLAGS), |
| 312 | GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, | 557 | GATE(PCLK_BUS, "pclk_bus", "pclk_bus_pre", 0, |
| 313 | RV1108_CLKGATE_CON(1), 6, GFLAGS), | 558 | RV1108_CLKGATE_CON(1), 6, GFLAGS), |
| 314 | GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, | 559 | GATE(0, "pclk_top_pre", "pclk_bus_pre", CLK_IGNORE_UNUSED, |
| 315 | RV1108_CLKGATE_CON(1), 7, GFLAGS), | 560 | RV1108_CLKGATE_CON(1), 7, GFLAGS), |
| 316 | GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, | 561 | GATE(0, "pclk_ddr_pre", "pclk_bus_pre", CLK_IGNORE_UNUSED, |
| 317 | RV1108_CLKGATE_CON(1), 8, GFLAGS), | 562 | RV1108_CLKGATE_CON(1), 8, GFLAGS), |
| 318 | GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, | 563 | GATE(SCLK_TIMER0, "clk_timer0", "xin24m", 0, |
| 319 | RV1108_CLKGATE_CON(1), 9, GFLAGS), | 564 | RV1108_CLKGATE_CON(1), 9, GFLAGS), |
| 320 | GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, | 565 | GATE(SCLK_TIMER1, "clk_timer1", "xin24m", CLK_IGNORE_UNUSED, |
| 321 | RV1108_CLKGATE_CON(1), 10, GFLAGS), | 566 | RV1108_CLKGATE_CON(1), 10, GFLAGS), |
| 322 | GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 567 | GATE(PCLK_TIMER, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, |
| 323 | RV1108_CLKGATE_CON(13), 4, GFLAGS), | 568 | RV1108_CLKGATE_CON(13), 4, GFLAGS), |
| 324 | 569 | ||
| 325 | COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | 570 | GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_bus_pre", 0, |
| 571 | RV1108_CLKGATE_CON(12), 7, GFLAGS), | ||
| 572 | GATE(HCLK_I2S1_2CH, "hclk_i2s1_2ch", "hclk_bus_pre", 0, | ||
| 573 | RV1108_CLKGATE_CON(12), 8, GFLAGS), | ||
| 574 | GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_bus_pre", 0, | ||
| 575 | RV1108_CLKGATE_CON(12), 9, GFLAGS), | ||
| 576 | |||
| 577 | GATE(HCLK_CRYPTO_MST, "hclk_crypto_mst", "hclk_bus_pre", 0, | ||
| 578 | RV1108_CLKGATE_CON(12), 10, GFLAGS), | ||
| 579 | GATE(HCLK_CRYPTO_SLV, "hclk_crypto_slv", "hclk_bus_pre", 0, | ||
| 580 | RV1108_CLKGATE_CON(12), 11, GFLAGS), | ||
| 581 | COMPOSITE(SCLK_CRYPTO, "sclk_crypto", mux_pll_src_2plls_p, 0, | ||
| 582 | RV1108_CLKSEL_CON(11), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
| 583 | RV1108_CLKGATE_CON(2), 12, GFLAGS), | ||
| 584 | |||
| 585 | COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_2plls_p, 0, | ||
| 586 | RV1108_CLKSEL_CON(11), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
| 587 | RV1108_CLKGATE_CON(3), 0, GFLAGS), | ||
| 588 | GATE(PCLK_SPI, "pclk_spi", "pclk_bus_pre", 0, | ||
| 589 | RV1108_CLKGATE_CON(13), 5, GFLAGS), | ||
| 590 | |||
| 591 | COMPOSITE(SCLK_UART0_SRC, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | ||
| 326 | RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, | 592 | RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 327 | RV1108_CLKGATE_CON(3), 1, GFLAGS), | 593 | RV1108_CLKGATE_CON(3), 1, GFLAGS), |
| 328 | COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | 594 | COMPOSITE(SCLK_UART1_SRC, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, |
| 329 | RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, | 595 | RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 330 | RV1108_CLKGATE_CON(3), 3, GFLAGS), | 596 | RV1108_CLKGATE_CON(3), 3, GFLAGS), |
| 331 | COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | 597 | COMPOSITE(SCLK_UART2_SRC, "uart2_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, |
| 332 | RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, | 598 | RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 333 | RV1108_CLKGATE_CON(3), 5, GFLAGS), | 599 | RV1108_CLKGATE_CON(3), 5, GFLAGS), |
| 334 | 600 | ||
| @@ -344,44 +610,58 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 344 | RV1108_CLKSEL_CON(18), 0, | 610 | RV1108_CLKSEL_CON(18), 0, |
| 345 | RV1108_CLKGATE_CON(3), 6, GFLAGS, | 611 | RV1108_CLKGATE_CON(3), 6, GFLAGS, |
| 346 | &rv1108_uart2_fracmux), | 612 | &rv1108_uart2_fracmux), |
| 347 | GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 613 | GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", 0, |
| 348 | RV1108_CLKGATE_CON(13), 10, GFLAGS), | 614 | RV1108_CLKGATE_CON(13), 10, GFLAGS), |
| 349 | GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 615 | GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", 0, |
| 350 | RV1108_CLKGATE_CON(13), 11, GFLAGS), | 616 | RV1108_CLKGATE_CON(13), 11, GFLAGS), |
| 351 | GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 617 | GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", 0, |
| 352 | RV1108_CLKGATE_CON(13), 12, GFLAGS), | 618 | RV1108_CLKGATE_CON(13), 12, GFLAGS), |
| 353 | 619 | ||
| 354 | COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 620 | COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_2plls_p, 0, |
| 355 | RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, | 621 | RV1108_CLKSEL_CON(19), 15, 1, MFLAGS, 8, 7, DFLAGS, |
| 356 | RV1108_CLKGATE_CON(3), 7, GFLAGS), | 622 | RV1108_CLKGATE_CON(3), 7, GFLAGS), |
| 357 | COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 623 | COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_2plls_p, 0, |
| 358 | RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, | 624 | RV1108_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 359 | RV1108_CLKGATE_CON(3), 8, GFLAGS), | 625 | RV1108_CLKGATE_CON(3), 8, GFLAGS), |
| 360 | COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 626 | COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_2plls_p, 0, |
| 361 | RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, | 627 | RV1108_CLKSEL_CON(20), 15, 1, MFLAGS, 8, 7, DFLAGS, |
| 362 | RV1108_CLKGATE_CON(3), 9, GFLAGS), | 628 | RV1108_CLKGATE_CON(3), 9, GFLAGS), |
| 363 | GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 629 | GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus_pre", 0, |
| 364 | RV1108_CLKGATE_CON(13), 0, GFLAGS), | 630 | RV1108_CLKGATE_CON(13), 0, GFLAGS), |
| 365 | GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 631 | GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus_pre", 0, |
| 366 | RV1108_CLKGATE_CON(13), 1, GFLAGS), | 632 | RV1108_CLKGATE_CON(13), 1, GFLAGS), |
| 367 | GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 633 | GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus_pre", 0, |
| 368 | RV1108_CLKGATE_CON(13), 2, GFLAGS), | 634 | RV1108_CLKGATE_CON(13), 2, GFLAGS), |
| 369 | COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | 635 | COMPOSITE(SCLK_PWM, "clk_pwm", mux_pll_src_2plls_p, 0, |
| 370 | RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, | 636 | RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, |
| 371 | RV1108_CLKGATE_CON(3), 10, GFLAGS), | 637 | RV1108_CLKGATE_CON(3), 10, GFLAGS), |
| 372 | GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 638 | GATE(PCLK_PWM, "pclk_pwm", "pclk_bus_pre", 0, |
| 373 | RV1108_CLKGATE_CON(13), 6, GFLAGS), | 639 | RV1108_CLKGATE_CON(13), 6, GFLAGS), |
| 374 | GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 640 | GATE(PCLK_WDT, "pclk_wdt", "pclk_bus_pre", 0, |
| 375 | RV1108_CLKGATE_CON(13), 3, GFLAGS), | 641 | RV1108_CLKGATE_CON(13), 3, GFLAGS), |
| 376 | GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 642 | GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus_pre", 0, |
| 377 | RV1108_CLKGATE_CON(13), 7, GFLAGS), | 643 | RV1108_CLKGATE_CON(13), 7, GFLAGS), |
| 378 | GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 644 | GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus_pre", 0, |
| 379 | RV1108_CLKGATE_CON(13), 8, GFLAGS), | 645 | RV1108_CLKGATE_CON(13), 8, GFLAGS), |
| 380 | GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 646 | GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus_pre", 0, |
| 381 | RV1108_CLKGATE_CON(13), 9, GFLAGS), | 647 | RV1108_CLKGATE_CON(13), 9, GFLAGS), |
| 382 | 648 | ||
| 383 | GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, | 649 | GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, |
| 384 | RV1108_CLKGATE_CON(14), 0, GFLAGS), | 650 | RV1108_CLKGATE_CON(14), 0, GFLAGS), |
| 651 | GATE(PCLK_EFUSE0, "pclk_efuse0", "pclk_bus_pre", 0, | ||
| 652 | RV1108_CLKGATE_CON(12), 12, GFLAGS), | ||
| 653 | GATE(PCLK_EFUSE1, "pclk_efuse1", "pclk_bus_pre", 0, | ||
| 654 | RV1108_CLKGATE_CON(12), 13, GFLAGS), | ||
| 655 | GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_pre", 0, | ||
| 656 | RV1108_CLKGATE_CON(13), 13, GFLAGS), | ||
| 657 | COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0, | ||
| 658 | RV1108_CLKSEL_CON(21), 0, 10, DFLAGS, | ||
| 659 | RV1108_CLKGATE_CON(3), 11, GFLAGS), | ||
| 660 | GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus_pre", 0, | ||
| 661 | RV1108_CLKGATE_CON(13), 14, GFLAGS), | ||
| 662 | COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, | ||
| 663 | RV1108_CLKSEL_CON(22), 0, 10, DFLAGS, | ||
| 664 | RV1108_CLKGATE_CON(3), 12, GFLAGS), | ||
| 385 | 665 | ||
| 386 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, | 666 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, |
| 387 | RV1108_CLKGATE_CON(12), 2, GFLAGS), | 667 | RV1108_CLKGATE_CON(12), 2, GFLAGS), |
| @@ -397,18 +677,24 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 397 | RV1108_CLKGATE_CON(0), 9, GFLAGS), | 677 | RV1108_CLKGATE_CON(0), 9, GFLAGS), |
| 398 | GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, | 678 | GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, |
| 399 | RV1108_CLKGATE_CON(0), 10, GFLAGS), | 679 | RV1108_CLKGATE_CON(0), 10, GFLAGS), |
| 400 | COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, | 680 | COMPOSITE_NOGATE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, |
| 401 | RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, | 681 | RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, |
| 402 | DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | 682 | DFLAGS | CLK_DIVIDER_POWER_OF_TWO), |
| 683 | FACTOR(0, "clk_ddr", "clk_ddrphy_src", 0, 1, 2), | ||
| 684 | GATE(0, "clk_ddrphy4x", "clk_ddr", CLK_IGNORE_UNUSED, | ||
| 403 | RV1108_CLKGATE_CON(10), 9, GFLAGS), | 685 | RV1108_CLKGATE_CON(10), 9, GFLAGS), |
| 404 | GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, | 686 | GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, |
| 405 | RV1108_CLKGATE_CON(12), 4, GFLAGS), | 687 | RV1108_CLKGATE_CON(12), 4, GFLAGS), |
| 406 | GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, | 688 | GATE(0, "nclk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, |
| 407 | RV1108_CLKGATE_CON(12), 5, GFLAGS), | 689 | RV1108_CLKGATE_CON(12), 5, GFLAGS), |
| 408 | GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, | 690 | GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, |
| 409 | RV1108_CLKGATE_CON(12), 6, GFLAGS), | 691 | RV1108_CLKGATE_CON(12), 6, GFLAGS), |
| 410 | GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, | 692 | GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, |
| 411 | RV1108_CLKGATE_CON(0), 11, GFLAGS), | 693 | RV1108_CLKGATE_CON(0), 11, GFLAGS), |
| 694 | GATE(0, "pclk_mschniu", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | ||
| 695 | RV1108_CLKGATE_CON(14), 2, GFLAGS), | ||
| 696 | GATE(0, "pclk_ddrphy", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | ||
| 697 | RV1108_CLKGATE_CON(14), 4, GFLAGS), | ||
| 412 | 698 | ||
| 413 | /* | 699 | /* |
| 414 | * Clock-Architecture Diagram 6 | 700 | * Clock-Architecture Diagram 6 |
| @@ -418,23 +704,23 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 418 | COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, | 704 | COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, |
| 419 | RV1108_CLKSEL_CON(23), 10, 5, DFLAGS, | 705 | RV1108_CLKSEL_CON(23), 10, 5, DFLAGS, |
| 420 | RV1108_CLKGATE_CON(4), 5, GFLAGS), | 706 | RV1108_CLKGATE_CON(4), 5, GFLAGS), |
| 421 | GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, | 707 | GATE(PCLK_PERI, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, |
| 422 | RV1108_CLKGATE_CON(15), 13, GFLAGS), | 708 | RV1108_CLKGATE_CON(15), 13, GFLAGS), |
| 423 | COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, | 709 | COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, |
| 424 | RV1108_CLKSEL_CON(23), 5, 5, DFLAGS, | 710 | RV1108_CLKSEL_CON(23), 5, 5, DFLAGS, |
| 425 | RV1108_CLKGATE_CON(4), 4, GFLAGS), | 711 | RV1108_CLKGATE_CON(4), 4, GFLAGS), |
| 426 | GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, | 712 | GATE(HCLK_PERI, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, |
| 427 | RV1108_CLKGATE_CON(15), 12, GFLAGS), | 713 | RV1108_CLKGATE_CON(15), 12, GFLAGS), |
| 428 | 714 | ||
| 429 | GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, | 715 | GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, |
| 430 | RV1108_CLKGATE_CON(4), 1, GFLAGS), | 716 | RV1108_CLKGATE_CON(4), 1, GFLAGS), |
| 431 | GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, | 717 | GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, |
| 432 | RV1108_CLKGATE_CON(4), 2, GFLAGS), | 718 | RV1108_CLKGATE_CON(4), 2, GFLAGS), |
| 433 | COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, | 719 | COMPOSITE(ACLK_PERI, "aclk_periph", mux_aclk_peri_src_p, 0, |
| 434 | RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, | 720 | RV1108_CLKSEL_CON(23), 15, 1, MFLAGS, 0, 5, DFLAGS, |
| 435 | RV1108_CLKGATE_CON(15), 11, GFLAGS), | 721 | RV1108_CLKGATE_CON(15), 11, GFLAGS), |
| 436 | 722 | ||
| 437 | COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, | 723 | COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, |
| 438 | RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, | 724 | RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, |
| 439 | RV1108_CLKGATE_CON(5), 0, GFLAGS), | 725 | RV1108_CLKGATE_CON(5), 0, GFLAGS), |
| 440 | 726 | ||
| @@ -454,23 +740,31 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 454 | GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS), | 740 | GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS), |
| 455 | 741 | ||
| 456 | COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, | 742 | COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, |
| 457 | RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, | 743 | RV1108_CLKSEL_CON(27), 14, 1, MFLAGS, 8, 5, DFLAGS, |
| 458 | RV1108_CLKGATE_CON(5), 3, GFLAGS), | 744 | RV1108_CLKGATE_CON(5), 3, GFLAGS), |
| 459 | GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS), | 745 | GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS), |
| 460 | 746 | ||
| 747 | GATE(HCLK_HOST0, "hclk_host0", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 6, GFLAGS), | ||
| 748 | GATE(0, "hclk_host0_arb", "hclk_periph", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(15), 7, GFLAGS), | ||
| 749 | GATE(HCLK_OTG, "hclk_otg", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 8, GFLAGS), | ||
| 750 | GATE(0, "hclk_otg_pmu", "hclk_periph", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(15), 9, GFLAGS), | ||
| 751 | GATE(SCLK_USBPHY, "clk_usbphy", "xin24m", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(5), 5, GFLAGS), | ||
| 752 | |||
| 461 | COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, | 753 | COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, |
| 462 | RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, | 754 | RV1108_CLKSEL_CON(27), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 463 | RV1108_CLKGATE_CON(5), 4, GFLAGS), | 755 | RV1108_CLKGATE_CON(5), 4, GFLAGS), |
| 464 | GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), | 756 | GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), |
| 465 | 757 | ||
| 466 | COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, | 758 | COMPOSITE(SCLK_MAC_PRE, "sclk_mac_pre", mux_pll_src_apll_gpll_p, 0, |
| 467 | RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, | 759 | RV1108_CLKSEL_CON(24), 12, 1, MFLAGS, 0, 5, DFLAGS, |
| 468 | RV1108_CLKGATE_CON(4), 10, GFLAGS), | 760 | RV1108_CLKGATE_CON(4), 10, GFLAGS), |
| 469 | MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, | 761 | MUX(SCLK_MAC, "sclk_mac", mux_sclk_mac_p, CLK_SET_RATE_PARENT, |
| 470 | RV1108_CLKSEL_CON(24), 8, 2, MFLAGS), | 762 | RV1108_CLKSEL_CON(24), 8, 1, MFLAGS), |
| 471 | GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), | 763 | GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), |
| 472 | GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), | 764 | GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), |
| 473 | GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), | 765 | GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), |
| 766 | GATE(ACLK_GMAC, "aclk_gmac", "aclk_periph", 0, RV1108_CLKGATE_CON(15), 4, GFLAGS), | ||
| 767 | GATE(PCLK_GMAC, "pclk_gmac", "pclk_periph", 0, RV1108_CLKGATE_CON(15), 5, GFLAGS), | ||
| 474 | 768 | ||
| 475 | MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1), | 769 | MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1), |
| 476 | MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1), | 770 | MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1), |
| @@ -484,10 +778,16 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { | |||
| 484 | 778 | ||
| 485 | static const char *const rv1108_critical_clocks[] __initconst = { | 779 | static const char *const rv1108_critical_clocks[] __initconst = { |
| 486 | "aclk_core", | 780 | "aclk_core", |
| 487 | "aclk_bus_src_gpll", | 781 | "aclk_bus", |
| 782 | "hclk_bus", | ||
| 783 | "pclk_bus", | ||
| 488 | "aclk_periph", | 784 | "aclk_periph", |
| 489 | "hclk_periph", | 785 | "hclk_periph", |
| 490 | "pclk_periph", | 786 | "pclk_periph", |
| 787 | "nclk_ddrupctl", | ||
| 788 | "pclk_ddrmon", | ||
| 789 | "pclk_acodecphy", | ||
| 790 | "pclk_pmu", | ||
| 491 | }; | 791 | }; |
| 492 | 792 | ||
| 493 | static void __init rv1108_clk_init(struct device_node *np) | 793 | static void __init rv1108_clk_init(struct device_node *np) |
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index fe1d393cf678..35dbd63c2f49 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/mfd/syscon.h> | 29 | #include <linux/mfd/syscon.h> |
| 30 | #include <linux/regmap.h> | 30 | #include <linux/regmap.h> |
| 31 | #include <linux/reboot.h> | 31 | #include <linux/reboot.h> |
| 32 | #include <linux/rational.h> | ||
| 32 | #include "clk.h" | 33 | #include "clk.h" |
| 33 | 34 | ||
| 34 | /** | 35 | /** |
| @@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, | |||
| 164 | return notifier_from_errno(ret); | 165 | return notifier_from_errno(ret); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 168 | /** | ||
| 169 | * fractional divider must set that denominator is 20 times larger than | ||
| 170 | * numerator to generate precise clock frequency. | ||
| 171 | */ | ||
| 172 | static void rockchip_fractional_approximation(struct clk_hw *hw, | ||
| 173 | unsigned long rate, unsigned long *parent_rate, | ||
| 174 | unsigned long *m, unsigned long *n) | ||
| 175 | { | ||
| 176 | struct clk_fractional_divider *fd = to_clk_fd(hw); | ||
| 177 | unsigned long p_rate, p_parent_rate; | ||
| 178 | struct clk_hw *p_parent; | ||
| 179 | unsigned long scale; | ||
| 180 | |||
| 181 | p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); | ||
| 182 | if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { | ||
| 183 | p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); | ||
| 184 | p_parent_rate = clk_hw_get_rate(p_parent); | ||
| 185 | *parent_rate = p_parent_rate; | ||
| 186 | } | ||
| 187 | |||
| 188 | /* | ||
| 189 | * Get rate closer to *parent_rate to guarantee there is no overflow | ||
| 190 | * for m and n. In the result it will be the nearest rate left shifted | ||
| 191 | * by (scale - fd->nwidth) bits. | ||
| 192 | */ | ||
| 193 | scale = fls_long(*parent_rate / rate - 1); | ||
| 194 | if (scale > fd->nwidth) | ||
| 195 | rate <<= scale - fd->nwidth; | ||
| 196 | |||
| 197 | rational_best_approximation(rate, *parent_rate, | ||
| 198 | GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), | ||
| 199 | m, n); | ||
| 200 | } | ||
| 201 | |||
| 167 | static struct clk *rockchip_clk_register_frac_branch( | 202 | static struct clk *rockchip_clk_register_frac_branch( |
| 168 | struct rockchip_clk_provider *ctx, const char *name, | 203 | struct rockchip_clk_provider *ctx, const char *name, |
| 169 | const char *const *parent_names, u8 num_parents, | 204 | const char *const *parent_names, u8 num_parents, |
| @@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch( | |||
| 210 | div->nwidth = 16; | 245 | div->nwidth = 16; |
| 211 | div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; | 246 | div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; |
| 212 | div->lock = lock; | 247 | div->lock = lock; |
| 248 | div->approximation = rockchip_fractional_approximation; | ||
| 213 | div_ops = &clk_fractional_divider_ops; | 249 | div_ops = &clk_fractional_divider_ops; |
| 214 | 250 | ||
| 215 | clk = clk_register_composite(NULL, name, parent_names, num_parents, | 251 | clk = clk_register_composite(NULL, name, parent_names, num_parents, |
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 1fab56f396d4..b117783ed404 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c | |||
| @@ -180,7 +180,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
| 180 | } | 180 | } |
| 181 | clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", | 181 | clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", |
| 182 | mout_audss_p, ARRAY_SIZE(mout_audss_p), | 182 | mout_audss_p, ARRAY_SIZE(mout_audss_p), |
| 183 | CLK_SET_RATE_NO_REPARENT, | 183 | CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, |
| 184 | reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); | 184 | reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); |
| 185 | 185 | ||
| 186 | cdclk = devm_clk_get(&pdev->dev, "cdclk"); | 186 | cdclk = devm_clk_get(&pdev->dev, "cdclk"); |
| @@ -195,11 +195,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
| 195 | reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); | 195 | reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); |
| 196 | 196 | ||
| 197 | clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", | 197 | clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", |
| 198 | "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, | 198 | "mout_audss", CLK_SET_RATE_PARENT, |
| 199 | 0, &lock); | 199 | reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); |
| 200 | 200 | ||
| 201 | clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, | 201 | clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, |
| 202 | "dout_aud_bus", "dout_srp", 0, | 202 | "dout_aud_bus", "dout_srp", CLK_SET_RATE_PARENT, |
| 203 | reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); | 203 | reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); |
| 204 | 204 | ||
| 205 | clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", | 205 | clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", |
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 9a6476aa7d81..25601967d1cd 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c | |||
| @@ -537,8 +537,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { | |||
| 537 | 537 | ||
| 538 | MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", | 538 | MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", |
| 539 | mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2), | 539 | mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2), |
| 540 | MUX(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, | 540 | MUX_F(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, |
| 541 | SRC_TOP7, 20, 2), | 541 | SRC_TOP7, 20, 2, CLK_SET_RATE_PARENT, 0), |
| 542 | MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1), | 542 | MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1), |
| 543 | MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1), | 543 | MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1), |
| 544 | 544 | ||
| @@ -547,8 +547,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { | |||
| 547 | MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2), | 547 | MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2), |
| 548 | MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2), | 548 | MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2), |
| 549 | 549 | ||
| 550 | MUX(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p, | 550 | MUX_F(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p, |
| 551 | SRC_TOP9, 8, 1), | 551 | SRC_TOP9, 8, 1, CLK_SET_RATE_PARENT, 0), |
| 552 | MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p, | 552 | MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p, |
| 553 | SRC_TOP9, 16, 1), | 553 | SRC_TOP9, 16, 1), |
| 554 | MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p, | 554 | MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p, |
| @@ -590,6 +590,8 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = { | |||
| 590 | GATE_BUS_TOP, 24, 0, 0), | 590 | GATE_BUS_TOP, 24, 0, 0), |
| 591 | GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", | 591 | GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", |
| 592 | GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0), | 592 | GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0), |
| 593 | GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll", | ||
| 594 | SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0), | ||
| 593 | }; | 595 | }; |
| 594 | 596 | ||
| 595 | static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { | 597 | static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { |
| @@ -629,6 +631,11 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = { | |||
| 629 | "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), | 631 | "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), |
| 630 | }; | 632 | }; |
| 631 | 633 | ||
| 634 | static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = { | ||
| 635 | GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", | ||
| 636 | SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0), | ||
| 637 | }; | ||
| 638 | |||
| 632 | static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { | 639 | static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { |
| 633 | MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, | 640 | MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, |
| 634 | SRC_TOP7, 4, 1), | 641 | SRC_TOP7, 4, 1), |
| @@ -706,7 +713,8 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { | |||
| 706 | MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1), | 713 | MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1), |
| 707 | MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1), | 714 | MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1), |
| 708 | MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1), | 715 | MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1), |
| 709 | MUX(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1), | 716 | MUX_F(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1, |
| 717 | CLK_SET_RATE_PARENT, 0), | ||
| 710 | MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1), | 718 | MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1), |
| 711 | MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1), | 719 | MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1), |
| 712 | 720 | ||
| @@ -1001,9 +1009,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { | |||
| 1001 | GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1", | 1009 | GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1", |
| 1002 | SRC_MASK_TOP2, 24, CLK_IS_CRITICAL, 0), | 1010 | SRC_MASK_TOP2, 24, CLK_IS_CRITICAL, 0), |
| 1003 | 1011 | ||
| 1004 | GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", | ||
| 1005 | SRC_MASK_TOP7, 20, 0, 0), | ||
| 1006 | |||
| 1007 | /* sclk */ | 1012 | /* sclk */ |
| 1008 | GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", | 1013 | GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", |
| 1009 | GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0), | 1014 | GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0), |
| @@ -1440,6 +1445,8 @@ static void __init exynos5x_clk_init(struct device_node *np, | |||
| 1440 | ARRAY_SIZE(exynos5420_mux_clks)); | 1445 | ARRAY_SIZE(exynos5420_mux_clks)); |
| 1441 | samsung_clk_register_div(ctx, exynos5420_div_clks, | 1446 | samsung_clk_register_div(ctx, exynos5420_div_clks, |
| 1442 | ARRAY_SIZE(exynos5420_div_clks)); | 1447 | ARRAY_SIZE(exynos5420_div_clks)); |
| 1448 | samsung_clk_register_gate(ctx, exynos5420_gate_clks, | ||
| 1449 | ARRAY_SIZE(exynos5420_gate_clks)); | ||
| 1443 | } else { | 1450 | } else { |
| 1444 | samsung_clk_register_fixed_factor( | 1451 | samsung_clk_register_fixed_factor( |
| 1445 | ctx, exynos5800_fixed_factor_clks, | 1452 | ctx, exynos5800_fixed_factor_clks, |
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 7342928c35cd..6427d0ebe2de 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig | |||
| @@ -11,6 +11,19 @@ config SUN50I_A64_CCU | |||
| 11 | default ARM64 && ARCH_SUNXI | 11 | default ARM64 && ARCH_SUNXI |
| 12 | depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST | 12 | depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST |
| 13 | 13 | ||
| 14 | config SUN4I_A10_CCU | ||
| 15 | bool "Support for the Allwinner A10/A20 CCU" | ||
| 16 | select SUNXI_CCU_DIV | ||
| 17 | select SUNXI_CCU_MULT | ||
| 18 | select SUNXI_CCU_NK | ||
| 19 | select SUNXI_CCU_NKM | ||
| 20 | select SUNXI_CCU_NM | ||
| 21 | select SUNXI_CCU_MP | ||
| 22 | select SUNXI_CCU_PHASE | ||
| 23 | default MACH_SUN4I | ||
| 24 | default MACH_SUN7I | ||
| 25 | depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST | ||
| 26 | |||
| 14 | config SUN5I_CCU | 27 | config SUN5I_CCU |
| 15 | bool "Support for the Allwinner sun5i family CCM" | 28 | bool "Support for the Allwinner sun5i family CCM" |
| 16 | default MACH_SUN5I | 29 | default MACH_SUN5I |
| @@ -48,6 +61,11 @@ config SUN8I_V3S_CCU | |||
| 48 | config SUN8I_DE2_CCU | 61 | config SUN8I_DE2_CCU |
| 49 | bool "Support for the Allwinner SoCs DE2 CCU" | 62 | bool "Support for the Allwinner SoCs DE2 CCU" |
| 50 | 63 | ||
| 64 | config SUN8I_R40_CCU | ||
| 65 | bool "Support for the Allwinner R40 CCU" | ||
| 66 | default MACH_SUN8I | ||
| 67 | depends on MACH_SUN8I || COMPILE_TEST | ||
| 68 | |||
| 51 | config SUN9I_A80_CCU | 69 | config SUN9I_A80_CCU |
| 52 | bool "Support for the Allwinner A80 CCU" | 70 | bool "Support for the Allwinner A80 CCU" |
| 53 | default MACH_SUN9I | 71 | default MACH_SUN9I |
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 45a5910379a5..85a0633c1eac 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile | |||
| @@ -20,6 +20,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_mp.o | |||
| 20 | 20 | ||
| 21 | # SoC support | 21 | # SoC support |
| 22 | obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o | 22 | obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o |
| 23 | obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o | ||
| 23 | obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o | 24 | obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o |
| 24 | obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o | 25 | obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o |
| 25 | obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o | 26 | obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o |
| @@ -29,6 +30,7 @@ obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o | |||
| 29 | obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o | 30 | obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o |
| 30 | obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o | 31 | obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o |
| 31 | obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o | 32 | obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o |
| 33 | obj-$(CONFIG_SUN8I_R40_CCU) += ccu-sun8i-r40.o | ||
| 32 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o | 34 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o |
| 33 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o | 35 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o |
| 34 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o | 36 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o |
diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c new file mode 100644 index 000000000000..286b0049b7b6 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c | |||
| @@ -0,0 +1,1456 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2017 Priit Laes <plaes@plaes.org>. | ||
| 3 | * Copyright (c) 2017 Maxime Ripard. | ||
| 4 | * Copyright (c) 2017 Jonathan Liu. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/clk-provider.h> | ||
| 17 | #include <linux/of_address.h> | ||
| 18 | |||
| 19 | #include "ccu_common.h" | ||
| 20 | #include "ccu_reset.h" | ||
| 21 | |||
| 22 | #include "ccu_div.h" | ||
| 23 | #include "ccu_gate.h" | ||
| 24 | #include "ccu_mp.h" | ||
| 25 | #include "ccu_mult.h" | ||
| 26 | #include "ccu_nk.h" | ||
| 27 | #include "ccu_nkm.h" | ||
| 28 | #include "ccu_nkmp.h" | ||
| 29 | #include "ccu_nm.h" | ||
| 30 | #include "ccu_phase.h" | ||
| 31 | |||
| 32 | #include "ccu-sun4i-a10.h" | ||
| 33 | |||
| 34 | static struct ccu_nkmp pll_core_clk = { | ||
| 35 | .enable = BIT(31), | ||
| 36 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 37 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 38 | .m = _SUNXI_CCU_DIV(0, 2), | ||
| 39 | .p = _SUNXI_CCU_DIV(16, 2), | ||
| 40 | .common = { | ||
| 41 | .reg = 0x000, | ||
| 42 | .hw.init = CLK_HW_INIT("pll-core", | ||
| 43 | "hosc", | ||
| 44 | &ccu_nkmp_ops, | ||
| 45 | 0), | ||
| 46 | }, | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from | ||
| 51 | * the base (2x, 4x and 8x), and one variable divider (the one true | ||
| 52 | * pll audio). | ||
| 53 | * | ||
| 54 | * We don't have any need for the variable divider for now, so we just | ||
| 55 | * hardcode it to match with the clock names. | ||
| 56 | */ | ||
| 57 | #define SUN4I_PLL_AUDIO_REG 0x008 | ||
| 58 | static struct ccu_nm pll_audio_base_clk = { | ||
| 59 | .enable = BIT(31), | ||
| 60 | .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), | ||
| 61 | .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), | ||
| 62 | .common = { | ||
| 63 | .reg = 0x008, | ||
| 64 | .hw.init = CLK_HW_INIT("pll-audio-base", | ||
| 65 | "hosc", | ||
| 66 | &ccu_nm_ops, | ||
| 67 | 0), | ||
| 68 | }, | ||
| 69 | |||
| 70 | }; | ||
| 71 | |||
| 72 | static struct ccu_mult pll_video0_clk = { | ||
| 73 | .enable = BIT(31), | ||
| 74 | .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), | ||
| 75 | .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), | ||
| 76 | 270000000, 297000000), | ||
| 77 | .common = { | ||
| 78 | .reg = 0x010, | ||
| 79 | .features = (CCU_FEATURE_FRACTIONAL | | ||
| 80 | CCU_FEATURE_ALL_PREDIV), | ||
| 81 | .prediv = 8, | ||
| 82 | .hw.init = CLK_HW_INIT("pll-video0", | ||
| 83 | "hosc", | ||
| 84 | &ccu_mult_ops, | ||
| 85 | 0), | ||
| 86 | }, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static struct ccu_nkmp pll_ve_sun4i_clk = { | ||
| 90 | .enable = BIT(31), | ||
| 91 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 92 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 93 | .m = _SUNXI_CCU_DIV(0, 2), | ||
| 94 | .p = _SUNXI_CCU_DIV(16, 2), | ||
| 95 | .common = { | ||
| 96 | .reg = 0x018, | ||
| 97 | .hw.init = CLK_HW_INIT("pll-ve", | ||
| 98 | "hosc", | ||
| 99 | &ccu_nkmp_ops, | ||
| 100 | 0), | ||
| 101 | }, | ||
| 102 | }; | ||
| 103 | |||
| 104 | static struct ccu_nk pll_ve_sun7i_clk = { | ||
| 105 | .enable = BIT(31), | ||
| 106 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 107 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 108 | .common = { | ||
| 109 | .reg = 0x018, | ||
| 110 | .hw.init = CLK_HW_INIT("pll-ve", | ||
| 111 | "hosc", | ||
| 112 | &ccu_nk_ops, | ||
| 113 | 0), | ||
| 114 | }, | ||
| 115 | }; | ||
| 116 | |||
| 117 | static struct ccu_nk pll_ddr_base_clk = { | ||
| 118 | .enable = BIT(31), | ||
| 119 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 120 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 121 | .common = { | ||
| 122 | .reg = 0x020, | ||
| 123 | .hw.init = CLK_HW_INIT("pll-ddr-base", | ||
| 124 | "hosc", | ||
| 125 | &ccu_nk_ops, | ||
| 126 | 0), | ||
| 127 | }, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2, | ||
| 131 | CLK_IS_CRITICAL); | ||
| 132 | |||
| 133 | static struct ccu_div pll_ddr_other_clk = { | ||
| 134 | .div = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO), | ||
| 135 | .common = { | ||
| 136 | .reg = 0x020, | ||
| 137 | .hw.init = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base", | ||
| 138 | &ccu_div_ops, | ||
| 139 | 0), | ||
| 140 | }, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static struct ccu_nk pll_periph_base_clk = { | ||
| 144 | .enable = BIT(31), | ||
| 145 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 146 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 147 | .common = { | ||
| 148 | .reg = 0x028, | ||
| 149 | .hw.init = CLK_HW_INIT("pll-periph-base", | ||
| 150 | "hosc", | ||
| 151 | &ccu_nk_ops, | ||
| 152 | 0), | ||
| 153 | }, | ||
| 154 | }; | ||
| 155 | |||
| 156 | static CLK_FIXED_FACTOR(pll_periph_clk, "pll-periph", "pll-periph-base", | ||
| 157 | 2, 1, CLK_SET_RATE_PARENT); | ||
| 158 | |||
| 159 | /* Not documented on A10 */ | ||
| 160 | static struct ccu_div pll_periph_sata_clk = { | ||
| 161 | .enable = BIT(14), | ||
| 162 | .div = _SUNXI_CCU_DIV(0, 2), | ||
| 163 | .fixed_post_div = 6, | ||
| 164 | .common = { | ||
| 165 | .reg = 0x028, | ||
| 166 | .features = CCU_FEATURE_FIXED_POSTDIV, | ||
| 167 | .hw.init = CLK_HW_INIT("pll-periph-sata", | ||
| 168 | "pll-periph-base", | ||
| 169 | &ccu_div_ops, 0), | ||
| 170 | }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static struct ccu_mult pll_video1_clk = { | ||
| 174 | .enable = BIT(31), | ||
| 175 | .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), | ||
| 176 | .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), | ||
| 177 | 270000000, 297000000), | ||
| 178 | .common = { | ||
| 179 | .reg = 0x030, | ||
| 180 | .features = (CCU_FEATURE_FRACTIONAL | | ||
| 181 | CCU_FEATURE_ALL_PREDIV), | ||
| 182 | .prediv = 8, | ||
| 183 | .hw.init = CLK_HW_INIT("pll-video1", | ||
| 184 | "hosc", | ||
| 185 | &ccu_mult_ops, | ||
| 186 | 0), | ||
| 187 | }, | ||
| 188 | }; | ||
| 189 | |||
| 190 | /* Not present on A10 */ | ||
| 191 | static struct ccu_nk pll_gpu_clk = { | ||
| 192 | .enable = BIT(31), | ||
| 193 | .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | ||
| 194 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 195 | .common = { | ||
| 196 | .reg = 0x040, | ||
| 197 | .hw.init = CLK_HW_INIT("pll-gpu", | ||
| 198 | "hosc", | ||
| 199 | &ccu_nk_ops, | ||
| 200 | 0), | ||
| 201 | }, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static SUNXI_CCU_GATE(hosc_clk, "hosc", "osc24M", 0x050, BIT(0), 0); | ||
| 205 | |||
| 206 | static const char *const cpu_parents[] = { "osc32k", "hosc", | ||
| 207 | "pll-core", "pll-periph" }; | ||
| 208 | static const struct ccu_mux_fixed_prediv cpu_predivs[] = { | ||
| 209 | { .index = 3, .div = 3, }, | ||
| 210 | }; | ||
| 211 | |||
| 212 | #define SUN4I_AHB_REG 0x054 | ||
| 213 | static struct ccu_mux cpu_clk = { | ||
| 214 | .mux = { | ||
| 215 | .shift = 16, | ||
| 216 | .width = 2, | ||
| 217 | .fixed_predivs = cpu_predivs, | ||
| 218 | .n_predivs = ARRAY_SIZE(cpu_predivs), | ||
| 219 | }, | ||
| 220 | .common = { | ||
| 221 | .reg = 0x054, | ||
| 222 | .features = CCU_FEATURE_FIXED_PREDIV, | ||
| 223 | .hw.init = CLK_HW_INIT_PARENTS("cpu", | ||
| 224 | cpu_parents, | ||
| 225 | &ccu_mux_ops, | ||
| 226 | CLK_IS_CRITICAL), | ||
| 227 | } | ||
| 228 | }; | ||
| 229 | |||
| 230 | static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0); | ||
| 231 | |||
| 232 | static struct ccu_div ahb_sun4i_clk = { | ||
| 233 | .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | ||
| 234 | .common = { | ||
| 235 | .reg = 0x054, | ||
| 236 | .hw.init = CLK_HW_INIT("ahb", "axi", &ccu_div_ops, 0), | ||
| 237 | }, | ||
| 238 | }; | ||
| 239 | |||
| 240 | static const char *const ahb_sun7i_parents[] = { "axi", "pll-periph", | ||
| 241 | "pll-periph" }; | ||
| 242 | static const struct ccu_mux_fixed_prediv ahb_sun7i_predivs[] = { | ||
| 243 | { .index = 1, .div = 2, }, | ||
| 244 | { /* Sentinel */ }, | ||
| 245 | }; | ||
| 246 | static struct ccu_div ahb_sun7i_clk = { | ||
| 247 | .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | ||
| 248 | .mux = { | ||
| 249 | .shift = 6, | ||
| 250 | .width = 2, | ||
| 251 | .fixed_predivs = ahb_sun7i_predivs, | ||
| 252 | .n_predivs = ARRAY_SIZE(ahb_sun7i_predivs), | ||
| 253 | }, | ||
| 254 | |||
| 255 | .common = { | ||
| 256 | .reg = 0x054, | ||
| 257 | .hw.init = CLK_HW_INIT_PARENTS("ahb", | ||
| 258 | ahb_sun7i_parents, | ||
| 259 | &ccu_div_ops, | ||
| 260 | 0), | ||
| 261 | }, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static struct clk_div_table apb0_div_table[] = { | ||
| 265 | { .val = 0, .div = 2 }, | ||
| 266 | { .val = 1, .div = 2 }, | ||
| 267 | { .val = 2, .div = 4 }, | ||
| 268 | { .val = 3, .div = 8 }, | ||
| 269 | { /* Sentinel */ }, | ||
| 270 | }; | ||
| 271 | static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb", | ||
| 272 | 0x054, 8, 2, apb0_div_table, 0); | ||
| 273 | |||
| 274 | static const char *const apb1_parents[] = { "hosc", "pll-periph", "osc32k" }; | ||
| 275 | static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058, | ||
| 276 | 0, 5, /* M */ | ||
| 277 | 16, 2, /* P */ | ||
| 278 | 24, 2, /* mux */ | ||
| 279 | 0); | ||
| 280 | |||
| 281 | /* Not present on A20 */ | ||
| 282 | static SUNXI_CCU_GATE(axi_dram_clk, "axi-dram", "ahb", | ||
| 283 | 0x05c, BIT(31), 0); | ||
| 284 | |||
| 285 | static SUNXI_CCU_GATE(ahb_otg_clk, "ahb-otg", "ahb", | ||
| 286 | 0x060, BIT(0), 0); | ||
| 287 | static SUNXI_CCU_GATE(ahb_ehci0_clk, "ahb-ehci0", "ahb", | ||
| 288 | 0x060, BIT(1), 0); | ||
| 289 | static SUNXI_CCU_GATE(ahb_ohci0_clk, "ahb-ohci0", "ahb", | ||
| 290 | 0x060, BIT(2), 0); | ||
| 291 | static SUNXI_CCU_GATE(ahb_ehci1_clk, "ahb-ehci1", "ahb", | ||
| 292 | 0x060, BIT(3), 0); | ||
| 293 | static SUNXI_CCU_GATE(ahb_ohci1_clk, "ahb-ohci1", "ahb", | ||
| 294 | 0x060, BIT(4), 0); | ||
| 295 | static SUNXI_CCU_GATE(ahb_ss_clk, "ahb-ss", "ahb", | ||
| 296 | 0x060, BIT(5), 0); | ||
| 297 | static SUNXI_CCU_GATE(ahb_dma_clk, "ahb-dma", "ahb", | ||
| 298 | 0x060, BIT(6), 0); | ||
| 299 | static SUNXI_CCU_GATE(ahb_bist_clk, "ahb-bist", "ahb", | ||
| 300 | 0x060, BIT(7), 0); | ||
| 301 | static SUNXI_CCU_GATE(ahb_mmc0_clk, "ahb-mmc0", "ahb", | ||
| 302 | 0x060, BIT(8), 0); | ||
| 303 | static SUNXI_CCU_GATE(ahb_mmc1_clk, "ahb-mmc1", "ahb", | ||
| 304 | 0x060, BIT(9), 0); | ||
| 305 | static SUNXI_CCU_GATE(ahb_mmc2_clk, "ahb-mmc2", "ahb", | ||
| 306 | 0x060, BIT(10), 0); | ||
| 307 | static SUNXI_CCU_GATE(ahb_mmc3_clk, "ahb-mmc3", "ahb", | ||
| 308 | 0x060, BIT(11), 0); | ||
| 309 | static SUNXI_CCU_GATE(ahb_ms_clk, "ahb-ms", "ahb", | ||
| 310 | 0x060, BIT(12), 0); | ||
| 311 | static SUNXI_CCU_GATE(ahb_nand_clk, "ahb-nand", "ahb", | ||
| 312 | 0x060, BIT(13), 0); | ||
| 313 | static SUNXI_CCU_GATE(ahb_sdram_clk, "ahb-sdram", "ahb", | ||
| 314 | 0x060, BIT(14), CLK_IS_CRITICAL); | ||
| 315 | |||
| 316 | static SUNXI_CCU_GATE(ahb_ace_clk, "ahb-ace", "ahb", | ||
| 317 | 0x060, BIT(16), 0); | ||
| 318 | static SUNXI_CCU_GATE(ahb_emac_clk, "ahb-emac", "ahb", | ||
| 319 | 0x060, BIT(17), 0); | ||
| 320 | static SUNXI_CCU_GATE(ahb_ts_clk, "ahb-ts", "ahb", | ||
| 321 | 0x060, BIT(18), 0); | ||
| 322 | static SUNXI_CCU_GATE(ahb_spi0_clk, "ahb-spi0", "ahb", | ||
| 323 | 0x060, BIT(20), 0); | ||
| 324 | static SUNXI_CCU_GATE(ahb_spi1_clk, "ahb-spi1", "ahb", | ||
| 325 | 0x060, BIT(21), 0); | ||
| 326 | static SUNXI_CCU_GATE(ahb_spi2_clk, "ahb-spi2", "ahb", | ||
| 327 | 0x060, BIT(22), 0); | ||
| 328 | static SUNXI_CCU_GATE(ahb_spi3_clk, "ahb-spi3", "ahb", | ||
| 329 | 0x060, BIT(23), 0); | ||
| 330 | static SUNXI_CCU_GATE(ahb_pata_clk, "ahb-pata", "ahb", | ||
| 331 | 0x060, BIT(24), 0); | ||
| 332 | /* Not documented on A20 */ | ||
| 333 | static SUNXI_CCU_GATE(ahb_sata_clk, "ahb-sata", "ahb", | ||
| 334 | 0x060, BIT(25), 0); | ||
| 335 | /* Not present on A20 */ | ||
| 336 | static SUNXI_CCU_GATE(ahb_gps_clk, "ahb-gps", "ahb", | ||
| 337 | 0x060, BIT(26), 0); | ||
| 338 | /* Not present on A10 */ | ||
| 339 | static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer", "ahb", | ||
| 340 | 0x060, BIT(28), 0); | ||
| 341 | |||
| 342 | static SUNXI_CCU_GATE(ahb_ve_clk, "ahb-ve", "ahb", | ||
| 343 | 0x064, BIT(0), 0); | ||
| 344 | static SUNXI_CCU_GATE(ahb_tvd_clk, "ahb-tvd", "ahb", | ||
| 345 | 0x064, BIT(1), 0); | ||
| 346 | static SUNXI_CCU_GATE(ahb_tve0_clk, "ahb-tve0", "ahb", | ||
| 347 | 0x064, BIT(2), 0); | ||
| 348 | static SUNXI_CCU_GATE(ahb_tve1_clk, "ahb-tve1", "ahb", | ||
| 349 | 0x064, BIT(3), 0); | ||
| 350 | static SUNXI_CCU_GATE(ahb_lcd0_clk, "ahb-lcd0", "ahb", | ||
| 351 | 0x064, BIT(4), 0); | ||
| 352 | static SUNXI_CCU_GATE(ahb_lcd1_clk, "ahb-lcd1", "ahb", | ||
| 353 | 0x064, BIT(5), 0); | ||
| 354 | static SUNXI_CCU_GATE(ahb_csi0_clk, "ahb-csi0", "ahb", | ||
| 355 | 0x064, BIT(8), 0); | ||
| 356 | static SUNXI_CCU_GATE(ahb_csi1_clk, "ahb-csi1", "ahb", | ||
| 357 | 0x064, BIT(9), 0); | ||
| 358 | /* Not present on A10 */ | ||
| 359 | static SUNXI_CCU_GATE(ahb_hdmi1_clk, "ahb-hdmi1", "ahb", | ||
| 360 | 0x064, BIT(10), 0); | ||
| 361 | static SUNXI_CCU_GATE(ahb_hdmi0_clk, "ahb-hdmi0", "ahb", | ||
| 362 | 0x064, BIT(11), 0); | ||
| 363 | static SUNXI_CCU_GATE(ahb_de_be0_clk, "ahb-de-be0", "ahb", | ||
| 364 | 0x064, BIT(12), 0); | ||
| 365 | static SUNXI_CCU_GATE(ahb_de_be1_clk, "ahb-de-be1", "ahb", | ||
| 366 | 0x064, BIT(13), 0); | ||
| 367 | static SUNXI_CCU_GATE(ahb_de_fe0_clk, "ahb-de-fe0", "ahb", | ||
| 368 | 0x064, BIT(14), 0); | ||
| 369 | static SUNXI_CCU_GATE(ahb_de_fe1_clk, "ahb-de-fe1", "ahb", | ||
| 370 | 0x064, BIT(15), 0); | ||
| 371 | /* Not present on A10 */ | ||
| 372 | static SUNXI_CCU_GATE(ahb_gmac_clk, "ahb-gmac", "ahb", | ||
| 373 | 0x064, BIT(17), 0); | ||
| 374 | static SUNXI_CCU_GATE(ahb_mp_clk, "ahb-mp", "ahb", | ||
| 375 | 0x064, BIT(18), 0); | ||
| 376 | static SUNXI_CCU_GATE(ahb_gpu_clk, "ahb-gpu", "ahb", | ||
| 377 | 0x064, BIT(20), 0); | ||
| 378 | |||
| 379 | static SUNXI_CCU_GATE(apb0_codec_clk, "apb0-codec", "apb0", | ||
| 380 | 0x068, BIT(0), 0); | ||
| 381 | static SUNXI_CCU_GATE(apb0_spdif_clk, "apb0-spdif", "apb0", | ||
| 382 | 0x068, BIT(1), 0); | ||
| 383 | static SUNXI_CCU_GATE(apb0_ac97_clk, "apb0-ac97", "apb0", | ||
| 384 | 0x068, BIT(2), 0); | ||
| 385 | static SUNXI_CCU_GATE(apb0_i2s0_clk, "apb0-i2s0", "apb0", | ||
| 386 | 0x068, BIT(3), 0); | ||
| 387 | /* Not present on A10 */ | ||
| 388 | static SUNXI_CCU_GATE(apb0_i2s1_clk, "apb0-i2s1", "apb0", | ||
| 389 | 0x068, BIT(4), 0); | ||
| 390 | static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0", | ||
| 391 | 0x068, BIT(5), 0); | ||
| 392 | static SUNXI_CCU_GATE(apb0_ir0_clk, "apb0-ir0", "apb0", | ||
| 393 | 0x068, BIT(6), 0); | ||
| 394 | static SUNXI_CCU_GATE(apb0_ir1_clk, "apb0-ir1", "apb0", | ||
| 395 | 0x068, BIT(7), 0); | ||
| 396 | /* Not present on A10 */ | ||
| 397 | static SUNXI_CCU_GATE(apb0_i2s2_clk, "apb0-i2s2", "apb0", | ||
| 398 | 0x068, BIT(8), 0); | ||
| 399 | static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad", "apb0", | ||
| 400 | 0x068, BIT(10), 0); | ||
| 401 | |||
| 402 | static SUNXI_CCU_GATE(apb1_i2c0_clk, "apb1-i2c0", "apb1", | ||
| 403 | 0x06c, BIT(0), 0); | ||
| 404 | static SUNXI_CCU_GATE(apb1_i2c1_clk, "apb1-i2c1", "apb1", | ||
| 405 | 0x06c, BIT(1), 0); | ||
| 406 | static SUNXI_CCU_GATE(apb1_i2c2_clk, "apb1-i2c2", "apb1", | ||
| 407 | 0x06c, BIT(2), 0); | ||
| 408 | /* Not present on A10 */ | ||
| 409 | static SUNXI_CCU_GATE(apb1_i2c3_clk, "apb1-i2c3", "apb1", | ||
| 410 | 0x06c, BIT(3), 0); | ||
| 411 | static SUNXI_CCU_GATE(apb1_can_clk, "apb1-can", "apb1", | ||
| 412 | 0x06c, BIT(4), 0); | ||
| 413 | static SUNXI_CCU_GATE(apb1_scr_clk, "apb1-scr", "apb1", | ||
| 414 | 0x06c, BIT(5), 0); | ||
| 415 | static SUNXI_CCU_GATE(apb1_ps20_clk, "apb1-ps20", "apb1", | ||
| 416 | 0x06c, BIT(6), 0); | ||
| 417 | static SUNXI_CCU_GATE(apb1_ps21_clk, "apb1-ps21", "apb1", | ||
| 418 | 0x06c, BIT(7), 0); | ||
| 419 | /* Not present on A10 */ | ||
| 420 | static SUNXI_CCU_GATE(apb1_i2c4_clk, "apb1-i2c4", "apb1", | ||
| 421 | 0x06c, BIT(15), 0); | ||
| 422 | static SUNXI_CCU_GATE(apb1_uart0_clk, "apb1-uart0", "apb1", | ||
| 423 | 0x06c, BIT(16), 0); | ||
| 424 | static SUNXI_CCU_GATE(apb1_uart1_clk, "apb1-uart1", "apb1", | ||
| 425 | 0x06c, BIT(17), 0); | ||
| 426 | static SUNXI_CCU_GATE(apb1_uart2_clk, "apb1-uart2", "apb1", | ||
| 427 | 0x06c, BIT(18), 0); | ||
| 428 | static SUNXI_CCU_GATE(apb1_uart3_clk, "apb1-uart3", "apb1", | ||
| 429 | 0x06c, BIT(19), 0); | ||
| 430 | static SUNXI_CCU_GATE(apb1_uart4_clk, "apb1-uart4", "apb1", | ||
| 431 | 0x06c, BIT(20), 0); | ||
| 432 | static SUNXI_CCU_GATE(apb1_uart5_clk, "apb1-uart5", "apb1", | ||
| 433 | 0x06c, BIT(21), 0); | ||
| 434 | static SUNXI_CCU_GATE(apb1_uart6_clk, "apb1-uart6", "apb1", | ||
| 435 | 0x06c, BIT(22), 0); | ||
| 436 | static SUNXI_CCU_GATE(apb1_uart7_clk, "apb1-uart7", "apb1", | ||
| 437 | 0x06c, BIT(23), 0); | ||
| 438 | |||
| 439 | static const char *const mod0_default_parents[] = { "hosc", "pll-periph", | ||
| 440 | "pll-ddr-other" }; | ||
| 441 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, | ||
| 442 | 0, 4, /* M */ | ||
| 443 | 16, 2, /* P */ | ||
| 444 | 24, 2, /* mux */ | ||
| 445 | BIT(31), /* gate */ | ||
| 446 | 0); | ||
| 447 | |||
| 448 | /* Undocumented on A10 */ | ||
| 449 | static SUNXI_CCU_MP_WITH_MUX_GATE(ms_clk, "ms", mod0_default_parents, 0x084, | ||
| 450 | 0, 4, /* M */ | ||
| 451 | 16, 2, /* P */ | ||
| 452 | 24, 2, /* mux */ | ||
| 453 | BIT(31), /* gate */ | ||
| 454 | 0); | ||
| 455 | |||
| 456 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, | ||
| 457 | 0, 4, /* M */ | ||
| 458 | 16, 2, /* P */ | ||
| 459 | 24, 2, /* mux */ | ||
| 460 | BIT(31), /* gate */ | ||
| 461 | 0); | ||
| 462 | |||
| 463 | /* MMC output and sample clocks are not present on A10 */ | ||
| 464 | static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0", | ||
| 465 | 0x088, 8, 3, 0); | ||
| 466 | static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0", | ||
| 467 | 0x088, 20, 3, 0); | ||
| 468 | |||
| 469 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, | ||
| 470 | 0, 4, /* M */ | ||
| 471 | 16, 2, /* P */ | ||
| 472 | 24, 2, /* mux */ | ||
| 473 | BIT(31), /* gate */ | ||
| 474 | 0); | ||
| 475 | |||
| 476 | /* MMC output and sample clocks are not present on A10 */ | ||
| 477 | static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1", | ||
| 478 | 0x08c, 8, 3, 0); | ||
| 479 | static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1", | ||
| 480 | 0x08c, 20, 3, 0); | ||
| 481 | |||
| 482 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, | ||
| 483 | 0, 4, /* M */ | ||
| 484 | 16, 2, /* P */ | ||
| 485 | 24, 2, /* mux */ | ||
| 486 | BIT(31), /* gate */ | ||
| 487 | 0); | ||
| 488 | |||
| 489 | /* MMC output and sample clocks are not present on A10 */ | ||
| 490 | static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2", | ||
| 491 | 0x090, 8, 3, 0); | ||
| 492 | static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2", | ||
| 493 | 0x090, 20, 3, 0); | ||
| 494 | |||
| 495 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, | ||
| 496 | 0, 4, /* M */ | ||
| 497 | 16, 2, /* P */ | ||
| 498 | 24, 2, /* mux */ | ||
| 499 | BIT(31), /* gate */ | ||
| 500 | 0); | ||
| 501 | |||
| 502 | /* MMC output and sample clocks are not present on A10 */ | ||
| 503 | static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3_output", "mmc3", | ||
| 504 | 0x094, 8, 3, 0); | ||
| 505 | static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3_sample", "mmc3", | ||
| 506 | 0x094, 20, 3, 0); | ||
| 507 | |||
| 508 | static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098, | ||
| 509 | 0, 4, /* M */ | ||
| 510 | 16, 2, /* P */ | ||
| 511 | 24, 2, /* mux */ | ||
| 512 | BIT(31), /* gate */ | ||
| 513 | 0); | ||
| 514 | |||
| 515 | static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c, | ||
| 516 | 0, 4, /* M */ | ||
| 517 | 16, 2, /* P */ | ||
| 518 | 24, 2, /* mux */ | ||
| 519 | BIT(31), /* gate */ | ||
| 520 | 0); | ||
| 521 | |||
| 522 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, | ||
| 523 | 0, 4, /* M */ | ||
| 524 | 16, 2, /* P */ | ||
| 525 | 24, 2, /* mux */ | ||
| 526 | BIT(31), /* gate */ | ||
| 527 | 0); | ||
| 528 | |||
| 529 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, | ||
| 530 | 0, 4, /* M */ | ||
| 531 | 16, 2, /* P */ | ||
| 532 | 24, 2, /* mux */ | ||
| 533 | BIT(31), /* gate */ | ||
| 534 | 0); | ||
| 535 | |||
| 536 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, | ||
| 537 | 0, 4, /* M */ | ||
| 538 | 16, 2, /* P */ | ||
| 539 | 24, 2, /* mux */ | ||
| 540 | BIT(31), /* gate */ | ||
| 541 | 0); | ||
| 542 | |||
| 543 | /* Undocumented on A10 */ | ||
| 544 | static SUNXI_CCU_MP_WITH_MUX_GATE(pata_clk, "pata", mod0_default_parents, 0x0ac, | ||
| 545 | 0, 4, /* M */ | ||
| 546 | 16, 2, /* P */ | ||
| 547 | 24, 2, /* mux */ | ||
| 548 | BIT(31), /* gate */ | ||
| 549 | 0); | ||
| 550 | |||
| 551 | /* TODO: Check whether A10 actually supports osc32k as 4th parent? */ | ||
| 552 | static const char *const ir_parents_sun4i[] = { "hosc", "pll-periph", | ||
| 553 | "pll-ddr-other" }; | ||
| 554 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun4i_clk, "ir0", ir_parents_sun4i, 0x0b0, | ||
| 555 | 0, 4, /* M */ | ||
| 556 | 16, 2, /* P */ | ||
| 557 | 24, 2, /* mux */ | ||
| 558 | BIT(31), /* gate */ | ||
| 559 | 0); | ||
| 560 | |||
| 561 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun4i_clk, "ir1", ir_parents_sun4i, 0x0b4, | ||
| 562 | 0, 4, /* M */ | ||
| 563 | 16, 2, /* P */ | ||
| 564 | 24, 2, /* mux */ | ||
| 565 | BIT(31), /* gate */ | ||
| 566 | 0); | ||
| 567 | static const char *const ir_parents_sun7i[] = { "hosc", "pll-periph", | ||
| 568 | "pll-ddr-other", "osc32k" }; | ||
| 569 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun7i_clk, "ir0", ir_parents_sun7i, 0x0b0, | ||
| 570 | 0, 4, /* M */ | ||
| 571 | 16, 2, /* P */ | ||
| 572 | 24, 2, /* mux */ | ||
| 573 | BIT(31), /* gate */ | ||
| 574 | 0); | ||
| 575 | |||
| 576 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun7i_clk, "ir1", ir_parents_sun7i, 0x0b4, | ||
| 577 | 0, 4, /* M */ | ||
| 578 | 16, 2, /* P */ | ||
| 579 | 24, 2, /* mux */ | ||
| 580 | BIT(31), /* gate */ | ||
| 581 | 0); | ||
| 582 | |||
| 583 | static const char *const audio_parents[] = { "pll-audio-8x", "pll-audio-4x", | ||
| 584 | "pll-audio-2x", "pll-audio" }; | ||
| 585 | static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", audio_parents, | ||
| 586 | 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 587 | |||
| 588 | static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", audio_parents, | ||
| 589 | 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 590 | |||
| 591 | /* Undocumented on A10 */ | ||
| 592 | static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", audio_parents, | ||
| 593 | 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 594 | |||
| 595 | static const char *const keypad_parents[] = { "hosc", "losc"}; | ||
| 596 | static const u8 keypad_table[] = { 0, 2 }; | ||
| 597 | static struct ccu_mp keypad_clk = { | ||
| 598 | .enable = BIT(31), | ||
| 599 | .m = _SUNXI_CCU_DIV(0, 5), | ||
| 600 | .p = _SUNXI_CCU_DIV(16, 2), | ||
| 601 | .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), | ||
| 602 | .common = { | ||
| 603 | .reg = 0x0c4, | ||
| 604 | .hw.init = CLK_HW_INIT_PARENTS("keypad", | ||
| 605 | keypad_parents, | ||
| 606 | &ccu_mp_ops, | ||
| 607 | 0), | ||
| 608 | }, | ||
| 609 | }; | ||
| 610 | |||
| 611 | /* | ||
| 612 | * SATA supports external clock as parent via BIT(24) and is probably an | ||
| 613 | * optional crystal or oscillator that can be connected to the | ||
| 614 | * SATA-CLKM / SATA-CLKP pins. | ||
| 615 | */ | ||
| 616 | static const char *const sata_parents[] = {"pll-periph-sata", "sata-ext"}; | ||
| 617 | static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, | ||
| 618 | 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); | ||
| 619 | |||
| 620 | |||
| 621 | static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "pll-periph", | ||
| 622 | 0x0cc, BIT(6), 0); | ||
| 623 | static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "pll-periph", | ||
| 624 | 0x0cc, BIT(7), 0); | ||
| 625 | static SUNXI_CCU_GATE(usb_phy_clk, "usb-phy", "pll-periph", | ||
| 626 | 0x0cc, BIT(8), 0); | ||
| 627 | |||
| 628 | /* TODO: GPS CLK 0x0d0 */ | ||
| 629 | |||
| 630 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0d4, | ||
| 631 | 0, 4, /* M */ | ||
| 632 | 16, 2, /* P */ | ||
| 633 | 24, 2, /* mux */ | ||
| 634 | BIT(31), /* gate */ | ||
| 635 | 0); | ||
| 636 | |||
| 637 | /* Not present on A10 */ | ||
| 638 | static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", audio_parents, | ||
| 639 | 0x0d8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 640 | |||
| 641 | /* Not present on A10 */ | ||
| 642 | static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", audio_parents, | ||
| 643 | 0x0dc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 644 | |||
| 645 | static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr", | ||
| 646 | 0x100, BIT(0), 0); | ||
| 647 | static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "pll-ddr", | ||
| 648 | 0x100, BIT(1), 0); | ||
| 649 | static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "pll-ddr", | ||
| 650 | 0x100, BIT(2), 0); | ||
| 651 | static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "pll-ddr", | ||
| 652 | 0x100, BIT(3), 0); | ||
| 653 | static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr", | ||
| 654 | 0x100, BIT(4), 0); | ||
| 655 | static SUNXI_CCU_GATE(dram_tve0_clk, "dram-tve0", "pll-ddr", | ||
| 656 | 0x100, BIT(5), 0); | ||
| 657 | static SUNXI_CCU_GATE(dram_tve1_clk, "dram-tve1", "pll-ddr", | ||
| 658 | 0x100, BIT(6), 0); | ||
| 659 | |||
| 660 | /* Clock seems to be critical only on sun4i */ | ||
| 661 | static SUNXI_CCU_GATE(dram_out_clk, "dram-out", "pll-ddr", | ||
| 662 | 0x100, BIT(15), CLK_IS_CRITICAL); | ||
| 663 | static SUNXI_CCU_GATE(dram_de_fe1_clk, "dram-de-fe1", "pll-ddr", | ||
| 664 | 0x100, BIT(24), 0); | ||
| 665 | static SUNXI_CCU_GATE(dram_de_fe0_clk, "dram-de-fe0", "pll-ddr", | ||
| 666 | 0x100, BIT(25), 0); | ||
| 667 | static SUNXI_CCU_GATE(dram_de_be0_clk, "dram-de-be0", "pll-ddr", | ||
| 668 | 0x100, BIT(26), 0); | ||
| 669 | static SUNXI_CCU_GATE(dram_de_be1_clk, "dram-de-be1", "pll-ddr", | ||
| 670 | 0x100, BIT(27), 0); | ||
| 671 | static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "pll-ddr", | ||
| 672 | 0x100, BIT(28), 0); | ||
| 673 | static SUNXI_CCU_GATE(dram_ace_clk, "dram-ace", "pll-ddr", | ||
| 674 | 0x100, BIT(29), 0); | ||
| 675 | |||
| 676 | static const char *const de_parents[] = { "pll-video0", "pll-video1", | ||
| 677 | "pll-ddr-other" }; | ||
| 678 | static SUNXI_CCU_M_WITH_MUX_GATE(de_be0_clk, "de-be0", de_parents, | ||
| 679 | 0x104, 0, 4, 24, 2, BIT(31), 0); | ||
| 680 | |||
| 681 | static SUNXI_CCU_M_WITH_MUX_GATE(de_be1_clk, "de-be1", de_parents, | ||
| 682 | 0x108, 0, 4, 24, 2, BIT(31), 0); | ||
| 683 | |||
| 684 | static SUNXI_CCU_M_WITH_MUX_GATE(de_fe0_clk, "de-fe0", de_parents, | ||
| 685 | 0x10c, 0, 4, 24, 2, BIT(31), 0); | ||
| 686 | |||
| 687 | static SUNXI_CCU_M_WITH_MUX_GATE(de_fe1_clk, "de-fe1", de_parents, | ||
| 688 | 0x110, 0, 4, 24, 2, BIT(31), 0); | ||
| 689 | |||
| 690 | /* Undocumented on A10 */ | ||
| 691 | static SUNXI_CCU_M_WITH_MUX_GATE(de_mp_clk, "de-mp", de_parents, | ||
| 692 | 0x114, 0, 4, 24, 2, BIT(31), 0); | ||
| 693 | |||
| 694 | static const char *const disp_parents[] = { "pll-video0", "pll-video1", | ||
| 695 | "pll-video0-2x", "pll-video1-2x" }; | ||
| 696 | static SUNXI_CCU_MUX_WITH_GATE(tcon0_ch0_clk, "tcon0-ch0-sclk", disp_parents, | ||
| 697 | 0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 698 | static SUNXI_CCU_MUX_WITH_GATE(tcon1_ch0_clk, "tcon1-ch0-sclk", disp_parents, | ||
| 699 | 0x11c, 24, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 700 | |||
| 701 | static const char *const csi_sclk_parents[] = { "pll-video0", "pll-ve", | ||
| 702 | "pll-ddr-other", "pll-periph" }; | ||
| 703 | |||
| 704 | static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", | ||
| 705 | csi_sclk_parents, | ||
| 706 | 0x120, 0, 4, 24, 2, BIT(31), 0); | ||
| 707 | |||
| 708 | /* TVD clock setup for A10 */ | ||
| 709 | static const char *const tvd_parents[] = { "pll-video0", "pll-video1" }; | ||
| 710 | static SUNXI_CCU_MUX_WITH_GATE(tvd_sun4i_clk, "tvd", tvd_parents, | ||
| 711 | 0x128, 24, 1, BIT(31), 0); | ||
| 712 | |||
| 713 | /* TVD clock setup for A20 */ | ||
| 714 | static SUNXI_CCU_MP_WITH_MUX_GATE(tvd_sclk2_sun7i_clk, | ||
| 715 | "tvd-sclk2", tvd_parents, | ||
| 716 | 0x128, | ||
| 717 | 0, 4, /* M */ | ||
| 718 | 16, 4, /* P */ | ||
| 719 | 8, 1, /* mux */ | ||
| 720 | BIT(15), /* gate */ | ||
| 721 | 0); | ||
| 722 | |||
| 723 | static SUNXI_CCU_M_WITH_GATE(tvd_sclk1_sun7i_clk, "tvd-sclk1", "tvd-sclk2", | ||
| 724 | 0x128, 0, 4, BIT(31), 0); | ||
| 725 | |||
| 726 | static SUNXI_CCU_M_WITH_MUX_GATE(tcon0_ch1_sclk2_clk, "tcon0-ch1-sclk2", | ||
| 727 | disp_parents, | ||
| 728 | 0x12c, 0, 4, 24, 2, BIT(31), | ||
| 729 | CLK_SET_RATE_PARENT); | ||
| 730 | |||
| 731 | static SUNXI_CCU_M_WITH_GATE(tcon0_ch1_clk, | ||
| 732 | "tcon0-ch1-sclk1", "tcon0-ch1-sclk2", | ||
| 733 | 0x12c, 11, 1, BIT(15), | ||
| 734 | CLK_SET_RATE_PARENT); | ||
| 735 | |||
| 736 | static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_ch1_sclk2_clk, "tcon1-ch1-sclk2", | ||
| 737 | disp_parents, | ||
| 738 | 0x130, 0, 4, 24, 2, BIT(31), | ||
| 739 | CLK_SET_RATE_PARENT); | ||
| 740 | |||
| 741 | static SUNXI_CCU_M_WITH_GATE(tcon1_ch1_clk, | ||
| 742 | "tcon1-ch1-sclk1", "tcon1-ch1-sclk2", | ||
| 743 | 0x130, 11, 1, BIT(15), | ||
| 744 | CLK_SET_RATE_PARENT); | ||
| 745 | |||
| 746 | static const char *const csi_parents[] = { "hosc", "pll-video0", "pll-video1", | ||
| 747 | "pll-video0-2x", "pll-video1-2x"}; | ||
| 748 | static const u8 csi_table[] = { 0, 1, 2, 5, 6}; | ||
| 749 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_clk, "csi0", | ||
| 750 | csi_parents, csi_table, | ||
| 751 | 0x134, 0, 5, 24, 3, BIT(31), 0); | ||
| 752 | |||
| 753 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_clk, "csi1", | ||
| 754 | csi_parents, csi_table, | ||
| 755 | 0x138, 0, 5, 24, 3, BIT(31), 0); | ||
| 756 | |||
| 757 | static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c, 16, 8, BIT(31), 0); | ||
| 758 | |||
| 759 | static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", | ||
| 760 | 0x140, BIT(31), CLK_SET_RATE_PARENT); | ||
| 761 | |||
| 762 | static SUNXI_CCU_GATE(avs_clk, "avs", "hosc", 0x144, BIT(31), 0); | ||
| 763 | |||
| 764 | static const char *const ace_parents[] = { "pll-ve", "pll-ddr-other" }; | ||
| 765 | static SUNXI_CCU_M_WITH_MUX_GATE(ace_clk, "ace", ace_parents, | ||
| 766 | 0x148, 0, 4, 24, 1, BIT(31), 0); | ||
| 767 | |||
| 768 | static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", disp_parents, | ||
| 769 | 0x150, 0, 4, 24, 2, BIT(31), | ||
| 770 | CLK_SET_RATE_PARENT); | ||
| 771 | |||
| 772 | static const char *const gpu_parents_sun4i[] = { "pll-video0", "pll-ve", | ||
| 773 | "pll-ddr-other", | ||
| 774 | "pll-video1" }; | ||
| 775 | static SUNXI_CCU_M_WITH_MUX_GATE(gpu_sun4i_clk, "gpu", gpu_parents_sun4i, | ||
| 776 | 0x154, 0, 4, 24, 2, BIT(31), | ||
| 777 | CLK_SET_RATE_PARENT); | ||
| 778 | |||
| 779 | static const char *const gpu_parents_sun7i[] = { "pll-video0", "pll-ve", | ||
| 780 | "pll-ddr-other", "pll-video1", | ||
| 781 | "pll-gpu" }; | ||
| 782 | static const u8 gpu_table_sun7i[] = { 0, 1, 2, 3, 4 }; | ||
| 783 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_sun7i_clk, "gpu", | ||
| 784 | gpu_parents_sun7i, gpu_table_sun7i, | ||
| 785 | 0x154, 0, 4, 24, 3, BIT(31), | ||
| 786 | CLK_SET_RATE_PARENT); | ||
| 787 | |||
| 788 | static const char *const mbus_sun4i_parents[] = { "hosc", "pll-periph", | ||
| 789 | "pll-ddr-other" }; | ||
| 790 | static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun4i_clk, "mbus", mbus_sun4i_parents, | ||
| 791 | 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), | ||
| 792 | 0); | ||
| 793 | static const char *const mbus_sun7i_parents[] = { "hosc", "pll-periph-base", | ||
| 794 | "pll-ddr-other" }; | ||
| 795 | static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun7i_clk, "mbus", mbus_sun7i_parents, | ||
| 796 | 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), | ||
| 797 | CLK_IS_CRITICAL); | ||
| 798 | |||
| 799 | static SUNXI_CCU_GATE(hdmi1_slow_clk, "hdmi1-slow", "hosc", 0x178, BIT(31), 0); | ||
| 800 | |||
| 801 | static const char *const hdmi1_parents[] = { "pll-video0", "pll-video1" }; | ||
| 802 | static const u8 hdmi1_table[] = { 0, 1}; | ||
| 803 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi1_clk, "hdmi1", | ||
| 804 | hdmi1_parents, hdmi1_table, | ||
| 805 | 0x17c, 0, 4, 24, 2, BIT(31), | ||
| 806 | CLK_SET_RATE_PARENT); | ||
| 807 | |||
| 808 | static const char *const out_parents[] = { "hosc", "osc32k", "hosc" }; | ||
| 809 | static const struct ccu_mux_fixed_prediv clk_out_predivs[] = { | ||
| 810 | { .index = 0, .div = 750, }, | ||
| 811 | }; | ||
| 812 | |||
| 813 | static struct ccu_mp out_a_clk = { | ||
| 814 | .enable = BIT(31), | ||
| 815 | .m = _SUNXI_CCU_DIV(8, 5), | ||
| 816 | .p = _SUNXI_CCU_DIV(20, 2), | ||
| 817 | .mux = { | ||
| 818 | .shift = 24, | ||
| 819 | .width = 2, | ||
| 820 | .fixed_predivs = clk_out_predivs, | ||
| 821 | .n_predivs = ARRAY_SIZE(clk_out_predivs), | ||
| 822 | }, | ||
| 823 | .common = { | ||
| 824 | .reg = 0x1f0, | ||
| 825 | .features = CCU_FEATURE_FIXED_PREDIV, | ||
| 826 | .hw.init = CLK_HW_INIT_PARENTS("out-a", | ||
| 827 | out_parents, | ||
| 828 | &ccu_mp_ops, | ||
| 829 | 0), | ||
| 830 | }, | ||
| 831 | }; | ||
| 832 | static struct ccu_mp out_b_clk = { | ||
| 833 | .enable = BIT(31), | ||
| 834 | .m = _SUNXI_CCU_DIV(8, 5), | ||
| 835 | .p = _SUNXI_CCU_DIV(20, 2), | ||
| 836 | .mux = { | ||
| 837 | .shift = 24, | ||
| 838 | .width = 2, | ||
| 839 | .fixed_predivs = clk_out_predivs, | ||
| 840 | .n_predivs = ARRAY_SIZE(clk_out_predivs), | ||
| 841 | }, | ||
| 842 | .common = { | ||
| 843 | .reg = 0x1f4, | ||
| 844 | .features = CCU_FEATURE_FIXED_PREDIV, | ||
| 845 | .hw.init = CLK_HW_INIT_PARENTS("out-b", | ||
| 846 | out_parents, | ||
| 847 | &ccu_mp_ops, | ||
| 848 | 0), | ||
| 849 | }, | ||
| 850 | }; | ||
| 851 | |||
| 852 | static struct ccu_common *sun4i_sun7i_ccu_clks[] = { | ||
| 853 | &hosc_clk.common, | ||
| 854 | &pll_core_clk.common, | ||
| 855 | &pll_audio_base_clk.common, | ||
| 856 | &pll_video0_clk.common, | ||
| 857 | &pll_ve_sun4i_clk.common, | ||
| 858 | &pll_ve_sun7i_clk.common, | ||
| 859 | &pll_ddr_base_clk.common, | ||
| 860 | &pll_ddr_clk.common, | ||
| 861 | &pll_ddr_other_clk.common, | ||
| 862 | &pll_periph_base_clk.common, | ||
| 863 | &pll_periph_sata_clk.common, | ||
| 864 | &pll_video1_clk.common, | ||
| 865 | &pll_gpu_clk.common, | ||
| 866 | &cpu_clk.common, | ||
| 867 | &axi_clk.common, | ||
| 868 | &axi_dram_clk.common, | ||
| 869 | &ahb_sun4i_clk.common, | ||
| 870 | &ahb_sun7i_clk.common, | ||
| 871 | &apb0_clk.common, | ||
| 872 | &apb1_clk.common, | ||
| 873 | &ahb_otg_clk.common, | ||
| 874 | &ahb_ehci0_clk.common, | ||
| 875 | &ahb_ohci0_clk.common, | ||
| 876 | &ahb_ehci1_clk.common, | ||
| 877 | &ahb_ohci1_clk.common, | ||
| 878 | &ahb_ss_clk.common, | ||
| 879 | &ahb_dma_clk.common, | ||
| 880 | &ahb_bist_clk.common, | ||
| 881 | &ahb_mmc0_clk.common, | ||
| 882 | &ahb_mmc1_clk.common, | ||
| 883 | &ahb_mmc2_clk.common, | ||
| 884 | &ahb_mmc3_clk.common, | ||
| 885 | &ahb_ms_clk.common, | ||
| 886 | &ahb_nand_clk.common, | ||
| 887 | &ahb_sdram_clk.common, | ||
| 888 | &ahb_ace_clk.common, | ||
| 889 | &ahb_emac_clk.common, | ||
| 890 | &ahb_ts_clk.common, | ||
| 891 | &ahb_spi0_clk.common, | ||
| 892 | &ahb_spi1_clk.common, | ||
| 893 | &ahb_spi2_clk.common, | ||
| 894 | &ahb_spi3_clk.common, | ||
| 895 | &ahb_pata_clk.common, | ||
| 896 | &ahb_sata_clk.common, | ||
| 897 | &ahb_gps_clk.common, | ||
| 898 | &ahb_hstimer_clk.common, | ||
| 899 | &ahb_ve_clk.common, | ||
| 900 | &ahb_tvd_clk.common, | ||
| 901 | &ahb_tve0_clk.common, | ||
| 902 | &ahb_tve1_clk.common, | ||
| 903 | &ahb_lcd0_clk.common, | ||
| 904 | &ahb_lcd1_clk.common, | ||
| 905 | &ahb_csi0_clk.common, | ||
| 906 | &ahb_csi1_clk.common, | ||
| 907 | &ahb_hdmi1_clk.common, | ||
| 908 | &ahb_hdmi0_clk.common, | ||
| 909 | &ahb_de_be0_clk.common, | ||
| 910 | &ahb_de_be1_clk.common, | ||
| 911 | &ahb_de_fe0_clk.common, | ||
| 912 | &ahb_de_fe1_clk.common, | ||
| 913 | &ahb_gmac_clk.common, | ||
| 914 | &ahb_mp_clk.common, | ||
| 915 | &ahb_gpu_clk.common, | ||
| 916 | &apb0_codec_clk.common, | ||
| 917 | &apb0_spdif_clk.common, | ||
| 918 | &apb0_ac97_clk.common, | ||
| 919 | &apb0_i2s0_clk.common, | ||
| 920 | &apb0_i2s1_clk.common, | ||
| 921 | &apb0_pio_clk.common, | ||
| 922 | &apb0_ir0_clk.common, | ||
| 923 | &apb0_ir1_clk.common, | ||
| 924 | &apb0_i2s2_clk.common, | ||
| 925 | &apb0_keypad_clk.common, | ||
| 926 | &apb1_i2c0_clk.common, | ||
| 927 | &apb1_i2c1_clk.common, | ||
| 928 | &apb1_i2c2_clk.common, | ||
| 929 | &apb1_i2c3_clk.common, | ||
| 930 | &apb1_can_clk.common, | ||
| 931 | &apb1_scr_clk.common, | ||
| 932 | &apb1_ps20_clk.common, | ||
| 933 | &apb1_ps21_clk.common, | ||
| 934 | &apb1_i2c4_clk.common, | ||
| 935 | &apb1_uart0_clk.common, | ||
| 936 | &apb1_uart1_clk.common, | ||
| 937 | &apb1_uart2_clk.common, | ||
| 938 | &apb1_uart3_clk.common, | ||
| 939 | &apb1_uart4_clk.common, | ||
| 940 | &apb1_uart5_clk.common, | ||
| 941 | &apb1_uart6_clk.common, | ||
| 942 | &apb1_uart7_clk.common, | ||
| 943 | &nand_clk.common, | ||
| 944 | &ms_clk.common, | ||
| 945 | &mmc0_clk.common, | ||
| 946 | &mmc0_output_clk.common, | ||
| 947 | &mmc0_sample_clk.common, | ||
| 948 | &mmc1_clk.common, | ||
| 949 | &mmc1_output_clk.common, | ||
| 950 | &mmc1_sample_clk.common, | ||
| 951 | &mmc2_clk.common, | ||
| 952 | &mmc2_output_clk.common, | ||
| 953 | &mmc2_sample_clk.common, | ||
| 954 | &mmc3_clk.common, | ||
| 955 | &mmc3_output_clk.common, | ||
| 956 | &mmc3_sample_clk.common, | ||
| 957 | &ts_clk.common, | ||
| 958 | &ss_clk.common, | ||
| 959 | &spi0_clk.common, | ||
| 960 | &spi1_clk.common, | ||
| 961 | &spi2_clk.common, | ||
| 962 | &pata_clk.common, | ||
| 963 | &ir0_sun4i_clk.common, | ||
| 964 | &ir1_sun4i_clk.common, | ||
| 965 | &ir0_sun7i_clk.common, | ||
| 966 | &ir1_sun7i_clk.common, | ||
| 967 | &i2s0_clk.common, | ||
| 968 | &ac97_clk.common, | ||
| 969 | &spdif_clk.common, | ||
| 970 | &keypad_clk.common, | ||
| 971 | &sata_clk.common, | ||
| 972 | &usb_ohci0_clk.common, | ||
| 973 | &usb_ohci1_clk.common, | ||
| 974 | &usb_phy_clk.common, | ||
| 975 | &spi3_clk.common, | ||
| 976 | &i2s1_clk.common, | ||
| 977 | &i2s2_clk.common, | ||
| 978 | &dram_ve_clk.common, | ||
| 979 | &dram_csi0_clk.common, | ||
| 980 | &dram_csi1_clk.common, | ||
| 981 | &dram_ts_clk.common, | ||
| 982 | &dram_tvd_clk.common, | ||
| 983 | &dram_tve0_clk.common, | ||
| 984 | &dram_tve1_clk.common, | ||
| 985 | &dram_out_clk.common, | ||
| 986 | &dram_de_fe1_clk.common, | ||
| 987 | &dram_de_fe0_clk.common, | ||
| 988 | &dram_de_be0_clk.common, | ||
| 989 | &dram_de_be1_clk.common, | ||
| 990 | &dram_mp_clk.common, | ||
| 991 | &dram_ace_clk.common, | ||
| 992 | &de_be0_clk.common, | ||
| 993 | &de_be1_clk.common, | ||
| 994 | &de_fe0_clk.common, | ||
| 995 | &de_fe1_clk.common, | ||
| 996 | &de_mp_clk.common, | ||
| 997 | &tcon0_ch0_clk.common, | ||
| 998 | &tcon1_ch0_clk.common, | ||
| 999 | &csi_sclk_clk.common, | ||
| 1000 | &tvd_sun4i_clk.common, | ||
| 1001 | &tvd_sclk1_sun7i_clk.common, | ||
| 1002 | &tvd_sclk2_sun7i_clk.common, | ||
| 1003 | &tcon0_ch1_sclk2_clk.common, | ||
| 1004 | &tcon0_ch1_clk.common, | ||
| 1005 | &tcon1_ch1_sclk2_clk.common, | ||
| 1006 | &tcon1_ch1_clk.common, | ||
| 1007 | &csi0_clk.common, | ||
| 1008 | &csi1_clk.common, | ||
| 1009 | &ve_clk.common, | ||
| 1010 | &codec_clk.common, | ||
| 1011 | &avs_clk.common, | ||
| 1012 | &ace_clk.common, | ||
| 1013 | &hdmi_clk.common, | ||
| 1014 | &gpu_sun4i_clk.common, | ||
| 1015 | &gpu_sun7i_clk.common, | ||
| 1016 | &mbus_sun4i_clk.common, | ||
| 1017 | &mbus_sun7i_clk.common, | ||
| 1018 | &hdmi1_slow_clk.common, | ||
| 1019 | &hdmi1_clk.common, | ||
| 1020 | &out_a_clk.common, | ||
| 1021 | &out_b_clk.common | ||
| 1022 | }; | ||
| 1023 | |||
| 1024 | /* Post-divider for pll-audio is hardcoded to 4 */ | ||
| 1025 | static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", | ||
| 1026 | "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); | ||
| 1027 | static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", | ||
| 1028 | "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); | ||
| 1029 | static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", | ||
| 1030 | "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); | ||
| 1031 | static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", | ||
| 1032 | "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); | ||
| 1033 | static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", | ||
| 1034 | "pll-video0", 1, 2, CLK_SET_RATE_PARENT); | ||
| 1035 | static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", | ||
| 1036 | "pll-video1", 1, 2, CLK_SET_RATE_PARENT); | ||
| 1037 | |||
| 1038 | |||
| 1039 | static struct clk_hw_onecell_data sun4i_a10_hw_clks = { | ||
| 1040 | .hws = { | ||
| 1041 | [CLK_HOSC] = &hosc_clk.common.hw, | ||
| 1042 | [CLK_PLL_CORE] = &pll_core_clk.common.hw, | ||
| 1043 | [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | ||
| 1044 | [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | ||
| 1045 | [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | ||
| 1046 | [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | ||
| 1047 | [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | ||
| 1048 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | ||
| 1049 | [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | ||
| 1050 | [CLK_PLL_VE] = &pll_ve_sun4i_clk.common.hw, | ||
| 1051 | [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, | ||
| 1052 | [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, | ||
| 1053 | [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, | ||
| 1054 | [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, | ||
| 1055 | [CLK_PLL_PERIPH] = &pll_periph_clk.hw, | ||
| 1056 | [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, | ||
| 1057 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | ||
| 1058 | [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | ||
| 1059 | [CLK_CPU] = &cpu_clk.common.hw, | ||
| 1060 | [CLK_AXI] = &axi_clk.common.hw, | ||
| 1061 | [CLK_AXI_DRAM] = &axi_dram_clk.common.hw, | ||
| 1062 | [CLK_AHB] = &ahb_sun4i_clk.common.hw, | ||
| 1063 | [CLK_APB0] = &apb0_clk.common.hw, | ||
| 1064 | [CLK_APB1] = &apb1_clk.common.hw, | ||
| 1065 | [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, | ||
| 1066 | [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, | ||
| 1067 | [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, | ||
| 1068 | [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, | ||
| 1069 | [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, | ||
| 1070 | [CLK_AHB_SS] = &ahb_ss_clk.common.hw, | ||
| 1071 | [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, | ||
| 1072 | [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, | ||
| 1073 | [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, | ||
| 1074 | [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, | ||
| 1075 | [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, | ||
| 1076 | [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, | ||
| 1077 | [CLK_AHB_MS] = &ahb_ms_clk.common.hw, | ||
| 1078 | [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, | ||
| 1079 | [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, | ||
| 1080 | [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, | ||
| 1081 | [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, | ||
| 1082 | [CLK_AHB_TS] = &ahb_ts_clk.common.hw, | ||
| 1083 | [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, | ||
| 1084 | [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, | ||
| 1085 | [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, | ||
| 1086 | [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, | ||
| 1087 | [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, | ||
| 1088 | [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, | ||
| 1089 | [CLK_AHB_GPS] = &ahb_gps_clk.common.hw, | ||
| 1090 | [CLK_AHB_VE] = &ahb_ve_clk.common.hw, | ||
| 1091 | [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, | ||
| 1092 | [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, | ||
| 1093 | [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, | ||
| 1094 | [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, | ||
| 1095 | [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, | ||
| 1096 | [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, | ||
| 1097 | [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, | ||
| 1098 | [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, | ||
| 1099 | [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, | ||
| 1100 | [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, | ||
| 1101 | [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, | ||
| 1102 | [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, | ||
| 1103 | [CLK_AHB_MP] = &ahb_mp_clk.common.hw, | ||
| 1104 | [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, | ||
| 1105 | [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, | ||
| 1106 | [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, | ||
| 1107 | [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, | ||
| 1108 | [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, | ||
| 1109 | [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | ||
| 1110 | [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, | ||
| 1111 | [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, | ||
| 1112 | [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, | ||
| 1113 | [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, | ||
| 1114 | [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, | ||
| 1115 | [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, | ||
| 1116 | [CLK_APB1_CAN] = &apb1_can_clk.common.hw, | ||
| 1117 | [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, | ||
| 1118 | [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, | ||
| 1119 | [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, | ||
| 1120 | [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, | ||
| 1121 | [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, | ||
| 1122 | [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, | ||
| 1123 | [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, | ||
| 1124 | [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, | ||
| 1125 | [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, | ||
| 1126 | [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, | ||
| 1127 | [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, | ||
| 1128 | [CLK_NAND] = &nand_clk.common.hw, | ||
| 1129 | [CLK_MS] = &ms_clk.common.hw, | ||
| 1130 | [CLK_MMC0] = &mmc0_clk.common.hw, | ||
| 1131 | [CLK_MMC1] = &mmc1_clk.common.hw, | ||
| 1132 | [CLK_MMC2] = &mmc2_clk.common.hw, | ||
| 1133 | [CLK_MMC3] = &mmc3_clk.common.hw, | ||
| 1134 | [CLK_TS] = &ts_clk.common.hw, | ||
| 1135 | [CLK_SS] = &ss_clk.common.hw, | ||
| 1136 | [CLK_SPI0] = &spi0_clk.common.hw, | ||
| 1137 | [CLK_SPI1] = &spi1_clk.common.hw, | ||
| 1138 | [CLK_SPI2] = &spi2_clk.common.hw, | ||
| 1139 | [CLK_PATA] = &pata_clk.common.hw, | ||
| 1140 | [CLK_IR0] = &ir0_sun4i_clk.common.hw, | ||
| 1141 | [CLK_IR1] = &ir1_sun4i_clk.common.hw, | ||
| 1142 | [CLK_I2S0] = &i2s0_clk.common.hw, | ||
| 1143 | [CLK_AC97] = &ac97_clk.common.hw, | ||
| 1144 | [CLK_SPDIF] = &spdif_clk.common.hw, | ||
| 1145 | [CLK_KEYPAD] = &keypad_clk.common.hw, | ||
| 1146 | [CLK_SATA] = &sata_clk.common.hw, | ||
| 1147 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | ||
| 1148 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | ||
| 1149 | [CLK_USB_PHY] = &usb_phy_clk.common.hw, | ||
| 1150 | /* CLK_GPS is unimplemented */ | ||
| 1151 | [CLK_SPI3] = &spi3_clk.common.hw, | ||
| 1152 | [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | ||
| 1153 | [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | ||
| 1154 | [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | ||
| 1155 | [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | ||
| 1156 | [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | ||
| 1157 | [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, | ||
| 1158 | [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, | ||
| 1159 | [CLK_DRAM_OUT] = &dram_out_clk.common.hw, | ||
| 1160 | [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, | ||
| 1161 | [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, | ||
| 1162 | [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, | ||
| 1163 | [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, | ||
| 1164 | [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | ||
| 1165 | [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, | ||
| 1166 | [CLK_DE_BE0] = &de_be0_clk.common.hw, | ||
| 1167 | [CLK_DE_BE1] = &de_be1_clk.common.hw, | ||
| 1168 | [CLK_DE_FE0] = &de_fe0_clk.common.hw, | ||
| 1169 | [CLK_DE_FE1] = &de_fe1_clk.common.hw, | ||
| 1170 | [CLK_DE_MP] = &de_mp_clk.common.hw, | ||
| 1171 | [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, | ||
| 1172 | [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, | ||
| 1173 | [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | ||
| 1174 | [CLK_TVD] = &tvd_sun4i_clk.common.hw, | ||
| 1175 | [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, | ||
| 1176 | [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, | ||
| 1177 | [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, | ||
| 1178 | [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, | ||
| 1179 | [CLK_CSI0] = &csi0_clk.common.hw, | ||
| 1180 | [CLK_CSI1] = &csi1_clk.common.hw, | ||
| 1181 | [CLK_VE] = &ve_clk.common.hw, | ||
| 1182 | [CLK_CODEC] = &codec_clk.common.hw, | ||
| 1183 | [CLK_AVS] = &avs_clk.common.hw, | ||
| 1184 | [CLK_ACE] = &ace_clk.common.hw, | ||
| 1185 | [CLK_HDMI] = &hdmi_clk.common.hw, | ||
| 1186 | [CLK_GPU] = &gpu_sun7i_clk.common.hw, | ||
| 1187 | [CLK_MBUS] = &mbus_sun4i_clk.common.hw, | ||
| 1188 | }, | ||
| 1189 | .num = CLK_NUMBER_SUN4I, | ||
| 1190 | }; | ||
| 1191 | static struct clk_hw_onecell_data sun7i_a20_hw_clks = { | ||
| 1192 | .hws = { | ||
| 1193 | [CLK_HOSC] = &hosc_clk.common.hw, | ||
| 1194 | [CLK_PLL_CORE] = &pll_core_clk.common.hw, | ||
| 1195 | [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | ||
| 1196 | [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | ||
| 1197 | [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | ||
| 1198 | [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | ||
| 1199 | [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | ||
| 1200 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | ||
| 1201 | [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | ||
| 1202 | [CLK_PLL_VE] = &pll_ve_sun7i_clk.common.hw, | ||
| 1203 | [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, | ||
| 1204 | [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, | ||
| 1205 | [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, | ||
| 1206 | [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, | ||
| 1207 | [CLK_PLL_PERIPH] = &pll_periph_clk.hw, | ||
| 1208 | [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, | ||
| 1209 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | ||
| 1210 | [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | ||
| 1211 | [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, | ||
| 1212 | [CLK_CPU] = &cpu_clk.common.hw, | ||
| 1213 | [CLK_AXI] = &axi_clk.common.hw, | ||
| 1214 | [CLK_AHB] = &ahb_sun7i_clk.common.hw, | ||
| 1215 | [CLK_APB0] = &apb0_clk.common.hw, | ||
| 1216 | [CLK_APB1] = &apb1_clk.common.hw, | ||
| 1217 | [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, | ||
| 1218 | [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, | ||
| 1219 | [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, | ||
| 1220 | [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, | ||
| 1221 | [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, | ||
| 1222 | [CLK_AHB_SS] = &ahb_ss_clk.common.hw, | ||
| 1223 | [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, | ||
| 1224 | [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, | ||
| 1225 | [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, | ||
| 1226 | [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, | ||
| 1227 | [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, | ||
| 1228 | [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, | ||
| 1229 | [CLK_AHB_MS] = &ahb_ms_clk.common.hw, | ||
| 1230 | [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, | ||
| 1231 | [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, | ||
| 1232 | [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, | ||
| 1233 | [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, | ||
| 1234 | [CLK_AHB_TS] = &ahb_ts_clk.common.hw, | ||
| 1235 | [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, | ||
| 1236 | [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, | ||
| 1237 | [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, | ||
| 1238 | [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, | ||
| 1239 | [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, | ||
| 1240 | [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, | ||
| 1241 | [CLK_AHB_HSTIMER] = &ahb_hstimer_clk.common.hw, | ||
| 1242 | [CLK_AHB_VE] = &ahb_ve_clk.common.hw, | ||
| 1243 | [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, | ||
| 1244 | [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, | ||
| 1245 | [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, | ||
| 1246 | [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, | ||
| 1247 | [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, | ||
| 1248 | [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, | ||
| 1249 | [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, | ||
| 1250 | [CLK_AHB_HDMI1] = &ahb_hdmi1_clk.common.hw, | ||
| 1251 | [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, | ||
| 1252 | [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, | ||
| 1253 | [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, | ||
| 1254 | [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, | ||
| 1255 | [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, | ||
| 1256 | [CLK_AHB_GMAC] = &ahb_gmac_clk.common.hw, | ||
| 1257 | [CLK_AHB_MP] = &ahb_mp_clk.common.hw, | ||
| 1258 | [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, | ||
| 1259 | [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, | ||
| 1260 | [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, | ||
| 1261 | [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, | ||
| 1262 | [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, | ||
| 1263 | [CLK_APB0_I2S1] = &apb0_i2s1_clk.common.hw, | ||
| 1264 | [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | ||
| 1265 | [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, | ||
| 1266 | [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, | ||
| 1267 | [CLK_APB0_I2S2] = &apb0_i2s2_clk.common.hw, | ||
| 1268 | [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, | ||
| 1269 | [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, | ||
| 1270 | [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, | ||
| 1271 | [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, | ||
| 1272 | [CLK_APB1_I2C3] = &apb1_i2c3_clk.common.hw, | ||
| 1273 | [CLK_APB1_CAN] = &apb1_can_clk.common.hw, | ||
| 1274 | [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, | ||
| 1275 | [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, | ||
| 1276 | [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, | ||
| 1277 | [CLK_APB1_I2C4] = &apb1_i2c4_clk.common.hw, | ||
| 1278 | [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, | ||
| 1279 | [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, | ||
| 1280 | [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, | ||
| 1281 | [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, | ||
| 1282 | [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, | ||
| 1283 | [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, | ||
| 1284 | [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, | ||
| 1285 | [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, | ||
| 1286 | [CLK_NAND] = &nand_clk.common.hw, | ||
| 1287 | [CLK_MS] = &ms_clk.common.hw, | ||
| 1288 | [CLK_MMC0] = &mmc0_clk.common.hw, | ||
| 1289 | [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, | ||
| 1290 | [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, | ||
| 1291 | [CLK_MMC1] = &mmc1_clk.common.hw, | ||
| 1292 | [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, | ||
| 1293 | [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, | ||
| 1294 | [CLK_MMC2] = &mmc2_clk.common.hw, | ||
| 1295 | [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw, | ||
| 1296 | [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw, | ||
| 1297 | [CLK_MMC3] = &mmc3_clk.common.hw, | ||
| 1298 | [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw, | ||
| 1299 | [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw, | ||
| 1300 | [CLK_TS] = &ts_clk.common.hw, | ||
| 1301 | [CLK_SS] = &ss_clk.common.hw, | ||
| 1302 | [CLK_SPI0] = &spi0_clk.common.hw, | ||
| 1303 | [CLK_SPI1] = &spi1_clk.common.hw, | ||
| 1304 | [CLK_SPI2] = &spi2_clk.common.hw, | ||
| 1305 | [CLK_PATA] = &pata_clk.common.hw, | ||
| 1306 | [CLK_IR0] = &ir0_sun7i_clk.common.hw, | ||
| 1307 | [CLK_IR1] = &ir1_sun7i_clk.common.hw, | ||
| 1308 | [CLK_I2S0] = &i2s0_clk.common.hw, | ||
| 1309 | [CLK_AC97] = &ac97_clk.common.hw, | ||
| 1310 | [CLK_SPDIF] = &spdif_clk.common.hw, | ||
| 1311 | [CLK_KEYPAD] = &keypad_clk.common.hw, | ||
| 1312 | [CLK_SATA] = &sata_clk.common.hw, | ||
| 1313 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | ||
| 1314 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | ||
| 1315 | [CLK_USB_PHY] = &usb_phy_clk.common.hw, | ||
| 1316 | /* CLK_GPS is unimplemented */ | ||
| 1317 | [CLK_SPI3] = &spi3_clk.common.hw, | ||
| 1318 | [CLK_I2S1] = &i2s1_clk.common.hw, | ||
| 1319 | [CLK_I2S2] = &i2s2_clk.common.hw, | ||
| 1320 | [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | ||
| 1321 | [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | ||
| 1322 | [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | ||
| 1323 | [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | ||
| 1324 | [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | ||
| 1325 | [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, | ||
| 1326 | [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, | ||
| 1327 | [CLK_DRAM_OUT] = &dram_out_clk.common.hw, | ||
| 1328 | [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, | ||
| 1329 | [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, | ||
| 1330 | [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, | ||
| 1331 | [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, | ||
| 1332 | [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | ||
| 1333 | [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, | ||
| 1334 | [CLK_DE_BE0] = &de_be0_clk.common.hw, | ||
| 1335 | [CLK_DE_BE1] = &de_be1_clk.common.hw, | ||
| 1336 | [CLK_DE_FE0] = &de_fe0_clk.common.hw, | ||
| 1337 | [CLK_DE_FE1] = &de_fe1_clk.common.hw, | ||
| 1338 | [CLK_DE_MP] = &de_mp_clk.common.hw, | ||
| 1339 | [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, | ||
| 1340 | [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, | ||
| 1341 | [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | ||
| 1342 | [CLK_TVD_SCLK2] = &tvd_sclk2_sun7i_clk.common.hw, | ||
| 1343 | [CLK_TVD] = &tvd_sclk1_sun7i_clk.common.hw, | ||
| 1344 | [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, | ||
| 1345 | [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, | ||
| 1346 | [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, | ||
| 1347 | [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, | ||
| 1348 | [CLK_CSI0] = &csi0_clk.common.hw, | ||
| 1349 | [CLK_CSI1] = &csi1_clk.common.hw, | ||
| 1350 | [CLK_VE] = &ve_clk.common.hw, | ||
| 1351 | [CLK_CODEC] = &codec_clk.common.hw, | ||
| 1352 | [CLK_AVS] = &avs_clk.common.hw, | ||
| 1353 | [CLK_ACE] = &ace_clk.common.hw, | ||
| 1354 | [CLK_HDMI] = &hdmi_clk.common.hw, | ||
| 1355 | [CLK_GPU] = &gpu_sun7i_clk.common.hw, | ||
| 1356 | [CLK_MBUS] = &mbus_sun7i_clk.common.hw, | ||
| 1357 | [CLK_HDMI1_SLOW] = &hdmi1_slow_clk.common.hw, | ||
| 1358 | [CLK_HDMI1] = &hdmi1_clk.common.hw, | ||
| 1359 | [CLK_OUT_A] = &out_a_clk.common.hw, | ||
| 1360 | [CLK_OUT_B] = &out_b_clk.common.hw, | ||
| 1361 | }, | ||
| 1362 | .num = CLK_NUMBER_SUN7I, | ||
| 1363 | }; | ||
| 1364 | |||
| 1365 | static struct ccu_reset_map sunxi_a10_a20_ccu_resets[] = { | ||
| 1366 | [RST_USB_PHY0] = { 0x0cc, BIT(0) }, | ||
| 1367 | [RST_USB_PHY1] = { 0x0cc, BIT(1) }, | ||
| 1368 | [RST_USB_PHY2] = { 0x0cc, BIT(2) }, | ||
| 1369 | [RST_GPS] = { 0x0d0, BIT(0) }, | ||
| 1370 | [RST_DE_BE0] = { 0x104, BIT(30) }, | ||
| 1371 | [RST_DE_BE1] = { 0x108, BIT(30) }, | ||
| 1372 | [RST_DE_FE0] = { 0x10c, BIT(30) }, | ||
| 1373 | [RST_DE_FE1] = { 0x110, BIT(30) }, | ||
| 1374 | [RST_DE_MP] = { 0x114, BIT(30) }, | ||
| 1375 | [RST_TVE0] = { 0x118, BIT(29) }, | ||
| 1376 | [RST_TCON0] = { 0x118, BIT(30) }, | ||
| 1377 | [RST_TVE1] = { 0x11c, BIT(29) }, | ||
| 1378 | [RST_TCON1] = { 0x11c, BIT(30) }, | ||
| 1379 | [RST_CSI0] = { 0x134, BIT(30) }, | ||
| 1380 | [RST_CSI1] = { 0x138, BIT(30) }, | ||
| 1381 | [RST_VE] = { 0x13c, BIT(0) }, | ||
| 1382 | [RST_ACE] = { 0x148, BIT(16) }, | ||
| 1383 | [RST_LVDS] = { 0x14c, BIT(0) }, | ||
| 1384 | [RST_GPU] = { 0x154, BIT(30) }, | ||
| 1385 | [RST_HDMI_H] = { 0x170, BIT(0) }, | ||
| 1386 | [RST_HDMI_SYS] = { 0x170, BIT(1) }, | ||
| 1387 | [RST_HDMI_AUDIO_DMA] = { 0x170, BIT(2) }, | ||
| 1388 | }; | ||
| 1389 | |||
| 1390 | static const struct sunxi_ccu_desc sun4i_a10_ccu_desc = { | ||
| 1391 | .ccu_clks = sun4i_sun7i_ccu_clks, | ||
| 1392 | .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), | ||
| 1393 | |||
| 1394 | .hw_clks = &sun4i_a10_hw_clks, | ||
| 1395 | |||
| 1396 | .resets = sunxi_a10_a20_ccu_resets, | ||
| 1397 | .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), | ||
| 1398 | }; | ||
| 1399 | |||
| 1400 | static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = { | ||
| 1401 | .ccu_clks = sun4i_sun7i_ccu_clks, | ||
| 1402 | .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), | ||
| 1403 | |||
| 1404 | .hw_clks = &sun7i_a20_hw_clks, | ||
| 1405 | |||
| 1406 | .resets = sunxi_a10_a20_ccu_resets, | ||
| 1407 | .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), | ||
| 1408 | }; | ||
| 1409 | |||
| 1410 | static void __init sun4i_ccu_init(struct device_node *node, | ||
| 1411 | const struct sunxi_ccu_desc *desc) | ||
| 1412 | { | ||
| 1413 | void __iomem *reg; | ||
| 1414 | u32 val; | ||
| 1415 | |||
| 1416 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
| 1417 | if (IS_ERR(reg)) { | ||
| 1418 | pr_err("%s: Could not map the clock registers\n", | ||
| 1419 | of_node_full_name(node)); | ||
| 1420 | return; | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | /* Force the PLL-Audio-1x divider to 4 */ | ||
| 1424 | val = readl(reg + SUN4I_PLL_AUDIO_REG); | ||
| 1425 | val &= ~GENMASK(29, 26); | ||
| 1426 | writel(val | (4 << 26), reg + SUN4I_PLL_AUDIO_REG); | ||
| 1427 | |||
| 1428 | /* | ||
| 1429 | * Use the peripheral PLL6 as the AHB parent, instead of CPU / | ||
| 1430 | * AXI which have rate changes due to cpufreq. | ||
| 1431 | * | ||
| 1432 | * This is especially a big deal for the HS timer whose parent | ||
| 1433 | * clock is AHB. | ||
| 1434 | * | ||
| 1435 | * NB! These bits are undocumented in A10 manual. | ||
| 1436 | */ | ||
| 1437 | val = readl(reg + SUN4I_AHB_REG); | ||
| 1438 | val &= ~GENMASK(7, 6); | ||
| 1439 | writel(val | (2 << 6), reg + SUN4I_AHB_REG); | ||
| 1440 | |||
| 1441 | sunxi_ccu_probe(node, reg, desc); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | static void __init sun4i_a10_ccu_setup(struct device_node *node) | ||
| 1445 | { | ||
| 1446 | sun4i_ccu_init(node, &sun4i_a10_ccu_desc); | ||
| 1447 | } | ||
| 1448 | CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu", | ||
| 1449 | sun4i_a10_ccu_setup); | ||
| 1450 | |||
| 1451 | static void __init sun7i_a20_ccu_setup(struct device_node *node) | ||
| 1452 | { | ||
| 1453 | sun4i_ccu_init(node, &sun7i_a20_ccu_desc); | ||
| 1454 | } | ||
| 1455 | CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu", | ||
| 1456 | sun7i_a20_ccu_setup); | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h new file mode 100644 index 000000000000..c5947c7c050e --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2017 Priit Laes | ||
| 3 | * | ||
| 4 | * Priit Laes <plaes@plaes.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _CCU_SUN4I_A10_H_ | ||
| 18 | #define _CCU_SUN4I_A10_H_ | ||
| 19 | |||
| 20 | #include <dt-bindings/clock/sun4i-a10-ccu.h> | ||
| 21 | #include <dt-bindings/clock/sun7i-a20-ccu.h> | ||
| 22 | #include <dt-bindings/reset/sun4i-a10-ccu.h> | ||
| 23 | |||
| 24 | /* The HOSC is exported */ | ||
| 25 | #define CLK_PLL_CORE 2 | ||
| 26 | #define CLK_PLL_AUDIO_BASE 3 | ||
| 27 | #define CLK_PLL_AUDIO 4 | ||
| 28 | #define CLK_PLL_AUDIO_2X 5 | ||
| 29 | #define CLK_PLL_AUDIO_4X 6 | ||
| 30 | #define CLK_PLL_AUDIO_8X 7 | ||
| 31 | #define CLK_PLL_VIDEO0 8 | ||
| 32 | #define CLK_PLL_VIDEO0_2X 9 | ||
| 33 | #define CLK_PLL_VE 10 | ||
| 34 | #define CLK_PLL_DDR_BASE 11 | ||
| 35 | #define CLK_PLL_DDR 12 | ||
| 36 | #define CLK_PLL_DDR_OTHER 13 | ||
| 37 | #define CLK_PLL_PERIPH_BASE 14 | ||
| 38 | #define CLK_PLL_PERIPH 15 | ||
| 39 | #define CLK_PLL_PERIPH_SATA 16 | ||
| 40 | #define CLK_PLL_VIDEO1 17 | ||
| 41 | #define CLK_PLL_VIDEO1_2X 18 | ||
| 42 | #define CLK_PLL_GPU 19 | ||
| 43 | |||
| 44 | /* The CPU clock is exported */ | ||
| 45 | #define CLK_AXI 21 | ||
| 46 | #define CLK_AXI_DRAM 22 | ||
| 47 | #define CLK_AHB 23 | ||
| 48 | #define CLK_APB0 24 | ||
| 49 | #define CLK_APB1 25 | ||
| 50 | |||
| 51 | /* AHB gates are exported (23..68) */ | ||
| 52 | /* APB0 gates are exported (69..78) */ | ||
| 53 | /* APB1 gates are exported (79..95) */ | ||
| 54 | /* IP module clocks are exported (96..128) */ | ||
| 55 | /* DRAM gates are exported (129..142)*/ | ||
| 56 | /* Media (display engine clocks & etc) are exported (143..169) */ | ||
| 57 | |||
| 58 | #define CLK_NUMBER_SUN4I (CLK_MBUS + 1) | ||
| 59 | #define CLK_NUMBER_SUN7I (CLK_OUT_B + 1) | ||
| 60 | |||
| 61 | #endif /* _CCU_SUN4I_A10_H_ */ | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index 31d7ffda9aab..ab9e850b3707 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c | |||
| @@ -976,8 +976,7 @@ static void __init sun5i_ccu_init(struct device_node *node, | |||
| 976 | 976 | ||
| 977 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 977 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 978 | if (IS_ERR(reg)) { | 978 | if (IS_ERR(reg)) { |
| 979 | pr_err("%s: Could not map the clock registers\n", | 979 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 980 | of_node_full_name(node)); | ||
| 981 | return; | 980 | return; |
| 982 | } | 981 | } |
| 983 | 982 | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 4d6078fca9ac..8af434815fba 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c | |||
| @@ -1217,8 +1217,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) | |||
| 1217 | 1217 | ||
| 1218 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 1218 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 1219 | if (IS_ERR(reg)) { | 1219 | if (IS_ERR(reg)) { |
| 1220 | pr_err("%s: Could not map the clock registers\n", | 1220 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 1221 | of_node_full_name(node)); | ||
| 1222 | return; | 1221 | return; |
| 1223 | } | 1222 | } |
| 1224 | 1223 | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index 8a753ed0426d..d93b452f0df9 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c | |||
| @@ -716,8 +716,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) | |||
| 716 | 716 | ||
| 717 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 717 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 718 | if (IS_ERR(reg)) { | 718 | if (IS_ERR(reg)) { |
| 719 | pr_err("%s: Could not map the clock registers\n", | 719 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 720 | of_node_full_name(node)); | ||
| 721 | return; | 720 | return; |
| 722 | } | 721 | } |
| 723 | 722 | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c index 10b38dc46f75..13eb5b23c5e7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c | |||
| @@ -777,8 +777,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) | |||
| 777 | 777 | ||
| 778 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 778 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 779 | if (IS_ERR(reg)) { | 779 | if (IS_ERR(reg)) { |
| 780 | pr_err("%s: Could not map the clock registers\n", | 780 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 781 | of_node_full_name(node)); | ||
| 782 | return; | 781 | return; |
| 783 | } | 782 | } |
| 784 | 783 | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 62e4f0d2b2fc..1729ff6a5aae 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c | |||
| @@ -135,7 +135,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", | |||
| 135 | static const char * const cpux_parents[] = { "osc32k", "osc24M", | 135 | static const char * const cpux_parents[] = { "osc32k", "osc24M", |
| 136 | "pll-cpux" , "pll-cpux" }; | 136 | "pll-cpux" , "pll-cpux" }; |
| 137 | static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, | 137 | static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, |
| 138 | 0x050, 16, 2, CLK_IS_CRITICAL); | 138 | 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); |
| 139 | 139 | ||
| 140 | static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); | 140 | static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); |
| 141 | 141 | ||
| @@ -1103,6 +1103,13 @@ static const struct sunxi_ccu_desc sun50i_h5_ccu_desc = { | |||
| 1103 | .num_resets = ARRAY_SIZE(sun50i_h5_ccu_resets), | 1103 | .num_resets = ARRAY_SIZE(sun50i_h5_ccu_resets), |
| 1104 | }; | 1104 | }; |
| 1105 | 1105 | ||
| 1106 | static struct ccu_pll_nb sun8i_h3_pll_cpu_nb = { | ||
| 1107 | .common = &pll_cpux_clk.common, | ||
| 1108 | /* copy from pll_cpux_clk */ | ||
| 1109 | .enable = BIT(31), | ||
| 1110 | .lock = BIT(28), | ||
| 1111 | }; | ||
| 1112 | |||
| 1106 | static struct ccu_mux_nb sun8i_h3_cpu_nb = { | 1113 | static struct ccu_mux_nb sun8i_h3_cpu_nb = { |
| 1107 | .common = &cpux_clk.common, | 1114 | .common = &cpux_clk.common, |
| 1108 | .cm = &cpux_clk.mux, | 1115 | .cm = &cpux_clk.mux, |
| @@ -1118,8 +1125,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, | |||
| 1118 | 1125 | ||
| 1119 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 1126 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 1120 | if (IS_ERR(reg)) { | 1127 | if (IS_ERR(reg)) { |
| 1121 | pr_err("%s: Could not map the clock registers\n", | 1128 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 1122 | of_node_full_name(node)); | ||
| 1123 | return; | 1129 | return; |
| 1124 | } | 1130 | } |
| 1125 | 1131 | ||
| @@ -1130,6 +1136,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, | |||
| 1130 | 1136 | ||
| 1131 | sunxi_ccu_probe(node, reg, desc); | 1137 | sunxi_ccu_probe(node, reg, desc); |
| 1132 | 1138 | ||
| 1139 | /* Gate then ungate PLL CPU after any rate changes */ | ||
| 1140 | ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); | ||
| 1141 | |||
| 1142 | /* Reparent CPU during PLL CPU rate changes */ | ||
| 1133 | ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, | 1143 | ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, |
| 1134 | &sun8i_h3_cpu_nb); | 1144 | &sun8i_h3_cpu_nb); |
| 1135 | } | 1145 | } |
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c index e54816ec1dbe..71feb7b24e8a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c | |||
| @@ -290,8 +290,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, | |||
| 290 | 290 | ||
| 291 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 291 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 292 | if (IS_ERR(reg)) { | 292 | if (IS_ERR(reg)) { |
| 293 | pr_err("%s: Could not map the clock registers\n", | 293 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 294 | of_node_full_name(node)); | ||
| 295 | return; | 294 | return; |
| 296 | } | 295 | } |
| 297 | 296 | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-r.h index a7a407f12b56..fb01bffb929d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.h +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #ifndef _CCU_SUN8I_R_H | 15 | #ifndef _CCU_SUN8I_R_H |
| 16 | #define _CCU_SUN8I_R_H_ | 16 | #define _CCU_SUN8I_R_H |
| 17 | 17 | ||
| 18 | #include <dt-bindings/clock/sun8i-r-ccu.h> | 18 | #include <dt-bindings/clock/sun8i-r-ccu.h> |
| 19 | #include <dt-bindings/reset/sun8i-r-ccu.h> | 19 | #include <dt-bindings/reset/sun8i-r-ccu.h> |
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c new file mode 100644 index 000000000000..933f2e68f42a --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c | |||
| @@ -0,0 +1,1290 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> | ||
| 3 | * | ||
| 4 | * This software is licensed under the terms of the GNU General Public | ||
| 5 | * License version 2, as published by the Free Software Foundation, and | ||
| 6 | * may be copied, distributed, and modified under those terms. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/clk-provider.h> | ||
| 15 | #include <linux/of_address.h> | ||
| 16 | |||
| 17 | #include "ccu_common.h" | ||
| 18 | #include "ccu_reset.h" | ||
| 19 | |||
| 20 | #include "ccu_div.h" | ||
| 21 | #include "ccu_gate.h" | ||
| 22 | #include "ccu_mp.h" | ||
| 23 | #include "ccu_mult.h" | ||
| 24 | #include "ccu_nk.h" | ||
| 25 | #include "ccu_nkm.h" | ||
| 26 | #include "ccu_nkmp.h" | ||
| 27 | #include "ccu_nm.h" | ||
| 28 | #include "ccu_phase.h" | ||
| 29 | |||
| 30 | #include "ccu-sun8i-r40.h" | ||
| 31 | |||
| 32 | /* TODO: The result of N*K is required to be in [10, 88] range. */ | ||
| 33 | static struct ccu_nkmp pll_cpu_clk = { | ||
| 34 | .enable = BIT(31), | ||
| 35 | .lock = BIT(28), | ||
| 36 | .n = _SUNXI_CCU_MULT(8, 5), | ||
| 37 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 38 | .m = _SUNXI_CCU_DIV(0, 2), | ||
| 39 | .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), | ||
| 40 | .common = { | ||
| 41 | .reg = 0x000, | ||
| 42 | .hw.init = CLK_HW_INIT("pll-cpu", | ||
| 43 | "osc24M", | ||
| 44 | &ccu_nkmp_ops, | ||
| 45 | CLK_SET_RATE_UNGATE), | ||
| 46 | }, | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from | ||
| 51 | * the base (2x, 4x and 8x), and one variable divider (the one true | ||
| 52 | * pll audio). | ||
| 53 | * | ||
| 54 | * We don't have any need for the variable divider for now, so we just | ||
| 55 | * hardcode it to match with the clock names | ||
| 56 | */ | ||
| 57 | #define SUN8I_R40_PLL_AUDIO_REG 0x008 | ||
| 58 | |||
| 59 | static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", | ||
| 60 | "osc24M", 0x008, | ||
| 61 | 8, 7, /* N */ | ||
| 62 | 0, 5, /* M */ | ||
| 63 | BIT(31), /* gate */ | ||
| 64 | BIT(28), /* lock */ | ||
| 65 | CLK_SET_RATE_UNGATE); | ||
| 66 | |||
| 67 | /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||
| 68 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", | ||
| 69 | "osc24M", 0x0010, | ||
| 70 | 8, 7, /* N */ | ||
| 71 | 0, 4, /* M */ | ||
| 72 | BIT(24), /* frac enable */ | ||
| 73 | BIT(25), /* frac select */ | ||
| 74 | 270000000, /* frac rate 0 */ | ||
| 75 | 297000000, /* frac rate 1 */ | ||
| 76 | BIT(31), /* gate */ | ||
| 77 | BIT(28), /* lock */ | ||
| 78 | CLK_SET_RATE_UNGATE); | ||
| 79 | |||
| 80 | /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||
| 81 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", | ||
| 82 | "osc24M", 0x0018, | ||
| 83 | 8, 7, /* N */ | ||
| 84 | 0, 4, /* M */ | ||
| 85 | BIT(24), /* frac enable */ | ||
| 86 | BIT(25), /* frac select */ | ||
| 87 | 270000000, /* frac rate 0 */ | ||
| 88 | 297000000, /* frac rate 1 */ | ||
| 89 | BIT(31), /* gate */ | ||
| 90 | BIT(28), /* lock */ | ||
| 91 | CLK_SET_RATE_UNGATE); | ||
| 92 | |||
| 93 | /* TODO: The result of N*K is required to be in [10, 77] range. */ | ||
| 94 | static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", | ||
| 95 | "osc24M", 0x020, | ||
| 96 | 8, 5, /* N */ | ||
| 97 | 4, 2, /* K */ | ||
| 98 | 0, 2, /* M */ | ||
| 99 | BIT(31), /* gate */ | ||
| 100 | BIT(28), /* lock */ | ||
| 101 | CLK_SET_RATE_UNGATE); | ||
| 102 | |||
| 103 | /* TODO: The result of N*K is required to be in [21, 58] range. */ | ||
| 104 | static struct ccu_nk pll_periph0_clk = { | ||
| 105 | .enable = BIT(31), | ||
| 106 | .lock = BIT(28), | ||
| 107 | .n = _SUNXI_CCU_MULT(8, 5), | ||
| 108 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 109 | .fixed_post_div = 2, | ||
| 110 | .common = { | ||
| 111 | .reg = 0x028, | ||
| 112 | .features = CCU_FEATURE_FIXED_POSTDIV, | ||
| 113 | .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", | ||
| 114 | &ccu_nk_ops, | ||
| 115 | CLK_SET_RATE_UNGATE), | ||
| 116 | }, | ||
| 117 | }; | ||
| 118 | |||
| 119 | static struct ccu_div pll_periph0_sata_clk = { | ||
| 120 | .enable = BIT(24), | ||
| 121 | .div = _SUNXI_CCU_DIV(0, 2), | ||
| 122 | /* | ||
| 123 | * The formula of pll-periph0 (1x) is 24MHz*N*K/2, and the formula | ||
| 124 | * of pll-periph0-sata is 24MHz*N*K/M/6, so the postdiv here is | ||
| 125 | * 6/2 = 3. | ||
| 126 | */ | ||
| 127 | .fixed_post_div = 3, | ||
| 128 | .common = { | ||
| 129 | .reg = 0x028, | ||
| 130 | .features = CCU_FEATURE_FIXED_POSTDIV, | ||
| 131 | .hw.init = CLK_HW_INIT("pll-periph0-sata", | ||
| 132 | "pll-periph0", | ||
| 133 | &ccu_div_ops, 0), | ||
| 134 | }, | ||
| 135 | }; | ||
| 136 | |||
| 137 | /* TODO: The result of N*K is required to be in [21, 58] range. */ | ||
| 138 | static struct ccu_nk pll_periph1_clk = { | ||
| 139 | .enable = BIT(31), | ||
| 140 | .lock = BIT(28), | ||
| 141 | .n = _SUNXI_CCU_MULT(8, 5), | ||
| 142 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 143 | .fixed_post_div = 2, | ||
| 144 | .common = { | ||
| 145 | .reg = 0x02c, | ||
| 146 | .features = CCU_FEATURE_FIXED_POSTDIV, | ||
| 147 | .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", | ||
| 148 | &ccu_nk_ops, | ||
| 149 | CLK_SET_RATE_UNGATE), | ||
| 150 | }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||
| 154 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", | ||
| 155 | "osc24M", 0x030, | ||
| 156 | 8, 7, /* N */ | ||
| 157 | 0, 4, /* M */ | ||
| 158 | BIT(24), /* frac enable */ | ||
| 159 | BIT(25), /* frac select */ | ||
| 160 | 270000000, /* frac rate 0 */ | ||
| 161 | 297000000, /* frac rate 1 */ | ||
| 162 | BIT(31), /* gate */ | ||
| 163 | BIT(28), /* lock */ | ||
| 164 | CLK_SET_RATE_UNGATE); | ||
| 165 | |||
| 166 | static struct ccu_nkm pll_sata_clk = { | ||
| 167 | .enable = BIT(31), | ||
| 168 | .lock = BIT(28), | ||
| 169 | .n = _SUNXI_CCU_MULT(8, 5), | ||
| 170 | .k = _SUNXI_CCU_MULT(4, 2), | ||
| 171 | .m = _SUNXI_CCU_DIV(0, 2), | ||
| 172 | .fixed_post_div = 6, | ||
| 173 | .common = { | ||
| 174 | .reg = 0x034, | ||
| 175 | .features = CCU_FEATURE_FIXED_POSTDIV, | ||
| 176 | .hw.init = CLK_HW_INIT("pll-sata", "osc24M", | ||
| 177 | &ccu_nkm_ops, | ||
| 178 | CLK_SET_RATE_UNGATE), | ||
| 179 | }, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static const char * const pll_sata_out_parents[] = { "pll-sata", | ||
| 183 | "pll-periph0-sata" }; | ||
| 184 | static SUNXI_CCU_MUX_WITH_GATE(pll_sata_out_clk, "pll-sata-out", | ||
| 185 | pll_sata_out_parents, 0x034, | ||
| 186 | 30, 1, /* mux */ | ||
| 187 | BIT(14), /* gate */ | ||
| 188 | CLK_SET_RATE_PARENT); | ||
| 189 | |||
| 190 | /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||
| 191 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", | ||
| 192 | "osc24M", 0x038, | ||
| 193 | 8, 7, /* N */ | ||
| 194 | 0, 4, /* M */ | ||
| 195 | BIT(24), /* frac enable */ | ||
| 196 | BIT(25), /* frac select */ | ||
| 197 | 270000000, /* frac rate 0 */ | ||
| 198 | 297000000, /* frac rate 1 */ | ||
| 199 | BIT(31), /* gate */ | ||
| 200 | BIT(28), /* lock */ | ||
| 201 | CLK_SET_RATE_UNGATE); | ||
| 202 | |||
| 203 | /* | ||
| 204 | * The MIPI PLL has 2 modes: "MIPI" and "HDMI". | ||
| 205 | * | ||
| 206 | * The MIPI mode is a standard NKM-style clock. The HDMI mode is an | ||
| 207 | * integer / fractional clock with switchable multipliers and dividers. | ||
| 208 | * This is not supported here. We hardcode the PLL to MIPI mode. | ||
| 209 | * | ||
| 210 | * TODO: In the MIPI mode, M/N is required to be equal or lesser than 3, | ||
| 211 | * which cannot be implemented now. | ||
| 212 | */ | ||
| 213 | #define SUN8I_R40_PLL_MIPI_REG 0x040 | ||
| 214 | |||
| 215 | static const char * const pll_mipi_parents[] = { "pll-video0" }; | ||
| 216 | static struct ccu_nkm pll_mipi_clk = { | ||
| 217 | .enable = BIT(31) | BIT(23) | BIT(22), | ||
| 218 | .lock = BIT(28), | ||
| 219 | .n = _SUNXI_CCU_MULT(8, 4), | ||
| 220 | .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), | ||
| 221 | .m = _SUNXI_CCU_DIV(0, 4), | ||
| 222 | .mux = _SUNXI_CCU_MUX(21, 1), | ||
| 223 | .common = { | ||
| 224 | .reg = 0x040, | ||
| 225 | .hw.init = CLK_HW_INIT_PARENTS("pll-mipi", | ||
| 226 | pll_mipi_parents, | ||
| 227 | &ccu_nkm_ops, | ||
| 228 | CLK_SET_RATE_UNGATE) | ||
| 229 | }, | ||
| 230 | }; | ||
| 231 | |||
| 232 | /* TODO: The result of N/M is required to be in [8, 25] range. */ | ||
| 233 | static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", | ||
| 234 | "osc24M", 0x048, | ||
| 235 | 8, 7, /* N */ | ||
| 236 | 0, 4, /* M */ | ||
| 237 | BIT(24), /* frac enable */ | ||
| 238 | BIT(25), /* frac select */ | ||
| 239 | 270000000, /* frac rate 0 */ | ||
| 240 | 297000000, /* frac rate 1 */ | ||
| 241 | BIT(31), /* gate */ | ||
| 242 | BIT(28), /* lock */ | ||
| 243 | CLK_SET_RATE_UNGATE); | ||
| 244 | |||
| 245 | /* TODO: The N factor is required to be in [16, 75] range. */ | ||
| 246 | static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", | ||
| 247 | "osc24M", 0x04c, | ||
| 248 | 8, 7, /* N */ | ||
| 249 | 0, 2, /* M */ | ||
| 250 | BIT(31), /* gate */ | ||
| 251 | BIT(28), /* lock */ | ||
| 252 | CLK_SET_RATE_UNGATE); | ||
| 253 | |||
| 254 | static const char * const cpu_parents[] = { "osc32k", "osc24M", | ||
| 255 | "pll-cpu", "pll-cpu" }; | ||
| 256 | static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents, | ||
| 257 | 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); | ||
| 258 | |||
| 259 | static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x050, 0, 2, 0); | ||
| 260 | |||
| 261 | static const char * const ahb1_parents[] = { "osc32k", "osc24M", | ||
| 262 | "axi", "pll-periph0" }; | ||
| 263 | static const struct ccu_mux_var_prediv ahb1_predivs[] = { | ||
| 264 | { .index = 3, .shift = 6, .width = 2 }, | ||
| 265 | }; | ||
| 266 | static struct ccu_div ahb1_clk = { | ||
| 267 | .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | ||
| 268 | |||
| 269 | .mux = { | ||
| 270 | .shift = 12, | ||
| 271 | .width = 2, | ||
| 272 | |||
| 273 | .var_predivs = ahb1_predivs, | ||
| 274 | .n_var_predivs = ARRAY_SIZE(ahb1_predivs), | ||
| 275 | }, | ||
| 276 | |||
| 277 | .common = { | ||
| 278 | .reg = 0x054, | ||
| 279 | .features = CCU_FEATURE_VARIABLE_PREDIV, | ||
| 280 | .hw.init = CLK_HW_INIT_PARENTS("ahb1", | ||
| 281 | ahb1_parents, | ||
| 282 | &ccu_div_ops, | ||
| 283 | 0), | ||
| 284 | }, | ||
| 285 | }; | ||
| 286 | |||
| 287 | static struct clk_div_table apb1_div_table[] = { | ||
| 288 | { .val = 0, .div = 2 }, | ||
| 289 | { .val = 1, .div = 2 }, | ||
| 290 | { .val = 2, .div = 4 }, | ||
| 291 | { .val = 3, .div = 8 }, | ||
| 292 | { /* Sentinel */ }, | ||
| 293 | }; | ||
| 294 | static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", | ||
| 295 | 0x054, 8, 2, apb1_div_table, 0); | ||
| 296 | |||
| 297 | static const char * const apb2_parents[] = { "osc32k", "osc24M", | ||
| 298 | "pll-periph0-2x", | ||
| 299 | "pll-periph0-2x" }; | ||
| 300 | static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, | ||
| 301 | 0, 5, /* M */ | ||
| 302 | 16, 2, /* P */ | ||
| 303 | 24, 2, /* mux */ | ||
| 304 | 0); | ||
| 305 | |||
| 306 | static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", | ||
| 307 | 0x060, BIT(1), 0); | ||
| 308 | static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", | ||
| 309 | 0x060, BIT(5), 0); | ||
| 310 | static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", | ||
| 311 | 0x060, BIT(6), 0); | ||
| 312 | static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", | ||
| 313 | 0x060, BIT(8), 0); | ||
| 314 | static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", | ||
| 315 | 0x060, BIT(9), 0); | ||
| 316 | static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", | ||
| 317 | 0x060, BIT(10), 0); | ||
| 318 | static SUNXI_CCU_GATE(bus_mmc3_clk, "bus-mmc3", "ahb1", | ||
| 319 | 0x060, BIT(11), 0); | ||
| 320 | static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", | ||
| 321 | 0x060, BIT(13), 0); | ||
| 322 | static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", | ||
| 323 | 0x060, BIT(14), 0); | ||
| 324 | static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb1", | ||
| 325 | 0x060, BIT(17), 0); | ||
| 326 | static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", | ||
| 327 | 0x060, BIT(18), 0); | ||
| 328 | static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", | ||
| 329 | 0x060, BIT(19), 0); | ||
| 330 | static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", | ||
| 331 | 0x060, BIT(20), 0); | ||
| 332 | static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", | ||
| 333 | 0x060, BIT(21), 0); | ||
| 334 | static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb1", | ||
| 335 | 0x060, BIT(22), 0); | ||
| 336 | static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3", "ahb1", | ||
| 337 | 0x060, BIT(23), 0); | ||
| 338 | static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata", "ahb1", | ||
| 339 | 0x060, BIT(24), 0); | ||
| 340 | static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", | ||
| 341 | 0x060, BIT(25), 0); | ||
| 342 | static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", | ||
| 343 | 0x060, BIT(26), 0); | ||
| 344 | static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb1", | ||
| 345 | 0x060, BIT(27), 0); | ||
| 346 | static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb1", | ||
| 347 | 0x060, BIT(28), 0); | ||
| 348 | static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", | ||
| 349 | 0x060, BIT(29), 0); | ||
| 350 | static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb1", | ||
| 351 | 0x060, BIT(30), 0); | ||
| 352 | static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb1", | ||
| 353 | 0x060, BIT(31), 0); | ||
| 354 | |||
| 355 | static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", | ||
| 356 | 0x064, BIT(0), 0); | ||
| 357 | static SUNXI_CCU_GATE(bus_mp_clk, "bus-mp", "ahb1", | ||
| 358 | 0x064, BIT(2), 0); | ||
| 359 | static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", | ||
| 360 | 0x064, BIT(5), 0); | ||
| 361 | static SUNXI_CCU_GATE(bus_csi0_clk, "bus-csi0", "ahb1", | ||
| 362 | 0x064, BIT(8), 0); | ||
| 363 | static SUNXI_CCU_GATE(bus_csi1_clk, "bus-csi1", "ahb1", | ||
| 364 | 0x064, BIT(9), 0); | ||
| 365 | static SUNXI_CCU_GATE(bus_hdmi0_clk, "bus-hdmi0", "ahb1", | ||
| 366 | 0x064, BIT(10), 0); | ||
| 367 | static SUNXI_CCU_GATE(bus_hdmi1_clk, "bus-hdmi1", "ahb1", | ||
| 368 | 0x064, BIT(11), 0); | ||
| 369 | static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", | ||
| 370 | 0x064, BIT(12), 0); | ||
| 371 | static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb1", | ||
| 372 | 0x064, BIT(13), 0); | ||
| 373 | static SUNXI_CCU_GATE(bus_tve1_clk, "bus-tve1", "ahb1", | ||
| 374 | 0x064, BIT(14), 0); | ||
| 375 | static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb1", | ||
| 376 | 0x064, BIT(15), 0); | ||
| 377 | static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac", "ahb1", | ||
| 378 | 0x064, BIT(17), 0); | ||
| 379 | static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", | ||
| 380 | 0x064, BIT(20), 0); | ||
| 381 | static SUNXI_CCU_GATE(bus_tvd0_clk, "bus-tvd0", "ahb1", | ||
| 382 | 0x064, BIT(21), 0); | ||
| 383 | static SUNXI_CCU_GATE(bus_tvd1_clk, "bus-tvd1", "ahb1", | ||
| 384 | 0x064, BIT(22), 0); | ||
| 385 | static SUNXI_CCU_GATE(bus_tvd2_clk, "bus-tvd2", "ahb1", | ||
| 386 | 0x064, BIT(23), 0); | ||
| 387 | static SUNXI_CCU_GATE(bus_tvd3_clk, "bus-tvd3", "ahb1", | ||
| 388 | 0x064, BIT(24), 0); | ||
| 389 | static SUNXI_CCU_GATE(bus_tvd_top_clk, "bus-tvd-top", "ahb1", | ||
| 390 | 0x064, BIT(25), 0); | ||
| 391 | static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb1", | ||
| 392 | 0x064, BIT(26), 0); | ||
| 393 | static SUNXI_CCU_GATE(bus_tcon_lcd1_clk, "bus-tcon-lcd1", "ahb1", | ||
| 394 | 0x064, BIT(27), 0); | ||
| 395 | static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb1", | ||
| 396 | 0x064, BIT(28), 0); | ||
| 397 | static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb1", | ||
| 398 | 0x064, BIT(29), 0); | ||
| 399 | static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb1", | ||
| 400 | 0x064, BIT(30), 0); | ||
| 401 | |||
| 402 | static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", | ||
| 403 | 0x068, BIT(0), 0); | ||
| 404 | static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", | ||
| 405 | 0x068, BIT(1), 0); | ||
| 406 | static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97", "apb1", | ||
| 407 | 0x068, BIT(2), 0); | ||
| 408 | static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", | ||
| 409 | 0x068, BIT(5), 0); | ||
| 410 | static SUNXI_CCU_GATE(bus_ir0_clk, "bus-ir0", "apb1", | ||
| 411 | 0x068, BIT(6), 0); | ||
| 412 | static SUNXI_CCU_GATE(bus_ir1_clk, "bus-ir1", "apb1", | ||
| 413 | 0x068, BIT(7), 0); | ||
| 414 | static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", | ||
| 415 | 0x068, BIT(8), 0); | ||
| 416 | static SUNXI_CCU_GATE(bus_keypad_clk, "bus-keypad", "apb1", | ||
| 417 | 0x068, BIT(10), 0); | ||
| 418 | static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", | ||
| 419 | 0x068, BIT(12), 0); | ||
| 420 | static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", | ||
| 421 | 0x068, BIT(13), 0); | ||
| 422 | static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", | ||
| 423 | 0x068, BIT(14), 0); | ||
| 424 | |||
| 425 | static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", | ||
| 426 | 0x06c, BIT(0), 0); | ||
| 427 | static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", | ||
| 428 | 0x06c, BIT(1), 0); | ||
| 429 | static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", | ||
| 430 | 0x06c, BIT(2), 0); | ||
| 431 | static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", | ||
| 432 | 0x06c, BIT(3), 0); | ||
| 433 | /* | ||
| 434 | * In datasheet here's "Reserved", however the gate exists in BSP soucre | ||
| 435 | * code. | ||
| 436 | */ | ||
| 437 | static SUNXI_CCU_GATE(bus_can_clk, "bus-can", "apb2", | ||
| 438 | 0x06c, BIT(4), 0); | ||
| 439 | static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", | ||
| 440 | 0x06c, BIT(5), 0); | ||
| 441 | static SUNXI_CCU_GATE(bus_ps20_clk, "bus-ps20", "apb2", | ||
| 442 | 0x06c, BIT(6), 0); | ||
| 443 | static SUNXI_CCU_GATE(bus_ps21_clk, "bus-ps21", "apb2", | ||
| 444 | 0x06c, BIT(7), 0); | ||
| 445 | static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", | ||
| 446 | 0x06c, BIT(15), 0); | ||
| 447 | static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", | ||
| 448 | 0x06c, BIT(16), 0); | ||
| 449 | static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", | ||
| 450 | 0x06c, BIT(17), 0); | ||
| 451 | static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", | ||
| 452 | 0x06c, BIT(18), 0); | ||
| 453 | static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", | ||
| 454 | 0x06c, BIT(19), 0); | ||
| 455 | static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", | ||
| 456 | 0x06c, BIT(20), 0); | ||
| 457 | static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", | ||
| 458 | 0x06c, BIT(21), 0); | ||
| 459 | static SUNXI_CCU_GATE(bus_uart6_clk, "bus-uart6", "apb2", | ||
| 460 | 0x06c, BIT(22), 0); | ||
| 461 | static SUNXI_CCU_GATE(bus_uart7_clk, "bus-uart7", "apb2", | ||
| 462 | 0x06c, BIT(23), 0); | ||
| 463 | |||
| 464 | static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", | ||
| 465 | 0x070, BIT(7), 0); | ||
| 466 | |||
| 467 | static const char * const ths_parents[] = { "osc24M" }; | ||
| 468 | static struct ccu_div ths_clk = { | ||
| 469 | .enable = BIT(31), | ||
| 470 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), | ||
| 471 | .mux = _SUNXI_CCU_MUX(24, 2), | ||
| 472 | .common = { | ||
| 473 | .reg = 0x074, | ||
| 474 | .hw.init = CLK_HW_INIT_PARENTS("ths", | ||
| 475 | ths_parents, | ||
| 476 | &ccu_div_ops, | ||
| 477 | 0), | ||
| 478 | }, | ||
| 479 | }; | ||
| 480 | |||
| 481 | static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", | ||
| 482 | "pll-periph1" }; | ||
| 483 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, | ||
| 484 | 0, 4, /* M */ | ||
| 485 | 16, 2, /* P */ | ||
| 486 | 24, 2, /* mux */ | ||
| 487 | BIT(31), /* gate */ | ||
| 488 | 0); | ||
| 489 | |||
| 490 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, | ||
| 491 | 0, 4, /* M */ | ||
| 492 | 16, 2, /* P */ | ||
| 493 | 24, 2, /* mux */ | ||
| 494 | BIT(31), /* gate */ | ||
| 495 | 0); | ||
| 496 | |||
| 497 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, | ||
| 498 | 0, 4, /* M */ | ||
| 499 | 16, 2, /* P */ | ||
| 500 | 24, 2, /* mux */ | ||
| 501 | BIT(31), /* gate */ | ||
| 502 | 0); | ||
| 503 | |||
| 504 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, | ||
| 505 | 0, 4, /* M */ | ||
| 506 | 16, 2, /* P */ | ||
| 507 | 24, 2, /* mux */ | ||
| 508 | BIT(31), /* gate */ | ||
| 509 | 0); | ||
| 510 | |||
| 511 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, | ||
| 512 | 0, 4, /* M */ | ||
| 513 | 16, 2, /* P */ | ||
| 514 | 24, 2, /* mux */ | ||
| 515 | BIT(31), /* gate */ | ||
| 516 | 0); | ||
| 517 | |||
| 518 | static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; | ||
| 519 | static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, | ||
| 520 | 0, 4, /* M */ | ||
| 521 | 16, 2, /* P */ | ||
| 522 | 24, 4, /* mux */ | ||
| 523 | BIT(31), /* gate */ | ||
| 524 | 0); | ||
| 525 | |||
| 526 | static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x", | ||
| 527 | "pll-periph1-2x" }; | ||
| 528 | static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c, | ||
| 529 | 0, 4, /* M */ | ||
| 530 | 16, 2, /* P */ | ||
| 531 | 24, 2, /* mux */ | ||
| 532 | BIT(31), /* gate */ | ||
| 533 | 0); | ||
| 534 | |||
| 535 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, | ||
| 536 | 0, 4, /* M */ | ||
| 537 | 16, 2, /* P */ | ||
| 538 | 24, 2, /* mux */ | ||
| 539 | BIT(31), /* gate */ | ||
| 540 | 0); | ||
| 541 | |||
| 542 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, | ||
| 543 | 0, 4, /* M */ | ||
| 544 | 16, 2, /* P */ | ||
| 545 | 24, 2, /* mux */ | ||
| 546 | BIT(31), /* gate */ | ||
| 547 | 0); | ||
| 548 | |||
| 549 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, | ||
| 550 | 0, 4, /* M */ | ||
| 551 | 16, 2, /* P */ | ||
| 552 | 24, 2, /* mux */ | ||
| 553 | BIT(31), /* gate */ | ||
| 554 | 0); | ||
| 555 | |||
| 556 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0ac, | ||
| 557 | 0, 4, /* M */ | ||
| 558 | 16, 2, /* P */ | ||
| 559 | 24, 2, /* mux */ | ||
| 560 | BIT(31), /* gate */ | ||
| 561 | 0); | ||
| 562 | |||
| 563 | static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", | ||
| 564 | "pll-audio-2x", "pll-audio" }; | ||
| 565 | static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, | ||
| 566 | 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 567 | |||
| 568 | static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, | ||
| 569 | 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 570 | |||
| 571 | static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, | ||
| 572 | 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 573 | |||
| 574 | static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", i2s_parents, | ||
| 575 | 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 576 | |||
| 577 | static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_parents, | ||
| 578 | 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | ||
| 579 | |||
| 580 | static const char * const keypad_parents[] = { "osc24M", "osc32k" }; | ||
| 581 | static const u8 keypad_table[] = { 0, 2 }; | ||
| 582 | static struct ccu_mp keypad_clk = { | ||
| 583 | .enable = BIT(31), | ||
| 584 | .m = _SUNXI_CCU_DIV(0, 5), | ||
| 585 | .p = _SUNXI_CCU_DIV(16, 2), | ||
| 586 | .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), | ||
| 587 | .common = { | ||
| 588 | .reg = 0x0c4, | ||
| 589 | .hw.init = CLK_HW_INIT_PARENTS("keypad", | ||
| 590 | keypad_parents, | ||
| 591 | &ccu_mp_ops, | ||
| 592 | 0), | ||
| 593 | } | ||
| 594 | }; | ||
| 595 | |||
| 596 | static const char * const sata_parents[] = { "pll-sata-out", "sata-ext" }; | ||
| 597 | static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, | ||
| 598 | 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); | ||
| 599 | |||
| 600 | /* | ||
| 601 | * There are 3 OHCI 12M clock source selection bits in this register. | ||
| 602 | * We will force them to 0 (12M divided from 48M). | ||
| 603 | */ | ||
| 604 | #define SUN8I_R40_USB_CLK_REG 0x0cc | ||
| 605 | |||
| 606 | static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", | ||
| 607 | 0x0cc, BIT(8), 0); | ||
| 608 | static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", | ||
| 609 | 0x0cc, BIT(9), 0); | ||
| 610 | static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", | ||
| 611 | 0x0cc, BIT(10), 0); | ||
| 612 | static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", | ||
| 613 | 0x0cc, BIT(16), 0); | ||
| 614 | static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", | ||
| 615 | 0x0cc, BIT(17), 0); | ||
| 616 | static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", | ||
| 617 | 0x0cc, BIT(18), 0); | ||
| 618 | |||
| 619 | static const char * const ir_parents[] = { "osc24M", "pll-periph0", | ||
| 620 | "pll-periph1", "osc32k" }; | ||
| 621 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_clk, "ir0", ir_parents, 0x0d0, | ||
| 622 | 0, 4, /* M */ | ||
| 623 | 16, 2, /* P */ | ||
| 624 | 24, 2, /* mux */ | ||
| 625 | BIT(31), /* gate */ | ||
| 626 | 0); | ||
| 627 | |||
| 628 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_clk, "ir1", ir_parents, 0x0d4, | ||
| 629 | 0, 4, /* M */ | ||
| 630 | 16, 2, /* P */ | ||
| 631 | 24, 2, /* mux */ | ||
| 632 | BIT(31), /* gate */ | ||
| 633 | 0); | ||
| 634 | |||
| 635 | static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; | ||
| 636 | static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, | ||
| 637 | 0x0f4, 0, 2, 20, 2, CLK_IS_CRITICAL); | ||
| 638 | |||
| 639 | static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", | ||
| 640 | 0x100, BIT(0), 0); | ||
| 641 | static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "dram", | ||
| 642 | 0x100, BIT(1), 0); | ||
| 643 | static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "dram", | ||
| 644 | 0x100, BIT(2), 0); | ||
| 645 | static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", | ||
| 646 | 0x100, BIT(3), 0); | ||
| 647 | static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "dram", | ||
| 648 | 0x100, BIT(4), 0); | ||
| 649 | static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "dram", | ||
| 650 | 0x100, BIT(5), 0); | ||
| 651 | static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", | ||
| 652 | 0x100, BIT(6), 0); | ||
| 653 | |||
| 654 | static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; | ||
| 655 | static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, | ||
| 656 | 0x104, 0, 4, 24, 3, BIT(31), 0); | ||
| 657 | static SUNXI_CCU_M_WITH_MUX_GATE(mp_clk, "mp", de_parents, | ||
| 658 | 0x108, 0, 4, 24, 3, BIT(31), 0); | ||
| 659 | |||
| 660 | static const char * const tcon_parents[] = { "pll-video0", "pll-video1", | ||
| 661 | "pll-video0-2x", "pll-video1-2x", | ||
| 662 | "pll-mipi" }; | ||
| 663 | static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents, | ||
| 664 | 0x110, 24, 3, BIT(31), CLK_SET_RATE_PARENT); | ||
| 665 | static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents, | ||
| 666 | 0x114, 24, 3, BIT(31), CLK_SET_RATE_PARENT); | ||
| 667 | static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents, | ||
| 668 | 0x118, 0, 4, 24, 3, BIT(31), 0); | ||
| 669 | static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents, | ||
| 670 | 0x11c, 0, 4, 24, 3, BIT(31), 0); | ||
| 671 | |||
| 672 | static const char * const deinterlace_parents[] = { "pll-periph0", | ||
| 673 | "pll-periph1" }; | ||
| 674 | static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", | ||
| 675 | deinterlace_parents, 0x124, 0, 4, 24, 3, | ||
| 676 | BIT(31), 0); | ||
| 677 | |||
| 678 | static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", | ||
| 679 | "pll-periph1" }; | ||
| 680 | static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", csi_mclk_parents, | ||
| 681 | 0x130, 0, 5, 8, 3, BIT(15), 0); | ||
| 682 | |||
| 683 | static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; | ||
| 684 | static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, | ||
| 685 | 0x134, 16, 4, 24, 3, BIT(31), 0); | ||
| 686 | |||
| 687 | static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", csi_mclk_parents, | ||
| 688 | 0x134, 0, 5, 8, 3, BIT(15), 0); | ||
| 689 | |||
| 690 | static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", | ||
| 691 | 0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT); | ||
| 692 | |||
| 693 | static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", | ||
| 694 | 0x140, BIT(31), CLK_SET_RATE_PARENT); | ||
| 695 | static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", | ||
| 696 | 0x144, BIT(31), 0); | ||
| 697 | |||
| 698 | static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; | ||
| 699 | static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, | ||
| 700 | 0x150, 0, 4, 24, 2, BIT(31), 0); | ||
| 701 | |||
| 702 | static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", | ||
| 703 | 0x154, BIT(31), 0); | ||
| 704 | |||
| 705 | /* | ||
| 706 | * In the SoC's user manual, the P factor is mentioned, but not used in | ||
| 707 | * the frequency formula. | ||
| 708 | * | ||
| 709 | * Here the factor is included, according to the BSP kernel source, | ||
| 710 | * which contains the P factor of this clock. | ||
| 711 | */ | ||
| 712 | static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", | ||
| 713 | "pll-ddr0" }; | ||
| 714 | static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, | ||
| 715 | 0, 4, /* M */ | ||
| 716 | 16, 2, /* P */ | ||
| 717 | 24, 2, /* mux */ | ||
| 718 | BIT(31), /* gate */ | ||
| 719 | CLK_IS_CRITICAL); | ||
| 720 | |||
| 721 | static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-video1", | ||
| 722 | "pll-periph0" }; | ||
| 723 | static SUNXI_CCU_M_WITH_MUX_GATE(dsi_dphy_clk, "dsi-dphy", dsi_dphy_parents, | ||
| 724 | 0x168, 0, 4, 8, 2, BIT(15), 0); | ||
| 725 | |||
| 726 | static SUNXI_CCU_M_WITH_MUX_GATE(tve0_clk, "tve0", tcon_parents, | ||
| 727 | 0x180, 0, 4, 24, 3, BIT(31), 0); | ||
| 728 | static SUNXI_CCU_M_WITH_MUX_GATE(tve1_clk, "tve1", tcon_parents, | ||
| 729 | 0x184, 0, 4, 24, 3, BIT(31), 0); | ||
| 730 | |||
| 731 | static const char * const tvd_parents[] = { "pll-video0", "pll-video1", | ||
| 732 | "pll-video0-2x", "pll-video1-2x" }; | ||
| 733 | static SUNXI_CCU_M_WITH_MUX_GATE(tvd0_clk, "tvd0", tvd_parents, | ||
| 734 | 0x188, 0, 4, 24, 3, BIT(31), 0); | ||
| 735 | static SUNXI_CCU_M_WITH_MUX_GATE(tvd1_clk, "tvd1", tvd_parents, | ||
| 736 | 0x18c, 0, 4, 24, 3, BIT(31), 0); | ||
| 737 | static SUNXI_CCU_M_WITH_MUX_GATE(tvd2_clk, "tvd2", tvd_parents, | ||
| 738 | 0x190, 0, 4, 24, 3, BIT(31), 0); | ||
| 739 | static SUNXI_CCU_M_WITH_MUX_GATE(tvd3_clk, "tvd3", tvd_parents, | ||
| 740 | 0x194, 0, 4, 24, 3, BIT(31), 0); | ||
| 741 | |||
| 742 | static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", | ||
| 743 | 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); | ||
| 744 | |||
| 745 | static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" }; | ||
| 746 | static const struct ccu_mux_fixed_prediv out_predivs[] = { | ||
| 747 | { .index = 0, .div = 750, }, | ||
| 748 | }; | ||
| 749 | |||
| 750 | static struct ccu_mp outa_clk = { | ||
| 751 | .enable = BIT(31), | ||
| 752 | .m = _SUNXI_CCU_DIV(8, 5), | ||
| 753 | .p = _SUNXI_CCU_DIV(20, 2), | ||
| 754 | .mux = { | ||
| 755 | .shift = 24, | ||
| 756 | .width = 2, | ||
| 757 | .fixed_predivs = out_predivs, | ||
| 758 | .n_predivs = ARRAY_SIZE(out_predivs), | ||
| 759 | }, | ||
| 760 | .common = { | ||
| 761 | .reg = 0x1f0, | ||
| 762 | .features = CCU_FEATURE_FIXED_PREDIV, | ||
| 763 | .hw.init = CLK_HW_INIT_PARENTS("outa", out_parents, | ||
| 764 | &ccu_mp_ops, 0), | ||
| 765 | } | ||
| 766 | }; | ||
| 767 | |||
| 768 | static struct ccu_mp outb_clk = { | ||
| 769 | .enable = BIT(31), | ||
| 770 | .m = _SUNXI_CCU_DIV(8, 5), | ||
| 771 | .p = _SUNXI_CCU_DIV(20, 2), | ||
| 772 | .mux = { | ||
| 773 | .shift = 24, | ||
| 774 | .width = 2, | ||
| 775 | .fixed_predivs = out_predivs, | ||
| 776 | .n_predivs = ARRAY_SIZE(out_predivs), | ||
| 777 | }, | ||
| 778 | .common = { | ||
| 779 | .reg = 0x1f4, | ||
| 780 | .features = CCU_FEATURE_FIXED_PREDIV, | ||
| 781 | .hw.init = CLK_HW_INIT_PARENTS("outb", out_parents, | ||
| 782 | &ccu_mp_ops, 0), | ||
| 783 | } | ||
| 784 | }; | ||
| 785 | |||
| 786 | static struct ccu_common *sun8i_r40_ccu_clks[] = { | ||
| 787 | &pll_cpu_clk.common, | ||
| 788 | &pll_audio_base_clk.common, | ||
| 789 | &pll_video0_clk.common, | ||
| 790 | &pll_ve_clk.common, | ||
| 791 | &pll_ddr0_clk.common, | ||
| 792 | &pll_periph0_clk.common, | ||
| 793 | &pll_periph0_sata_clk.common, | ||
| 794 | &pll_periph1_clk.common, | ||
| 795 | &pll_video1_clk.common, | ||
| 796 | &pll_sata_clk.common, | ||
| 797 | &pll_sata_out_clk.common, | ||
| 798 | &pll_gpu_clk.common, | ||
| 799 | &pll_mipi_clk.common, | ||
| 800 | &pll_de_clk.common, | ||
| 801 | &pll_ddr1_clk.common, | ||
| 802 | &cpu_clk.common, | ||
| 803 | &axi_clk.common, | ||
| 804 | &ahb1_clk.common, | ||
| 805 | &apb1_clk.common, | ||
| 806 | &apb2_clk.common, | ||
| 807 | &bus_mipi_dsi_clk.common, | ||
| 808 | &bus_ce_clk.common, | ||
| 809 | &bus_dma_clk.common, | ||
| 810 | &bus_mmc0_clk.common, | ||
| 811 | &bus_mmc1_clk.common, | ||
| 812 | &bus_mmc2_clk.common, | ||
| 813 | &bus_mmc3_clk.common, | ||
| 814 | &bus_nand_clk.common, | ||
| 815 | &bus_dram_clk.common, | ||
| 816 | &bus_emac_clk.common, | ||
| 817 | &bus_ts_clk.common, | ||
| 818 | &bus_hstimer_clk.common, | ||
| 819 | &bus_spi0_clk.common, | ||
| 820 | &bus_spi1_clk.common, | ||
| 821 | &bus_spi2_clk.common, | ||
| 822 | &bus_spi3_clk.common, | ||
| 823 | &bus_sata_clk.common, | ||
| 824 | &bus_otg_clk.common, | ||
| 825 | &bus_ehci0_clk.common, | ||
| 826 | &bus_ehci1_clk.common, | ||
| 827 | &bus_ehci2_clk.common, | ||
| 828 | &bus_ohci0_clk.common, | ||
| 829 | &bus_ohci1_clk.common, | ||
| 830 | &bus_ohci2_clk.common, | ||
| 831 | &bus_ve_clk.common, | ||
| 832 | &bus_mp_clk.common, | ||
| 833 | &bus_deinterlace_clk.common, | ||
| 834 | &bus_csi0_clk.common, | ||
| 835 | &bus_csi1_clk.common, | ||
| 836 | &bus_hdmi0_clk.common, | ||
| 837 | &bus_hdmi1_clk.common, | ||
| 838 | &bus_de_clk.common, | ||
| 839 | &bus_tve0_clk.common, | ||
| 840 | &bus_tve1_clk.common, | ||
| 841 | &bus_tve_top_clk.common, | ||
| 842 | &bus_gmac_clk.common, | ||
| 843 | &bus_gpu_clk.common, | ||
| 844 | &bus_tvd0_clk.common, | ||
| 845 | &bus_tvd1_clk.common, | ||
| 846 | &bus_tvd2_clk.common, | ||
| 847 | &bus_tvd3_clk.common, | ||
| 848 | &bus_tvd_top_clk.common, | ||
| 849 | &bus_tcon_lcd0_clk.common, | ||
| 850 | &bus_tcon_lcd1_clk.common, | ||
| 851 | &bus_tcon_tv0_clk.common, | ||
| 852 | &bus_tcon_tv1_clk.common, | ||
| 853 | &bus_tcon_top_clk.common, | ||
| 854 | &bus_codec_clk.common, | ||
| 855 | &bus_spdif_clk.common, | ||
| 856 | &bus_ac97_clk.common, | ||
| 857 | &bus_pio_clk.common, | ||
| 858 | &bus_ir0_clk.common, | ||
| 859 | &bus_ir1_clk.common, | ||
| 860 | &bus_ths_clk.common, | ||
| 861 | &bus_keypad_clk.common, | ||
| 862 | &bus_i2s0_clk.common, | ||
| 863 | &bus_i2s1_clk.common, | ||
| 864 | &bus_i2s2_clk.common, | ||
| 865 | &bus_i2c0_clk.common, | ||
| 866 | &bus_i2c1_clk.common, | ||
| 867 | &bus_i2c2_clk.common, | ||
| 868 | &bus_i2c3_clk.common, | ||
| 869 | &bus_can_clk.common, | ||
| 870 | &bus_scr_clk.common, | ||
| 871 | &bus_ps20_clk.common, | ||
| 872 | &bus_ps21_clk.common, | ||
| 873 | &bus_i2c4_clk.common, | ||
| 874 | &bus_uart0_clk.common, | ||
| 875 | &bus_uart1_clk.common, | ||
| 876 | &bus_uart2_clk.common, | ||
| 877 | &bus_uart3_clk.common, | ||
| 878 | &bus_uart4_clk.common, | ||
| 879 | &bus_uart5_clk.common, | ||
| 880 | &bus_uart6_clk.common, | ||
| 881 | &bus_uart7_clk.common, | ||
| 882 | &bus_dbg_clk.common, | ||
| 883 | &ths_clk.common, | ||
| 884 | &nand_clk.common, | ||
| 885 | &mmc0_clk.common, | ||
| 886 | &mmc1_clk.common, | ||
| 887 | &mmc2_clk.common, | ||
| 888 | &mmc3_clk.common, | ||
| 889 | &ts_clk.common, | ||
| 890 | &ce_clk.common, | ||
| 891 | &spi0_clk.common, | ||
| 892 | &spi1_clk.common, | ||
| 893 | &spi2_clk.common, | ||
| 894 | &spi3_clk.common, | ||
| 895 | &i2s0_clk.common, | ||
| 896 | &i2s1_clk.common, | ||
| 897 | &i2s2_clk.common, | ||
| 898 | &ac97_clk.common, | ||
| 899 | &spdif_clk.common, | ||
| 900 | &keypad_clk.common, | ||
| 901 | &sata_clk.common, | ||
| 902 | &usb_phy0_clk.common, | ||
| 903 | &usb_phy1_clk.common, | ||
| 904 | &usb_phy2_clk.common, | ||
| 905 | &usb_ohci0_clk.common, | ||
| 906 | &usb_ohci1_clk.common, | ||
| 907 | &usb_ohci2_clk.common, | ||
| 908 | &ir0_clk.common, | ||
| 909 | &ir1_clk.common, | ||
| 910 | &dram_clk.common, | ||
| 911 | &dram_ve_clk.common, | ||
| 912 | &dram_csi0_clk.common, | ||
| 913 | &dram_csi1_clk.common, | ||
| 914 | &dram_ts_clk.common, | ||
| 915 | &dram_tvd_clk.common, | ||
| 916 | &dram_mp_clk.common, | ||
| 917 | &dram_deinterlace_clk.common, | ||
| 918 | &de_clk.common, | ||
| 919 | &mp_clk.common, | ||
| 920 | &tcon_lcd0_clk.common, | ||
| 921 | &tcon_lcd1_clk.common, | ||
| 922 | &tcon_tv0_clk.common, | ||
| 923 | &tcon_tv1_clk.common, | ||
| 924 | &deinterlace_clk.common, | ||
| 925 | &csi1_mclk_clk.common, | ||
| 926 | &csi_sclk_clk.common, | ||
| 927 | &csi0_mclk_clk.common, | ||
| 928 | &ve_clk.common, | ||
| 929 | &codec_clk.common, | ||
| 930 | &avs_clk.common, | ||
| 931 | &hdmi_clk.common, | ||
| 932 | &hdmi_slow_clk.common, | ||
| 933 | &mbus_clk.common, | ||
| 934 | &dsi_dphy_clk.common, | ||
| 935 | &tve0_clk.common, | ||
| 936 | &tve1_clk.common, | ||
| 937 | &tvd0_clk.common, | ||
| 938 | &tvd1_clk.common, | ||
| 939 | &tvd2_clk.common, | ||
| 940 | &tvd3_clk.common, | ||
| 941 | &gpu_clk.common, | ||
| 942 | &outa_clk.common, | ||
| 943 | &outb_clk.common, | ||
| 944 | }; | ||
| 945 | |||
| 946 | /* Fixed Factor clocks */ | ||
| 947 | static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0); | ||
| 948 | |||
| 949 | /* We hardcode the divider to 4 for now */ | ||
| 950 | static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", | ||
| 951 | "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); | ||
| 952 | static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", | ||
| 953 | "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); | ||
| 954 | static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", | ||
| 955 | "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); | ||
| 956 | static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", | ||
| 957 | "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); | ||
| 958 | static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", | ||
| 959 | "pll-periph0", 1, 2, 0); | ||
| 960 | static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", | ||
| 961 | "pll-periph1", 1, 2, 0); | ||
| 962 | static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", | ||
| 963 | "pll-video0", 1, 2, 0); | ||
| 964 | static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", | ||
| 965 | "pll-video1", 1, 2, 0); | ||
| 966 | |||
| 967 | static struct clk_hw_onecell_data sun8i_r40_hw_clks = { | ||
| 968 | .hws = { | ||
| 969 | [CLK_OSC_12M] = &osc12M_clk.hw, | ||
| 970 | [CLK_PLL_CPU] = &pll_cpu_clk.common.hw, | ||
| 971 | [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | ||
| 972 | [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | ||
| 973 | [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | ||
| 974 | [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | ||
| 975 | [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | ||
| 976 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | ||
| 977 | [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | ||
| 978 | [CLK_PLL_VE] = &pll_ve_clk.common.hw, | ||
| 979 | [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, | ||
| 980 | [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, | ||
| 981 | [CLK_PLL_PERIPH0_SATA] = &pll_periph0_sata_clk.common.hw, | ||
| 982 | [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, | ||
| 983 | [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, | ||
| 984 | [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, | ||
| 985 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | ||
| 986 | [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | ||
| 987 | [CLK_PLL_SATA] = &pll_sata_clk.common.hw, | ||
| 988 | [CLK_PLL_SATA_OUT] = &pll_sata_out_clk.common.hw, | ||
| 989 | [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, | ||
| 990 | [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, | ||
| 991 | [CLK_PLL_DE] = &pll_de_clk.common.hw, | ||
| 992 | [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, | ||
| 993 | [CLK_CPU] = &cpu_clk.common.hw, | ||
| 994 | [CLK_AXI] = &axi_clk.common.hw, | ||
| 995 | [CLK_AHB1] = &ahb1_clk.common.hw, | ||
| 996 | [CLK_APB1] = &apb1_clk.common.hw, | ||
| 997 | [CLK_APB2] = &apb2_clk.common.hw, | ||
| 998 | [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, | ||
| 999 | [CLK_BUS_CE] = &bus_ce_clk.common.hw, | ||
| 1000 | [CLK_BUS_DMA] = &bus_dma_clk.common.hw, | ||
| 1001 | [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, | ||
| 1002 | [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, | ||
| 1003 | [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, | ||
| 1004 | [CLK_BUS_MMC3] = &bus_mmc3_clk.common.hw, | ||
| 1005 | [CLK_BUS_NAND] = &bus_nand_clk.common.hw, | ||
| 1006 | [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, | ||
| 1007 | [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, | ||
| 1008 | [CLK_BUS_TS] = &bus_ts_clk.common.hw, | ||
| 1009 | [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, | ||
| 1010 | [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, | ||
| 1011 | [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, | ||
| 1012 | [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, | ||
| 1013 | [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw, | ||
| 1014 | [CLK_BUS_SATA] = &bus_sata_clk.common.hw, | ||
| 1015 | [CLK_BUS_OTG] = &bus_otg_clk.common.hw, | ||
| 1016 | [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, | ||
| 1017 | [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, | ||
| 1018 | [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, | ||
| 1019 | [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, | ||
| 1020 | [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, | ||
| 1021 | [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, | ||
| 1022 | [CLK_BUS_VE] = &bus_ve_clk.common.hw, | ||
| 1023 | [CLK_BUS_MP] = &bus_mp_clk.common.hw, | ||
| 1024 | [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, | ||
| 1025 | [CLK_BUS_CSI0] = &bus_csi0_clk.common.hw, | ||
| 1026 | [CLK_BUS_CSI1] = &bus_csi1_clk.common.hw, | ||
| 1027 | [CLK_BUS_HDMI0] = &bus_hdmi0_clk.common.hw, | ||
| 1028 | [CLK_BUS_HDMI1] = &bus_hdmi1_clk.common.hw, | ||
| 1029 | [CLK_BUS_DE] = &bus_de_clk.common.hw, | ||
| 1030 | [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, | ||
| 1031 | [CLK_BUS_TVE1] = &bus_tve1_clk.common.hw, | ||
| 1032 | [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, | ||
| 1033 | [CLK_BUS_GMAC] = &bus_gmac_clk.common.hw, | ||
| 1034 | [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, | ||
| 1035 | [CLK_BUS_TVD0] = &bus_tvd0_clk.common.hw, | ||
| 1036 | [CLK_BUS_TVD1] = &bus_tvd1_clk.common.hw, | ||
| 1037 | [CLK_BUS_TVD2] = &bus_tvd2_clk.common.hw, | ||
| 1038 | [CLK_BUS_TVD3] = &bus_tvd3_clk.common.hw, | ||
| 1039 | [CLK_BUS_TVD_TOP] = &bus_tvd_top_clk.common.hw, | ||
| 1040 | [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw, | ||
| 1041 | [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw, | ||
| 1042 | [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, | ||
| 1043 | [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, | ||
| 1044 | [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, | ||
| 1045 | [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, | ||
| 1046 | [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, | ||
| 1047 | [CLK_BUS_AC97] = &bus_ac97_clk.common.hw, | ||
| 1048 | [CLK_BUS_PIO] = &bus_pio_clk.common.hw, | ||
| 1049 | [CLK_BUS_IR0] = &bus_ir0_clk.common.hw, | ||
| 1050 | [CLK_BUS_IR1] = &bus_ir1_clk.common.hw, | ||
| 1051 | [CLK_BUS_THS] = &bus_ths_clk.common.hw, | ||
| 1052 | [CLK_BUS_KEYPAD] = &bus_keypad_clk.common.hw, | ||
| 1053 | [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, | ||
| 1054 | [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, | ||
| 1055 | [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, | ||
| 1056 | [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, | ||
| 1057 | [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, | ||
| 1058 | [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, | ||
| 1059 | [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, | ||
| 1060 | [CLK_BUS_CAN] = &bus_can_clk.common.hw, | ||
| 1061 | [CLK_BUS_SCR] = &bus_scr_clk.common.hw, | ||
| 1062 | [CLK_BUS_PS20] = &bus_ps20_clk.common.hw, | ||
| 1063 | [CLK_BUS_PS21] = &bus_ps21_clk.common.hw, | ||
| 1064 | [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, | ||
| 1065 | [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, | ||
| 1066 | [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, | ||
| 1067 | [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, | ||
| 1068 | [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, | ||
| 1069 | [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, | ||
| 1070 | [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, | ||
| 1071 | [CLK_BUS_UART6] = &bus_uart6_clk.common.hw, | ||
| 1072 | [CLK_BUS_UART7] = &bus_uart7_clk.common.hw, | ||
| 1073 | [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, | ||
| 1074 | [CLK_THS] = &ths_clk.common.hw, | ||
| 1075 | [CLK_NAND] = &nand_clk.common.hw, | ||
| 1076 | [CLK_MMC0] = &mmc0_clk.common.hw, | ||
| 1077 | [CLK_MMC1] = &mmc1_clk.common.hw, | ||
| 1078 | [CLK_MMC2] = &mmc2_clk.common.hw, | ||
| 1079 | [CLK_MMC3] = &mmc3_clk.common.hw, | ||
| 1080 | [CLK_TS] = &ts_clk.common.hw, | ||
| 1081 | [CLK_CE] = &ce_clk.common.hw, | ||
| 1082 | [CLK_SPI0] = &spi0_clk.common.hw, | ||
| 1083 | [CLK_SPI1] = &spi1_clk.common.hw, | ||
| 1084 | [CLK_SPI2] = &spi2_clk.common.hw, | ||
| 1085 | [CLK_SPI3] = &spi3_clk.common.hw, | ||
| 1086 | [CLK_I2S0] = &i2s0_clk.common.hw, | ||
| 1087 | [CLK_I2S1] = &i2s1_clk.common.hw, | ||
| 1088 | [CLK_I2S2] = &i2s2_clk.common.hw, | ||
| 1089 | [CLK_AC97] = &ac97_clk.common.hw, | ||
| 1090 | [CLK_SPDIF] = &spdif_clk.common.hw, | ||
| 1091 | [CLK_KEYPAD] = &keypad_clk.common.hw, | ||
| 1092 | [CLK_SATA] = &sata_clk.common.hw, | ||
| 1093 | [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, | ||
| 1094 | [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, | ||
| 1095 | [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, | ||
| 1096 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | ||
| 1097 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | ||
| 1098 | [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, | ||
| 1099 | [CLK_IR0] = &ir0_clk.common.hw, | ||
| 1100 | [CLK_IR1] = &ir1_clk.common.hw, | ||
| 1101 | [CLK_DRAM] = &dram_clk.common.hw, | ||
| 1102 | [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | ||
| 1103 | [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | ||
| 1104 | [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | ||
| 1105 | [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | ||
| 1106 | [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | ||
| 1107 | [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | ||
| 1108 | [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, | ||
| 1109 | [CLK_DE] = &de_clk.common.hw, | ||
| 1110 | [CLK_MP] = &mp_clk.common.hw, | ||
| 1111 | [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw, | ||
| 1112 | [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw, | ||
| 1113 | [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, | ||
| 1114 | [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, | ||
| 1115 | [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, | ||
| 1116 | [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, | ||
| 1117 | [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | ||
| 1118 | [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, | ||
| 1119 | [CLK_VE] = &ve_clk.common.hw, | ||
| 1120 | [CLK_CODEC] = &codec_clk.common.hw, | ||
| 1121 | [CLK_AVS] = &avs_clk.common.hw, | ||
| 1122 | [CLK_HDMI] = &hdmi_clk.common.hw, | ||
| 1123 | [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, | ||
| 1124 | [CLK_MBUS] = &mbus_clk.common.hw, | ||
| 1125 | [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, | ||
| 1126 | [CLK_TVE0] = &tve0_clk.common.hw, | ||
| 1127 | [CLK_TVE1] = &tve1_clk.common.hw, | ||
| 1128 | [CLK_TVD0] = &tvd0_clk.common.hw, | ||
| 1129 | [CLK_TVD1] = &tvd1_clk.common.hw, | ||
| 1130 | [CLK_TVD2] = &tvd2_clk.common.hw, | ||
| 1131 | [CLK_TVD3] = &tvd3_clk.common.hw, | ||
| 1132 | [CLK_GPU] = &gpu_clk.common.hw, | ||
| 1133 | [CLK_OUTA] = &outa_clk.common.hw, | ||
| 1134 | [CLK_OUTB] = &outb_clk.common.hw, | ||
| 1135 | }, | ||
| 1136 | .num = CLK_NUMBER, | ||
| 1137 | }; | ||
| 1138 | |||
| 1139 | static struct ccu_reset_map sun8i_r40_ccu_resets[] = { | ||
| 1140 | [RST_USB_PHY0] = { 0x0cc, BIT(0) }, | ||
| 1141 | [RST_USB_PHY1] = { 0x0cc, BIT(1) }, | ||
| 1142 | [RST_USB_PHY2] = { 0x0cc, BIT(2) }, | ||
| 1143 | |||
| 1144 | [RST_DRAM] = { 0x0f4, BIT(31) }, | ||
| 1145 | [RST_MBUS] = { 0x0fc, BIT(31) }, | ||
| 1146 | |||
| 1147 | [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, | ||
| 1148 | [RST_BUS_CE] = { 0x2c0, BIT(5) }, | ||
| 1149 | [RST_BUS_DMA] = { 0x2c0, BIT(6) }, | ||
| 1150 | [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, | ||
| 1151 | [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, | ||
| 1152 | [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, | ||
| 1153 | [RST_BUS_MMC3] = { 0x2c0, BIT(11) }, | ||
| 1154 | [RST_BUS_NAND] = { 0x2c0, BIT(13) }, | ||
| 1155 | [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, | ||
| 1156 | [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, | ||
| 1157 | [RST_BUS_TS] = { 0x2c0, BIT(18) }, | ||
| 1158 | [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, | ||
| 1159 | [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, | ||
| 1160 | [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, | ||
| 1161 | [RST_BUS_SPI2] = { 0x2c0, BIT(22) }, | ||
| 1162 | [RST_BUS_SPI3] = { 0x2c0, BIT(23) }, | ||
| 1163 | [RST_BUS_SATA] = { 0x2c0, BIT(24) }, | ||
| 1164 | [RST_BUS_OTG] = { 0x2c0, BIT(25) }, | ||
| 1165 | [RST_BUS_EHCI0] = { 0x2c0, BIT(26) }, | ||
| 1166 | [RST_BUS_EHCI1] = { 0x2c0, BIT(27) }, | ||
| 1167 | [RST_BUS_EHCI2] = { 0x2c0, BIT(28) }, | ||
| 1168 | [RST_BUS_OHCI0] = { 0x2c0, BIT(29) }, | ||
| 1169 | [RST_BUS_OHCI1] = { 0x2c0, BIT(30) }, | ||
| 1170 | [RST_BUS_OHCI2] = { 0x2c0, BIT(31) }, | ||
| 1171 | |||
| 1172 | [RST_BUS_VE] = { 0x2c4, BIT(0) }, | ||
| 1173 | [RST_BUS_MP] = { 0x2c4, BIT(2) }, | ||
| 1174 | [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, | ||
| 1175 | [RST_BUS_CSI0] = { 0x2c4, BIT(8) }, | ||
| 1176 | [RST_BUS_CSI1] = { 0x2c4, BIT(9) }, | ||
| 1177 | [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, | ||
| 1178 | [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, | ||
| 1179 | [RST_BUS_DE] = { 0x2c4, BIT(12) }, | ||
| 1180 | [RST_BUS_TVE0] = { 0x2c4, BIT(13) }, | ||
| 1181 | [RST_BUS_TVE1] = { 0x2c4, BIT(14) }, | ||
| 1182 | [RST_BUS_TVE_TOP] = { 0x2c4, BIT(15) }, | ||
| 1183 | [RST_BUS_GMAC] = { 0x2c4, BIT(17) }, | ||
| 1184 | [RST_BUS_GPU] = { 0x2c4, BIT(20) }, | ||
| 1185 | [RST_BUS_TVD0] = { 0x2c4, BIT(21) }, | ||
| 1186 | [RST_BUS_TVD1] = { 0x2c4, BIT(22) }, | ||
| 1187 | [RST_BUS_TVD2] = { 0x2c4, BIT(23) }, | ||
| 1188 | [RST_BUS_TVD3] = { 0x2c4, BIT(24) }, | ||
| 1189 | [RST_BUS_TVD_TOP] = { 0x2c4, BIT(25) }, | ||
| 1190 | [RST_BUS_TCON_LCD0] = { 0x2c4, BIT(26) }, | ||
| 1191 | [RST_BUS_TCON_LCD1] = { 0x2c4, BIT(27) }, | ||
| 1192 | [RST_BUS_TCON_TV0] = { 0x2c4, BIT(28) }, | ||
| 1193 | [RST_BUS_TCON_TV1] = { 0x2c4, BIT(29) }, | ||
| 1194 | [RST_BUS_TCON_TOP] = { 0x2c4, BIT(30) }, | ||
| 1195 | [RST_BUS_DBG] = { 0x2c4, BIT(31) }, | ||
| 1196 | |||
| 1197 | [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, | ||
| 1198 | |||
| 1199 | [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, | ||
| 1200 | [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, | ||
| 1201 | [RST_BUS_AC97] = { 0x2d0, BIT(2) }, | ||
| 1202 | [RST_BUS_IR0] = { 0x2d0, BIT(6) }, | ||
| 1203 | [RST_BUS_IR1] = { 0x2d0, BIT(7) }, | ||
| 1204 | [RST_BUS_THS] = { 0x2d0, BIT(8) }, | ||
| 1205 | [RST_BUS_KEYPAD] = { 0x2d0, BIT(10) }, | ||
| 1206 | [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, | ||
| 1207 | [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, | ||
| 1208 | [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, | ||
| 1209 | |||
| 1210 | [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, | ||
| 1211 | [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, | ||
| 1212 | [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, | ||
| 1213 | [RST_BUS_I2C3] = { 0x2d8, BIT(3) }, | ||
| 1214 | [RST_BUS_CAN] = { 0x2d8, BIT(4) }, | ||
| 1215 | [RST_BUS_SCR] = { 0x2d8, BIT(5) }, | ||
| 1216 | [RST_BUS_PS20] = { 0x2d8, BIT(6) }, | ||
| 1217 | [RST_BUS_PS21] = { 0x2d8, BIT(7) }, | ||
| 1218 | [RST_BUS_I2C4] = { 0x2d8, BIT(15) }, | ||
| 1219 | [RST_BUS_UART0] = { 0x2d8, BIT(16) }, | ||
| 1220 | [RST_BUS_UART1] = { 0x2d8, BIT(17) }, | ||
| 1221 | [RST_BUS_UART2] = { 0x2d8, BIT(18) }, | ||
| 1222 | [RST_BUS_UART3] = { 0x2d8, BIT(19) }, | ||
| 1223 | [RST_BUS_UART4] = { 0x2d8, BIT(20) }, | ||
| 1224 | [RST_BUS_UART5] = { 0x2d8, BIT(21) }, | ||
| 1225 | [RST_BUS_UART6] = { 0x2d8, BIT(22) }, | ||
| 1226 | [RST_BUS_UART7] = { 0x2d8, BIT(23) }, | ||
| 1227 | }; | ||
| 1228 | |||
| 1229 | static const struct sunxi_ccu_desc sun8i_r40_ccu_desc = { | ||
| 1230 | .ccu_clks = sun8i_r40_ccu_clks, | ||
| 1231 | .num_ccu_clks = ARRAY_SIZE(sun8i_r40_ccu_clks), | ||
| 1232 | |||
| 1233 | .hw_clks = &sun8i_r40_hw_clks, | ||
| 1234 | |||
| 1235 | .resets = sun8i_r40_ccu_resets, | ||
| 1236 | .num_resets = ARRAY_SIZE(sun8i_r40_ccu_resets), | ||
| 1237 | }; | ||
| 1238 | |||
| 1239 | static struct ccu_pll_nb sun8i_r40_pll_cpu_nb = { | ||
| 1240 | .common = &pll_cpu_clk.common, | ||
| 1241 | /* copy from pll_cpu_clk */ | ||
| 1242 | .enable = BIT(31), | ||
| 1243 | .lock = BIT(28), | ||
| 1244 | }; | ||
| 1245 | |||
| 1246 | static struct ccu_mux_nb sun8i_r40_cpu_nb = { | ||
| 1247 | .common = &cpu_clk.common, | ||
| 1248 | .cm = &cpu_clk.mux, | ||
| 1249 | .delay_us = 1, /* > 8 clock cycles at 24 MHz */ | ||
| 1250 | .bypass_index = 1, /* index of 24 MHz oscillator */ | ||
| 1251 | }; | ||
| 1252 | |||
| 1253 | static void __init sun8i_r40_ccu_setup(struct device_node *node) | ||
| 1254 | { | ||
| 1255 | void __iomem *reg; | ||
| 1256 | u32 val; | ||
| 1257 | |||
| 1258 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
| 1259 | if (IS_ERR(reg)) { | ||
| 1260 | pr_err("%s: Could not map the clock registers\n", | ||
| 1261 | of_node_full_name(node)); | ||
| 1262 | return; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | /* Force the PLL-Audio-1x divider to 4 */ | ||
| 1266 | val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); | ||
| 1267 | val &= ~GENMASK(19, 16); | ||
| 1268 | writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); | ||
| 1269 | |||
| 1270 | /* Force PLL-MIPI to MIPI mode */ | ||
| 1271 | val = readl(reg + SUN8I_R40_PLL_MIPI_REG); | ||
| 1272 | val &= ~BIT(16); | ||
| 1273 | writel(val, reg + SUN8I_R40_PLL_MIPI_REG); | ||
| 1274 | |||
| 1275 | /* Force OHCI 12M parent to 12M divided from 48M */ | ||
| 1276 | val = readl(reg + SUN8I_R40_USB_CLK_REG); | ||
| 1277 | val &= ~GENMASK(25, 20); | ||
| 1278 | writel(val, reg + SUN8I_R40_USB_CLK_REG); | ||
| 1279 | |||
| 1280 | sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc); | ||
| 1281 | |||
| 1282 | /* Gate then ungate PLL CPU after any rate changes */ | ||
| 1283 | ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb); | ||
| 1284 | |||
| 1285 | /* Reparent CPU during PLL CPU rate changes */ | ||
| 1286 | ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, | ||
| 1287 | &sun8i_r40_cpu_nb); | ||
| 1288 | } | ||
| 1289 | CLK_OF_DECLARE(sun8i_r40_ccu, "allwinner,sun8i-r40-ccu", | ||
| 1290 | sun8i_r40_ccu_setup); | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.h b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h new file mode 100644 index 000000000000..0db8e1e97af8 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2017 Icenowy Zheng <icenowy@aosc.io> | ||
| 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 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef _CCU_SUN8I_R40_H_ | ||
| 16 | #define _CCU_SUN8I_R40_H_ | ||
| 17 | |||
| 18 | #include <dt-bindings/clock/sun8i-r40-ccu.h> | ||
| 19 | #include <dt-bindings/reset/sun8i-r40-ccu.h> | ||
| 20 | |||
| 21 | #define CLK_OSC_12M 0 | ||
| 22 | #define CLK_PLL_CPU 1 | ||
| 23 | #define CLK_PLL_AUDIO_BASE 2 | ||
| 24 | #define CLK_PLL_AUDIO 3 | ||
| 25 | #define CLK_PLL_AUDIO_2X 4 | ||
| 26 | #define CLK_PLL_AUDIO_4X 5 | ||
| 27 | #define CLK_PLL_AUDIO_8X 6 | ||
| 28 | #define CLK_PLL_VIDEO0 7 | ||
| 29 | #define CLK_PLL_VIDEO0_2X 8 | ||
| 30 | #define CLK_PLL_VE 9 | ||
| 31 | #define CLK_PLL_DDR0 10 | ||
| 32 | #define CLK_PLL_PERIPH0 11 | ||
| 33 | #define CLK_PLL_PERIPH0_SATA 12 | ||
| 34 | #define CLK_PLL_PERIPH0_2X 13 | ||
| 35 | #define CLK_PLL_PERIPH1 14 | ||
| 36 | #define CLK_PLL_PERIPH1_2X 15 | ||
| 37 | #define CLK_PLL_VIDEO1 16 | ||
| 38 | #define CLK_PLL_VIDEO1_2X 17 | ||
| 39 | #define CLK_PLL_SATA 18 | ||
| 40 | #define CLK_PLL_SATA_OUT 19 | ||
| 41 | #define CLK_PLL_GPU 20 | ||
| 42 | #define CLK_PLL_MIPI 21 | ||
| 43 | #define CLK_PLL_DE 22 | ||
| 44 | #define CLK_PLL_DDR1 23 | ||
| 45 | |||
| 46 | /* The CPU clock is exported */ | ||
| 47 | |||
| 48 | #define CLK_AXI 25 | ||
| 49 | #define CLK_AHB1 26 | ||
| 50 | #define CLK_APB1 27 | ||
| 51 | #define CLK_APB2 28 | ||
| 52 | |||
| 53 | /* All the bus gates are exported */ | ||
| 54 | |||
| 55 | /* The first bunch of module clocks are exported */ | ||
| 56 | |||
| 57 | #define CLK_DRAM 132 | ||
| 58 | |||
| 59 | /* All the DRAM gates are exported */ | ||
| 60 | |||
| 61 | /* Some more module clocks are exported */ | ||
| 62 | |||
| 63 | #define CLK_MBUS 155 | ||
| 64 | |||
| 65 | /* Another bunch of module clocks are exported */ | ||
| 66 | |||
| 67 | #define CLK_NUMBER (CLK_OUTB + 1) | ||
| 68 | |||
| 69 | #endif /* _CCU_SUN8I_R40_H_ */ | ||
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index a34a78d7fb28..621b1cd996db 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | |||
| @@ -575,8 +575,7 @@ static void __init sun8i_v3s_ccu_setup(struct device_node *node) | |||
| 575 | 575 | ||
| 576 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 576 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 577 | if (IS_ERR(reg)) { | 577 | if (IS_ERR(reg)) { |
| 578 | pr_err("%s: Could not map the clock registers\n", | 578 | pr_err("%pOF: Could not map the clock registers\n", node); |
| 579 | of_node_full_name(node)); | ||
| 580 | return; | 579 | return; |
| 581 | } | 580 | } |
| 582 | 581 | ||
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c index c0e5c10d0091..baa3cf96507b 100644 --- a/drivers/clk/sunxi-ng/ccu_div.c +++ b/drivers/clk/sunxi-ng/ccu_div.c | |||
| @@ -21,10 +21,18 @@ static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux, | |||
| 21 | { | 21 | { |
| 22 | struct ccu_div *cd = data; | 22 | struct ccu_div *cd = data; |
| 23 | 23 | ||
| 24 | return divider_round_rate_parent(&cd->common.hw, parent, | 24 | if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) |
| 25 | rate *= cd->fixed_post_div; | ||
| 26 | |||
| 27 | rate = divider_round_rate_parent(&cd->common.hw, parent, | ||
| 25 | rate, parent_rate, | 28 | rate, parent_rate, |
| 26 | cd->div.table, cd->div.width, | 29 | cd->div.table, cd->div.width, |
| 27 | cd->div.flags); | 30 | cd->div.flags); |
| 31 | |||
| 32 | if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 33 | rate /= cd->fixed_post_div; | ||
| 34 | |||
| 35 | return rate; | ||
| 28 | } | 36 | } |
| 29 | 37 | ||
| 30 | static void ccu_div_disable(struct clk_hw *hw) | 38 | static void ccu_div_disable(struct clk_hw *hw) |
| @@ -62,8 +70,13 @@ static unsigned long ccu_div_recalc_rate(struct clk_hw *hw, | |||
| 62 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, | 70 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, |
| 63 | parent_rate); | 71 | parent_rate); |
| 64 | 72 | ||
| 65 | return divider_recalc_rate(hw, parent_rate, val, cd->div.table, | 73 | val = divider_recalc_rate(hw, parent_rate, val, cd->div.table, |
| 66 | cd->div.flags); | 74 | cd->div.flags); |
| 75 | |||
| 76 | if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 77 | val /= cd->fixed_post_div; | ||
| 78 | |||
| 79 | return val; | ||
| 67 | } | 80 | } |
| 68 | 81 | ||
| 69 | static int ccu_div_determine_rate(struct clk_hw *hw, | 82 | static int ccu_div_determine_rate(struct clk_hw *hw, |
| @@ -86,6 +99,9 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 86 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, | 99 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, |
| 87 | parent_rate); | 100 | parent_rate); |
| 88 | 101 | ||
| 102 | if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 103 | rate *= cd->fixed_post_div; | ||
| 104 | |||
| 89 | val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width, | 105 | val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width, |
| 90 | cd->div.flags); | 106 | cd->div.flags); |
| 91 | 107 | ||
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h index 08d074451204..f3a5028dcd14 100644 --- a/drivers/clk/sunxi-ng/ccu_div.h +++ b/drivers/clk/sunxi-ng/ccu_div.h | |||
| @@ -86,9 +86,10 @@ struct ccu_div_internal { | |||
| 86 | struct ccu_div { | 86 | struct ccu_div { |
| 87 | u32 enable; | 87 | u32 enable; |
| 88 | 88 | ||
| 89 | struct ccu_div_internal div; | 89 | struct ccu_div_internal div; |
| 90 | struct ccu_mux_internal mux; | 90 | struct ccu_mux_internal mux; |
| 91 | struct ccu_common common; | 91 | struct ccu_common common; |
| 92 | unsigned int fixed_post_div; | ||
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 94 | #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ | 95 | #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ |
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c index 8b5eb7756bf7..d1d168d4c4f0 100644 --- a/drivers/clk/sunxi-ng/ccu_frac.c +++ b/drivers/clk/sunxi-ng/ccu_frac.c | |||
| @@ -67,25 +67,25 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, | |||
| 67 | { | 67 | { |
| 68 | u32 reg; | 68 | u32 reg; |
| 69 | 69 | ||
| 70 | printk("%s: Read fractional\n", clk_hw_get_name(&common->hw)); | 70 | pr_debug("%s: Read fractional\n", clk_hw_get_name(&common->hw)); |
| 71 | 71 | ||
| 72 | if (!(common->features & CCU_FEATURE_FRACTIONAL)) | 72 | if (!(common->features & CCU_FEATURE_FRACTIONAL)) |
| 73 | return 0; | 73 | return 0; |
| 74 | 74 | ||
| 75 | printk("%s: clock is fractional (rates %lu and %lu)\n", | 75 | pr_debug("%s: clock is fractional (rates %lu and %lu)\n", |
| 76 | clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]); | 76 | clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]); |
| 77 | 77 | ||
| 78 | reg = readl(common->base + common->reg); | 78 | reg = readl(common->base + common->reg); |
| 79 | 79 | ||
| 80 | printk("%s: clock reg is 0x%x (select is 0x%x)\n", | 80 | pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n", |
| 81 | clk_hw_get_name(&common->hw), reg, cf->select); | 81 | clk_hw_get_name(&common->hw), reg, cf->select); |
| 82 | 82 | ||
| 83 | return (reg & cf->select) ? cf->rates[1] : cf->rates[0]; | 83 | return (reg & cf->select) ? cf->rates[1] : cf->rates[0]; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | int ccu_frac_helper_set_rate(struct ccu_common *common, | 86 | int ccu_frac_helper_set_rate(struct ccu_common *common, |
| 87 | struct ccu_frac_internal *cf, | 87 | struct ccu_frac_internal *cf, |
| 88 | unsigned long rate) | 88 | unsigned long rate, u32 lock) |
| 89 | { | 89 | { |
| 90 | unsigned long flags; | 90 | unsigned long flags; |
| 91 | u32 reg, sel; | 91 | u32 reg, sel; |
| @@ -106,5 +106,7 @@ int ccu_frac_helper_set_rate(struct ccu_common *common, | |||
| 106 | writel(reg | sel, common->base + common->reg); | 106 | writel(reg | sel, common->base + common->reg); |
| 107 | spin_unlock_irqrestore(common->lock, flags); | 107 | spin_unlock_irqrestore(common->lock, flags); |
| 108 | 108 | ||
| 109 | ccu_helper_wait_for_lock(common, lock); | ||
| 110 | |||
| 109 | return 0; | 111 | return 0; |
| 110 | } | 112 | } |
diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h index 7b1ee380156f..efe2dd6bac01 100644 --- a/drivers/clk/sunxi-ng/ccu_frac.h +++ b/drivers/clk/sunxi-ng/ccu_frac.h | |||
| @@ -48,6 +48,6 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, | |||
| 48 | 48 | ||
| 49 | int ccu_frac_helper_set_rate(struct ccu_common *common, | 49 | int ccu_frac_helper_set_rate(struct ccu_common *common, |
| 50 | struct ccu_frac_internal *cf, | 50 | struct ccu_frac_internal *cf, |
| 51 | unsigned long rate); | 51 | unsigned long rate, u32 lock); |
| 52 | 52 | ||
| 53 | #endif /* _CCU_FRAC_H_ */ | 53 | #endif /* _CCU_FRAC_H_ */ |
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c index 20d0300867f2..12e0783caee6 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.c +++ b/drivers/clk/sunxi-ng/ccu_mult.c | |||
| @@ -111,10 +111,14 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 111 | unsigned long flags; | 111 | unsigned long flags; |
| 112 | u32 reg; | 112 | u32 reg; |
| 113 | 113 | ||
| 114 | if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) | 114 | if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) { |
| 115 | return ccu_frac_helper_set_rate(&cm->common, &cm->frac, rate); | 115 | ccu_frac_helper_enable(&cm->common, &cm->frac); |
| 116 | else | 116 | |
| 117 | return ccu_frac_helper_set_rate(&cm->common, &cm->frac, | ||
| 118 | rate, cm->lock); | ||
| 119 | } else { | ||
| 117 | ccu_frac_helper_disable(&cm->common, &cm->frac); | 120 | ccu_frac_helper_disable(&cm->common, &cm->frac); |
| 121 | } | ||
| 118 | 122 | ||
| 119 | parent_rate = ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1, | 123 | parent_rate = ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1, |
| 120 | parent_rate); | 124 | parent_rate); |
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 44b16dc8fea6..841840e35e61 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c | |||
| @@ -75,7 +75,7 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, | |||
| 75 | unsigned long parent_rate) | 75 | unsigned long parent_rate) |
| 76 | { | 76 | { |
| 77 | struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); | 77 | struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); |
| 78 | unsigned long n, m, k; | 78 | unsigned long n, m, k, rate; |
| 79 | u32 reg; | 79 | u32 reg; |
| 80 | 80 | ||
| 81 | reg = readl(nkm->common.base + nkm->common.reg); | 81 | reg = readl(nkm->common.base + nkm->common.reg); |
| @@ -98,7 +98,12 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, | |||
| 98 | if (!m) | 98 | if (!m) |
| 99 | m++; | 99 | m++; |
| 100 | 100 | ||
| 101 | return parent_rate * n * k / m; | 101 | rate = parent_rate * n * k / m; |
| 102 | |||
| 103 | if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 104 | rate /= nkm->fixed_post_div; | ||
| 105 | |||
| 106 | return rate; | ||
| 102 | } | 107 | } |
| 103 | 108 | ||
| 104 | static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, | 109 | static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, |
| @@ -117,9 +122,17 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, | |||
| 117 | _nkm.min_m = 1; | 122 | _nkm.min_m = 1; |
| 118 | _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; | 123 | _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; |
| 119 | 124 | ||
| 125 | if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 126 | rate *= nkm->fixed_post_div; | ||
| 127 | |||
| 120 | ccu_nkm_find_best(*parent_rate, rate, &_nkm); | 128 | ccu_nkm_find_best(*parent_rate, rate, &_nkm); |
| 121 | 129 | ||
| 122 | return *parent_rate * _nkm.n * _nkm.k / _nkm.m; | 130 | rate = *parent_rate * _nkm.n * _nkm.k / _nkm.m; |
| 131 | |||
| 132 | if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 133 | rate /= nkm->fixed_post_div; | ||
| 134 | |||
| 135 | return rate; | ||
| 123 | } | 136 | } |
| 124 | 137 | ||
| 125 | static int ccu_nkm_determine_rate(struct clk_hw *hw, | 138 | static int ccu_nkm_determine_rate(struct clk_hw *hw, |
| @@ -139,6 +152,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 139 | unsigned long flags; | 152 | unsigned long flags; |
| 140 | u32 reg; | 153 | u32 reg; |
| 141 | 154 | ||
| 155 | if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | ||
| 156 | rate *= nkm->fixed_post_div; | ||
| 157 | |||
| 142 | _nkm.min_n = nkm->n.min ?: 1; | 158 | _nkm.min_n = nkm->n.min ?: 1; |
| 143 | _nkm.max_n = nkm->n.max ?: 1 << nkm->n.width; | 159 | _nkm.max_n = nkm->n.max ?: 1 << nkm->n.width; |
| 144 | _nkm.min_k = nkm->k.min ?: 1; | 160 | _nkm.min_k = nkm->k.min ?: 1; |
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h index 34580894f4d1..cc6efb70a102 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.h +++ b/drivers/clk/sunxi-ng/ccu_nkm.h | |||
| @@ -34,6 +34,8 @@ struct ccu_nkm { | |||
| 34 | struct ccu_div_internal m; | 34 | struct ccu_div_internal m; |
| 35 | struct ccu_mux_internal mux; | 35 | struct ccu_mux_internal mux; |
| 36 | 36 | ||
| 37 | unsigned int fixed_post_div; | ||
| 38 | |||
| 37 | struct ccu_common common; | 39 | struct ccu_common common; |
| 38 | }; | 40 | }; |
| 39 | 41 | ||
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 5e5e90a4a50c..a32158e8f2e3 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c | |||
| @@ -117,10 +117,23 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 117 | unsigned long flags; | 117 | unsigned long flags; |
| 118 | u32 reg; | 118 | u32 reg; |
| 119 | 119 | ||
| 120 | if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) | 120 | if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) { |
| 121 | return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate); | 121 | spin_lock_irqsave(nm->common.lock, flags); |
| 122 | else | 122 | |
| 123 | /* most SoCs require M to be 0 if fractional mode is used */ | ||
| 124 | reg = readl(nm->common.base + nm->common.reg); | ||
| 125 | reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); | ||
| 126 | writel(reg, nm->common.base + nm->common.reg); | ||
| 127 | |||
| 128 | spin_unlock_irqrestore(nm->common.lock, flags); | ||
| 129 | |||
| 130 | ccu_frac_helper_enable(&nm->common, &nm->frac); | ||
| 131 | |||
| 132 | return ccu_frac_helper_set_rate(&nm->common, &nm->frac, | ||
| 133 | rate, nm->lock); | ||
| 134 | } else { | ||
| 123 | ccu_frac_helper_disable(&nm->common, &nm->frac); | 135 | ccu_frac_helper_disable(&nm->common, &nm->frac); |
| 136 | } | ||
| 124 | 137 | ||
| 125 | _nm.min_n = nm->n.min ?: 1; | 138 | _nm.min_n = nm->n.min ?: 1; |
| 126 | _nm.max_n = nm->n.max ?: 1 << nm->n.width; | 139 | _nm.max_n = nm->n.max ?: 1 << nm->n.width; |
diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c index 63fdb790df29..bee305bdddbe 100644 --- a/drivers/clk/sunxi/clk-sun8i-bus-gates.c +++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c | |||
| @@ -78,6 +78,10 @@ static void __init sun8i_h3_bus_gates_init(struct device_node *node) | |||
| 78 | clk_parent = APB1; | 78 | clk_parent = APB1; |
| 79 | else if (index >= 96 && index <= 127) | 79 | else if (index >= 96 && index <= 127) |
| 80 | clk_parent = APB2; | 80 | clk_parent = APB2; |
| 81 | else { | ||
| 82 | WARN_ON(true); | ||
| 83 | continue; | ||
| 84 | } | ||
| 81 | 85 | ||
| 82 | clk_reg = reg + 4 * (index / 32); | 86 | clk_reg = reg + 4 * (index / 32); |
| 83 | clk_bit = index % 32; | 87 | clk_bit = index % 32; |
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index f2c9274b8bd5..aa4add580516 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
| @@ -666,15 +666,14 @@ static struct clk * __init sunxi_mux_clk_setup(struct device_node *node, | |||
| 666 | 666 | ||
| 667 | reg = of_iomap(node, 0); | 667 | reg = of_iomap(node, 0); |
| 668 | if (!reg) { | 668 | if (!reg) { |
| 669 | pr_err("Could not map registers for mux-clk: %s\n", | 669 | pr_err("Could not map registers for mux-clk: %pOF\n", node); |
| 670 | of_node_full_name(node)); | ||
| 671 | return NULL; | 670 | return NULL; |
| 672 | } | 671 | } |
| 673 | 672 | ||
| 674 | i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS); | 673 | i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS); |
| 675 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { | 674 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { |
| 676 | pr_err("%s: could not read clock-output-names from \"%s\"\n", | 675 | pr_err("%s: could not read clock-output-names from \"%pOF\"\n", |
| 677 | __func__, of_node_full_name(node)); | 676 | __func__, node); |
| 678 | goto out_unmap; | 677 | goto out_unmap; |
| 679 | } | 678 | } |
| 680 | 679 | ||
| @@ -797,16 +796,15 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
| 797 | 796 | ||
| 798 | reg = of_iomap(node, 0); | 797 | reg = of_iomap(node, 0); |
| 799 | if (!reg) { | 798 | if (!reg) { |
| 800 | pr_err("Could not map registers for mux-clk: %s\n", | 799 | pr_err("Could not map registers for mux-clk: %pOF\n", node); |
| 801 | of_node_full_name(node)); | ||
| 802 | return; | 800 | return; |
| 803 | } | 801 | } |
| 804 | 802 | ||
| 805 | clk_parent = of_clk_get_parent_name(node, 0); | 803 | clk_parent = of_clk_get_parent_name(node, 0); |
| 806 | 804 | ||
| 807 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { | 805 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { |
| 808 | pr_err("%s: could not read clock-output-names from \"%s\"\n", | 806 | pr_err("%s: could not read clock-output-names from \"%pOF\"\n", |
| 809 | __func__, of_node_full_name(node)); | 807 | __func__, node); |
| 810 | goto out_unmap; | 808 | goto out_unmap; |
| 811 | } | 809 | } |
| 812 | 810 | ||
| @@ -1010,8 +1008,7 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, | |||
| 1010 | 1008 | ||
| 1011 | reg = of_iomap(node, 0); | 1009 | reg = of_iomap(node, 0); |
| 1012 | if (!reg) { | 1010 | if (!reg) { |
| 1013 | pr_err("Could not map registers for divs-clk: %s\n", | 1011 | pr_err("Could not map registers for divs-clk: %pOF\n", node); |
| 1014 | of_node_full_name(node)); | ||
| 1015 | return NULL; | 1012 | return NULL; |
| 1016 | } | 1013 | } |
| 1017 | 1014 | ||
diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c index 74e7544f861b..11a5066e5c27 100644 --- a/drivers/clk/tegra/clk-emc.c +++ b/drivers/clk/tegra/clk-emc.c | |||
| @@ -378,7 +378,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, | |||
| 378 | 378 | ||
| 379 | err = of_property_read_u32(node, "clock-frequency", &tmp); | 379 | err = of_property_read_u32(node, "clock-frequency", &tmp); |
| 380 | if (err) { | 380 | if (err) { |
| 381 | pr_err("timing %s: failed to read rate\n", node->full_name); | 381 | pr_err("timing %pOF: failed to read rate\n", node); |
| 382 | return err; | 382 | return err; |
| 383 | } | 383 | } |
| 384 | 384 | ||
| @@ -386,8 +386,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, | |||
| 386 | 386 | ||
| 387 | err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp); | 387 | err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp); |
| 388 | if (err) { | 388 | if (err) { |
| 389 | pr_err("timing %s: failed to read parent rate\n", | 389 | pr_err("timing %pOF: failed to read parent rate\n", node); |
| 390 | node->full_name); | ||
| 391 | return err; | 390 | return err; |
| 392 | } | 391 | } |
| 393 | 392 | ||
| @@ -395,8 +394,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, | |||
| 395 | 394 | ||
| 396 | timing->parent = of_clk_get_by_name(node, "emc-parent"); | 395 | timing->parent = of_clk_get_by_name(node, "emc-parent"); |
| 397 | if (IS_ERR(timing->parent)) { | 396 | if (IS_ERR(timing->parent)) { |
| 398 | pr_err("timing %s: failed to get parent clock\n", | 397 | pr_err("timing %pOF: failed to get parent clock\n", node); |
| 399 | node->full_name); | ||
| 400 | return PTR_ERR(timing->parent); | 398 | return PTR_ERR(timing->parent); |
| 401 | } | 399 | } |
| 402 | 400 | ||
| @@ -409,8 +407,8 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, | |||
| 409 | } | 407 | } |
| 410 | } | 408 | } |
| 411 | if (timing->parent_index == 0xff) { | 409 | if (timing->parent_index == 0xff) { |
| 412 | pr_err("timing %s: %s is not a valid parent\n", | 410 | pr_err("timing %pOF: %s is not a valid parent\n", |
| 413 | node->full_name, __clk_get_name(timing->parent)); | 411 | node, __clk_get_name(timing->parent)); |
| 414 | clk_put(timing->parent); | 412 | clk_put(timing->parent); |
| 415 | return -EINVAL; | 413 | return -EINVAL; |
| 416 | } | 414 | } |
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 159a854779e6..7c369e21c91c 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c | |||
| @@ -363,7 +363,7 @@ static void _clk_pll_enable(struct clk_hw *hw) | |||
| 363 | val = pll_readl(pll->params->iddq_reg, pll); | 363 | val = pll_readl(pll->params->iddq_reg, pll); |
| 364 | val &= ~BIT(pll->params->iddq_bit_idx); | 364 | val &= ~BIT(pll->params->iddq_bit_idx); |
| 365 | pll_writel(val, pll->params->iddq_reg, pll); | 365 | pll_writel(val, pll->params->iddq_reg, pll); |
| 366 | udelay(2); | 366 | udelay(5); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | if (pll->params->reset_reg) { | 369 | if (pll->params->reset_reg) { |
| @@ -418,6 +418,26 @@ static void _clk_pll_disable(struct clk_hw *hw) | |||
| 418 | } | 418 | } |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | static void pll_clk_start_ss(struct tegra_clk_pll *pll) | ||
| 422 | { | ||
| 423 | if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | ||
| 424 | u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | ||
| 425 | |||
| 426 | val |= pll->params->ssc_ctrl_en_mask; | ||
| 427 | pll_writel(val, pll->params->ssc_ctrl_reg, pll); | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | static void pll_clk_stop_ss(struct tegra_clk_pll *pll) | ||
| 432 | { | ||
| 433 | if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | ||
| 434 | u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | ||
| 435 | |||
| 436 | val &= ~pll->params->ssc_ctrl_en_mask; | ||
| 437 | pll_writel(val, pll->params->ssc_ctrl_reg, pll); | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 421 | static int clk_pll_enable(struct clk_hw *hw) | 441 | static int clk_pll_enable(struct clk_hw *hw) |
| 422 | { | 442 | { |
| 423 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 443 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
| @@ -431,6 +451,8 @@ static int clk_pll_enable(struct clk_hw *hw) | |||
| 431 | 451 | ||
| 432 | ret = clk_pll_wait_for_lock(pll); | 452 | ret = clk_pll_wait_for_lock(pll); |
| 433 | 453 | ||
| 454 | pll_clk_start_ss(pll); | ||
| 455 | |||
| 434 | if (pll->lock) | 456 | if (pll->lock) |
| 435 | spin_unlock_irqrestore(pll->lock, flags); | 457 | spin_unlock_irqrestore(pll->lock, flags); |
| 436 | 458 | ||
| @@ -445,6 +467,8 @@ static void clk_pll_disable(struct clk_hw *hw) | |||
| 445 | if (pll->lock) | 467 | if (pll->lock) |
| 446 | spin_lock_irqsave(pll->lock, flags); | 468 | spin_lock_irqsave(pll->lock, flags); |
| 447 | 469 | ||
| 470 | pll_clk_stop_ss(pll); | ||
| 471 | |||
| 448 | _clk_pll_disable(hw); | 472 | _clk_pll_disable(hw); |
| 449 | 473 | ||
| 450 | if (pll->lock) | 474 | if (pll->lock) |
| @@ -666,6 +690,8 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, | |||
| 666 | struct tegra_clk_pll_params *params = pll->params; | 690 | struct tegra_clk_pll_params *params = pll->params; |
| 667 | struct div_nmp *div_nmp = params->div_nmp; | 691 | struct div_nmp *div_nmp = params->div_nmp; |
| 668 | 692 | ||
| 693 | *cfg = (struct tegra_clk_pll_freq_table) { }; | ||
| 694 | |||
| 669 | if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && | 695 | if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && |
| 670 | (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & | 696 | (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & |
| 671 | PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { | 697 | PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { |
| @@ -716,26 +742,6 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll, | |||
| 716 | pll_writel_misc(val, pll); | 742 | pll_writel_misc(val, pll); |
| 717 | } | 743 | } |
| 718 | 744 | ||
| 719 | static void pll_clk_start_ss(struct tegra_clk_pll *pll) | ||
| 720 | { | ||
| 721 | if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | ||
| 722 | u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | ||
| 723 | |||
| 724 | val |= pll->params->ssc_ctrl_en_mask; | ||
| 725 | pll_writel(val, pll->params->ssc_ctrl_reg, pll); | ||
| 726 | } | ||
| 727 | } | ||
| 728 | |||
| 729 | static void pll_clk_stop_ss(struct tegra_clk_pll *pll) | ||
| 730 | { | ||
| 731 | if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | ||
| 732 | u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | ||
| 733 | |||
| 734 | val &= ~pll->params->ssc_ctrl_en_mask; | ||
| 735 | pll_writel(val, pll->params->ssc_ctrl_reg, pll); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 739 | static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, | 745 | static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, |
| 740 | unsigned long rate) | 746 | unsigned long rate) |
| 741 | { | 747 | { |
| @@ -2251,7 +2257,7 @@ tegra_clk_register_pllu_tegra114(const char *name, const char *parent_name, | |||
| 2251 | } | 2257 | } |
| 2252 | #endif | 2258 | #endif |
| 2253 | 2259 | ||
| 2254 | #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) | 2260 | #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) || defined(CONFIG_ARCH_TEGRA_210_SOC) |
| 2255 | static const struct clk_ops tegra_clk_pllss_ops = { | 2261 | static const struct clk_ops tegra_clk_pllss_ops = { |
| 2256 | .is_enabled = clk_pll_is_enabled, | 2262 | .is_enabled = clk_pll_is_enabled, |
| 2257 | .enable = clk_pll_enable, | 2263 | .enable = clk_pll_enable, |
| @@ -2349,7 +2355,6 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, | |||
| 2349 | struct tegra_clk_pll_params *pll_params, | 2355 | struct tegra_clk_pll_params *pll_params, |
| 2350 | spinlock_t *lock, unsigned long parent_rate) | 2356 | spinlock_t *lock, unsigned long parent_rate) |
| 2351 | { | 2357 | { |
| 2352 | u32 val; | ||
| 2353 | struct tegra_clk_pll *pll; | 2358 | struct tegra_clk_pll *pll; |
| 2354 | struct clk *clk; | 2359 | struct clk *clk; |
| 2355 | 2360 | ||
| @@ -2363,26 +2368,8 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, | |||
| 2363 | if (IS_ERR(pll)) | 2368 | if (IS_ERR(pll)) |
| 2364 | return ERR_CAST(pll); | 2369 | return ERR_CAST(pll); |
| 2365 | 2370 | ||
| 2366 | /* program minimum rate by default */ | ||
| 2367 | |||
| 2368 | val = pll_readl_base(pll); | ||
| 2369 | if (val & PLL_BASE_ENABLE) | ||
| 2370 | WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & | ||
| 2371 | BIT(pll_params->iddq_bit_idx)); | ||
| 2372 | else { | ||
| 2373 | val = 0x4 << divm_shift(pll); | ||
| 2374 | val |= 0x41 << divn_shift(pll); | ||
| 2375 | pll_writel_base(val, pll); | ||
| 2376 | } | ||
| 2377 | |||
| 2378 | /* disable lock override */ | ||
| 2379 | |||
| 2380 | val = pll_readl_misc(pll); | ||
| 2381 | val &= ~BIT(29); | ||
| 2382 | pll_writel_misc(val, pll); | ||
| 2383 | |||
| 2384 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | 2371 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, |
| 2385 | &tegra_clk_pllre_ops); | 2372 | &tegra_clk_pll_ops); |
| 2386 | if (IS_ERR(clk)) | 2373 | if (IS_ERR(clk)) |
| 2387 | kfree(pll); | 2374 | kfree(pll); |
| 2388 | 2375 | ||
| @@ -2604,46 +2591,6 @@ struct clk *tegra_clk_register_pllc_tegra210(const char *name, | |||
| 2604 | return clk; | 2591 | return clk; |
| 2605 | } | 2592 | } |
| 2606 | 2593 | ||
| 2607 | struct clk *tegra_clk_register_pllxc_tegra210(const char *name, | ||
| 2608 | const char *parent_name, void __iomem *clk_base, | ||
| 2609 | void __iomem *pmc, unsigned long flags, | ||
| 2610 | struct tegra_clk_pll_params *pll_params, | ||
| 2611 | spinlock_t *lock) | ||
| 2612 | { | ||
| 2613 | struct tegra_clk_pll *pll; | ||
| 2614 | struct clk *clk, *parent; | ||
| 2615 | unsigned long parent_rate; | ||
| 2616 | |||
| 2617 | parent = __clk_lookup(parent_name); | ||
| 2618 | if (!parent) { | ||
| 2619 | WARN(1, "parent clk %s of %s must be registered first\n", | ||
| 2620 | name, parent_name); | ||
| 2621 | return ERR_PTR(-EINVAL); | ||
| 2622 | } | ||
| 2623 | |||
| 2624 | if (!pll_params->pdiv_tohw) | ||
| 2625 | return ERR_PTR(-EINVAL); | ||
| 2626 | |||
| 2627 | parent_rate = clk_get_rate(parent); | ||
| 2628 | |||
| 2629 | pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); | ||
| 2630 | |||
| 2631 | if (pll_params->adjust_vco) | ||
| 2632 | pll_params->vco_min = pll_params->adjust_vco(pll_params, | ||
| 2633 | parent_rate); | ||
| 2634 | |||
| 2635 | pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); | ||
| 2636 | if (IS_ERR(pll)) | ||
| 2637 | return ERR_CAST(pll); | ||
| 2638 | |||
| 2639 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
| 2640 | &tegra_clk_pll_ops); | ||
| 2641 | if (IS_ERR(clk)) | ||
| 2642 | kfree(pll); | ||
| 2643 | |||
| 2644 | return clk; | ||
| 2645 | } | ||
| 2646 | |||
| 2647 | struct clk *tegra_clk_register_pllss_tegra210(const char *name, | 2594 | struct clk *tegra_clk_register_pllss_tegra210(const char *name, |
| 2648 | const char *parent_name, void __iomem *clk_base, | 2595 | const char *parent_name, void __iomem *clk_base, |
| 2649 | unsigned long flags, | 2596 | unsigned long flags, |
| @@ -2652,10 +2599,8 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, | |||
| 2652 | { | 2599 | { |
| 2653 | struct tegra_clk_pll *pll; | 2600 | struct tegra_clk_pll *pll; |
| 2654 | struct clk *clk, *parent; | 2601 | struct clk *clk, *parent; |
| 2655 | struct tegra_clk_pll_freq_table cfg; | ||
| 2656 | unsigned long parent_rate; | 2602 | unsigned long parent_rate; |
| 2657 | u32 val; | 2603 | u32 val; |
| 2658 | int i; | ||
| 2659 | 2604 | ||
| 2660 | if (!pll_params->div_nmp) | 2605 | if (!pll_params->div_nmp) |
| 2661 | return ERR_PTR(-EINVAL); | 2606 | return ERR_PTR(-EINVAL); |
| @@ -2667,13 +2612,11 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, | |||
| 2667 | return ERR_PTR(-EINVAL); | 2612 | return ERR_PTR(-EINVAL); |
| 2668 | } | 2613 | } |
| 2669 | 2614 | ||
| 2670 | pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); | 2615 | val = readl_relaxed(clk_base + pll_params->base_reg); |
| 2671 | if (IS_ERR(pll)) | 2616 | if (val & PLLSS_REF_SRC_SEL_MASK) { |
| 2672 | return ERR_CAST(pll); | 2617 | WARN(1, "not supported reference clock for %s\n", name); |
| 2673 | 2618 | return ERR_PTR(-EINVAL); | |
| 2674 | val = pll_readl_base(pll); | 2619 | } |
| 2675 | val &= ~PLLSS_REF_SRC_SEL_MASK; | ||
| 2676 | pll_writel_base(val, pll); | ||
| 2677 | 2620 | ||
| 2678 | parent_rate = clk_get_rate(parent); | 2621 | parent_rate = clk_get_rate(parent); |
| 2679 | 2622 | ||
| @@ -2683,36 +2626,10 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, | |||
| 2683 | pll_params->vco_min = pll_params->adjust_vco(pll_params, | 2626 | pll_params->vco_min = pll_params->adjust_vco(pll_params, |
| 2684 | parent_rate); | 2627 | parent_rate); |
| 2685 | 2628 | ||
| 2686 | /* initialize PLL to minimum rate */ | 2629 | pll_params->flags |= TEGRA_PLL_BYPASS; |
| 2687 | 2630 | pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); | |
| 2688 | cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); | 2631 | if (IS_ERR(pll)) |
| 2689 | cfg.n = cfg.m * pll_params->vco_min / parent_rate; | 2632 | return ERR_CAST(pll); |
| 2690 | |||
| 2691 | for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++) | ||
| 2692 | ; | ||
| 2693 | if (!i) { | ||
| 2694 | kfree(pll); | ||
| 2695 | return ERR_PTR(-EINVAL); | ||
| 2696 | } | ||
| 2697 | |||
| 2698 | cfg.p = pll_params->pdiv_tohw[i-1].hw_val; | ||
| 2699 | |||
| 2700 | _update_pll_mnp(pll, &cfg); | ||
| 2701 | |||
| 2702 | pll_writel_misc(PLLSS_MISC_DEFAULT, pll); | ||
| 2703 | |||
| 2704 | val = pll_readl_base(pll); | ||
| 2705 | if (val & PLL_BASE_ENABLE) { | ||
| 2706 | if (val & BIT(pll_params->iddq_bit_idx)) { | ||
| 2707 | WARN(1, "%s is on but IDDQ set\n", name); | ||
| 2708 | kfree(pll); | ||
| 2709 | return ERR_PTR(-EINVAL); | ||
| 2710 | } | ||
| 2711 | } else | ||
| 2712 | val |= BIT(pll_params->iddq_bit_idx); | ||
| 2713 | |||
| 2714 | val &= ~PLLSS_LOCK_OVERRIDE; | ||
| 2715 | pll_writel_base(val, pll); | ||
| 2716 | 2633 | ||
| 2717 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | 2634 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, |
| 2718 | &tegra_clk_pll_ops); | 2635 | &tegra_clk_pll_ops); |
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 294bfe40a4f5..848255cc0209 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c | |||
| @@ -216,7 +216,8 @@ | |||
| 216 | _clk_num, _clk_id) \ | 216 | _clk_num, _clk_id) \ |
| 217 | TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ | 217 | TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ |
| 218 | 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ | 218 | 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ |
| 219 | _clk_num, 0, _clk_id, _parents##_idx, 0, NULL) | 219 | _clk_num, TEGRA_PERIPH_ON_APB, _clk_id, \ |
| 220 | _parents##_idx, 0, NULL) | ||
| 220 | 221 | ||
| 221 | #define XUSB(_name, _parents, _offset, \ | 222 | #define XUSB(_name, _parents, _offset, \ |
| 222 | _clk_num, _gate_flags, _clk_id) \ | 223 | _clk_num, _gate_flags, _clk_id) \ |
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 474de0f0c26d..4f6fd307cb70 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c | |||
| @@ -232,8 +232,15 @@ static void __init tegra_super_clk_init(void __iomem *clk_base, | |||
| 232 | if (!dt_clk) | 232 | if (!dt_clk) |
| 233 | return; | 233 | return; |
| 234 | 234 | ||
| 235 | clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, | 235 | #if defined(CONFIG_ARCH_TEGRA_210_SOC) |
| 236 | pmc_base, CLK_IGNORE_UNUSED, params, NULL); | 236 | if (gen_info->gen == gen5) |
| 237 | clk = tegra_clk_register_pllc_tegra210("pll_x", "pll_ref", | ||
| 238 | clk_base, pmc_base, CLK_IGNORE_UNUSED, params, NULL); | ||
| 239 | else | ||
| 240 | #endif | ||
| 241 | clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, | ||
| 242 | pmc_base, CLK_IGNORE_UNUSED, params, NULL); | ||
| 243 | |||
| 237 | *dt_clk = clk; | 244 | *dt_clk = clk; |
| 238 | 245 | ||
| 239 | /* PLLX_OUT0 */ | 246 | /* PLLX_OUT0 */ |
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 1024e853ea65..6d7a613f2656 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c | |||
| @@ -146,7 +146,7 @@ | |||
| 146 | #define PLLD_SDM_EN_MASK BIT(16) | 146 | #define PLLD_SDM_EN_MASK BIT(16) |
| 147 | 147 | ||
| 148 | #define PLLD2_SDM_EN_MASK BIT(31) | 148 | #define PLLD2_SDM_EN_MASK BIT(31) |
| 149 | #define PLLD2_SSC_EN_MASK BIT(30) | 149 | #define PLLD2_SSC_EN_MASK 0 |
| 150 | 150 | ||
| 151 | #define PLLDP_SS_CFG 0x598 | 151 | #define PLLDP_SS_CFG 0x598 |
| 152 | #define PLLDP_SDM_EN_MASK BIT(31) | 152 | #define PLLDP_SDM_EN_MASK BIT(31) |
| @@ -241,6 +241,9 @@ | |||
| 241 | #define PLL_SDM_COEFF BIT(13) | 241 | #define PLL_SDM_COEFF BIT(13) |
| 242 | #define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU)) | 242 | #define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU)) |
| 243 | #define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat) | 243 | #define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat) |
| 244 | /* This macro returns ndiv effective scaled to SDM range */ | ||
| 245 | #define sdin_get_n_eff(cfg) ((cfg)->n * PLL_SDM_COEFF + ((cfg)->sdm_data ? \ | ||
| 246 | (PLL_SDM_COEFF/2 + sdin_data_to_din((cfg)->sdm_data)) : 0)) | ||
| 244 | 247 | ||
| 245 | /* Tegra CPU clock and reset control regs */ | 248 | /* Tegra CPU clock and reset control regs */ |
| 246 | #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 | 249 | #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 |
| @@ -715,8 +718,6 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, | |||
| 715 | plldss->params->defaults_set = true; | 718 | plldss->params->defaults_set = true; |
| 716 | 719 | ||
| 717 | if (val & PLL_ENABLE) { | 720 | if (val & PLL_ENABLE) { |
| 718 | pr_warn("%s already enabled. Postponing set full defaults\n", | ||
| 719 | pll_name); | ||
| 720 | 721 | ||
| 721 | /* | 722 | /* |
| 722 | * PLL is ON: check if defaults already set, then set those | 723 | * PLL is ON: check if defaults already set, then set those |
| @@ -755,6 +756,10 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, | |||
| 755 | (~PLLDSS_MISC1_CFG_EN_SDM)); | 756 | (~PLLDSS_MISC1_CFG_EN_SDM)); |
| 756 | } | 757 | } |
| 757 | 758 | ||
| 759 | if (!plldss->params->defaults_set) | ||
| 760 | pr_warn("%s already enabled. Postponing set full defaults\n", | ||
| 761 | pll_name); | ||
| 762 | |||
| 758 | /* Enable lock detect */ | 763 | /* Enable lock detect */ |
| 759 | if (val & PLLDSS_BASE_LOCK_OVERRIDE) { | 764 | if (val & PLLDSS_BASE_LOCK_OVERRIDE) { |
| 760 | val &= ~PLLDSS_BASE_LOCK_OVERRIDE; | 765 | val &= ~PLLDSS_BASE_LOCK_OVERRIDE; |
| @@ -1288,8 +1293,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, | |||
| 1288 | s -= PLL_SDM_COEFF / 2; | 1293 | s -= PLL_SDM_COEFF / 2; |
| 1289 | cfg->sdm_data = sdin_din_to_data(s); | 1294 | cfg->sdm_data = sdin_din_to_data(s); |
| 1290 | } | 1295 | } |
| 1291 | cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + | 1296 | cfg->output_rate *= sdin_get_n_eff(cfg); |
| 1292 | sdin_data_to_din(cfg->sdm_data); | ||
| 1293 | cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF; | 1297 | cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF; |
| 1294 | } else { | 1298 | } else { |
| 1295 | cfg->output_rate *= cfg->n; | 1299 | cfg->output_rate *= cfg->n; |
| @@ -1314,8 +1318,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, | |||
| 1314 | */ | 1318 | */ |
| 1315 | static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) | 1319 | static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) |
| 1316 | { | 1320 | { |
| 1317 | cfg->n = cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + | 1321 | cfg->n = sdin_get_n_eff(cfg); |
| 1318 | sdin_data_to_din(cfg->sdm_data); | ||
| 1319 | cfg->m *= PLL_SDM_COEFF; | 1322 | cfg->m *= PLL_SDM_COEFF; |
| 1320 | } | 1323 | } |
| 1321 | 1324 | ||
| @@ -2204,7 +2207,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { | |||
| 2204 | [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, | 2207 | [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, |
| 2205 | [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, | 2208 | [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, |
| 2206 | [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, | 2209 | [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, |
| 2207 | [tegra_clk_vfir] = { .dt_id = TEGRA210_CLK_VFIR, .present = true }, | ||
| 2208 | [tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true }, | 2210 | [tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true }, |
| 2209 | [tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true }, | 2211 | [tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true }, |
| 2210 | [tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true }, | 2212 | [tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true }, |
| @@ -2470,15 +2472,14 @@ static void tegra210_utmi_param_configure(void) | |||
| 2470 | reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); | 2472 | reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); |
| 2471 | 2473 | ||
| 2472 | reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); | 2474 | reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); |
| 2473 | |||
| 2474 | reg |= | 2475 | reg |= |
| 2475 | UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count); | 2476 | UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count); |
| 2476 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); | 2477 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); |
| 2477 | 2478 | ||
| 2478 | /* Program UTMIP PLL delay and oscillator frequency counts */ | 2479 | /* Program UTMIP PLL delay and oscillator frequency counts */ |
| 2479 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); | 2480 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); |
| 2480 | reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); | ||
| 2481 | 2481 | ||
| 2482 | reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); | ||
| 2482 | reg |= | 2483 | reg |= |
| 2483 | UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count); | 2484 | UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count); |
| 2484 | 2485 | ||
| @@ -2494,7 +2495,8 @@ static void tegra210_utmi_param_configure(void) | |||
| 2494 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; | 2495 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; |
| 2495 | reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; | 2496 | reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; |
| 2496 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); | 2497 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); |
| 2497 | udelay(1); | 2498 | |
| 2499 | udelay(20); | ||
| 2498 | 2500 | ||
| 2499 | /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ | 2501 | /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ |
| 2500 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); | 2502 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); |
| @@ -2552,6 +2554,7 @@ static int tegra210_enable_pllu(void) | |||
| 2552 | reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]); | 2554 | reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]); |
| 2553 | reg &= ~BIT(pllu.params->iddq_bit_idx); | 2555 | reg &= ~BIT(pllu.params->iddq_bit_idx); |
| 2554 | writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]); | 2556 | writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]); |
| 2557 | udelay(5); | ||
| 2555 | 2558 | ||
| 2556 | reg = readl_relaxed(clk_base + PLLU_BASE); | 2559 | reg = readl_relaxed(clk_base + PLLU_BASE); |
| 2557 | reg &= ~GENMASK(20, 0); | 2560 | reg &= ~GENMASK(20, 0); |
| @@ -2559,6 +2562,7 @@ static int tegra210_enable_pllu(void) | |||
| 2559 | reg |= fentry->n << 8; | 2562 | reg |= fentry->n << 8; |
| 2560 | reg |= fentry->p << 16; | 2563 | reg |= fentry->p << 16; |
| 2561 | writel(reg, clk_base + PLLU_BASE); | 2564 | writel(reg, clk_base + PLLU_BASE); |
| 2565 | udelay(1); | ||
| 2562 | reg |= PLL_ENABLE; | 2566 | reg |= PLL_ENABLE; |
| 2563 | writel(reg, clk_base + PLLU_BASE); | 2567 | writel(reg, clk_base + PLLU_BASE); |
| 2564 | 2568 | ||
| @@ -2699,7 +2703,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base, | |||
| 2699 | struct clk *clk; | 2703 | struct clk *clk; |
| 2700 | 2704 | ||
| 2701 | /* PLLC */ | 2705 | /* PLLC */ |
| 2702 | clk = tegra_clk_register_pllxc_tegra210("pll_c", "pll_ref", clk_base, | 2706 | clk = tegra_clk_register_pllc_tegra210("pll_c", "pll_ref", clk_base, |
| 2703 | pmc, 0, &pll_c_params, NULL); | 2707 | pmc, 0, &pll_c_params, NULL); |
| 2704 | if (!WARN_ON(IS_ERR(clk))) | 2708 | if (!WARN_ON(IS_ERR(clk))) |
| 2705 | clk_register_clkdev(clk, "pll_c", NULL); | 2709 | clk_register_clkdev(clk, "pll_c", NULL); |
| @@ -2798,14 +2802,14 @@ static void __init tegra210_pll_init(void __iomem *clk_base, | |||
| 2798 | /* PLLU_60M */ | 2802 | /* PLLU_60M */ |
| 2799 | clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_out2", | 2803 | clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_out2", |
| 2800 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, | 2804 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, |
| 2801 | 23, 0, NULL); | 2805 | 23, 0, &pll_u_lock); |
| 2802 | clk_register_clkdev(clk, "pll_u_60M", NULL); | 2806 | clk_register_clkdev(clk, "pll_u_60M", NULL); |
| 2803 | clks[TEGRA210_CLK_PLL_U_60M] = clk; | 2807 | clks[TEGRA210_CLK_PLL_U_60M] = clk; |
| 2804 | 2808 | ||
| 2805 | /* PLLU_48M */ | 2809 | /* PLLU_48M */ |
| 2806 | clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_out1", | 2810 | clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_out1", |
| 2807 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, | 2811 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, |
| 2808 | 25, 0, NULL); | 2812 | 25, 0, &pll_u_lock); |
| 2809 | clk_register_clkdev(clk, "pll_u_48M", NULL); | 2813 | clk_register_clkdev(clk, "pll_u_48M", NULL); |
| 2810 | clks[TEGRA210_CLK_PLL_U_48M] = clk; | 2814 | clks[TEGRA210_CLK_PLL_U_48M] = clk; |
| 2811 | 2815 | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 945b07093afa..872f1189ad7f 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
| @@ -362,12 +362,6 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, | |||
| 362 | struct tegra_clk_pll_params *pll_params, | 362 | struct tegra_clk_pll_params *pll_params, |
| 363 | spinlock_t *lock); | 363 | spinlock_t *lock); |
| 364 | 364 | ||
| 365 | struct clk *tegra_clk_register_pllxc_tegra210(const char *name, | ||
| 366 | const char *parent_name, void __iomem *clk_base, | ||
| 367 | void __iomem *pmc, unsigned long flags, | ||
| 368 | struct tegra_clk_pll_params *pll_params, | ||
| 369 | spinlock_t *lock); | ||
| 370 | |||
| 371 | struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, | 365 | struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, |
| 372 | void __iomem *clk_base, void __iomem *pmc, | 366 | void __iomem *clk_base, void __iomem *pmc, |
| 373 | unsigned long flags, | 367 | unsigned long flags, |
diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index 255cafb18336..d6036c788fab 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c | |||
| @@ -222,7 +222,7 @@ static int ti_adpll_setup_clock(struct ti_adpll_data *d, struct clk *clock, | |||
| 222 | 222 | ||
| 223 | /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */ | 223 | /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */ |
| 224 | postfix = strrchr(name, '.'); | 224 | postfix = strrchr(name, '.'); |
| 225 | if (strlen(postfix) > 1) { | 225 | if (postfix && strlen(postfix) > 1) { |
| 226 | if (strlen(postfix) > ADPLL_MAX_CON_ID) | 226 | if (strlen(postfix) > ADPLL_MAX_CON_ID) |
| 227 | dev_warn(d->dev, "clock %s con_id lookup may fail\n", | 227 | dev_warn(d->dev, "clock %s con_id lookup may fail\n", |
| 228 | name); | 228 | name); |
| @@ -486,7 +486,7 @@ static u8 ti_adpll_get_parent(struct clk_hw *hw) | |||
| 486 | return 0; | 486 | return 0; |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | static struct clk_ops ti_adpll_ops = { | 489 | static const struct clk_ops ti_adpll_ops = { |
| 490 | .prepare = ti_adpll_prepare, | 490 | .prepare = ti_adpll_prepare, |
| 491 | .unprepare = ti_adpll_unprepare, | 491 | .unprepare = ti_adpll_unprepare, |
| 492 | .is_prepared = ti_adpll_is_prepared, | 492 | .is_prepared = ti_adpll_is_prepared, |
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index 06f486b3488c..83b148f8037c 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c | |||
| @@ -304,7 +304,7 @@ static void omap2_apll_disable(struct clk_hw *hw) | |||
| 304 | ti_clk_ll_ops->clk_writel(v, &ad->control_reg); | 304 | ti_clk_ll_ops->clk_writel(v, &ad->control_reg); |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | static struct clk_ops omap2_apll_ops = { | 307 | static const struct clk_ops omap2_apll_ops = { |
| 308 | .enable = &omap2_apll_enable, | 308 | .enable = &omap2_apll_enable, |
| 309 | .disable = &omap2_apll_disable, | 309 | .disable = &omap2_apll_disable, |
| 310 | .is_enabled = &omap2_apll_is_enabled, | 310 | .is_enabled = &omap2_apll_is_enabled, |
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c index fbedc6a9fed0..07a805125e98 100644 --- a/drivers/clk/ti/clockdomain.c +++ b/drivers/clk/ti/clockdomain.c | |||
| @@ -138,8 +138,8 @@ static void __init of_ti_clockdomain_setup(struct device_node *node) | |||
| 138 | for (i = 0; i < num_clks; i++) { | 138 | for (i = 0; i < num_clks; i++) { |
| 139 | clk = of_clk_get(node, i); | 139 | clk = of_clk_get(node, i); |
| 140 | if (IS_ERR(clk)) { | 140 | if (IS_ERR(clk)) { |
| 141 | pr_err("%s: Failed get %s' clock nr %d (%ld)\n", | 141 | pr_err("%s: Failed get %pOF' clock nr %d (%ld)\n", |
| 142 | __func__, node->full_name, i, PTR_ERR(clk)); | 142 | __func__, node, i, PTR_ERR(clk)); |
| 143 | continue; | 143 | continue; |
| 144 | } | 144 | } |
| 145 | clk_hw = __clk_get_hw(clk); | 145 | clk_hw = __clk_get_hw(clk); |
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 66a0d0ed8b55..071af44b1ba8 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c | |||
| @@ -268,7 +268,7 @@ static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 268 | return 0; | 268 | return 0; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | static struct clk_ops ti_fapll_ops = { | 271 | static const struct clk_ops ti_fapll_ops = { |
| 272 | .enable = ti_fapll_enable, | 272 | .enable = ti_fapll_enable, |
| 273 | .disable = ti_fapll_disable, | 273 | .disable = ti_fapll_disable, |
| 274 | .is_enabled = ti_fapll_is_enabled, | 274 | .is_enabled = ti_fapll_is_enabled, |
| @@ -478,7 +478,7 @@ static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 478 | return 0; | 478 | return 0; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | static struct clk_ops ti_fapll_synt_ops = { | 481 | static const struct clk_ops ti_fapll_synt_ops = { |
| 482 | .enable = ti_fapll_synth_enable, | 482 | .enable = ti_fapll_synth_enable, |
| 483 | .disable = ti_fapll_synth_disable, | 483 | .disable = ti_fapll_synth_disable, |
| 484 | .is_enabled = ti_fapll_synth_is_enabled, | 484 | .is_enabled = ti_fapll_synth_is_enabled, |
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index 2cf386347f0c..e09f3dd46318 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c | |||
| @@ -111,10 +111,6 @@ static int uniphier_clk_remove(struct platform_device *pdev) | |||
| 111 | static const struct of_device_id uniphier_clk_match[] = { | 111 | static const struct of_device_id uniphier_clk_match[] = { |
| 112 | /* System clock */ | 112 | /* System clock */ |
| 113 | { | 113 | { |
| 114 | .compatible = "socionext,uniphier-sld3-clock", | ||
| 115 | .data = uniphier_sld3_sys_clk_data, | ||
| 116 | }, | ||
| 117 | { | ||
| 118 | .compatible = "socionext,uniphier-ld4-clock", | 114 | .compatible = "socionext,uniphier-ld4-clock", |
| 119 | .data = uniphier_ld4_sys_clk_data, | 115 | .data = uniphier_ld4_sys_clk_data, |
| 120 | }, | 116 | }, |
| @@ -142,22 +138,22 @@ static const struct of_device_id uniphier_clk_match[] = { | |||
| 142 | .compatible = "socionext,uniphier-ld20-clock", | 138 | .compatible = "socionext,uniphier-ld20-clock", |
| 143 | .data = uniphier_ld20_sys_clk_data, | 139 | .data = uniphier_ld20_sys_clk_data, |
| 144 | }, | 140 | }, |
| 145 | /* Media I/O clock, SD clock */ | ||
| 146 | { | 141 | { |
| 147 | .compatible = "socionext,uniphier-sld3-mio-clock", | 142 | .compatible = "socionext,uniphier-pxs3-clock", |
| 148 | .data = uniphier_sld3_mio_clk_data, | 143 | .data = uniphier_pxs3_sys_clk_data, |
| 149 | }, | 144 | }, |
| 145 | /* Media I/O clock, SD clock */ | ||
| 150 | { | 146 | { |
| 151 | .compatible = "socionext,uniphier-ld4-mio-clock", | 147 | .compatible = "socionext,uniphier-ld4-mio-clock", |
| 152 | .data = uniphier_sld3_mio_clk_data, | 148 | .data = uniphier_ld4_mio_clk_data, |
| 153 | }, | 149 | }, |
| 154 | { | 150 | { |
| 155 | .compatible = "socionext,uniphier-pro4-mio-clock", | 151 | .compatible = "socionext,uniphier-pro4-mio-clock", |
| 156 | .data = uniphier_sld3_mio_clk_data, | 152 | .data = uniphier_ld4_mio_clk_data, |
| 157 | }, | 153 | }, |
| 158 | { | 154 | { |
| 159 | .compatible = "socionext,uniphier-sld8-mio-clock", | 155 | .compatible = "socionext,uniphier-sld8-mio-clock", |
| 160 | .data = uniphier_sld3_mio_clk_data, | 156 | .data = uniphier_ld4_mio_clk_data, |
| 161 | }, | 157 | }, |
| 162 | { | 158 | { |
| 163 | .compatible = "socionext,uniphier-pro5-sd-clock", | 159 | .compatible = "socionext,uniphier-pro5-sd-clock", |
| @@ -169,12 +165,16 @@ static const struct of_device_id uniphier_clk_match[] = { | |||
| 169 | }, | 165 | }, |
| 170 | { | 166 | { |
| 171 | .compatible = "socionext,uniphier-ld11-mio-clock", | 167 | .compatible = "socionext,uniphier-ld11-mio-clock", |
| 172 | .data = uniphier_sld3_mio_clk_data, | 168 | .data = uniphier_ld4_mio_clk_data, |
| 173 | }, | 169 | }, |
| 174 | { | 170 | { |
| 175 | .compatible = "socionext,uniphier-ld20-sd-clock", | 171 | .compatible = "socionext,uniphier-ld20-sd-clock", |
| 176 | .data = uniphier_pro5_sd_clk_data, | 172 | .data = uniphier_pro5_sd_clk_data, |
| 177 | }, | 173 | }, |
| 174 | { | ||
| 175 | .compatible = "socionext,uniphier-pxs3-sd-clock", | ||
| 176 | .data = uniphier_pro5_sd_clk_data, | ||
| 177 | }, | ||
| 178 | /* Peripheral clock */ | 178 | /* Peripheral clock */ |
| 179 | { | 179 | { |
| 180 | .compatible = "socionext,uniphier-ld4-peri-clock", | 180 | .compatible = "socionext,uniphier-ld4-peri-clock", |
| @@ -204,6 +204,10 @@ static const struct of_device_id uniphier_clk_match[] = { | |||
| 204 | .compatible = "socionext,uniphier-ld20-peri-clock", | 204 | .compatible = "socionext,uniphier-ld20-peri-clock", |
| 205 | .data = uniphier_pro4_peri_clk_data, | 205 | .data = uniphier_pro4_peri_clk_data, |
| 206 | }, | 206 | }, |
| 207 | { | ||
| 208 | .compatible = "socionext,uniphier-pxs3-peri-clock", | ||
| 209 | .data = uniphier_pro4_peri_clk_data, | ||
| 210 | }, | ||
| 207 | { /* sentinel */ } | 211 | { /* sentinel */ } |
| 208 | }; | 212 | }; |
| 209 | 213 | ||
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c index 218d20f099ce..16e4d303f535 100644 --- a/drivers/clk/uniphier/clk-uniphier-mio.c +++ b/drivers/clk/uniphier/clk-uniphier-mio.c | |||
| @@ -76,7 +76,7 @@ | |||
| 76 | #define UNIPHIER_MIO_CLK_DMAC(idx) \ | 76 | #define UNIPHIER_MIO_CLK_DMAC(idx) \ |
| 77 | UNIPHIER_CLK_GATE("miodmac", (idx), "stdmac", 0x20, 25) | 77 | UNIPHIER_CLK_GATE("miodmac", (idx), "stdmac", 0x20, 25) |
| 78 | 78 | ||
| 79 | const struct uniphier_clk_data uniphier_sld3_mio_clk_data[] = { | 79 | const struct uniphier_clk_data uniphier_ld4_mio_clk_data[] = { |
| 80 | UNIPHIER_MIO_CLK_SD_FIXED, | 80 | UNIPHIER_MIO_CLK_SD_FIXED, |
| 81 | UNIPHIER_MIO_CLK_SD(0, 0), | 81 | UNIPHIER_MIO_CLK_SD(0, 0), |
| 82 | UNIPHIER_MIO_CLK_SD(1, 1), | 82 | UNIPHIER_MIO_CLK_SD(1, 1), |
| @@ -85,11 +85,9 @@ const struct uniphier_clk_data uniphier_sld3_mio_clk_data[] = { | |||
| 85 | UNIPHIER_MIO_CLK_USB2(8, 0), | 85 | UNIPHIER_MIO_CLK_USB2(8, 0), |
| 86 | UNIPHIER_MIO_CLK_USB2(9, 1), | 86 | UNIPHIER_MIO_CLK_USB2(9, 1), |
| 87 | UNIPHIER_MIO_CLK_USB2(10, 2), | 87 | UNIPHIER_MIO_CLK_USB2(10, 2), |
| 88 | UNIPHIER_MIO_CLK_USB2(11, 3), | ||
| 89 | UNIPHIER_MIO_CLK_USB2_PHY(12, 0), | 88 | UNIPHIER_MIO_CLK_USB2_PHY(12, 0), |
| 90 | UNIPHIER_MIO_CLK_USB2_PHY(13, 1), | 89 | UNIPHIER_MIO_CLK_USB2_PHY(13, 1), |
| 91 | UNIPHIER_MIO_CLK_USB2_PHY(14, 2), | 90 | UNIPHIER_MIO_CLK_USB2_PHY(14, 2), |
| 92 | UNIPHIER_MIO_CLK_USB2_PHY(15, 3), | ||
| 93 | { /* sentinel */ } | 91 | { /* sentinel */ } |
| 94 | }; | 92 | }; |
| 95 | 93 | ||
diff --git a/drivers/clk/uniphier/clk-uniphier-sys.c b/drivers/clk/uniphier/clk-uniphier-sys.c index ad0218182a9f..0e396f3da526 100644 --- a/drivers/clk/uniphier/clk-uniphier-sys.c +++ b/drivers/clk/uniphier/clk-uniphier-sys.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include "clk-uniphier.h" | 18 | #include "clk-uniphier.h" |
| 19 | 19 | ||
| 20 | #define UNIPHIER_SLD3_SYS_CLK_SD \ | 20 | #define UNIPHIER_LD4_SYS_CLK_SD \ |
| 21 | UNIPHIER_CLK_FACTOR("sd-200m", -1, "spll", 1, 8), \ | 21 | UNIPHIER_CLK_FACTOR("sd-200m", -1, "spll", 1, 8), \ |
| 22 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "vpll27a", 1, 2) | 22 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "vpll27a", 1, 2) |
| 23 | 23 | ||
| @@ -30,7 +30,7 @@ | |||
| 30 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "spll", 1, 15) | 30 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "spll", 1, 15) |
| 31 | 31 | ||
| 32 | /* Denali driver requires clk_x rate (clk: 50MHz, clk_x & ecc_clk: 200MHz) */ | 32 | /* Denali driver requires clk_x rate (clk: 50MHz, clk_x & ecc_clk: 200MHz) */ |
| 33 | #define UNIPHIER_SLD3_SYS_CLK_NAND(idx) \ | 33 | #define UNIPHIER_LD4_SYS_CLK_NAND(idx) \ |
| 34 | UNIPHIER_CLK_FACTOR("nand-200m", -1, "spll", 1, 8), \ | 34 | UNIPHIER_CLK_FACTOR("nand-200m", -1, "spll", 1, 8), \ |
| 35 | UNIPHIER_CLK_GATE("nand", (idx), "nand-200m", 0x2104, 2) | 35 | UNIPHIER_CLK_GATE("nand", (idx), "nand-200m", 0x2104, 2) |
| 36 | 36 | ||
| @@ -45,7 +45,7 @@ | |||
| 45 | #define UNIPHIER_LD11_SYS_CLK_EMMC(idx) \ | 45 | #define UNIPHIER_LD11_SYS_CLK_EMMC(idx) \ |
| 46 | UNIPHIER_CLK_GATE("emmc", (idx), NULL, 0x210c, 2) | 46 | UNIPHIER_CLK_GATE("emmc", (idx), NULL, 0x210c, 2) |
| 47 | 47 | ||
| 48 | #define UNIPHIER_SLD3_SYS_CLK_STDMAC(idx) \ | 48 | #define UNIPHIER_LD4_SYS_CLK_STDMAC(idx) \ |
| 49 | UNIPHIER_CLK_GATE("stdmac", (idx), NULL, 0x2104, 10) | 49 | UNIPHIER_CLK_GATE("stdmac", (idx), NULL, 0x2104, 10) |
| 50 | 50 | ||
| 51 | #define UNIPHIER_LD11_SYS_CLK_STDMAC(idx) \ | 51 | #define UNIPHIER_LD11_SYS_CLK_STDMAC(idx) \ |
| @@ -57,19 +57,23 @@ | |||
| 57 | #define UNIPHIER_PRO4_SYS_CLK_USB3(idx, ch) \ | 57 | #define UNIPHIER_PRO4_SYS_CLK_USB3(idx, ch) \ |
| 58 | UNIPHIER_CLK_GATE("usb3" #ch, (idx), NULL, 0x2104, 16 + (ch)) | 58 | UNIPHIER_CLK_GATE("usb3" #ch, (idx), NULL, 0x2104, 16 + (ch)) |
| 59 | 59 | ||
| 60 | const struct uniphier_clk_data uniphier_sld3_sys_clk_data[] = { | 60 | #define UNIPHIER_LD11_SYS_CLK_AIO(idx) \ |
| 61 | UNIPHIER_CLK_FACTOR("spll", -1, "ref", 65, 1), /* 1597.44 MHz */ | 61 | UNIPHIER_CLK_FACTOR("aio-io200m", -1, "spll", 1, 10), \ |
| 62 | UNIPHIER_CLK_FACTOR("upll", -1, "ref", 6000, 512), /* 288 MHz */ | 62 | UNIPHIER_CLK_GATE("aio", (idx), "aio-io200m", 0x2108, 0) |
| 63 | UNIPHIER_CLK_FACTOR("a2pll", -1, "ref", 24, 1), /* 589.824 MHz */ | 63 | |
| 64 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 5625, 512), /* 270 MHz */ | 64 | #define UNIPHIER_LD11_SYS_CLK_EVEA(idx) \ |
| 65 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 16), | 65 | UNIPHIER_CLK_FACTOR("evea-io100m", -1, "spll", 1, 20), \ |
| 66 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), | 66 | UNIPHIER_CLK_GATE("evea", (idx), "evea-io100m", 0x2108, 1) |
| 67 | UNIPHIER_SLD3_SYS_CLK_NAND(2), | 67 | |
| 68 | UNIPHIER_SLD3_SYS_CLK_SD, | 68 | #define UNIPHIER_LD11_SYS_CLK_EXIV(idx) \ |
| 69 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), | 69 | UNIPHIER_CLK_FACTOR("exiv-io200m", -1, "spll", 1, 10), \ |
| 70 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), | 70 | UNIPHIER_CLK_GATE("exiv", (idx), "exiv-io200m", 0x2110, 2) |
| 71 | { /* sentinel */ } | 71 | |
| 72 | }; | 72 | #define UNIPHIER_PRO4_SYS_CLK_ETHER(idx) \ |
| 73 | UNIPHIER_CLK_GATE("ether", (idx), NULL, 0x2104, 12) | ||
| 74 | |||
| 75 | #define UNIPHIER_LD11_SYS_CLK_ETHER(idx) \ | ||
| 76 | UNIPHIER_CLK_GATE("ether", (idx), NULL, 0x210c, 6) | ||
| 73 | 77 | ||
| 74 | const struct uniphier_clk_data uniphier_ld4_sys_clk_data[] = { | 78 | const struct uniphier_clk_data uniphier_ld4_sys_clk_data[] = { |
| 75 | UNIPHIER_CLK_FACTOR("spll", -1, "ref", 65, 1), /* 1597.44 MHz */ | 79 | UNIPHIER_CLK_FACTOR("spll", -1, "ref", 65, 1), /* 1597.44 MHz */ |
| @@ -78,10 +82,10 @@ const struct uniphier_clk_data uniphier_ld4_sys_clk_data[] = { | |||
| 78 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 5625, 512), /* 270 MHz */ | 82 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 5625, 512), /* 270 MHz */ |
| 79 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 16), | 83 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 16), |
| 80 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), | 84 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), |
| 81 | UNIPHIER_SLD3_SYS_CLK_NAND(2), | 85 | UNIPHIER_LD4_SYS_CLK_NAND(2), |
| 82 | UNIPHIER_SLD3_SYS_CLK_SD, | 86 | UNIPHIER_LD4_SYS_CLK_SD, |
| 83 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), | 87 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 84 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | 88 | UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ |
| 85 | { /* sentinel */ } | 89 | { /* sentinel */ } |
| 86 | }; | 90 | }; |
| 87 | 91 | ||
| @@ -92,10 +96,11 @@ const struct uniphier_clk_data uniphier_pro4_sys_clk_data[] = { | |||
| 92 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ | 96 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ |
| 93 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 8), | 97 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 8), |
| 94 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 32), | 98 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 32), |
| 95 | UNIPHIER_SLD3_SYS_CLK_NAND(2), | 99 | UNIPHIER_LD4_SYS_CLK_NAND(2), |
| 96 | UNIPHIER_SLD3_SYS_CLK_SD, | 100 | UNIPHIER_LD4_SYS_CLK_SD, |
| 97 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), | 101 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 98 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC, MIO, RLE */ | 102 | UNIPHIER_PRO4_SYS_CLK_ETHER(6), |
| 103 | UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC, MIO, RLE */ | ||
| 99 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* Ether, SATA, USB3 */ | 104 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* Ether, SATA, USB3 */ |
| 100 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), | 105 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 101 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), | 106 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -108,10 +113,10 @@ const struct uniphier_clk_data uniphier_sld8_sys_clk_data[] = { | |||
| 108 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ | 113 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ |
| 109 | UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 20), | 114 | UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 20), |
| 110 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), | 115 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), |
| 111 | UNIPHIER_SLD3_SYS_CLK_NAND(2), | 116 | UNIPHIER_LD4_SYS_CLK_NAND(2), |
| 112 | UNIPHIER_SLD3_SYS_CLK_SD, | 117 | UNIPHIER_LD4_SYS_CLK_SD, |
| 113 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), | 118 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 114 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | 119 | UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ |
| 115 | { /* sentinel */ } | 120 | { /* sentinel */ } |
| 116 | }; | 121 | }; |
| 117 | 122 | ||
| @@ -123,7 +128,7 @@ const struct uniphier_clk_data uniphier_pro5_sys_clk_data[] = { | |||
| 123 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), | 128 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), |
| 124 | UNIPHIER_PRO5_SYS_CLK_NAND(2), | 129 | UNIPHIER_PRO5_SYS_CLK_NAND(2), |
| 125 | UNIPHIER_PRO5_SYS_CLK_SD, | 130 | UNIPHIER_PRO5_SYS_CLK_SD, |
| 126 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC */ | 131 | UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC */ |
| 127 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* PCIe, USB3 */ | 132 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* PCIe, USB3 */ |
| 128 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), | 133 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 129 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), | 134 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -136,7 +141,8 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { | |||
| 136 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), | 141 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), |
| 137 | UNIPHIER_PRO5_SYS_CLK_NAND(2), | 142 | UNIPHIER_PRO5_SYS_CLK_NAND(2), |
| 138 | UNIPHIER_PRO5_SYS_CLK_SD, | 143 | UNIPHIER_PRO5_SYS_CLK_SD, |
| 139 | UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC, RLE */ | 144 | UNIPHIER_PRO4_SYS_CLK_ETHER(6), |
| 145 | UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC, RLE */ | ||
| 140 | /* GIO is always clock-enabled: no function for 0x2104 bit6 */ | 146 | /* GIO is always clock-enabled: no function for 0x2104 bit6 */ |
| 141 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), | 147 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 142 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), | 148 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -156,8 +162,12 @@ const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = { | |||
| 156 | UNIPHIER_LD11_SYS_CLK_NAND(2), | 162 | UNIPHIER_LD11_SYS_CLK_NAND(2), |
| 157 | UNIPHIER_LD11_SYS_CLK_EMMC(4), | 163 | UNIPHIER_LD11_SYS_CLK_EMMC(4), |
| 158 | /* Index 5 reserved for eMMC PHY */ | 164 | /* Index 5 reserved for eMMC PHY */ |
| 165 | UNIPHIER_LD11_SYS_CLK_ETHER(6), | ||
| 159 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC, MIO */ | 166 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC, MIO */ |
| 160 | UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25), | 167 | UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25), |
| 168 | UNIPHIER_LD11_SYS_CLK_AIO(40), | ||
| 169 | UNIPHIER_LD11_SYS_CLK_EVEA(41), | ||
| 170 | UNIPHIER_LD11_SYS_CLK_EXIV(42), | ||
| 161 | /* CPU gears */ | 171 | /* CPU gears */ |
| 162 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), | 172 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), |
| 163 | UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8), | 173 | UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8), |
| @@ -185,6 +195,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { | |||
| 185 | UNIPHIER_LD11_SYS_CLK_EMMC(4), | 195 | UNIPHIER_LD11_SYS_CLK_EMMC(4), |
| 186 | /* Index 5 reserved for eMMC PHY */ | 196 | /* Index 5 reserved for eMMC PHY */ |
| 187 | UNIPHIER_LD20_SYS_CLK_SD, | 197 | UNIPHIER_LD20_SYS_CLK_SD, |
| 198 | UNIPHIER_LD11_SYS_CLK_ETHER(6), | ||
| 188 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC */ | 199 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC */ |
| 189 | /* GIO is always clock-enabled: no function for 0x210c bit5 */ | 200 | /* GIO is always clock-enabled: no function for 0x210c bit5 */ |
| 190 | /* | 201 | /* |
| @@ -194,6 +205,9 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { | |||
| 194 | UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14), | 205 | UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14), |
| 195 | UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12), | 206 | UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12), |
| 196 | UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13), | 207 | UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13), |
| 208 | UNIPHIER_LD11_SYS_CLK_AIO(40), | ||
| 209 | UNIPHIER_LD11_SYS_CLK_EVEA(41), | ||
| 210 | UNIPHIER_LD11_SYS_CLK_EXIV(42), | ||
| 197 | /* CPU gears */ | 211 | /* CPU gears */ |
| 198 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), | 212 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), |
| 199 | UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8), | 213 | UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8), |
| @@ -209,3 +223,33 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { | |||
| 209 | "spll/4", "spll/8", "s2pll/4", "s2pll/8"), | 223 | "spll/4", "spll/8", "s2pll/4", "s2pll/8"), |
| 210 | { /* sentinel */ } | 224 | { /* sentinel */ } |
| 211 | }; | 225 | }; |
| 226 | |||
| 227 | const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = { | ||
| 228 | UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 104, 1), /* ARM: 2600 MHz */ | ||
| 229 | UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1), /* 2000 MHz */ | ||
| 230 | UNIPHIER_CLK_FACTOR("s2pll", -1, "ref", 88, 1), /* IPP: 2400 MHz */ | ||
| 231 | UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34), | ||
| 232 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40), | ||
| 233 | UNIPHIER_LD20_SYS_CLK_SD, | ||
| 234 | UNIPHIER_LD11_SYS_CLK_NAND(2), | ||
| 235 | UNIPHIER_LD11_SYS_CLK_EMMC(4), | ||
| 236 | UNIPHIER_CLK_GATE("usb30", 12, NULL, 0x2104, 4), /* =GIO0 */ | ||
| 237 | UNIPHIER_CLK_GATE("usb31-0", 13, NULL, 0x2104, 5), /* =GIO1 */ | ||
| 238 | UNIPHIER_CLK_GATE("usb31-1", 14, NULL, 0x2104, 6), /* =GIO1-1 */ | ||
| 239 | UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 16), | ||
| 240 | UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 18), | ||
| 241 | UNIPHIER_CLK_GATE("usb30-phy2", 18, NULL, 0x210c, 20), | ||
| 242 | UNIPHIER_CLK_GATE("usb31-phy0", 20, NULL, 0x210c, 17), | ||
| 243 | UNIPHIER_CLK_GATE("usb31-phy1", 21, NULL, 0x210c, 19), | ||
| 244 | /* CPU gears */ | ||
| 245 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), | ||
| 246 | UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8), | ||
| 247 | UNIPHIER_CLK_DIV4("s2pll", 2, 3, 4, 8), | ||
| 248 | UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8, | ||
| 249 | "cpll/2", "spll/2", "cpll/3", "spll/3", | ||
| 250 | "spll/4", "spll/8", "cpll/4", "cpll/8"), | ||
| 251 | UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8, | ||
| 252 | "s2pll/2", "spll/2", "s2pll/3", "spll/3", | ||
| 253 | "spll/4", "spll/8", "s2pll/4", "s2pll/8"), | ||
| 254 | { /* sentinel */ } | ||
| 255 | }; | ||
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h index 01c16ecec48f..d10a009ada96 100644 --- a/drivers/clk/uniphier/clk-uniphier.h +++ b/drivers/clk/uniphier/clk-uniphier.h | |||
| @@ -147,7 +147,6 @@ struct clk_hw *uniphier_clk_register_mux(struct device *dev, | |||
| 147 | const char *name, | 147 | const char *name, |
| 148 | const struct uniphier_clk_mux_data *data); | 148 | const struct uniphier_clk_mux_data *data); |
| 149 | 149 | ||
| 150 | extern const struct uniphier_clk_data uniphier_sld3_sys_clk_data[]; | ||
| 151 | extern const struct uniphier_clk_data uniphier_ld4_sys_clk_data[]; | 150 | extern const struct uniphier_clk_data uniphier_ld4_sys_clk_data[]; |
| 152 | extern const struct uniphier_clk_data uniphier_pro4_sys_clk_data[]; | 151 | extern const struct uniphier_clk_data uniphier_pro4_sys_clk_data[]; |
| 153 | extern const struct uniphier_clk_data uniphier_sld8_sys_clk_data[]; | 152 | extern const struct uniphier_clk_data uniphier_sld8_sys_clk_data[]; |
| @@ -155,7 +154,8 @@ extern const struct uniphier_clk_data uniphier_pro5_sys_clk_data[]; | |||
| 155 | extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[]; | 154 | extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[]; |
| 156 | extern const struct uniphier_clk_data uniphier_ld11_sys_clk_data[]; | 155 | extern const struct uniphier_clk_data uniphier_ld11_sys_clk_data[]; |
| 157 | extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[]; | 156 | extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[]; |
| 158 | extern const struct uniphier_clk_data uniphier_sld3_mio_clk_data[]; | 157 | extern const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[]; |
| 158 | extern const struct uniphier_clk_data uniphier_ld4_mio_clk_data[]; | ||
| 159 | extern const struct uniphier_clk_data uniphier_pro5_sd_clk_data[]; | 159 | extern const struct uniphier_clk_data uniphier_pro5_sd_clk_data[]; |
| 160 | extern const struct uniphier_clk_data uniphier_ld4_peri_clk_data[]; | 160 | extern const struct uniphier_clk_data uniphier_ld4_peri_clk_data[]; |
| 161 | extern const struct uniphier_clk_data uniphier_pro4_peri_clk_data[]; | 161 | extern const struct uniphier_clk_data uniphier_pro4_peri_clk_data[]; |
diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c index 0e950769ed03..f50592775c9d 100644 --- a/drivers/clk/ux500/clk-prcc.c +++ b/drivers/clk/ux500/clk-prcc.c | |||
| @@ -79,13 +79,13 @@ static int clk_prcc_is_enabled(struct clk_hw *hw) | |||
| 79 | return clk->is_enabled; | 79 | return clk->is_enabled; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static struct clk_ops clk_prcc_pclk_ops = { | 82 | static const struct clk_ops clk_prcc_pclk_ops = { |
| 83 | .enable = clk_prcc_pclk_enable, | 83 | .enable = clk_prcc_pclk_enable, |
| 84 | .disable = clk_prcc_pclk_disable, | 84 | .disable = clk_prcc_pclk_disable, |
| 85 | .is_enabled = clk_prcc_is_enabled, | 85 | .is_enabled = clk_prcc_is_enabled, |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | static struct clk_ops clk_prcc_kclk_ops = { | 88 | static const struct clk_ops clk_prcc_kclk_ops = { |
| 89 | .enable = clk_prcc_kclk_enable, | 89 | .enable = clk_prcc_kclk_enable, |
| 90 | .disable = clk_prcc_kclk_disable, | 90 | .disable = clk_prcc_kclk_disable, |
| 91 | .is_enabled = clk_prcc_is_enabled, | 91 | .is_enabled = clk_prcc_is_enabled, |
| @@ -96,7 +96,7 @@ static struct clk *clk_reg_prcc(const char *name, | |||
| 96 | resource_size_t phy_base, | 96 | resource_size_t phy_base, |
| 97 | u32 cg_sel, | 97 | u32 cg_sel, |
| 98 | unsigned long flags, | 98 | unsigned long flags, |
| 99 | struct clk_ops *clk_prcc_ops) | 99 | const struct clk_ops *clk_prcc_ops) |
| 100 | { | 100 | { |
| 101 | struct clk_prcc *clk; | 101 | struct clk_prcc *clk; |
| 102 | struct clk_init_data clk_prcc_init; | 102 | struct clk_init_data clk_prcc_init; |
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 7f343821f4e4..6e3e16b2e5ca 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c | |||
| @@ -186,7 +186,7 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) | |||
| 186 | clk->is_prepared = 0; | 186 | clk->is_prepared = 0; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static struct clk_ops clk_prcmu_scalable_ops = { | 189 | static const struct clk_ops clk_prcmu_scalable_ops = { |
| 190 | .prepare = clk_prcmu_prepare, | 190 | .prepare = clk_prcmu_prepare, |
| 191 | .unprepare = clk_prcmu_unprepare, | 191 | .unprepare = clk_prcmu_unprepare, |
| 192 | .is_prepared = clk_prcmu_is_prepared, | 192 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -198,7 +198,7 @@ static struct clk_ops clk_prcmu_scalable_ops = { | |||
| 198 | .set_rate = clk_prcmu_set_rate, | 198 | .set_rate = clk_prcmu_set_rate, |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | static struct clk_ops clk_prcmu_gate_ops = { | 201 | static const struct clk_ops clk_prcmu_gate_ops = { |
| 202 | .prepare = clk_prcmu_prepare, | 202 | .prepare = clk_prcmu_prepare, |
| 203 | .unprepare = clk_prcmu_unprepare, | 203 | .unprepare = clk_prcmu_unprepare, |
| 204 | .is_prepared = clk_prcmu_is_prepared, | 204 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -208,19 +208,19 @@ static struct clk_ops clk_prcmu_gate_ops = { | |||
| 208 | .recalc_rate = clk_prcmu_recalc_rate, | 208 | .recalc_rate = clk_prcmu_recalc_rate, |
| 209 | }; | 209 | }; |
| 210 | 210 | ||
| 211 | static struct clk_ops clk_prcmu_scalable_rate_ops = { | 211 | static const struct clk_ops clk_prcmu_scalable_rate_ops = { |
| 212 | .is_enabled = clk_prcmu_is_enabled, | 212 | .is_enabled = clk_prcmu_is_enabled, |
| 213 | .recalc_rate = clk_prcmu_recalc_rate, | 213 | .recalc_rate = clk_prcmu_recalc_rate, |
| 214 | .round_rate = clk_prcmu_round_rate, | 214 | .round_rate = clk_prcmu_round_rate, |
| 215 | .set_rate = clk_prcmu_set_rate, | 215 | .set_rate = clk_prcmu_set_rate, |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | static struct clk_ops clk_prcmu_rate_ops = { | 218 | static const struct clk_ops clk_prcmu_rate_ops = { |
| 219 | .is_enabled = clk_prcmu_is_enabled, | 219 | .is_enabled = clk_prcmu_is_enabled, |
| 220 | .recalc_rate = clk_prcmu_recalc_rate, | 220 | .recalc_rate = clk_prcmu_recalc_rate, |
| 221 | }; | 221 | }; |
| 222 | 222 | ||
| 223 | static struct clk_ops clk_prcmu_opp_gate_ops = { | 223 | static const struct clk_ops clk_prcmu_opp_gate_ops = { |
| 224 | .prepare = clk_prcmu_opp_prepare, | 224 | .prepare = clk_prcmu_opp_prepare, |
| 225 | .unprepare = clk_prcmu_opp_unprepare, | 225 | .unprepare = clk_prcmu_opp_unprepare, |
| 226 | .is_prepared = clk_prcmu_is_prepared, | 226 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -230,7 +230,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = { | |||
| 230 | .recalc_rate = clk_prcmu_recalc_rate, | 230 | .recalc_rate = clk_prcmu_recalc_rate, |
| 231 | }; | 231 | }; |
| 232 | 232 | ||
| 233 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | 233 | static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = { |
| 234 | .prepare = clk_prcmu_opp_volt_prepare, | 234 | .prepare = clk_prcmu_opp_volt_prepare, |
| 235 | .unprepare = clk_prcmu_opp_volt_unprepare, | 235 | .unprepare = clk_prcmu_opp_volt_unprepare, |
| 236 | .is_prepared = clk_prcmu_is_prepared, | 236 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -247,7 +247,7 @@ static struct clk *clk_reg_prcmu(const char *name, | |||
| 247 | u8 cg_sel, | 247 | u8 cg_sel, |
| 248 | unsigned long rate, | 248 | unsigned long rate, |
| 249 | unsigned long flags, | 249 | unsigned long flags, |
| 250 | struct clk_ops *clk_prcmu_ops) | 250 | const struct clk_ops *clk_prcmu_ops) |
| 251 | { | 251 | { |
| 252 | struct clk_prcmu *clk; | 252 | struct clk_prcmu *clk; |
| 253 | struct clk_init_data clk_prcmu_init; | 253 | struct clk_init_data clk_prcmu_init; |
diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c index 266ddea630d2..8a4e93ce1e42 100644 --- a/drivers/clk/ux500/clk-sysctrl.c +++ b/drivers/clk/ux500/clk-sysctrl.c | |||
| @@ -98,18 +98,18 @@ static u8 clk_sysctrl_get_parent(struct clk_hw *hw) | |||
| 98 | return clk->parent_index; | 98 | return clk->parent_index; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static struct clk_ops clk_sysctrl_gate_ops = { | 101 | static const struct clk_ops clk_sysctrl_gate_ops = { |
| 102 | .prepare = clk_sysctrl_prepare, | 102 | .prepare = clk_sysctrl_prepare, |
| 103 | .unprepare = clk_sysctrl_unprepare, | 103 | .unprepare = clk_sysctrl_unprepare, |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | static struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { | 106 | static const struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { |
| 107 | .prepare = clk_sysctrl_prepare, | 107 | .prepare = clk_sysctrl_prepare, |
| 108 | .unprepare = clk_sysctrl_unprepare, | 108 | .unprepare = clk_sysctrl_unprepare, |
| 109 | .recalc_rate = clk_sysctrl_recalc_rate, | 109 | .recalc_rate = clk_sysctrl_recalc_rate, |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | static struct clk_ops clk_sysctrl_set_parent_ops = { | 112 | static const struct clk_ops clk_sysctrl_set_parent_ops = { |
| 113 | .set_parent = clk_sysctrl_set_parent, | 113 | .set_parent = clk_sysctrl_set_parent, |
| 114 | .get_parent = clk_sysctrl_get_parent, | 114 | .get_parent = clk_sysctrl_get_parent, |
| 115 | }; | 115 | }; |
| @@ -124,7 +124,7 @@ static struct clk *clk_reg_sysctrl(struct device *dev, | |||
| 124 | unsigned long rate, | 124 | unsigned long rate, |
| 125 | unsigned long enable_delay_us, | 125 | unsigned long enable_delay_us, |
| 126 | unsigned long flags, | 126 | unsigned long flags, |
| 127 | struct clk_ops *clk_sysctrl_ops) | 127 | const struct clk_ops *clk_sysctrl_ops) |
| 128 | { | 128 | { |
| 129 | struct clk_sysctrl *clk; | 129 | struct clk_sysctrl *clk; |
| 130 | struct clk_init_data clk_sysctrl_init; | 130 | struct clk_init_data clk_sysctrl_init; |
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index 7e5add7d7752..e7a868b83fe5 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c | |||
| @@ -61,7 +61,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 61 | return regmap_write(osc->reg, 0, rate); | 61 | return regmap_write(osc->reg, 0, rate); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static struct clk_ops vexpress_osc_ops = { | 64 | static const struct clk_ops vexpress_osc_ops = { |
| 65 | .recalc_rate = vexpress_osc_recalc_rate, | 65 | .recalc_rate = vexpress_osc_recalc_rate, |
| 66 | .round_rate = vexpress_osc_round_rate, | 66 | .round_rate = vexpress_osc_round_rate, |
| 67 | .set_rate = vexpress_osc_set_rate, | 67 | .set_rate = vexpress_osc_set_rate, |
diff --git a/drivers/clk/zte/clk-zx296718.c b/drivers/clk/zte/clk-zx296718.c index 27f853d4c76b..354dd508c516 100644 --- a/drivers/clk/zte/clk-zx296718.c +++ b/drivers/clk/zte/clk-zx296718.c | |||
| @@ -451,7 +451,7 @@ static struct zx_clk_fixed_factor top_ffactor_clk[] = { | |||
| 451 | FFACTOR(0, "emmc_mux_div2", "emmc_mux", 1, 2, CLK_SET_RATE_PARENT), | 451 | FFACTOR(0, "emmc_mux_div2", "emmc_mux", 1, 2, CLK_SET_RATE_PARENT), |
| 452 | }; | 452 | }; |
| 453 | 453 | ||
| 454 | static struct clk_div_table noc_div_table[] = { | 454 | static const struct clk_div_table noc_div_table[] = { |
| 455 | { .val = 1, .div = 2, }, | 455 | { .val = 1, .div = 2, }, |
| 456 | { .val = 3, .div = 4, }, | 456 | { .val = 3, .div = 4, }, |
| 457 | }; | 457 | }; |
| @@ -644,7 +644,7 @@ static int __init top_clocks_init(struct device_node *np) | |||
| 644 | return 0; | 644 | return 0; |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | static struct clk_div_table common_even_div_table[] = { | 647 | static const struct clk_div_table common_even_div_table[] = { |
| 648 | { .val = 0, .div = 1, }, | 648 | { .val = 0, .div = 1, }, |
| 649 | { .val = 1, .div = 2, }, | 649 | { .val = 1, .div = 2, }, |
| 650 | { .val = 3, .div = 4, }, | 650 | { .val = 3, .div = 4, }, |
| @@ -656,7 +656,7 @@ static struct clk_div_table common_even_div_table[] = { | |||
| 656 | { .val = 15, .div = 16, }, | 656 | { .val = 15, .div = 16, }, |
| 657 | }; | 657 | }; |
| 658 | 658 | ||
| 659 | static struct clk_div_table common_div_table[] = { | 659 | static const struct clk_div_table common_div_table[] = { |
| 660 | { .val = 0, .div = 1, }, | 660 | { .val = 0, .div = 1, }, |
| 661 | { .val = 1, .div = 2, }, | 661 | { .val = 1, .div = 2, }, |
| 662 | { .val = 2, .div = 3, }, | 662 | { .val = 2, .div = 3, }, |
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 277a7a02cba5..acc816b67582 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c | |||
| @@ -1897,6 +1897,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) | |||
| 1897 | ctrl->cntlid = le16_to_cpu(id->cntlid); | 1897 | ctrl->cntlid = le16_to_cpu(id->cntlid); |
| 1898 | ctrl->hmpre = le32_to_cpu(id->hmpre); | 1898 | ctrl->hmpre = le32_to_cpu(id->hmpre); |
| 1899 | ctrl->hmmin = le32_to_cpu(id->hmmin); | 1899 | ctrl->hmmin = le32_to_cpu(id->hmmin); |
| 1900 | ctrl->hmminds = le32_to_cpu(id->hmminds); | ||
| 1901 | ctrl->hmmaxd = le16_to_cpu(id->hmmaxd); | ||
| 1900 | } | 1902 | } |
| 1901 | 1903 | ||
| 1902 | kfree(id); | 1904 | kfree(id); |
| @@ -2377,10 +2379,11 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) | |||
| 2377 | 2379 | ||
| 2378 | nvme_report_ns_ids(ctrl, ns->ns_id, id, ns->eui, ns->nguid, &ns->uuid); | 2380 | nvme_report_ns_ids(ctrl, ns->ns_id, id, ns->eui, ns->nguid, &ns->uuid); |
| 2379 | 2381 | ||
| 2380 | if (nvme_nvm_ns_supported(ns, id) && | 2382 | if ((ctrl->quirks & NVME_QUIRK_LIGHTNVM) && id->vs[0] == 0x1) { |
| 2381 | nvme_nvm_register(ns, disk_name, node)) { | 2383 | if (nvme_nvm_register(ns, disk_name, node)) { |
| 2382 | dev_warn(ctrl->device, "%s: LightNVM init failure\n", __func__); | 2384 | dev_warn(ctrl->device, "LightNVM init failure\n"); |
| 2383 | goto out_free_id; | 2385 | goto out_free_id; |
| 2386 | } | ||
| 2384 | } | 2387 | } |
| 2385 | 2388 | ||
| 2386 | disk = alloc_disk_node(0, node); | 2389 | disk = alloc_disk_node(0, node); |
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index c1a28569e843..1f79e3f141e6 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c | |||
| @@ -955,29 +955,3 @@ void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) | |||
| 955 | sysfs_remove_group(&disk_to_dev(ns->disk)->kobj, | 955 | sysfs_remove_group(&disk_to_dev(ns->disk)->kobj, |
| 956 | &nvm_dev_attr_group); | 956 | &nvm_dev_attr_group); |
| 957 | } | 957 | } |
| 958 | |||
| 959 | /* move to shared place when used in multiple places. */ | ||
| 960 | #define PCI_VENDOR_ID_CNEX 0x1d1d | ||
| 961 | #define PCI_DEVICE_ID_CNEX_WL 0x2807 | ||
| 962 | #define PCI_DEVICE_ID_CNEX_QEMU 0x1f1f | ||
| 963 | |||
| 964 | int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id) | ||
| 965 | { | ||
| 966 | struct nvme_ctrl *ctrl = ns->ctrl; | ||
| 967 | /* XXX: this is poking into PCI structures from generic code! */ | ||
| 968 | struct pci_dev *pdev = to_pci_dev(ctrl->dev); | ||
| 969 | |||
| 970 | /* QEMU NVMe simulator - PCI ID + Vendor specific bit */ | ||
| 971 | if (pdev->vendor == PCI_VENDOR_ID_CNEX && | ||
| 972 | pdev->device == PCI_DEVICE_ID_CNEX_QEMU && | ||
| 973 | id->vs[0] == 0x1) | ||
| 974 | return 1; | ||
| 975 | |||
| 976 | /* CNEX Labs - PCI ID + Vendor specific bit */ | ||
| 977 | if (pdev->vendor == PCI_VENDOR_ID_CNEX && | ||
| 978 | pdev->device == PCI_DEVICE_ID_CNEX_WL && | ||
| 979 | id->vs[0] == 0x1) | ||
| 980 | return 1; | ||
| 981 | |||
| 982 | return 0; | ||
| 983 | } | ||
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index a19a587d60ed..d3f3c4447515 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h | |||
| @@ -75,6 +75,11 @@ enum nvme_quirks { | |||
| 75 | * The deepest sleep state should not be used. | 75 | * The deepest sleep state should not be used. |
| 76 | */ | 76 | */ |
| 77 | NVME_QUIRK_NO_DEEPEST_PS = (1 << 5), | 77 | NVME_QUIRK_NO_DEEPEST_PS = (1 << 5), |
| 78 | |||
| 79 | /* | ||
| 80 | * Supports the LighNVM command set if indicated in vs[1]. | ||
| 81 | */ | ||
| 82 | NVME_QUIRK_LIGHTNVM = (1 << 6), | ||
| 78 | }; | 83 | }; |
| 79 | 84 | ||
| 80 | /* | 85 | /* |
| @@ -176,8 +181,11 @@ struct nvme_ctrl { | |||
| 176 | u64 ps_max_latency_us; | 181 | u64 ps_max_latency_us; |
| 177 | bool apst_enabled; | 182 | bool apst_enabled; |
| 178 | 183 | ||
| 184 | /* PCIe only: */ | ||
| 179 | u32 hmpre; | 185 | u32 hmpre; |
| 180 | u32 hmmin; | 186 | u32 hmmin; |
| 187 | u32 hmminds; | ||
| 188 | u16 hmmaxd; | ||
| 181 | 189 | ||
| 182 | /* Fabrics only */ | 190 | /* Fabrics only */ |
| 183 | u16 sqsize; | 191 | u16 sqsize; |
| @@ -320,7 +328,6 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl); | |||
| 320 | int nvme_reset_ctrl(struct nvme_ctrl *ctrl); | 328 | int nvme_reset_ctrl(struct nvme_ctrl *ctrl); |
| 321 | 329 | ||
| 322 | #ifdef CONFIG_NVM | 330 | #ifdef CONFIG_NVM |
| 323 | int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id); | ||
| 324 | int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node); | 331 | int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node); |
| 325 | void nvme_nvm_unregister(struct nvme_ns *ns); | 332 | void nvme_nvm_unregister(struct nvme_ns *ns); |
| 326 | int nvme_nvm_register_sysfs(struct nvme_ns *ns); | 333 | int nvme_nvm_register_sysfs(struct nvme_ns *ns); |
| @@ -339,10 +346,6 @@ static inline int nvme_nvm_register_sysfs(struct nvme_ns *ns) | |||
| 339 | return 0; | 346 | return 0; |
| 340 | } | 347 | } |
| 341 | static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {}; | 348 | static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {}; |
| 342 | static inline int nvme_nvm_ns_supported(struct nvme_ns *ns, struct nvme_id_ns *id) | ||
| 343 | { | ||
| 344 | return 0; | ||
| 345 | } | ||
| 346 | static inline int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, | 349 | static inline int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, |
| 347 | unsigned long arg) | 350 | unsigned long arg) |
| 348 | { | 351 | { |
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 198245faba6b..4a2121335f48 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
| @@ -1612,21 +1612,23 @@ static void nvme_free_host_mem(struct nvme_dev *dev) | |||
| 1612 | dev->host_mem_descs = NULL; | 1612 | dev->host_mem_descs = NULL; |
| 1613 | } | 1613 | } |
| 1614 | 1614 | ||
| 1615 | static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred) | 1615 | static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, |
| 1616 | u32 chunk_size) | ||
| 1616 | { | 1617 | { |
| 1617 | struct nvme_host_mem_buf_desc *descs; | 1618 | struct nvme_host_mem_buf_desc *descs; |
| 1618 | u32 chunk_size, max_entries, len; | 1619 | u32 max_entries, len; |
| 1619 | dma_addr_t descs_dma; | 1620 | dma_addr_t descs_dma; |
| 1620 | int i = 0; | 1621 | int i = 0; |
| 1621 | void **bufs; | 1622 | void **bufs; |
| 1622 | u64 size = 0, tmp; | 1623 | u64 size = 0, tmp; |
| 1623 | 1624 | ||
| 1624 | /* start big and work our way down */ | ||
| 1625 | chunk_size = min(preferred, (u64)PAGE_SIZE << MAX_ORDER); | ||
| 1626 | retry: | ||
| 1627 | tmp = (preferred + chunk_size - 1); | 1625 | tmp = (preferred + chunk_size - 1); |
| 1628 | do_div(tmp, chunk_size); | 1626 | do_div(tmp, chunk_size); |
| 1629 | max_entries = tmp; | 1627 | max_entries = tmp; |
| 1628 | |||
| 1629 | if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries) | ||
| 1630 | max_entries = dev->ctrl.hmmaxd; | ||
| 1631 | |||
| 1630 | descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs), | 1632 | descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs), |
| 1631 | &descs_dma, GFP_KERNEL); | 1633 | &descs_dma, GFP_KERNEL); |
| 1632 | if (!descs) | 1634 | if (!descs) |
| @@ -1650,15 +1652,9 @@ retry: | |||
| 1650 | i++; | 1652 | i++; |
| 1651 | } | 1653 | } |
| 1652 | 1654 | ||
| 1653 | if (!size || (min && size < min)) { | 1655 | if (!size) |
| 1654 | dev_warn(dev->ctrl.device, | ||
| 1655 | "failed to allocate host memory buffer.\n"); | ||
| 1656 | goto out_free_bufs; | 1656 | goto out_free_bufs; |
| 1657 | } | ||
| 1658 | 1657 | ||
| 1659 | dev_info(dev->ctrl.device, | ||
| 1660 | "allocated %lld MiB host memory buffer.\n", | ||
| 1661 | size >> ilog2(SZ_1M)); | ||
| 1662 | dev->nr_host_mem_descs = i; | 1658 | dev->nr_host_mem_descs = i; |
| 1663 | dev->host_mem_size = size; | 1659 | dev->host_mem_size = size; |
| 1664 | dev->host_mem_descs = descs; | 1660 | dev->host_mem_descs = descs; |
| @@ -1679,21 +1675,35 @@ out_free_descs: | |||
| 1679 | dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs, | 1675 | dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs, |
| 1680 | descs_dma); | 1676 | descs_dma); |
| 1681 | out: | 1677 | out: |
| 1682 | /* try a smaller chunk size if we failed early */ | ||
| 1683 | if (chunk_size >= PAGE_SIZE * 2 && (i == 0 || size < min)) { | ||
| 1684 | chunk_size /= 2; | ||
| 1685 | goto retry; | ||
| 1686 | } | ||
| 1687 | dev->host_mem_descs = NULL; | 1678 | dev->host_mem_descs = NULL; |
| 1688 | return -ENOMEM; | 1679 | return -ENOMEM; |
| 1689 | } | 1680 | } |
| 1690 | 1681 | ||
| 1691 | static void nvme_setup_host_mem(struct nvme_dev *dev) | 1682 | static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred) |
| 1683 | { | ||
| 1684 | u32 chunk_size; | ||
| 1685 | |||
| 1686 | /* start big and work our way down */ | ||
| 1687 | for (chunk_size = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES); | ||
| 1688 | chunk_size >= max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2); | ||
| 1689 | chunk_size /= 2) { | ||
| 1690 | if (!__nvme_alloc_host_mem(dev, preferred, chunk_size)) { | ||
| 1691 | if (!min || dev->host_mem_size >= min) | ||
| 1692 | return 0; | ||
| 1693 | nvme_free_host_mem(dev); | ||
| 1694 | } | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | return -ENOMEM; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | static int nvme_setup_host_mem(struct nvme_dev *dev) | ||
| 1692 | { | 1701 | { |
| 1693 | u64 max = (u64)max_host_mem_size_mb * SZ_1M; | 1702 | u64 max = (u64)max_host_mem_size_mb * SZ_1M; |
| 1694 | u64 preferred = (u64)dev->ctrl.hmpre * 4096; | 1703 | u64 preferred = (u64)dev->ctrl.hmpre * 4096; |
| 1695 | u64 min = (u64)dev->ctrl.hmmin * 4096; | 1704 | u64 min = (u64)dev->ctrl.hmmin * 4096; |
| 1696 | u32 enable_bits = NVME_HOST_MEM_ENABLE; | 1705 | u32 enable_bits = NVME_HOST_MEM_ENABLE; |
| 1706 | int ret = 0; | ||
| 1697 | 1707 | ||
| 1698 | preferred = min(preferred, max); | 1708 | preferred = min(preferred, max); |
| 1699 | if (min > max) { | 1709 | if (min > max) { |
| @@ -1701,7 +1711,7 @@ static void nvme_setup_host_mem(struct nvme_dev *dev) | |||
| 1701 | "min host memory (%lld MiB) above limit (%d MiB).\n", | 1711 | "min host memory (%lld MiB) above limit (%d MiB).\n", |
| 1702 | min >> ilog2(SZ_1M), max_host_mem_size_mb); | 1712 | min >> ilog2(SZ_1M), max_host_mem_size_mb); |
| 1703 | nvme_free_host_mem(dev); | 1713 | nvme_free_host_mem(dev); |
| 1704 | return; | 1714 | return 0; |
| 1705 | } | 1715 | } |
| 1706 | 1716 | ||
| 1707 | /* | 1717 | /* |
| @@ -1715,12 +1725,21 @@ static void nvme_setup_host_mem(struct nvme_dev *dev) | |||
| 1715 | } | 1725 | } |
| 1716 | 1726 | ||
| 1717 | if (!dev->host_mem_descs) { | 1727 | if (!dev->host_mem_descs) { |
| 1718 | if (nvme_alloc_host_mem(dev, min, preferred)) | 1728 | if (nvme_alloc_host_mem(dev, min, preferred)) { |
| 1719 | return; | 1729 | dev_warn(dev->ctrl.device, |
| 1730 | "failed to allocate host memory buffer.\n"); | ||
| 1731 | return 0; /* controller must work without HMB */ | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | dev_info(dev->ctrl.device, | ||
| 1735 | "allocated %lld MiB host memory buffer.\n", | ||
| 1736 | dev->host_mem_size >> ilog2(SZ_1M)); | ||
| 1720 | } | 1737 | } |
| 1721 | 1738 | ||
| 1722 | if (nvme_set_host_mem(dev, enable_bits)) | 1739 | ret = nvme_set_host_mem(dev, enable_bits); |
| 1740 | if (ret) | ||
| 1723 | nvme_free_host_mem(dev); | 1741 | nvme_free_host_mem(dev); |
| 1742 | return ret; | ||
| 1724 | } | 1743 | } |
| 1725 | 1744 | ||
| 1726 | static int nvme_setup_io_queues(struct nvme_dev *dev) | 1745 | static int nvme_setup_io_queues(struct nvme_dev *dev) |
| @@ -2164,8 +2183,11 @@ static void nvme_reset_work(struct work_struct *work) | |||
| 2164 | "unable to allocate dma for dbbuf\n"); | 2183 | "unable to allocate dma for dbbuf\n"); |
| 2165 | } | 2184 | } |
| 2166 | 2185 | ||
| 2167 | if (dev->ctrl.hmpre) | 2186 | if (dev->ctrl.hmpre) { |
| 2168 | nvme_setup_host_mem(dev); | 2187 | result = nvme_setup_host_mem(dev); |
| 2188 | if (result < 0) | ||
| 2189 | goto out; | ||
| 2190 | } | ||
| 2169 | 2191 | ||
| 2170 | result = nvme_setup_io_queues(dev); | 2192 | result = nvme_setup_io_queues(dev); |
| 2171 | if (result) | 2193 | if (result) |
| @@ -2497,6 +2519,10 @@ static const struct pci_device_id nvme_id_table[] = { | |||
| 2497 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, | 2519 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, |
| 2498 | { PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */ | 2520 | { PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */ |
| 2499 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, | 2521 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, |
| 2522 | { PCI_DEVICE(0x1d1d, 0x1f1f), /* LighNVM qemu device */ | ||
| 2523 | .driver_data = NVME_QUIRK_LIGHTNVM, }, | ||
| 2524 | { PCI_DEVICE(0x1d1d, 0x2807), /* CNEX WL */ | ||
| 2525 | .driver_data = NVME_QUIRK_LIGHTNVM, }, | ||
| 2500 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, | 2526 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, |
| 2501 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, | 2527 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, |
| 2502 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) }, | 2528 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) }, |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 72419ac2c52a..e0e58f3b1420 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -227,14 +227,14 @@ config RTC_DRV_AS3722 | |||
| 227 | will be called rtc-as3722. | 227 | will be called rtc-as3722. |
| 228 | 228 | ||
| 229 | config RTC_DRV_DS1307 | 229 | config RTC_DRV_DS1307 |
| 230 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025, ISL12057" | 230 | tristate "Dallas/Maxim DS1307/37/38/39/40/41, ST M41T00, EPSON RX-8025, ISL12057" |
| 231 | help | 231 | help |
| 232 | If you say yes here you get support for various compatible RTC | 232 | If you say yes here you get support for various compatible RTC |
| 233 | chips (often with battery backup) connected with I2C. This driver | 233 | chips (often with battery backup) connected with I2C. This driver |
| 234 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, | 234 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, DS1341, |
| 235 | EPSON RX-8025, Intersil ISL12057 and probably other chips. In some | 235 | ST M41T00, EPSON RX-8025, Intersil ISL12057 and probably other chips. |
| 236 | cases the RTC must already have been initialized (by manufacturing or | 236 | In some cases the RTC must already have been initialized (by |
| 237 | a bootloader). | 237 | manufacturing or a bootloader). |
| 238 | 238 | ||
| 239 | The first seven registers on these chips hold an RTC, and other | 239 | The first seven registers on these chips hold an RTC, and other |
| 240 | registers may add features such as NVRAM, a trickle charger for | 240 | registers may add features such as NVRAM, a trickle charger for |
| @@ -371,11 +371,11 @@ config RTC_DRV_MAX77686 | |||
| 371 | will be called rtc-max77686. | 371 | will be called rtc-max77686. |
| 372 | 372 | ||
| 373 | config RTC_DRV_RK808 | 373 | config RTC_DRV_RK808 |
| 374 | tristate "Rockchip RK808/RK818 RTC" | 374 | tristate "Rockchip RK805/RK808/RK818 RTC" |
| 375 | depends on MFD_RK808 | 375 | depends on MFD_RK808 |
| 376 | help | 376 | help |
| 377 | If you say yes here you will get support for the | 377 | If you say yes here you will get support for the |
| 378 | RTC of RK808 and RK818 PMIC. | 378 | RTC of RK805, RK808 and RK818 PMIC. |
| 379 | 379 | ||
| 380 | This driver can also be built as a module. If so, the module | 380 | This driver can also be built as a module. If so, the module |
| 381 | will be called rk808-rtc. | 381 | will be called rk808-rtc. |
| @@ -1765,6 +1765,14 @@ config RTC_DRV_CPCAP | |||
| 1765 | Say y here for CPCAP rtc found on some Motorola phones | 1765 | Say y here for CPCAP rtc found on some Motorola phones |
| 1766 | and tablets such as Droid 4. | 1766 | and tablets such as Droid 4. |
| 1767 | 1767 | ||
| 1768 | config RTC_DRV_RTD119X | ||
| 1769 | bool "Realtek RTD129x RTC" | ||
| 1770 | depends on ARCH_REALTEK || COMPILE_TEST | ||
| 1771 | default ARCH_REALTEK | ||
| 1772 | help | ||
| 1773 | If you say yes here, you get support for the RTD1295 SoC | ||
| 1774 | Real Time Clock. | ||
| 1775 | |||
| 1768 | comment "HID Sensor RTC drivers" | 1776 | comment "HID Sensor RTC drivers" |
| 1769 | 1777 | ||
| 1770 | config RTC_DRV_HID_SENSOR_TIME | 1778 | config RTC_DRV_HID_SENSOR_TIME |
| @@ -1780,5 +1788,13 @@ config RTC_DRV_HID_SENSOR_TIME | |||
| 1780 | If this driver is compiled as a module, it will be named | 1788 | If this driver is compiled as a module, it will be named |
| 1781 | rtc-hid-sensor-time. | 1789 | rtc-hid-sensor-time. |
| 1782 | 1790 | ||
| 1791 | config RTC_DRV_GOLDFISH | ||
| 1792 | tristate "Goldfish Real Time Clock" | ||
| 1793 | depends on MIPS && (GOLDFISH || COMPILE_TEST) | ||
| 1794 | help | ||
| 1795 | Say yes to enable RTC driver for the Goldfish based virtual platform. | ||
| 1796 | |||
| 1797 | Goldfish is a code name for the virtual platform developed by Google | ||
| 1798 | for Android emulation. | ||
| 1783 | 1799 | ||
| 1784 | endif # RTC_CLASS | 1800 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index acd366b41c85..7230014c92af 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -131,6 +131,7 @@ obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o | |||
| 131 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 131 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
| 132 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 132 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
| 133 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 133 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
| 134 | obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o | ||
| 134 | obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o | 135 | obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o |
| 135 | obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o | 136 | obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o |
| 136 | obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o | 137 | obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o |
| @@ -170,3 +171,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | |||
| 170 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 171 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
| 171 | obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o | 172 | obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o |
| 172 | obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o | 173 | obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o |
| 174 | obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 794bc4fa4937..00efe24a6063 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -24,28 +24,19 @@ static dev_t rtc_devt; | |||
| 24 | 24 | ||
| 25 | static int rtc_dev_open(struct inode *inode, struct file *file) | 25 | static int rtc_dev_open(struct inode *inode, struct file *file) |
| 26 | { | 26 | { |
| 27 | int err; | ||
| 28 | struct rtc_device *rtc = container_of(inode->i_cdev, | 27 | struct rtc_device *rtc = container_of(inode->i_cdev, |
| 29 | struct rtc_device, char_dev); | 28 | struct rtc_device, char_dev); |
| 30 | const struct rtc_class_ops *ops = rtc->ops; | ||
| 31 | 29 | ||
| 32 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) | 30 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) |
| 33 | return -EBUSY; | 31 | return -EBUSY; |
| 34 | 32 | ||
| 35 | file->private_data = rtc; | 33 | file->private_data = rtc; |
| 36 | 34 | ||
| 37 | err = ops->open ? ops->open(rtc->dev.parent) : 0; | 35 | spin_lock_irq(&rtc->irq_lock); |
| 38 | if (err == 0) { | 36 | rtc->irq_data = 0; |
| 39 | spin_lock_irq(&rtc->irq_lock); | 37 | spin_unlock_irq(&rtc->irq_lock); |
| 40 | rtc->irq_data = 0; | ||
| 41 | spin_unlock_irq(&rtc->irq_lock); | ||
| 42 | |||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | 38 | ||
| 46 | /* something has gone wrong */ | 39 | return 0; |
| 47 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | ||
| 48 | return err; | ||
| 49 | } | 40 | } |
| 50 | 41 | ||
| 51 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 42 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL |
| @@ -438,9 +429,6 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
| 438 | rtc_update_irq_enable(rtc, 0); | 429 | rtc_update_irq_enable(rtc, 0); |
| 439 | rtc_irq_set_state(rtc, NULL, 0); | 430 | rtc_irq_set_state(rtc, NULL, 0); |
| 440 | 431 | ||
| 441 | if (rtc->ops->release) | ||
| 442 | rtc->ops->release(rtc->dev.parent); | ||
| 443 | |||
| 444 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | 432 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); |
| 445 | return 0; | 433 | return 0; |
| 446 | } | 434 | } |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 4b43aa62fbc7..e7d9215c9201 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
| @@ -39,6 +39,7 @@ enum ds_type { | |||
| 39 | ds_1338, | 39 | ds_1338, |
| 40 | ds_1339, | 40 | ds_1339, |
| 41 | ds_1340, | 41 | ds_1340, |
| 42 | ds_1341, | ||
| 42 | ds_1388, | 43 | ds_1388, |
| 43 | ds_3231, | 44 | ds_3231, |
| 44 | m41t0, | 45 | m41t0, |
| @@ -50,7 +51,6 @@ enum ds_type { | |||
| 50 | /* rs5c372 too? different address... */ | 51 | /* rs5c372 too? different address... */ |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | |||
| 54 | /* RTC registers don't differ much, except for the century flag */ | 54 | /* RTC registers don't differ much, except for the century flag */ |
| 55 | #define DS1307_REG_SECS 0x00 /* 00-59 */ | 55 | #define DS1307_REG_SECS 0x00 /* 00-59 */ |
| 56 | # define DS1307_BIT_CH 0x80 | 56 | # define DS1307_BIT_CH 0x80 |
| @@ -113,11 +113,7 @@ enum ds_type { | |||
| 113 | # define RX8025_BIT_VDET 0x40 | 113 | # define RX8025_BIT_VDET 0x40 |
| 114 | # define RX8025_BIT_XST 0x20 | 114 | # define RX8025_BIT_XST 0x20 |
| 115 | 115 | ||
| 116 | |||
| 117 | struct ds1307 { | 116 | struct ds1307 { |
| 118 | u8 offset; /* register's offset */ | ||
| 119 | u8 regs[11]; | ||
| 120 | u16 nvram_offset; | ||
| 121 | struct nvmem_config nvmem_cfg; | 117 | struct nvmem_config nvmem_cfg; |
| 122 | enum ds_type type; | 118 | enum ds_type type; |
| 123 | unsigned long flags; | 119 | unsigned long flags; |
| @@ -126,7 +122,6 @@ struct ds1307 { | |||
| 126 | struct device *dev; | 122 | struct device *dev; |
| 127 | struct regmap *regmap; | 123 | struct regmap *regmap; |
| 128 | const char *name; | 124 | const char *name; |
| 129 | int irq; | ||
| 130 | struct rtc_device *rtc; | 125 | struct rtc_device *rtc; |
| 131 | #ifdef CONFIG_COMMON_CLK | 126 | #ifdef CONFIG_COMMON_CLK |
| 132 | struct clk_hw clks[2]; | 127 | struct clk_hw clks[2]; |
| @@ -137,18 +132,47 @@ struct chip_desc { | |||
| 137 | unsigned alarm:1; | 132 | unsigned alarm:1; |
| 138 | u16 nvram_offset; | 133 | u16 nvram_offset; |
| 139 | u16 nvram_size; | 134 | u16 nvram_size; |
| 135 | u8 offset; /* register's offset */ | ||
| 140 | u8 century_reg; | 136 | u8 century_reg; |
| 141 | u8 century_enable_bit; | 137 | u8 century_enable_bit; |
| 142 | u8 century_bit; | 138 | u8 century_bit; |
| 139 | u8 bbsqi_bit; | ||
| 140 | irq_handler_t irq_handler; | ||
| 141 | const struct rtc_class_ops *rtc_ops; | ||
| 143 | u16 trickle_charger_reg; | 142 | u16 trickle_charger_reg; |
| 144 | u8 trickle_charger_setup; | 143 | u8 (*do_trickle_setup)(struct ds1307 *, u32, |
| 145 | u8 (*do_trickle_setup)(struct ds1307 *, uint32_t, | ||
| 146 | bool); | 144 | bool); |
| 147 | }; | 145 | }; |
| 148 | 146 | ||
| 149 | static u8 do_trickle_setup_ds1339(struct ds1307 *, uint32_t ohms, bool diode); | 147 | static int ds1307_get_time(struct device *dev, struct rtc_time *t); |
| 148 | static int ds1307_set_time(struct device *dev, struct rtc_time *t); | ||
| 149 | static u8 do_trickle_setup_ds1339(struct ds1307 *, u32 ohms, bool diode); | ||
| 150 | static irqreturn_t rx8130_irq(int irq, void *dev_id); | ||
| 151 | static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t); | ||
| 152 | static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t); | ||
| 153 | static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled); | ||
| 154 | static irqreturn_t mcp794xx_irq(int irq, void *dev_id); | ||
| 155 | static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t); | ||
| 156 | static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t); | ||
| 157 | static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled); | ||
| 150 | 158 | ||
| 151 | static struct chip_desc chips[last_ds_type] = { | 159 | static const struct rtc_class_ops rx8130_rtc_ops = { |
| 160 | .read_time = ds1307_get_time, | ||
| 161 | .set_time = ds1307_set_time, | ||
| 162 | .read_alarm = rx8130_read_alarm, | ||
| 163 | .set_alarm = rx8130_set_alarm, | ||
| 164 | .alarm_irq_enable = rx8130_alarm_irq_enable, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static const struct rtc_class_ops mcp794xx_rtc_ops = { | ||
| 168 | .read_time = ds1307_get_time, | ||
| 169 | .set_time = ds1307_set_time, | ||
| 170 | .read_alarm = mcp794xx_read_alarm, | ||
| 171 | .set_alarm = mcp794xx_set_alarm, | ||
| 172 | .alarm_irq_enable = mcp794xx_alarm_irq_enable, | ||
| 173 | }; | ||
| 174 | |||
| 175 | static const struct chip_desc chips[last_ds_type] = { | ||
| 152 | [ds_1307] = { | 176 | [ds_1307] = { |
| 153 | .nvram_offset = 8, | 177 | .nvram_offset = 8, |
| 154 | .nvram_size = 56, | 178 | .nvram_size = 56, |
| @@ -170,6 +194,7 @@ static struct chip_desc chips[last_ds_type] = { | |||
| 170 | .alarm = 1, | 194 | .alarm = 1, |
| 171 | .century_reg = DS1307_REG_MONTH, | 195 | .century_reg = DS1307_REG_MONTH, |
| 172 | .century_bit = DS1337_BIT_CENTURY, | 196 | .century_bit = DS1337_BIT_CENTURY, |
| 197 | .bbsqi_bit = DS1339_BIT_BBSQI, | ||
| 173 | .trickle_charger_reg = 0x10, | 198 | .trickle_charger_reg = 0x10, |
| 174 | .do_trickle_setup = &do_trickle_setup_ds1339, | 199 | .do_trickle_setup = &do_trickle_setup_ds1339, |
| 175 | }, | 200 | }, |
| @@ -179,25 +204,36 @@ static struct chip_desc chips[last_ds_type] = { | |||
| 179 | .century_bit = DS1340_BIT_CENTURY, | 204 | .century_bit = DS1340_BIT_CENTURY, |
| 180 | .trickle_charger_reg = 0x08, | 205 | .trickle_charger_reg = 0x08, |
| 181 | }, | 206 | }, |
| 207 | [ds_1341] = { | ||
| 208 | .century_reg = DS1307_REG_MONTH, | ||
| 209 | .century_bit = DS1337_BIT_CENTURY, | ||
| 210 | }, | ||
| 182 | [ds_1388] = { | 211 | [ds_1388] = { |
| 212 | .offset = 1, | ||
| 183 | .trickle_charger_reg = 0x0a, | 213 | .trickle_charger_reg = 0x0a, |
| 184 | }, | 214 | }, |
| 185 | [ds_3231] = { | 215 | [ds_3231] = { |
| 186 | .alarm = 1, | 216 | .alarm = 1, |
| 187 | .century_reg = DS1307_REG_MONTH, | 217 | .century_reg = DS1307_REG_MONTH, |
| 188 | .century_bit = DS1337_BIT_CENTURY, | 218 | .century_bit = DS1337_BIT_CENTURY, |
| 219 | .bbsqi_bit = DS3231_BIT_BBSQW, | ||
| 189 | }, | 220 | }, |
| 190 | [rx_8130] = { | 221 | [rx_8130] = { |
| 191 | .alarm = 1, | 222 | .alarm = 1, |
| 192 | /* this is battery backed SRAM */ | 223 | /* this is battery backed SRAM */ |
| 193 | .nvram_offset = 0x20, | 224 | .nvram_offset = 0x20, |
| 194 | .nvram_size = 4, /* 32bit (4 word x 8 bit) */ | 225 | .nvram_size = 4, /* 32bit (4 word x 8 bit) */ |
| 226 | .offset = 0x10, | ||
| 227 | .irq_handler = rx8130_irq, | ||
| 228 | .rtc_ops = &rx8130_rtc_ops, | ||
| 195 | }, | 229 | }, |
| 196 | [mcp794xx] = { | 230 | [mcp794xx] = { |
| 197 | .alarm = 1, | 231 | .alarm = 1, |
| 198 | /* this is battery backed SRAM */ | 232 | /* this is battery backed SRAM */ |
| 199 | .nvram_offset = 0x20, | 233 | .nvram_offset = 0x20, |
| 200 | .nvram_size = 0x40, | 234 | .nvram_size = 0x40, |
| 235 | .irq_handler = mcp794xx_irq, | ||
| 236 | .rtc_ops = &mcp794xx_rtc_ops, | ||
| 201 | }, | 237 | }, |
| 202 | }; | 238 | }; |
| 203 | 239 | ||
| @@ -209,6 +245,7 @@ static const struct i2c_device_id ds1307_id[] = { | |||
| 209 | { "ds1339", ds_1339 }, | 245 | { "ds1339", ds_1339 }, |
| 210 | { "ds1388", ds_1388 }, | 246 | { "ds1388", ds_1388 }, |
| 211 | { "ds1340", ds_1340 }, | 247 | { "ds1340", ds_1340 }, |
| 248 | { "ds1341", ds_1341 }, | ||
| 212 | { "ds3231", ds_3231 }, | 249 | { "ds3231", ds_3231 }, |
| 213 | { "m41t0", m41t0 }, | 250 | { "m41t0", m41t0 }, |
| 214 | { "m41t00", m41t00 }, | 251 | { "m41t00", m41t00 }, |
| @@ -253,6 +290,10 @@ static const struct of_device_id ds1307_of_match[] = { | |||
| 253 | .data = (void *)ds_1340 | 290 | .data = (void *)ds_1340 |
| 254 | }, | 291 | }, |
| 255 | { | 292 | { |
| 293 | .compatible = "dallas,ds1341", | ||
| 294 | .data = (void *)ds_1341 | ||
| 295 | }, | ||
| 296 | { | ||
| 256 | .compatible = "maxim,ds3231", | 297 | .compatible = "maxim,ds3231", |
| 257 | .data = (void *)ds_3231 | 298 | .data = (void *)ds_3231 |
| 258 | }, | 299 | }, |
| @@ -298,6 +339,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = { | |||
| 298 | { .id = "DS1339", .driver_data = ds_1339 }, | 339 | { .id = "DS1339", .driver_data = ds_1339 }, |
| 299 | { .id = "DS1388", .driver_data = ds_1388 }, | 340 | { .id = "DS1388", .driver_data = ds_1388 }, |
| 300 | { .id = "DS1340", .driver_data = ds_1340 }, | 341 | { .id = "DS1340", .driver_data = ds_1340 }, |
| 342 | { .id = "DS1341", .driver_data = ds_1341 }, | ||
| 301 | { .id = "DS3231", .driver_data = ds_3231 }, | 343 | { .id = "DS3231", .driver_data = ds_3231 }, |
| 302 | { .id = "M41T0", .driver_data = m41t0 }, | 344 | { .id = "M41T0", .driver_data = m41t0 }, |
| 303 | { .id = "M41T00", .driver_data = m41t00 }, | 345 | { .id = "M41T00", .driver_data = m41t00 }, |
| @@ -352,34 +394,36 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) | |||
| 352 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 394 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 353 | int tmp, ret; | 395 | int tmp, ret; |
| 354 | const struct chip_desc *chip = &chips[ds1307->type]; | 396 | const struct chip_desc *chip = &chips[ds1307->type]; |
| 397 | u8 regs[7]; | ||
| 355 | 398 | ||
| 356 | /* read the RTC date and time registers all at once */ | 399 | /* read the RTC date and time registers all at once */ |
| 357 | ret = regmap_bulk_read(ds1307->regmap, ds1307->offset, ds1307->regs, 7); | 400 | ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs, |
| 401 | sizeof(regs)); | ||
| 358 | if (ret) { | 402 | if (ret) { |
| 359 | dev_err(dev, "%s error %d\n", "read", ret); | 403 | dev_err(dev, "%s error %d\n", "read", ret); |
| 360 | return ret; | 404 | return ret; |
| 361 | } | 405 | } |
| 362 | 406 | ||
| 363 | dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs); | 407 | dev_dbg(dev, "%s: %7ph\n", "read", regs); |
| 364 | 408 | ||
| 365 | /* if oscillator fail bit is set, no data can be trusted */ | 409 | /* if oscillator fail bit is set, no data can be trusted */ |
| 366 | if (ds1307->type == m41t0 && | 410 | if (ds1307->type == m41t0 && |
| 367 | ds1307->regs[DS1307_REG_MIN] & M41T0_BIT_OF) { | 411 | regs[DS1307_REG_MIN] & M41T0_BIT_OF) { |
| 368 | dev_warn_once(dev, "oscillator failed, set time!\n"); | 412 | dev_warn_once(dev, "oscillator failed, set time!\n"); |
| 369 | return -EINVAL; | 413 | return -EINVAL; |
| 370 | } | 414 | } |
| 371 | 415 | ||
| 372 | t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f); | 416 | t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f); |
| 373 | t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f); | 417 | t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); |
| 374 | tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; | 418 | tmp = regs[DS1307_REG_HOUR] & 0x3f; |
| 375 | t->tm_hour = bcd2bin(tmp); | 419 | t->tm_hour = bcd2bin(tmp); |
| 376 | t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; | 420 | t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; |
| 377 | t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f); | 421 | t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f); |
| 378 | tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; | 422 | tmp = regs[DS1307_REG_MONTH] & 0x1f; |
| 379 | t->tm_mon = bcd2bin(tmp) - 1; | 423 | t->tm_mon = bcd2bin(tmp) - 1; |
| 380 | t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100; | 424 | t->tm_year = bcd2bin(regs[DS1307_REG_YEAR]) + 100; |
| 381 | 425 | ||
| 382 | if (ds1307->regs[chip->century_reg] & chip->century_bit && | 426 | if (regs[chip->century_reg] & chip->century_bit && |
| 383 | IS_ENABLED(CONFIG_RTC_DRV_DS1307_CENTURY)) | 427 | IS_ENABLED(CONFIG_RTC_DRV_DS1307_CENTURY)) |
| 384 | t->tm_year += 100; | 428 | t->tm_year += 100; |
| 385 | 429 | ||
| @@ -399,7 +443,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
| 399 | const struct chip_desc *chip = &chips[ds1307->type]; | 443 | const struct chip_desc *chip = &chips[ds1307->type]; |
| 400 | int result; | 444 | int result; |
| 401 | int tmp; | 445 | int tmp; |
| 402 | u8 *buf = ds1307->regs; | 446 | u8 regs[7]; |
| 403 | 447 | ||
| 404 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 448 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
| 405 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | 449 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", |
| @@ -418,35 +462,36 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
| 418 | return -EINVAL; | 462 | return -EINVAL; |
| 419 | #endif | 463 | #endif |
| 420 | 464 | ||
| 421 | buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec); | 465 | regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec); |
| 422 | buf[DS1307_REG_MIN] = bin2bcd(t->tm_min); | 466 | regs[DS1307_REG_MIN] = bin2bcd(t->tm_min); |
| 423 | buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); | 467 | regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); |
| 424 | buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); | 468 | regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); |
| 425 | buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); | 469 | regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); |
| 426 | buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); | 470 | regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); |
| 427 | 471 | ||
| 428 | /* assume 20YY not 19YY */ | 472 | /* assume 20YY not 19YY */ |
| 429 | tmp = t->tm_year - 100; | 473 | tmp = t->tm_year - 100; |
| 430 | buf[DS1307_REG_YEAR] = bin2bcd(tmp); | 474 | regs[DS1307_REG_YEAR] = bin2bcd(tmp); |
| 431 | 475 | ||
| 432 | if (chip->century_enable_bit) | 476 | if (chip->century_enable_bit) |
| 433 | buf[chip->century_reg] |= chip->century_enable_bit; | 477 | regs[chip->century_reg] |= chip->century_enable_bit; |
| 434 | if (t->tm_year > 199 && chip->century_bit) | 478 | if (t->tm_year > 199 && chip->century_bit) |
| 435 | buf[chip->century_reg] |= chip->century_bit; | 479 | regs[chip->century_reg] |= chip->century_bit; |
| 436 | 480 | ||
| 437 | if (ds1307->type == mcp794xx) { | 481 | if (ds1307->type == mcp794xx) { |
| 438 | /* | 482 | /* |
| 439 | * these bits were cleared when preparing the date/time | 483 | * these bits were cleared when preparing the date/time |
| 440 | * values and need to be set again before writing the | 484 | * values and need to be set again before writing the |
| 441 | * buffer out to the device. | 485 | * regsfer out to the device. |
| 442 | */ | 486 | */ |
| 443 | buf[DS1307_REG_SECS] |= MCP794XX_BIT_ST; | 487 | regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST; |
| 444 | buf[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; | 488 | regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; |
| 445 | } | 489 | } |
| 446 | 490 | ||
| 447 | dev_dbg(dev, "%s: %7ph\n", "write", buf); | 491 | dev_dbg(dev, "%s: %7ph\n", "write", regs); |
| 448 | 492 | ||
| 449 | result = regmap_bulk_write(ds1307->regmap, ds1307->offset, buf, 7); | 493 | result = regmap_bulk_write(ds1307->regmap, chip->offset, regs, |
| 494 | sizeof(regs)); | ||
| 450 | if (result) { | 495 | if (result) { |
| 451 | dev_err(dev, "%s error %d\n", "write", result); | 496 | dev_err(dev, "%s error %d\n", "write", result); |
| 452 | return result; | 497 | return result; |
| @@ -458,33 +503,34 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 458 | { | 503 | { |
| 459 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 504 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 460 | int ret; | 505 | int ret; |
| 506 | u8 regs[9]; | ||
| 461 | 507 | ||
| 462 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | 508 | if (!test_bit(HAS_ALARM, &ds1307->flags)) |
| 463 | return -EINVAL; | 509 | return -EINVAL; |
| 464 | 510 | ||
| 465 | /* read all ALARM1, ALARM2, and status registers at once */ | 511 | /* read all ALARM1, ALARM2, and status registers at once */ |
| 466 | ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, | 512 | ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, |
| 467 | ds1307->regs, 9); | 513 | regs, sizeof(regs)); |
| 468 | if (ret) { | 514 | if (ret) { |
| 469 | dev_err(dev, "%s error %d\n", "alarm read", ret); | 515 | dev_err(dev, "%s error %d\n", "alarm read", ret); |
| 470 | return ret; | 516 | return ret; |
| 471 | } | 517 | } |
| 472 | 518 | ||
| 473 | dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read", | 519 | dev_dbg(dev, "%s: %4ph, %3ph, %2ph\n", "alarm read", |
| 474 | &ds1307->regs[0], &ds1307->regs[4], &ds1307->regs[7]); | 520 | ®s[0], ®s[4], ®s[7]); |
| 475 | 521 | ||
| 476 | /* | 522 | /* |
| 477 | * report alarm time (ALARM1); assume 24 hour and day-of-month modes, | 523 | * report alarm time (ALARM1); assume 24 hour and day-of-month modes, |
| 478 | * and that all four fields are checked matches | 524 | * and that all four fields are checked matches |
| 479 | */ | 525 | */ |
| 480 | t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); | 526 | t->time.tm_sec = bcd2bin(regs[0] & 0x7f); |
| 481 | t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); | 527 | t->time.tm_min = bcd2bin(regs[1] & 0x7f); |
| 482 | t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); | 528 | t->time.tm_hour = bcd2bin(regs[2] & 0x3f); |
| 483 | t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); | 529 | t->time.tm_mday = bcd2bin(regs[3] & 0x3f); |
| 484 | 530 | ||
| 485 | /* ... and status */ | 531 | /* ... and status */ |
| 486 | t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); | 532 | t->enabled = !!(regs[7] & DS1337_BIT_A1IE); |
| 487 | t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I); | 533 | t->pending = !!(regs[8] & DS1337_BIT_A1I); |
| 488 | 534 | ||
| 489 | dev_dbg(dev, "%s secs=%d, mins=%d, " | 535 | dev_dbg(dev, "%s secs=%d, mins=%d, " |
| 490 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | 536 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", |
| @@ -498,7 +544,7 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 498 | static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 544 | static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
| 499 | { | 545 | { |
| 500 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 546 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 501 | unsigned char *buf = ds1307->regs; | 547 | unsigned char regs[9]; |
| 502 | u8 control, status; | 548 | u8 control, status; |
| 503 | int ret; | 549 | int ret; |
| 504 | 550 | ||
| @@ -512,33 +558,35 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 512 | t->enabled, t->pending); | 558 | t->enabled, t->pending); |
| 513 | 559 | ||
| 514 | /* read current status of both alarms and the chip */ | 560 | /* read current status of both alarms and the chip */ |
| 515 | ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9); | 561 | ret = regmap_bulk_read(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs, |
| 562 | sizeof(regs)); | ||
| 516 | if (ret) { | 563 | if (ret) { |
| 517 | dev_err(dev, "%s error %d\n", "alarm write", ret); | 564 | dev_err(dev, "%s error %d\n", "alarm write", ret); |
| 518 | return ret; | 565 | return ret; |
| 519 | } | 566 | } |
| 520 | control = ds1307->regs[7]; | 567 | control = regs[7]; |
| 521 | status = ds1307->regs[8]; | 568 | status = regs[8]; |
| 522 | 569 | ||
| 523 | dev_dbg(dev, "%s: %4ph, %3ph, %02x %02x\n", "alarm set (old status)", | 570 | dev_dbg(dev, "%s: %4ph, %3ph, %02x %02x\n", "alarm set (old status)", |
| 524 | &ds1307->regs[0], &ds1307->regs[4], control, status); | 571 | ®s[0], ®s[4], control, status); |
| 525 | 572 | ||
| 526 | /* set ALARM1, using 24 hour and day-of-month modes */ | 573 | /* set ALARM1, using 24 hour and day-of-month modes */ |
| 527 | buf[0] = bin2bcd(t->time.tm_sec); | 574 | regs[0] = bin2bcd(t->time.tm_sec); |
| 528 | buf[1] = bin2bcd(t->time.tm_min); | 575 | regs[1] = bin2bcd(t->time.tm_min); |
| 529 | buf[2] = bin2bcd(t->time.tm_hour); | 576 | regs[2] = bin2bcd(t->time.tm_hour); |
| 530 | buf[3] = bin2bcd(t->time.tm_mday); | 577 | regs[3] = bin2bcd(t->time.tm_mday); |
| 531 | 578 | ||
| 532 | /* set ALARM2 to non-garbage */ | 579 | /* set ALARM2 to non-garbage */ |
| 533 | buf[4] = 0; | 580 | regs[4] = 0; |
| 534 | buf[5] = 0; | 581 | regs[5] = 0; |
| 535 | buf[6] = 0; | 582 | regs[6] = 0; |
| 536 | 583 | ||
| 537 | /* disable alarms */ | 584 | /* disable alarms */ |
| 538 | buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); | 585 | regs[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); |
| 539 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | 586 | regs[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); |
| 540 | 587 | ||
| 541 | ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, buf, 9); | 588 | ret = regmap_bulk_write(ds1307->regmap, DS1339_REG_ALARM1_SECS, regs, |
| 589 | sizeof(regs)); | ||
| 542 | if (ret) { | 590 | if (ret) { |
| 543 | dev_err(dev, "can't set alarm time\n"); | 591 | dev_err(dev, "can't set alarm time\n"); |
| 544 | return ret; | 592 | return ret; |
| @@ -547,8 +595,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 547 | /* optionally enable ALARM1 */ | 595 | /* optionally enable ALARM1 */ |
| 548 | if (t->enabled) { | 596 | if (t->enabled) { |
| 549 | dev_dbg(dev, "alarm IRQ armed\n"); | 597 | dev_dbg(dev, "alarm IRQ armed\n"); |
| 550 | buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ | 598 | regs[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ |
| 551 | regmap_write(ds1307->regmap, DS1337_REG_CONTROL, buf[7]); | 599 | regmap_write(ds1307->regmap, DS1337_REG_CONTROL, regs[7]); |
| 552 | } | 600 | } |
| 553 | 601 | ||
| 554 | return 0; | 602 | return 0; |
| @@ -584,11 +632,11 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { | |||
| 584 | #define RX8130_REG_ALARM_HOUR 0x08 | 632 | #define RX8130_REG_ALARM_HOUR 0x08 |
| 585 | #define RX8130_REG_ALARM_WEEK_OR_DAY 0x09 | 633 | #define RX8130_REG_ALARM_WEEK_OR_DAY 0x09 |
| 586 | #define RX8130_REG_EXTENSION 0x0c | 634 | #define RX8130_REG_EXTENSION 0x0c |
| 587 | #define RX8130_REG_EXTENSION_WADA (1 << 3) | 635 | #define RX8130_REG_EXTENSION_WADA BIT(3) |
| 588 | #define RX8130_REG_FLAG 0x0d | 636 | #define RX8130_REG_FLAG 0x0d |
| 589 | #define RX8130_REG_FLAG_AF (1 << 3) | 637 | #define RX8130_REG_FLAG_AF BIT(3) |
| 590 | #define RX8130_REG_CONTROL0 0x0e | 638 | #define RX8130_REG_CONTROL0 0x0e |
| 591 | #define RX8130_REG_CONTROL0_AIE (1 << 3) | 639 | #define RX8130_REG_CONTROL0_AIE BIT(3) |
| 592 | 640 | ||
| 593 | static irqreturn_t rx8130_irq(int irq, void *dev_id) | 641 | static irqreturn_t rx8130_irq(int irq, void *dev_id) |
| 594 | { | 642 | { |
| @@ -600,7 +648,8 @@ static irqreturn_t rx8130_irq(int irq, void *dev_id) | |||
| 600 | mutex_lock(lock); | 648 | mutex_lock(lock); |
| 601 | 649 | ||
| 602 | /* Read control registers. */ | 650 | /* Read control registers. */ |
| 603 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 651 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 652 | sizeof(ctl)); | ||
| 604 | if (ret < 0) | 653 | if (ret < 0) |
| 605 | goto out; | 654 | goto out; |
| 606 | if (!(ctl[1] & RX8130_REG_FLAG_AF)) | 655 | if (!(ctl[1] & RX8130_REG_FLAG_AF)) |
| @@ -608,7 +657,8 @@ static irqreturn_t rx8130_irq(int irq, void *dev_id) | |||
| 608 | ctl[1] &= ~RX8130_REG_FLAG_AF; | 657 | ctl[1] &= ~RX8130_REG_FLAG_AF; |
| 609 | ctl[2] &= ~RX8130_REG_CONTROL0_AIE; | 658 | ctl[2] &= ~RX8130_REG_CONTROL0_AIE; |
| 610 | 659 | ||
| 611 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 660 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 661 | sizeof(ctl)); | ||
| 612 | if (ret < 0) | 662 | if (ret < 0) |
| 613 | goto out; | 663 | goto out; |
| 614 | 664 | ||
| @@ -630,12 +680,14 @@ static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 630 | return -EINVAL; | 680 | return -EINVAL; |
| 631 | 681 | ||
| 632 | /* Read alarm registers. */ | 682 | /* Read alarm registers. */ |
| 633 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); | 683 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, |
| 684 | sizeof(ald)); | ||
| 634 | if (ret < 0) | 685 | if (ret < 0) |
| 635 | return ret; | 686 | return ret; |
| 636 | 687 | ||
| 637 | /* Read control registers. */ | 688 | /* Read control registers. */ |
| 638 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 689 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 690 | sizeof(ctl)); | ||
| 639 | if (ret < 0) | 691 | if (ret < 0) |
| 640 | return ret; | 692 | return ret; |
| 641 | 693 | ||
| @@ -676,7 +728,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 676 | t->enabled, t->pending); | 728 | t->enabled, t->pending); |
| 677 | 729 | ||
| 678 | /* Read control registers. */ | 730 | /* Read control registers. */ |
| 679 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 731 | ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 732 | sizeof(ctl)); | ||
| 680 | if (ret < 0) | 733 | if (ret < 0) |
| 681 | return ret; | 734 | return ret; |
| 682 | 735 | ||
| @@ -684,7 +737,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 684 | ctl[1] |= RX8130_REG_FLAG_AF; | 737 | ctl[1] |= RX8130_REG_FLAG_AF; |
| 685 | ctl[2] &= ~RX8130_REG_CONTROL0_AIE; | 738 | ctl[2] &= ~RX8130_REG_CONTROL0_AIE; |
| 686 | 739 | ||
| 687 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 740 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 741 | sizeof(ctl)); | ||
| 688 | if (ret < 0) | 742 | if (ret < 0) |
| 689 | return ret; | 743 | return ret; |
| 690 | 744 | ||
| @@ -693,7 +747,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 693 | ald[1] = bin2bcd(t->time.tm_hour); | 747 | ald[1] = bin2bcd(t->time.tm_hour); |
| 694 | ald[2] = bin2bcd(t->time.tm_mday); | 748 | ald[2] = bin2bcd(t->time.tm_mday); |
| 695 | 749 | ||
| 696 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, 3); | 750 | ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald, |
| 751 | sizeof(ald)); | ||
| 697 | if (ret < 0) | 752 | if (ret < 0) |
| 698 | return ret; | 753 | return ret; |
| 699 | 754 | ||
| @@ -702,7 +757,8 @@ static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 702 | 757 | ||
| 703 | ctl[2] |= RX8130_REG_CONTROL0_AIE; | 758 | ctl[2] |= RX8130_REG_CONTROL0_AIE; |
| 704 | 759 | ||
| 705 | return regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, 3); | 760 | return regmap_bulk_write(ds1307->regmap, RX8130_REG_EXTENSION, ctl, |
| 761 | sizeof(ctl)); | ||
| 706 | } | 762 | } |
| 707 | 763 | ||
| 708 | static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) | 764 | static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| @@ -725,14 +781,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
| 725 | return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg); | 781 | return regmap_write(ds1307->regmap, RX8130_REG_CONTROL0, reg); |
| 726 | } | 782 | } |
| 727 | 783 | ||
| 728 | static const struct rtc_class_ops rx8130_rtc_ops = { | ||
| 729 | .read_time = ds1307_get_time, | ||
| 730 | .set_time = ds1307_set_time, | ||
| 731 | .read_alarm = rx8130_read_alarm, | ||
| 732 | .set_alarm = rx8130_set_alarm, | ||
| 733 | .alarm_irq_enable = rx8130_alarm_irq_enable, | ||
| 734 | }; | ||
| 735 | |||
| 736 | /*----------------------------------------------------------------------*/ | 784 | /*----------------------------------------------------------------------*/ |
| 737 | 785 | ||
| 738 | /* | 786 | /* |
| @@ -748,11 +796,11 @@ static const struct rtc_class_ops rx8130_rtc_ops = { | |||
| 748 | #define MCP794XX_REG_ALARM0_CTRL 0x0d | 796 | #define MCP794XX_REG_ALARM0_CTRL 0x0d |
| 749 | #define MCP794XX_REG_ALARM1_BASE 0x11 | 797 | #define MCP794XX_REG_ALARM1_BASE 0x11 |
| 750 | #define MCP794XX_REG_ALARM1_CTRL 0x14 | 798 | #define MCP794XX_REG_ALARM1_CTRL 0x14 |
| 751 | # define MCP794XX_BIT_ALMX_IF (1 << 3) | 799 | # define MCP794XX_BIT_ALMX_IF BIT(3) |
| 752 | # define MCP794XX_BIT_ALMX_C0 (1 << 4) | 800 | # define MCP794XX_BIT_ALMX_C0 BIT(4) |
| 753 | # define MCP794XX_BIT_ALMX_C1 (1 << 5) | 801 | # define MCP794XX_BIT_ALMX_C1 BIT(5) |
| 754 | # define MCP794XX_BIT_ALMX_C2 (1 << 6) | 802 | # define MCP794XX_BIT_ALMX_C2 BIT(6) |
| 755 | # define MCP794XX_BIT_ALMX_POL (1 << 7) | 803 | # define MCP794XX_BIT_ALMX_POL BIT(7) |
| 756 | # define MCP794XX_MSK_ALMX_MATCH (MCP794XX_BIT_ALMX_C0 | \ | 804 | # define MCP794XX_MSK_ALMX_MATCH (MCP794XX_BIT_ALMX_C0 | \ |
| 757 | MCP794XX_BIT_ALMX_C1 | \ | 805 | MCP794XX_BIT_ALMX_C1 | \ |
| 758 | MCP794XX_BIT_ALMX_C2) | 806 | MCP794XX_BIT_ALMX_C2) |
| @@ -793,37 +841,38 @@ out: | |||
| 793 | static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) | 841 | static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) |
| 794 | { | 842 | { |
| 795 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 843 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 796 | u8 *regs = ds1307->regs; | 844 | u8 regs[10]; |
| 797 | int ret; | 845 | int ret; |
| 798 | 846 | ||
| 799 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | 847 | if (!test_bit(HAS_ALARM, &ds1307->flags)) |
| 800 | return -EINVAL; | 848 | return -EINVAL; |
| 801 | 849 | ||
| 802 | /* Read control and alarm 0 registers. */ | 850 | /* Read control and alarm 0 registers. */ |
| 803 | ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); | 851 | ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, |
| 852 | sizeof(regs)); | ||
| 804 | if (ret) | 853 | if (ret) |
| 805 | return ret; | 854 | return ret; |
| 806 | 855 | ||
| 807 | t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN); | 856 | t->enabled = !!(regs[0] & MCP794XX_BIT_ALM0_EN); |
| 808 | 857 | ||
| 809 | /* Report alarm 0 time assuming 24-hour and day-of-month modes. */ | 858 | /* Report alarm 0 time assuming 24-hour and day-of-month modes. */ |
| 810 | t->time.tm_sec = bcd2bin(ds1307->regs[3] & 0x7f); | 859 | t->time.tm_sec = bcd2bin(regs[3] & 0x7f); |
| 811 | t->time.tm_min = bcd2bin(ds1307->regs[4] & 0x7f); | 860 | t->time.tm_min = bcd2bin(regs[4] & 0x7f); |
| 812 | t->time.tm_hour = bcd2bin(ds1307->regs[5] & 0x3f); | 861 | t->time.tm_hour = bcd2bin(regs[5] & 0x3f); |
| 813 | t->time.tm_wday = bcd2bin(ds1307->regs[6] & 0x7) - 1; | 862 | t->time.tm_wday = bcd2bin(regs[6] & 0x7) - 1; |
| 814 | t->time.tm_mday = bcd2bin(ds1307->regs[7] & 0x3f); | 863 | t->time.tm_mday = bcd2bin(regs[7] & 0x3f); |
| 815 | t->time.tm_mon = bcd2bin(ds1307->regs[8] & 0x1f) - 1; | 864 | t->time.tm_mon = bcd2bin(regs[8] & 0x1f) - 1; |
| 816 | t->time.tm_year = -1; | 865 | t->time.tm_year = -1; |
| 817 | t->time.tm_yday = -1; | 866 | t->time.tm_yday = -1; |
| 818 | t->time.tm_isdst = -1; | 867 | t->time.tm_isdst = -1; |
| 819 | 868 | ||
| 820 | dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " | 869 | dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " |
| 821 | "enabled=%d polarity=%d irq=%d match=%d\n", __func__, | 870 | "enabled=%d polarity=%d irq=%d match=%lu\n", __func__, |
| 822 | t->time.tm_sec, t->time.tm_min, t->time.tm_hour, | 871 | t->time.tm_sec, t->time.tm_min, t->time.tm_hour, |
| 823 | t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled, | 872 | t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled, |
| 824 | !!(ds1307->regs[6] & MCP794XX_BIT_ALMX_POL), | 873 | !!(regs[6] & MCP794XX_BIT_ALMX_POL), |
| 825 | !!(ds1307->regs[6] & MCP794XX_BIT_ALMX_IF), | 874 | !!(regs[6] & MCP794XX_BIT_ALMX_IF), |
| 826 | (ds1307->regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4); | 875 | (regs[6] & MCP794XX_MSK_ALMX_MATCH) >> 4); |
| 827 | 876 | ||
| 828 | return 0; | 877 | return 0; |
| 829 | } | 878 | } |
| @@ -831,7 +880,7 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 831 | static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) | 880 | static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) |
| 832 | { | 881 | { |
| 833 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 882 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 834 | unsigned char *regs = ds1307->regs; | 883 | unsigned char regs[10]; |
| 835 | int ret; | 884 | int ret; |
| 836 | 885 | ||
| 837 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | 886 | if (!test_bit(HAS_ALARM, &ds1307->flags)) |
| @@ -844,7 +893,8 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 844 | t->enabled, t->pending); | 893 | t->enabled, t->pending); |
| 845 | 894 | ||
| 846 | /* Read control and alarm 0 registers. */ | 895 | /* Read control and alarm 0 registers. */ |
| 847 | ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); | 896 | ret = regmap_bulk_read(ds1307->regmap, MCP794XX_REG_CONTROL, regs, |
| 897 | sizeof(regs)); | ||
| 848 | if (ret) | 898 | if (ret) |
| 849 | return ret; | 899 | return ret; |
| 850 | 900 | ||
| @@ -863,7 +913,8 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 863 | /* Disable interrupt. We will not enable until completely programmed */ | 913 | /* Disable interrupt. We will not enable until completely programmed */ |
| 864 | regs[0] &= ~MCP794XX_BIT_ALM0_EN; | 914 | regs[0] &= ~MCP794XX_BIT_ALM0_EN; |
| 865 | 915 | ||
| 866 | ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs, 10); | 916 | ret = regmap_bulk_write(ds1307->regmap, MCP794XX_REG_CONTROL, regs, |
| 917 | sizeof(regs)); | ||
| 867 | if (ret) | 918 | if (ret) |
| 868 | return ret; | 919 | return ret; |
| 869 | 920 | ||
| @@ -885,22 +936,15 @@ static int mcp794xx_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
| 885 | enabled ? MCP794XX_BIT_ALM0_EN : 0); | 936 | enabled ? MCP794XX_BIT_ALM0_EN : 0); |
| 886 | } | 937 | } |
| 887 | 938 | ||
| 888 | static const struct rtc_class_ops mcp794xx_rtc_ops = { | ||
| 889 | .read_time = ds1307_get_time, | ||
| 890 | .set_time = ds1307_set_time, | ||
| 891 | .read_alarm = mcp794xx_read_alarm, | ||
| 892 | .set_alarm = mcp794xx_set_alarm, | ||
| 893 | .alarm_irq_enable = mcp794xx_alarm_irq_enable, | ||
| 894 | }; | ||
| 895 | |||
| 896 | /*----------------------------------------------------------------------*/ | 939 | /*----------------------------------------------------------------------*/ |
| 897 | 940 | ||
| 898 | static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, | 941 | static int ds1307_nvram_read(void *priv, unsigned int offset, void *val, |
| 899 | size_t bytes) | 942 | size_t bytes) |
| 900 | { | 943 | { |
| 901 | struct ds1307 *ds1307 = priv; | 944 | struct ds1307 *ds1307 = priv; |
| 945 | const struct chip_desc *chip = &chips[ds1307->type]; | ||
| 902 | 946 | ||
| 903 | return regmap_bulk_read(ds1307->regmap, ds1307->nvram_offset + offset, | 947 | return regmap_bulk_read(ds1307->regmap, chip->nvram_offset + offset, |
| 904 | val, bytes); | 948 | val, bytes); |
| 905 | } | 949 | } |
| 906 | 950 | ||
| @@ -908,15 +952,16 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val, | |||
| 908 | size_t bytes) | 952 | size_t bytes) |
| 909 | { | 953 | { |
| 910 | struct ds1307 *ds1307 = priv; | 954 | struct ds1307 *ds1307 = priv; |
| 955 | const struct chip_desc *chip = &chips[ds1307->type]; | ||
| 911 | 956 | ||
| 912 | return regmap_bulk_write(ds1307->regmap, ds1307->nvram_offset + offset, | 957 | return regmap_bulk_write(ds1307->regmap, chip->nvram_offset + offset, |
| 913 | val, bytes); | 958 | val, bytes); |
| 914 | } | 959 | } |
| 915 | 960 | ||
| 916 | /*----------------------------------------------------------------------*/ | 961 | /*----------------------------------------------------------------------*/ |
| 917 | 962 | ||
| 918 | static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, | 963 | static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, |
| 919 | uint32_t ohms, bool diode) | 964 | u32 ohms, bool diode) |
| 920 | { | 965 | { |
| 921 | u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : | 966 | u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : |
| 922 | DS1307_TRICKLE_CHARGER_NO_DIODE; | 967 | DS1307_TRICKLE_CHARGER_NO_DIODE; |
| @@ -939,23 +984,23 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, | |||
| 939 | return setup; | 984 | return setup; |
| 940 | } | 985 | } |
| 941 | 986 | ||
| 942 | static void ds1307_trickle_init(struct ds1307 *ds1307, | 987 | static u8 ds1307_trickle_init(struct ds1307 *ds1307, |
| 943 | struct chip_desc *chip) | 988 | const struct chip_desc *chip) |
| 944 | { | 989 | { |
| 945 | uint32_t ohms = 0; | 990 | u32 ohms; |
| 946 | bool diode = true; | 991 | bool diode = true; |
| 947 | 992 | ||
| 948 | if (!chip->do_trickle_setup) | 993 | if (!chip->do_trickle_setup) |
| 949 | goto out; | 994 | return 0; |
| 995 | |||
| 950 | if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms", | 996 | if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms", |
| 951 | &ohms)) | 997 | &ohms)) |
| 952 | goto out; | 998 | return 0; |
| 999 | |||
| 953 | if (device_property_read_bool(ds1307->dev, "trickle-diode-disable")) | 1000 | if (device_property_read_bool(ds1307->dev, "trickle-diode-disable")) |
| 954 | diode = false; | 1001 | diode = false; |
| 955 | chip->trickle_charger_setup = chip->do_trickle_setup(ds1307, | 1002 | |
| 956 | ohms, diode); | 1003 | return chip->do_trickle_setup(ds1307, ohms, diode); |
| 957 | out: | ||
| 958 | return; | ||
| 959 | } | 1004 | } |
| 960 | 1005 | ||
| 961 | /*----------------------------------------------------------------------*/ | 1006 | /*----------------------------------------------------------------------*/ |
| @@ -995,7 +1040,7 @@ static int ds3231_hwmon_read_temp(struct device *dev, s32 *mC) | |||
| 995 | } | 1040 | } |
| 996 | 1041 | ||
| 997 | static ssize_t ds3231_hwmon_show_temp(struct device *dev, | 1042 | static ssize_t ds3231_hwmon_show_temp(struct device *dev, |
| 998 | struct device_attribute *attr, char *buf) | 1043 | struct device_attribute *attr, char *buf) |
| 999 | { | 1044 | { |
| 1000 | int ret; | 1045 | int ret; |
| 1001 | s32 temp; | 1046 | s32 temp; |
| @@ -1006,8 +1051,8 @@ static ssize_t ds3231_hwmon_show_temp(struct device *dev, | |||
| 1006 | 1051 | ||
| 1007 | return sprintf(buf, "%d\n", temp); | 1052 | return sprintf(buf, "%d\n", temp); |
| 1008 | } | 1053 | } |
| 1009 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp, | 1054 | static SENSOR_DEVICE_ATTR(temp1_input, 0444, ds3231_hwmon_show_temp, |
| 1010 | NULL, 0); | 1055 | NULL, 0); |
| 1011 | 1056 | ||
| 1012 | static struct attribute *ds3231_hwmon_attrs[] = { | 1057 | static struct attribute *ds3231_hwmon_attrs[] = { |
| 1013 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 1058 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
| @@ -1023,7 +1068,8 @@ static void ds1307_hwmon_register(struct ds1307 *ds1307) | |||
| 1023 | return; | 1068 | return; |
| 1024 | 1069 | ||
| 1025 | dev = devm_hwmon_device_register_with_groups(ds1307->dev, ds1307->name, | 1070 | dev = devm_hwmon_device_register_with_groups(ds1307->dev, ds1307->name, |
| 1026 | ds1307, ds3231_hwmon_groups); | 1071 | ds1307, |
| 1072 | ds3231_hwmon_groups); | ||
| 1027 | if (IS_ERR(dev)) { | 1073 | if (IS_ERR(dev)) { |
| 1028 | dev_warn(ds1307->dev, "unable to register hwmon device %ld\n", | 1074 | dev_warn(ds1307->dev, "unable to register hwmon device %ld\n", |
| 1029 | PTR_ERR(dev)); | 1075 | PTR_ERR(dev)); |
| @@ -1095,7 +1141,7 @@ static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw, | |||
| 1095 | } | 1141 | } |
| 1096 | 1142 | ||
| 1097 | static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate, | 1143 | static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate, |
| 1098 | unsigned long *prate) | 1144 | unsigned long *prate) |
| 1099 | { | 1145 | { |
| 1100 | int i; | 1146 | int i; |
| 1101 | 1147 | ||
| @@ -1108,7 +1154,7 @@ static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 1108 | } | 1154 | } |
| 1109 | 1155 | ||
| 1110 | static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate, | 1156 | static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate, |
| 1111 | unsigned long parent_rate) | 1157 | unsigned long parent_rate) |
| 1112 | { | 1158 | { |
| 1113 | struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw); | 1159 | struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw); |
| 1114 | int control = 0; | 1160 | int control = 0; |
| @@ -1168,7 +1214,7 @@ static const struct clk_ops ds3231_clk_sqw_ops = { | |||
| 1168 | }; | 1214 | }; |
| 1169 | 1215 | ||
| 1170 | static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw, | 1216 | static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw, |
| 1171 | unsigned long parent_rate) | 1217 | unsigned long parent_rate) |
| 1172 | { | 1218 | { |
| 1173 | return 32768; | 1219 | return 32768; |
| 1174 | } | 1220 | } |
| @@ -1259,7 +1305,7 @@ static int ds3231_clks_register(struct ds1307 *ds1307) | |||
| 1259 | 1305 | ||
| 1260 | /* optional override of the clockname */ | 1306 | /* optional override of the clockname */ |
| 1261 | of_property_read_string_index(node, "clock-output-names", i, | 1307 | of_property_read_string_index(node, "clock-output-names", i, |
| 1262 | &init.name); | 1308 | &init.name); |
| 1263 | ds1307->clks[i].init = &init; | 1309 | ds1307->clks[i].init = &init; |
| 1264 | 1310 | ||
| 1265 | onecell->clks[i] = devm_clk_register(ds1307->dev, | 1311 | onecell->clks[i] = devm_clk_register(ds1307->dev, |
| @@ -1309,22 +1355,14 @@ static int ds1307_probe(struct i2c_client *client, | |||
| 1309 | struct ds1307 *ds1307; | 1355 | struct ds1307 *ds1307; |
| 1310 | int err = -ENODEV; | 1356 | int err = -ENODEV; |
| 1311 | int tmp, wday; | 1357 | int tmp, wday; |
| 1312 | struct chip_desc *chip; | 1358 | const struct chip_desc *chip; |
| 1313 | bool want_irq = false; | 1359 | bool want_irq; |
| 1314 | bool ds1307_can_wakeup_device = false; | 1360 | bool ds1307_can_wakeup_device = false; |
| 1315 | unsigned char *buf; | 1361 | unsigned char regs[8]; |
| 1316 | struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); | 1362 | struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); |
| 1317 | struct rtc_time tm; | 1363 | struct rtc_time tm; |
| 1318 | unsigned long timestamp; | 1364 | unsigned long timestamp; |
| 1319 | 1365 | u8 trickle_charger_setup = 0; | |
| 1320 | irq_handler_t irq_handler = ds1307_irq; | ||
| 1321 | |||
| 1322 | static const int bbsqi_bitpos[] = { | ||
| 1323 | [ds_1337] = 0, | ||
| 1324 | [ds_1339] = DS1339_BIT_BBSQI, | ||
| 1325 | [ds_3231] = DS3231_BIT_BBSQW, | ||
| 1326 | }; | ||
| 1327 | const struct rtc_class_ops *rtc_ops = &ds13xx_rtc_ops; | ||
| 1328 | 1366 | ||
| 1329 | ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL); | 1367 | ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL); |
| 1330 | if (!ds1307) | 1368 | if (!ds1307) |
| @@ -1333,7 +1371,6 @@ static int ds1307_probe(struct i2c_client *client, | |||
| 1333 | dev_set_drvdata(&client->dev, ds1307); | 1371 | dev_set_drvdata(&client->dev, ds1307); |
| 1334 | ds1307->dev = &client->dev; | 1372 | ds1307->dev = &client->dev; |
| 1335 | ds1307->name = client->name; | 1373 | ds1307->name = client->name; |
| 1336 | ds1307->irq = client->irq; | ||
| 1337 | 1374 | ||
| 1338 | ds1307->regmap = devm_regmap_init_i2c(client, ®map_config); | 1375 | ds1307->regmap = devm_regmap_init_i2c(client, ®map_config); |
| 1339 | if (IS_ERR(ds1307->regmap)) { | 1376 | if (IS_ERR(ds1307->regmap)) { |
| @@ -1361,23 +1398,22 @@ static int ds1307_probe(struct i2c_client *client, | |||
| 1361 | ds1307->type = acpi_id->driver_data; | 1398 | ds1307->type = acpi_id->driver_data; |
| 1362 | } | 1399 | } |
| 1363 | 1400 | ||
| 1401 | want_irq = client->irq > 0 && chip->alarm; | ||
| 1402 | |||
| 1364 | if (!pdata) | 1403 | if (!pdata) |
| 1365 | ds1307_trickle_init(ds1307, chip); | 1404 | trickle_charger_setup = ds1307_trickle_init(ds1307, chip); |
| 1366 | else if (pdata->trickle_charger_setup) | 1405 | else if (pdata->trickle_charger_setup) |
| 1367 | chip->trickle_charger_setup = pdata->trickle_charger_setup; | 1406 | trickle_charger_setup = pdata->trickle_charger_setup; |
| 1368 | 1407 | ||
| 1369 | if (chip->trickle_charger_setup && chip->trickle_charger_reg) { | 1408 | if (trickle_charger_setup && chip->trickle_charger_reg) { |
| 1409 | trickle_charger_setup |= DS13XX_TRICKLE_CHARGER_MAGIC; | ||
| 1370 | dev_dbg(ds1307->dev, | 1410 | dev_dbg(ds1307->dev, |
| 1371 | "writing trickle charger info 0x%x to 0x%x\n", | 1411 | "writing trickle charger info 0x%x to 0x%x\n", |
| 1372 | DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup, | 1412 | trickle_charger_setup, chip->trickle_charger_reg); |
| 1373 | chip->trickle_charger_reg); | ||
| 1374 | regmap_write(ds1307->regmap, chip->trickle_charger_reg, | 1413 | regmap_write(ds1307->regmap, chip->trickle_charger_reg, |
| 1375 | DS13XX_TRICKLE_CHARGER_MAGIC | | 1414 | trickle_charger_setup); |
| 1376 | chip->trickle_charger_setup); | ||
| 1377 | } | 1415 | } |
| 1378 | 1416 | ||
| 1379 | buf = ds1307->regs; | ||
| 1380 | |||
| 1381 | #ifdef CONFIG_OF | 1417 | #ifdef CONFIG_OF |
| 1382 | /* | 1418 | /* |
| 1383 | * For devices with no IRQ directly connected to the SoC, the RTC chip | 1419 | * For devices with no IRQ directly connected to the SoC, the RTC chip |
| @@ -1387,31 +1423,27 @@ static int ds1307_probe(struct i2c_client *client, | |||
| 1387 | * This will guarantee the 'wakealarm' sysfs entry is available on the device, | 1423 | * This will guarantee the 'wakealarm' sysfs entry is available on the device, |
| 1388 | * if supported by the RTC. | 1424 | * if supported by the RTC. |
| 1389 | */ | 1425 | */ |
| 1390 | if (of_property_read_bool(client->dev.of_node, "wakeup-source")) { | 1426 | if (chip->alarm && of_property_read_bool(client->dev.of_node, |
| 1391 | ds1307_can_wakeup_device = true; | 1427 | "wakeup-source")) |
| 1392 | } | ||
| 1393 | /* Intersil ISL12057 DT backward compatibility */ | ||
| 1394 | if (of_property_read_bool(client->dev.of_node, | ||
| 1395 | "isil,irq2-can-wakeup-machine")) { | ||
| 1396 | ds1307_can_wakeup_device = true; | 1428 | ds1307_can_wakeup_device = true; |
| 1397 | } | ||
| 1398 | #endif | 1429 | #endif |
| 1399 | 1430 | ||
| 1400 | switch (ds1307->type) { | 1431 | switch (ds1307->type) { |
| 1401 | case ds_1337: | 1432 | case ds_1337: |
| 1402 | case ds_1339: | 1433 | case ds_1339: |
| 1434 | case ds_1341: | ||
| 1403 | case ds_3231: | 1435 | case ds_3231: |
| 1404 | /* get registers that the "rtc" read below won't read... */ | 1436 | /* get registers that the "rtc" read below won't read... */ |
| 1405 | err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL, | 1437 | err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL, |
| 1406 | buf, 2); | 1438 | regs, 2); |
| 1407 | if (err) { | 1439 | if (err) { |
| 1408 | dev_dbg(ds1307->dev, "read error %d\n", err); | 1440 | dev_dbg(ds1307->dev, "read error %d\n", err); |
| 1409 | goto exit; | 1441 | goto exit; |
| 1410 | } | 1442 | } |
| 1411 | 1443 | ||
| 1412 | /* oscillator off? turn it on, so clock can tick. */ | 1444 | /* oscillator off? turn it on, so clock can tick. */ |
| 1413 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) | 1445 | if (regs[0] & DS1337_BIT_nEOSC) |
| 1414 | ds1307->regs[0] &= ~DS1337_BIT_nEOSC; | 1446 | regs[0] &= ~DS1337_BIT_nEOSC; |
| 1415 | 1447 | ||
| 1416 | /* | 1448 | /* |
| 1417 | * Using IRQ or defined as wakeup-source? | 1449 | * Using IRQ or defined as wakeup-source? |
| @@ -1419,114 +1451,92 @@ static int ds1307_probe(struct i2c_client *client, | |||
| 1419 | * For some variants, be sure alarms can trigger when we're | 1451 | * For some variants, be sure alarms can trigger when we're |
| 1420 | * running on Vbackup (BBSQI/BBSQW) | 1452 | * running on Vbackup (BBSQI/BBSQW) |
| 1421 | */ | 1453 | */ |
| 1422 | if (chip->alarm && (ds1307->irq > 0 || | 1454 | if (want_irq || ds1307_can_wakeup_device) { |
| 1423 | ds1307_can_wakeup_device)) { | 1455 | regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; |
| 1424 | ds1307->regs[0] |= DS1337_BIT_INTCN | 1456 | regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); |
| 1425 | | bbsqi_bitpos[ds1307->type]; | ||
| 1426 | ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); | ||
| 1427 | |||
| 1428 | want_irq = true; | ||
| 1429 | } | 1457 | } |
| 1430 | 1458 | ||
| 1431 | regmap_write(ds1307->regmap, DS1337_REG_CONTROL, | 1459 | regmap_write(ds1307->regmap, DS1337_REG_CONTROL, |
| 1432 | ds1307->regs[0]); | 1460 | regs[0]); |
| 1433 | 1461 | ||
| 1434 | /* oscillator fault? clear flag, and warn */ | 1462 | /* oscillator fault? clear flag, and warn */ |
| 1435 | if (ds1307->regs[1] & DS1337_BIT_OSF) { | 1463 | if (regs[1] & DS1337_BIT_OSF) { |
| 1436 | regmap_write(ds1307->regmap, DS1337_REG_STATUS, | 1464 | regmap_write(ds1307->regmap, DS1337_REG_STATUS, |
| 1437 | ds1307->regs[1] & ~DS1337_BIT_OSF); | 1465 | regs[1] & ~DS1337_BIT_OSF); |
| 1438 | dev_warn(ds1307->dev, "SET TIME!\n"); | 1466 | dev_warn(ds1307->dev, "SET TIME!\n"); |
| 1439 | } | 1467 | } |
| 1440 | break; | 1468 | break; |
| 1441 | 1469 | ||
| 1442 | case rx_8025: | 1470 | case rx_8025: |
| 1443 | err = regmap_bulk_read(ds1307->regmap, | 1471 | err = regmap_bulk_read(ds1307->regmap, |
| 1444 | RX8025_REG_CTRL1 << 4 | 0x08, buf, 2); | 1472 | RX8025_REG_CTRL1 << 4 | 0x08, regs, 2); |
| 1445 | if (err) { | 1473 | if (err) { |
| 1446 | dev_dbg(ds1307->dev, "read error %d\n", err); | 1474 | dev_dbg(ds1307->dev, "read error %d\n", err); |
| 1447 | goto exit; | 1475 | goto exit; |
| 1448 | } | 1476 | } |
| 1449 | 1477 | ||
| 1450 | /* oscillator off? turn it on, so clock can tick. */ | 1478 | /* oscillator off? turn it on, so clock can tick. */ |
| 1451 | if (!(ds1307->regs[1] & RX8025_BIT_XST)) { | 1479 | if (!(regs[1] & RX8025_BIT_XST)) { |
| 1452 | ds1307->regs[1] |= RX8025_BIT_XST; | 1480 | regs[1] |= RX8025_BIT_XST; |
| 1453 | regmap_write(ds1307->regmap, | 1481 | regmap_write(ds1307->regmap, |
| 1454 | RX8025_REG_CTRL2 << 4 | 0x08, | 1482 | RX8025_REG_CTRL2 << 4 | 0x08, |
| 1455 | ds1307->regs[1]); | 1483 | regs[1]); |
| 1456 | dev_warn(ds1307->dev, | 1484 | dev_warn(ds1307->dev, |
| 1457 | "oscillator stop detected - SET TIME!\n"); | 1485 | "oscillator stop detected - SET TIME!\n"); |
| 1458 | } | 1486 | } |
| 1459 | 1487 | ||
| 1460 | if (ds1307->regs[1] & RX8025_BIT_PON) { | 1488 | if (regs[1] & RX8025_BIT_PON) { |
| 1461 | ds1307->regs[1] &= ~RX8025_BIT_PON; | 1489 | regs[1] &= ~RX8025_BIT_PON; |
| 1462 | regmap_write(ds1307->regmap, | 1490 | regmap_write(ds1307->regmap, |
| 1463 | RX8025_REG_CTRL2 << 4 | 0x08, | 1491 | RX8025_REG_CTRL2 << 4 | 0x08, |
| 1464 | ds1307->regs[1]); | 1492 | regs[1]); |
| 1465 | dev_warn(ds1307->dev, "power-on detected\n"); | 1493 | dev_warn(ds1307->dev, "power-on detected\n"); |
| 1466 | } | 1494 | } |
| 1467 | 1495 | ||
| 1468 | if (ds1307->regs[1] & RX8025_BIT_VDET) { | 1496 | if (regs[1] & RX8025_BIT_VDET) { |
| 1469 | ds1307->regs[1] &= ~RX8025_BIT_VDET; | 1497 | regs[1] &= ~RX8025_BIT_VDET; |
| 1470 | regmap_write(ds1307->regmap, | 1498 | regmap_write(ds1307->regmap, |
| 1471 | RX8025_REG_CTRL2 << 4 | 0x08, | 1499 | RX8025_REG_CTRL2 << 4 | 0x08, |
| 1472 | ds1307->regs[1]); | 1500 | regs[1]); |
| 1473 | dev_warn(ds1307->dev, "voltage drop detected\n"); | 1501 | dev_warn(ds1307->dev, "voltage drop detected\n"); |
| 1474 | } | 1502 | } |
| 1475 | 1503 | ||
| 1476 | /* make sure we are running in 24hour mode */ | 1504 | /* make sure we are running in 24hour mode */ |
| 1477 | if (!(ds1307->regs[0] & RX8025_BIT_2412)) { | 1505 | if (!(regs[0] & RX8025_BIT_2412)) { |
| 1478 | u8 hour; | 1506 | u8 hour; |
| 1479 | 1507 | ||
| 1480 | /* switch to 24 hour mode */ | 1508 | /* switch to 24 hour mode */ |
| 1481 | regmap_write(ds1307->regmap, | 1509 | regmap_write(ds1307->regmap, |
| 1482 | RX8025_REG_CTRL1 << 4 | 0x08, | 1510 | RX8025_REG_CTRL1 << 4 | 0x08, |
| 1483 | ds1307->regs[0] | RX8025_BIT_2412); | 1511 | regs[0] | RX8025_BIT_2412); |
| 1484 | 1512 | ||
| 1485 | err = regmap_bulk_read(ds1307->regmap, | 1513 | err = regmap_bulk_read(ds1307->regmap, |
| 1486 | RX8025_REG_CTRL1 << 4 | 0x08, | 1514 | RX8025_REG_CTRL1 << 4 | 0x08, |
| 1487 | buf, 2); | 1515 | regs, 2); |
| 1488 | if (err) { | 1516 | if (err) { |
| 1489 | dev_dbg(ds1307->dev, "read error %d\n", err); | 1517 | dev_dbg(ds1307->dev, "read error %d\n", err); |
| 1490 | goto exit; | 1518 | goto exit; |
| 1491 | } | 1519 | } |
| 1492 | 1520 | ||
| 1493 | /* correct hour */ | 1521 | /* correct hour */ |
| 1494 | hour = bcd2bin(ds1307->regs[DS1307_REG_HOUR]); | 1522 | hour = bcd2bin(regs[DS1307_REG_HOUR]); |
| 1495 | if (hour == 12) | 1523 | if (hour == 12) |
| 1496 | hour = 0; | 1524 | hour = 0; |
| 1497 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | 1525 | if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM) |
| 1498 | hour += 12; | 1526 | hour += 12; |
| 1499 | 1527 | ||
| 1500 | regmap_write(ds1307->regmap, | 1528 | regmap_write(ds1307->regmap, |
| 1501 | DS1307_REG_HOUR << 4 | 0x08, hour); | 1529 | DS1307_REG_HOUR << 4 | 0x08, hour); |
| 1502 | } | 1530 | } |
| 1503 | break; | 1531 | break; |
| 1504 | case rx_8130: | ||
| 1505 | ds1307->offset = 0x10; /* Seconds starts at 0x10 */ | ||
| 1506 | rtc_ops = &rx8130_rtc_ops; | ||
| 1507 | if (chip->alarm && ds1307->irq > 0) { | ||
| 1508 | irq_handler = rx8130_irq; | ||
| 1509 | want_irq = true; | ||
| 1510 | } | ||
| 1511 | break; | ||
| 1512 | case ds_1388: | ||
| 1513 | ds1307->offset = 1; /* Seconds starts at 1 */ | ||
| 1514 | break; | ||
| 1515 | case mcp794xx: | ||
| 1516 | rtc_ops = &mcp794xx_rtc_ops; | ||
| 1517 | if (chip->alarm && (ds1307->irq > 0 || | ||
| 1518 | ds1307_can_wakeup_device)) { | ||
| 1519 | irq_handler = mcp794xx_irq; | ||
| 1520 | want_irq = true; | ||
| 1521 | } | ||
| 1522 | break; | ||
| 1523 | default: | 1532 | default: |
| 1524 | break; | 1533 | break; |
| 1525 | } | 1534 | } |
| 1526 | 1535 | ||
| 1527 | read_rtc: | 1536 | read_rtc: |
| 1528 | /* read RTC registers */ | 1537 | /* read RTC registers */ |
| 1529 | err = regmap_bulk_read(ds1307->regmap, ds1307->offset, buf, 8); | 1538 | err = regmap_bulk_read(ds1307->regmap, chip->offset, regs, |
| 1539 | sizeof(regs)); | ||
| 1530 | if (err) { | 1540 | if (err) { |
| 1531 | dev_dbg(ds1307->dev, "read error %d\n", err); | 1541 | dev_dbg(ds1307->dev, "read error %d\n", err); |
| 1532 | goto exit; | 1542 | goto exit; |
| @@ -1537,7 +1547,7 @@ read_rtc: | |||
| 1537 | * specify the extra bits as must-be-zero, but there are | 1547 | * specify the extra bits as must-be-zero, but there are |
| 1538 | * still a few values that are clearly out-of-range. | 1548 | * still a few values that are clearly out-of-range. |
| 1539 | */ | 1549 | */ |
| 1540 | tmp = ds1307->regs[DS1307_REG_SECS]; | 1550 | tmp = regs[DS1307_REG_SECS]; |
| 1541 | switch (ds1307->type) { | 1551 | switch (ds1307->type) { |
| 1542 | case ds_1307: | 1552 | case ds_1307: |
| 1543 | case m41t0: | 1553 | case m41t0: |
| @@ -1556,10 +1566,10 @@ read_rtc: | |||
| 1556 | regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); | 1566 | regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); |
| 1557 | 1567 | ||
| 1558 | /* oscillator fault? clear flag, and warn */ | 1568 | /* oscillator fault? clear flag, and warn */ |
| 1559 | if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { | 1569 | if (regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { |
| 1560 | regmap_write(ds1307->regmap, DS1307_REG_CONTROL, | 1570 | regmap_write(ds1307->regmap, DS1307_REG_CONTROL, |
| 1561 | ds1307->regs[DS1307_REG_CONTROL] & | 1571 | regs[DS1307_REG_CONTROL] & |
| 1562 | ~DS1338_BIT_OSF); | 1572 | ~DS1338_BIT_OSF); |
| 1563 | dev_warn(ds1307->dev, "SET TIME!\n"); | 1573 | dev_warn(ds1307->dev, "SET TIME!\n"); |
| 1564 | goto read_rtc; | 1574 | goto read_rtc; |
| 1565 | } | 1575 | } |
| @@ -1583,9 +1593,9 @@ read_rtc: | |||
| 1583 | break; | 1593 | break; |
| 1584 | case mcp794xx: | 1594 | case mcp794xx: |
| 1585 | /* make sure that the backup battery is enabled */ | 1595 | /* make sure that the backup battery is enabled */ |
| 1586 | if (!(ds1307->regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { | 1596 | if (!(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { |
| 1587 | regmap_write(ds1307->regmap, DS1307_REG_WDAY, | 1597 | regmap_write(ds1307->regmap, DS1307_REG_WDAY, |
| 1588 | ds1307->regs[DS1307_REG_WDAY] | | 1598 | regs[DS1307_REG_WDAY] | |
| 1589 | MCP794XX_BIT_VBATEN); | 1599 | MCP794XX_BIT_VBATEN); |
| 1590 | } | 1600 | } |
| 1591 | 1601 | ||
| @@ -1602,7 +1612,7 @@ read_rtc: | |||
| 1602 | break; | 1612 | break; |
| 1603 | } | 1613 | } |
| 1604 | 1614 | ||
| 1605 | tmp = ds1307->regs[DS1307_REG_HOUR]; | 1615 | tmp = regs[DS1307_REG_HOUR]; |
| 1606 | switch (ds1307->type) { | 1616 | switch (ds1307->type) { |
| 1607 | case ds_1340: | 1617 | case ds_1340: |
| 1608 | case m41t0: | 1618 | case m41t0: |
| @@ -1625,9 +1635,9 @@ read_rtc: | |||
| 1625 | tmp = bcd2bin(tmp & 0x1f); | 1635 | tmp = bcd2bin(tmp & 0x1f); |
| 1626 | if (tmp == 12) | 1636 | if (tmp == 12) |
| 1627 | tmp = 0; | 1637 | tmp = 0; |
| 1628 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | 1638 | if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM) |
| 1629 | tmp += 12; | 1639 | tmp += 12; |
| 1630 | regmap_write(ds1307->regmap, ds1307->offset + DS1307_REG_HOUR, | 1640 | regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR, |
| 1631 | bin2bcd(tmp)); | 1641 | bin2bcd(tmp)); |
| 1632 | } | 1642 | } |
| 1633 | 1643 | ||
| @@ -1650,19 +1660,16 @@ read_rtc: | |||
| 1650 | MCP794XX_REG_WEEKDAY_WDAY_MASK, | 1660 | MCP794XX_REG_WEEKDAY_WDAY_MASK, |
| 1651 | tm.tm_wday + 1); | 1661 | tm.tm_wday + 1); |
| 1652 | 1662 | ||
| 1653 | if (want_irq) { | 1663 | if (want_irq || ds1307_can_wakeup_device) { |
| 1654 | device_set_wakeup_capable(ds1307->dev, true); | 1664 | device_set_wakeup_capable(ds1307->dev, true); |
| 1655 | set_bit(HAS_ALARM, &ds1307->flags); | 1665 | set_bit(HAS_ALARM, &ds1307->flags); |
| 1656 | } | 1666 | } |
| 1657 | 1667 | ||
| 1658 | ds1307->rtc = devm_rtc_allocate_device(ds1307->dev); | 1668 | ds1307->rtc = devm_rtc_allocate_device(ds1307->dev); |
| 1659 | if (IS_ERR(ds1307->rtc)) { | 1669 | if (IS_ERR(ds1307->rtc)) |
| 1660 | return PTR_ERR(ds1307->rtc); | 1670 | return PTR_ERR(ds1307->rtc); |
| 1661 | } | ||
| 1662 | 1671 | ||
| 1663 | if (ds1307_can_wakeup_device && ds1307->irq <= 0) { | 1672 | if (ds1307_can_wakeup_device && !want_irq) { |
| 1664 | /* Disable request for an IRQ */ | ||
| 1665 | want_irq = false; | ||
| 1666 | dev_info(ds1307->dev, | 1673 | dev_info(ds1307->dev, |
| 1667 | "'wakeup-source' is set, request for an IRQ is disabled!\n"); | 1674 | "'wakeup-source' is set, request for an IRQ is disabled!\n"); |
| 1668 | /* We cannot support UIE mode if we do not have an IRQ line */ | 1675 | /* We cannot support UIE mode if we do not have an IRQ line */ |
| @@ -1670,8 +1677,8 @@ read_rtc: | |||
| 1670 | } | 1677 | } |
| 1671 | 1678 | ||
| 1672 | if (want_irq) { | 1679 | if (want_irq) { |
| 1673 | err = devm_request_threaded_irq(ds1307->dev, | 1680 | err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL, |
| 1674 | ds1307->irq, NULL, irq_handler, | 1681 | chip->irq_handler ?: ds1307_irq, |
| 1675 | IRQF_SHARED | IRQF_ONESHOT, | 1682 | IRQF_SHARED | IRQF_ONESHOT, |
| 1676 | ds1307->name, ds1307); | 1683 | ds1307->name, ds1307); |
| 1677 | if (err) { | 1684 | if (err) { |
| @@ -1679,8 +1686,9 @@ read_rtc: | |||
| 1679 | device_set_wakeup_capable(ds1307->dev, false); | 1686 | device_set_wakeup_capable(ds1307->dev, false); |
| 1680 | clear_bit(HAS_ALARM, &ds1307->flags); | 1687 | clear_bit(HAS_ALARM, &ds1307->flags); |
| 1681 | dev_err(ds1307->dev, "unable to request IRQ!\n"); | 1688 | dev_err(ds1307->dev, "unable to request IRQ!\n"); |
| 1682 | } else | 1689 | } else { |
| 1683 | dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq); | 1690 | dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq); |
| 1691 | } | ||
| 1684 | } | 1692 | } |
| 1685 | 1693 | ||
| 1686 | if (chip->nvram_size) { | 1694 | if (chip->nvram_size) { |
| @@ -1691,13 +1699,12 @@ read_rtc: | |||
| 1691 | ds1307->nvmem_cfg.reg_read = ds1307_nvram_read; | 1699 | ds1307->nvmem_cfg.reg_read = ds1307_nvram_read; |
| 1692 | ds1307->nvmem_cfg.reg_write = ds1307_nvram_write; | 1700 | ds1307->nvmem_cfg.reg_write = ds1307_nvram_write; |
| 1693 | ds1307->nvmem_cfg.priv = ds1307; | 1701 | ds1307->nvmem_cfg.priv = ds1307; |
| 1694 | ds1307->nvram_offset = chip->nvram_offset; | ||
| 1695 | 1702 | ||
| 1696 | ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg; | 1703 | ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg; |
| 1697 | ds1307->rtc->nvram_old_abi = true; | 1704 | ds1307->rtc->nvram_old_abi = true; |
| 1698 | } | 1705 | } |
| 1699 | 1706 | ||
| 1700 | ds1307->rtc->ops = rtc_ops; | 1707 | ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops; |
| 1701 | err = rtc_register_device(ds1307->rtc); | 1708 | err = rtc_register_device(ds1307->rtc); |
| 1702 | if (err) | 1709 | if (err) |
| 1703 | return err; | 1710 | return err; |
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 7bf46bfe11a4..9caaccccaa57 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
| @@ -190,7 +190,7 @@ static int ds1672_probe(struct i2c_client *client, | |||
| 190 | return 0; | 190 | return 0; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static struct i2c_device_id ds1672_id[] = { | 193 | static const struct i2c_device_id ds1672_id[] = { |
| 194 | { "ds1672", 0 }, | 194 | { "ds1672", 0 }, |
| 195 | { } | 195 | { } |
| 196 | }; | 196 | }; |
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index 4f4930a2004c..b0ef8cfe742d 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c | |||
| @@ -132,7 +132,7 @@ static int em3027_probe(struct i2c_client *client, | |||
| 132 | return 0; | 132 | return 0; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | static struct i2c_device_id em3027_id[] = { | 135 | static const struct i2c_device_id em3027_id[] = { |
| 136 | { "em3027", 0 }, | 136 | { "em3027", 0 }, |
| 137 | { } | 137 | { } |
| 138 | }; | 138 | }; |
diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c new file mode 100644 index 000000000000..d67769265185 --- /dev/null +++ b/drivers/rtc/rtc-goldfish.c | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | /* drivers/rtc/rtc-goldfish.c | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Google, Inc. | ||
| 4 | * Copyright (C) 2017 Imagination Technologies Ltd. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/rtc.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | |||
| 22 | #define TIMER_TIME_LOW 0x00 /* get low bits of current time */ | ||
| 23 | /* and update TIMER_TIME_HIGH */ | ||
| 24 | #define TIMER_TIME_HIGH 0x04 /* get high bits of time at last */ | ||
| 25 | /* TIMER_TIME_LOW read */ | ||
| 26 | #define TIMER_ALARM_LOW 0x08 /* set low bits of alarm and */ | ||
| 27 | /* activate it */ | ||
| 28 | #define TIMER_ALARM_HIGH 0x0c /* set high bits of next alarm */ | ||
| 29 | #define TIMER_IRQ_ENABLED 0x10 | ||
| 30 | #define TIMER_CLEAR_ALARM 0x14 | ||
| 31 | #define TIMER_ALARM_STATUS 0x18 | ||
| 32 | #define TIMER_CLEAR_INTERRUPT 0x1c | ||
| 33 | |||
| 34 | struct goldfish_rtc { | ||
| 35 | void __iomem *base; | ||
| 36 | int irq; | ||
| 37 | struct rtc_device *rtc; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int goldfish_rtc_read_alarm(struct device *dev, | ||
| 41 | struct rtc_wkalrm *alrm) | ||
| 42 | { | ||
| 43 | u64 rtc_alarm; | ||
| 44 | u64 rtc_alarm_low; | ||
| 45 | u64 rtc_alarm_high; | ||
| 46 | void __iomem *base; | ||
| 47 | struct goldfish_rtc *rtcdrv; | ||
| 48 | |||
| 49 | rtcdrv = dev_get_drvdata(dev); | ||
| 50 | base = rtcdrv->base; | ||
| 51 | |||
| 52 | rtc_alarm_low = readl(base + TIMER_ALARM_LOW); | ||
| 53 | rtc_alarm_high = readl(base + TIMER_ALARM_HIGH); | ||
| 54 | rtc_alarm = (rtc_alarm_high << 32) | rtc_alarm_low; | ||
| 55 | |||
| 56 | do_div(rtc_alarm, NSEC_PER_SEC); | ||
| 57 | memset(alrm, 0, sizeof(struct rtc_wkalrm)); | ||
| 58 | |||
| 59 | rtc_time_to_tm(rtc_alarm, &alrm->time); | ||
| 60 | |||
| 61 | if (readl(base + TIMER_ALARM_STATUS)) | ||
| 62 | alrm->enabled = 1; | ||
| 63 | else | ||
| 64 | alrm->enabled = 0; | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int goldfish_rtc_set_alarm(struct device *dev, | ||
| 70 | struct rtc_wkalrm *alrm) | ||
| 71 | { | ||
| 72 | struct goldfish_rtc *rtcdrv; | ||
| 73 | unsigned long rtc_alarm; | ||
| 74 | u64 rtc_alarm64; | ||
| 75 | u64 rtc_status_reg; | ||
| 76 | void __iomem *base; | ||
| 77 | int ret = 0; | ||
| 78 | |||
| 79 | rtcdrv = dev_get_drvdata(dev); | ||
| 80 | base = rtcdrv->base; | ||
| 81 | |||
| 82 | if (alrm->enabled) { | ||
| 83 | ret = rtc_tm_to_time(&alrm->time, &rtc_alarm); | ||
| 84 | if (ret != 0) | ||
| 85 | return ret; | ||
| 86 | |||
| 87 | rtc_alarm64 = rtc_alarm * NSEC_PER_SEC; | ||
| 88 | writel((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH); | ||
| 89 | writel(rtc_alarm64, base + TIMER_ALARM_LOW); | ||
| 90 | } else { | ||
| 91 | /* | ||
| 92 | * if this function was called with enabled=0 | ||
| 93 | * then it could mean that the application is | ||
| 94 | * trying to cancel an ongoing alarm | ||
| 95 | */ | ||
| 96 | rtc_status_reg = readl(base + TIMER_ALARM_STATUS); | ||
| 97 | if (rtc_status_reg) | ||
| 98 | writel(1, base + TIMER_CLEAR_ALARM); | ||
| 99 | } | ||
| 100 | |||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int goldfish_rtc_alarm_irq_enable(struct device *dev, | ||
| 105 | unsigned int enabled) | ||
| 106 | { | ||
| 107 | void __iomem *base; | ||
| 108 | struct goldfish_rtc *rtcdrv; | ||
| 109 | |||
| 110 | rtcdrv = dev_get_drvdata(dev); | ||
| 111 | base = rtcdrv->base; | ||
| 112 | |||
| 113 | if (enabled) | ||
| 114 | writel(1, base + TIMER_IRQ_ENABLED); | ||
| 115 | else | ||
| 116 | writel(0, base + TIMER_IRQ_ENABLED); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id) | ||
| 122 | { | ||
| 123 | struct goldfish_rtc *rtcdrv = dev_id; | ||
| 124 | void __iomem *base = rtcdrv->base; | ||
| 125 | |||
| 126 | writel(1, base + TIMER_CLEAR_INTERRUPT); | ||
| 127 | |||
| 128 | rtc_update_irq(rtcdrv->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 129 | |||
| 130 | return IRQ_HANDLED; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int goldfish_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 134 | { | ||
| 135 | struct goldfish_rtc *rtcdrv; | ||
| 136 | void __iomem *base; | ||
| 137 | u64 time_high; | ||
| 138 | u64 time_low; | ||
| 139 | u64 time; | ||
| 140 | |||
| 141 | rtcdrv = dev_get_drvdata(dev); | ||
| 142 | base = rtcdrv->base; | ||
| 143 | |||
| 144 | time_low = readl(base + TIMER_TIME_LOW); | ||
| 145 | time_high = readl(base + TIMER_TIME_HIGH); | ||
| 146 | time = (time_high << 32) | time_low; | ||
| 147 | |||
| 148 | do_div(time, NSEC_PER_SEC); | ||
| 149 | |||
| 150 | rtc_time_to_tm(time, tm); | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int goldfish_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 156 | { | ||
| 157 | struct goldfish_rtc *rtcdrv; | ||
| 158 | void __iomem *base; | ||
| 159 | unsigned long now; | ||
| 160 | u64 now64; | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | rtcdrv = dev_get_drvdata(dev); | ||
| 164 | base = rtcdrv->base; | ||
| 165 | |||
| 166 | ret = rtc_tm_to_time(tm, &now); | ||
| 167 | if (ret == 0) { | ||
| 168 | now64 = now * NSEC_PER_SEC; | ||
| 169 | writel((now64 >> 32), base + TIMER_TIME_HIGH); | ||
| 170 | writel(now64, base + TIMER_TIME_LOW); | ||
| 171 | } | ||
| 172 | |||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | static const struct rtc_class_ops goldfish_rtc_ops = { | ||
| 177 | .read_time = goldfish_rtc_read_time, | ||
| 178 | .set_time = goldfish_rtc_set_time, | ||
| 179 | .read_alarm = goldfish_rtc_read_alarm, | ||
| 180 | .set_alarm = goldfish_rtc_set_alarm, | ||
| 181 | .alarm_irq_enable = goldfish_rtc_alarm_irq_enable | ||
| 182 | }; | ||
| 183 | |||
| 184 | static int goldfish_rtc_probe(struct platform_device *pdev) | ||
| 185 | { | ||
| 186 | struct goldfish_rtc *rtcdrv; | ||
| 187 | struct resource *r; | ||
| 188 | int err; | ||
| 189 | |||
| 190 | rtcdrv = devm_kzalloc(&pdev->dev, sizeof(*rtcdrv), GFP_KERNEL); | ||
| 191 | if (!rtcdrv) | ||
| 192 | return -ENOMEM; | ||
| 193 | |||
| 194 | platform_set_drvdata(pdev, rtcdrv); | ||
| 195 | |||
| 196 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 197 | if (!r) | ||
| 198 | return -ENODEV; | ||
| 199 | |||
| 200 | rtcdrv->base = devm_ioremap_resource(&pdev->dev, r); | ||
| 201 | if (IS_ERR(rtcdrv->base)) | ||
| 202 | return -ENODEV; | ||
| 203 | |||
| 204 | rtcdrv->irq = platform_get_irq(pdev, 0); | ||
| 205 | if (rtcdrv->irq < 0) | ||
| 206 | return -ENODEV; | ||
| 207 | |||
| 208 | rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, | ||
| 209 | &goldfish_rtc_ops, | ||
| 210 | THIS_MODULE); | ||
| 211 | if (IS_ERR(rtcdrv->rtc)) | ||
| 212 | return PTR_ERR(rtcdrv->rtc); | ||
| 213 | |||
| 214 | err = devm_request_irq(&pdev->dev, rtcdrv->irq, | ||
| 215 | goldfish_rtc_interrupt, | ||
| 216 | 0, pdev->name, rtcdrv); | ||
| 217 | if (err) | ||
| 218 | return err; | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static const struct of_device_id goldfish_rtc_of_match[] = { | ||
| 224 | { .compatible = "google,goldfish-rtc", }, | ||
| 225 | {}, | ||
| 226 | }; | ||
| 227 | MODULE_DEVICE_TABLE(of, goldfish_rtc_of_match); | ||
| 228 | |||
| 229 | static struct platform_driver goldfish_rtc = { | ||
| 230 | .probe = goldfish_rtc_probe, | ||
| 231 | .driver = { | ||
| 232 | .name = "goldfish_rtc", | ||
| 233 | .of_match_table = goldfish_rtc_of_match, | ||
| 234 | } | ||
| 235 | }; | ||
| 236 | |||
| 237 | module_platform_driver(goldfish_rtc); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 8940e9e43ea0..f4c070ea8384 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
| @@ -440,28 +440,6 @@ static int m41t80_resume(struct device *dev) | |||
| 440 | 440 | ||
| 441 | static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); | 441 | static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); |
| 442 | 442 | ||
| 443 | static ssize_t flags_show(struct device *dev, | ||
| 444 | struct device_attribute *attr, char *buf) | ||
| 445 | { | ||
| 446 | struct i2c_client *client = to_i2c_client(dev); | ||
| 447 | int val; | ||
| 448 | |||
| 449 | val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS); | ||
| 450 | if (val < 0) | ||
| 451 | return val; | ||
| 452 | return sprintf(buf, "%#x\n", val); | ||
| 453 | } | ||
| 454 | static DEVICE_ATTR_RO(flags); | ||
| 455 | |||
| 456 | static struct attribute *attrs[] = { | ||
| 457 | &dev_attr_flags.attr, | ||
| 458 | NULL, | ||
| 459 | }; | ||
| 460 | |||
| 461 | static struct attribute_group attr_group = { | ||
| 462 | .attrs = attrs, | ||
| 463 | }; | ||
| 464 | |||
| 465 | #ifdef CONFIG_COMMON_CLK | 443 | #ifdef CONFIG_COMMON_CLK |
| 466 | #define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw) | 444 | #define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw) |
| 467 | 445 | ||
| @@ -912,13 +890,6 @@ static struct notifier_block wdt_notifier = { | |||
| 912 | ***************************************************************************** | 890 | ***************************************************************************** |
| 913 | */ | 891 | */ |
| 914 | 892 | ||
| 915 | static void m41t80_remove_sysfs_group(void *_dev) | ||
| 916 | { | ||
| 917 | struct device *dev = _dev; | ||
| 918 | |||
| 919 | sysfs_remove_group(&dev->kobj, &attr_group); | ||
| 920 | } | ||
| 921 | |||
| 922 | static int m41t80_probe(struct i2c_client *client, | 893 | static int m41t80_probe(struct i2c_client *client, |
| 923 | const struct i2c_device_id *id) | 894 | const struct i2c_device_id *id) |
| 924 | { | 895 | { |
| @@ -927,6 +898,7 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 927 | struct rtc_device *rtc = NULL; | 898 | struct rtc_device *rtc = NULL; |
| 928 | struct rtc_time tm; | 899 | struct rtc_time tm; |
| 929 | struct m41t80_data *m41t80_data = NULL; | 900 | struct m41t80_data *m41t80_data = NULL; |
| 901 | bool wakeup_source = false; | ||
| 930 | 902 | ||
| 931 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK | | 903 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK | |
| 932 | I2C_FUNC_SMBUS_BYTE_DATA)) { | 904 | I2C_FUNC_SMBUS_BYTE_DATA)) { |
| @@ -947,6 +919,10 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 947 | m41t80_data->features = id->driver_data; | 919 | m41t80_data->features = id->driver_data; |
| 948 | i2c_set_clientdata(client, m41t80_data); | 920 | i2c_set_clientdata(client, m41t80_data); |
| 949 | 921 | ||
| 922 | #ifdef CONFIG_OF | ||
| 923 | wakeup_source = of_property_read_bool(client->dev.of_node, | ||
| 924 | "wakeup-source"); | ||
| 925 | #endif | ||
| 950 | if (client->irq > 0) { | 926 | if (client->irq > 0) { |
| 951 | rc = devm_request_threaded_irq(&client->dev, client->irq, | 927 | rc = devm_request_threaded_irq(&client->dev, client->irq, |
| 952 | NULL, m41t80_handle_irq, | 928 | NULL, m41t80_handle_irq, |
| @@ -955,14 +931,16 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 955 | if (rc) { | 931 | if (rc) { |
| 956 | dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); | 932 | dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); |
| 957 | client->irq = 0; | 933 | client->irq = 0; |
| 958 | } else { | 934 | wakeup_source = false; |
| 959 | m41t80_rtc_ops.read_alarm = m41t80_read_alarm; | ||
| 960 | m41t80_rtc_ops.set_alarm = m41t80_set_alarm; | ||
| 961 | m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable; | ||
| 962 | /* Enable the wakealarm */ | ||
| 963 | device_init_wakeup(&client->dev, true); | ||
| 964 | } | 935 | } |
| 965 | } | 936 | } |
| 937 | if (client->irq > 0 || wakeup_source) { | ||
| 938 | m41t80_rtc_ops.read_alarm = m41t80_read_alarm; | ||
| 939 | m41t80_rtc_ops.set_alarm = m41t80_set_alarm; | ||
| 940 | m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable; | ||
| 941 | /* Enable the wakealarm */ | ||
| 942 | device_init_wakeup(&client->dev, true); | ||
| 943 | } | ||
| 966 | 944 | ||
| 967 | rtc = devm_rtc_device_register(&client->dev, client->name, | 945 | rtc = devm_rtc_device_register(&client->dev, client->name, |
| 968 | &m41t80_rtc_ops, THIS_MODULE); | 946 | &m41t80_rtc_ops, THIS_MODULE); |
| @@ -970,6 +948,10 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 970 | return PTR_ERR(rtc); | 948 | return PTR_ERR(rtc); |
| 971 | 949 | ||
| 972 | m41t80_data->rtc = rtc; | 950 | m41t80_data->rtc = rtc; |
| 951 | if (client->irq <= 0) { | ||
| 952 | /* We cannot support UIE mode if we do not have an IRQ line */ | ||
| 953 | rtc->uie_unsupported = 1; | ||
| 954 | } | ||
| 973 | 955 | ||
| 974 | /* Make sure HT (Halt Update) bit is cleared */ | 956 | /* Make sure HT (Halt Update) bit is cleared */ |
| 975 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); | 957 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR); |
| @@ -1004,21 +986,6 @@ static int m41t80_probe(struct i2c_client *client, | |||
| 1004 | return rc; | 986 | return rc; |
| 1005 | } | 987 | } |
| 1006 | 988 | ||
| 1007 | /* Export sysfs entries */ | ||
| 1008 | rc = sysfs_create_group(&(&client->dev)->kobj, &attr_group); | ||
| 1009 | if (rc) { | ||
| 1010 | dev_err(&client->dev, "Failed to create sysfs group: %d\n", rc); | ||
| 1011 | return rc; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group, | ||
| 1015 | &client->dev); | ||
| 1016 | if (rc) { | ||
| 1017 | dev_err(&client->dev, | ||
| 1018 | "Failed to add sysfs cleanup action: %d\n", rc); | ||
| 1019 | return rc; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | #ifdef CONFIG_RTC_DRV_M41T80_WDT | 989 | #ifdef CONFIG_RTC_DRV_M41T80_WDT |
| 1023 | if (m41t80_data->features & M41T80_FEATURE_HT) { | 990 | if (m41t80_data->features & M41T80_FEATURE_HT) { |
| 1024 | save_client = client; | 991 | save_client = client; |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 48b6b411f8b2..cbdc86a560ba 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
| @@ -226,7 +226,7 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 226 | return 0; | 226 | return 0; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static struct i2c_device_id max6900_id[] = { | 229 | static const struct i2c_device_id max6900_id[] = { |
| 230 | { "max6900", 0 }, | 230 | { "max6900", 0 }, |
| 231 | { } | 231 | { } |
| 232 | }; | 232 | }; |
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 16d129a0bb3b..67d6fc2d23e6 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c | |||
| @@ -234,8 +234,6 @@ static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 234 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); | 234 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); |
| 235 | else | 235 | else |
| 236 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x0); | 236 | ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x0); |
| 237 | if (ret < 0) | ||
| 238 | goto out; | ||
| 239 | out: | 237 | out: |
| 240 | return ret; | 238 | return ret; |
| 241 | } | 239 | } |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 401f46d8f21b..bce427d202ee 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
| @@ -238,26 +238,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | |||
| 238 | return IRQ_HANDLED; | 238 | return IRQ_HANDLED; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | /* | ||
| 242 | * Clear all interrupts and release the IRQ | ||
| 243 | */ | ||
| 244 | static void mxc_rtc_release(struct device *dev) | ||
| 245 | { | ||
| 246 | struct platform_device *pdev = to_platform_device(dev); | ||
| 247 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 248 | void __iomem *ioaddr = pdata->ioaddr; | ||
| 249 | |||
| 250 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
| 251 | |||
| 252 | /* Disable all rtc interrupts */ | ||
| 253 | writew(0, ioaddr + RTC_RTCIENR); | ||
| 254 | |||
| 255 | /* Clear all interrupt status */ | ||
| 256 | writew(0xffffffff, ioaddr + RTC_RTCISR); | ||
| 257 | |||
| 258 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
| 259 | } | ||
| 260 | |||
| 261 | static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 241 | static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| 262 | { | 242 | { |
| 263 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); | 243 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); |
| @@ -343,7 +323,6 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 343 | 323 | ||
| 344 | /* RTC layer */ | 324 | /* RTC layer */ |
| 345 | static const struct rtc_class_ops mxc_rtc_ops = { | 325 | static const struct rtc_class_ops mxc_rtc_ops = { |
| 346 | .release = mxc_rtc_release, | ||
| 347 | .read_time = mxc_rtc_read_time, | 326 | .read_time = mxc_rtc_read_time, |
| 348 | .set_mmss64 = mxc_rtc_set_mmss, | 327 | .set_mmss64 = mxc_rtc_set_mmss, |
| 349 | .read_alarm = mxc_rtc_read_alarm, | 328 | .read_alarm = mxc_rtc_read_alarm, |
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index c0a6e638c672..9e83be32ff43 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c | |||
| @@ -157,49 +157,7 @@ static int puv3_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 157 | return 0; | 157 | return 0; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | static int puv3_rtc_open(struct device *dev) | ||
| 161 | { | ||
| 162 | struct platform_device *pdev = to_platform_device(dev); | ||
| 163 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq, | ||
| 167 | 0, "pkunity-rtc alarm", rtc_dev); | ||
| 168 | |||
| 169 | if (ret) { | ||
| 170 | dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq, | ||
| 175 | 0, "pkunity-rtc tick", rtc_dev); | ||
| 176 | |||
| 177 | if (ret) { | ||
| 178 | dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret); | ||
| 179 | goto tick_err; | ||
| 180 | } | ||
| 181 | |||
| 182 | return ret; | ||
| 183 | |||
| 184 | tick_err: | ||
| 185 | free_irq(puv3_rtc_alarmno, rtc_dev); | ||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 189 | static void puv3_rtc_release(struct device *dev) | ||
| 190 | { | ||
| 191 | struct platform_device *pdev = to_platform_device(dev); | ||
| 192 | struct rtc_device *rtc_dev = platform_get_drvdata(pdev); | ||
| 193 | |||
| 194 | /* do not clear AIE here, it may be needed for wake */ | ||
| 195 | puv3_rtc_setpie(dev, 0); | ||
| 196 | free_irq(puv3_rtc_alarmno, rtc_dev); | ||
| 197 | free_irq(puv3_rtc_tickno, rtc_dev); | ||
| 198 | } | ||
| 199 | |||
| 200 | static const struct rtc_class_ops puv3_rtcops = { | 160 | static const struct rtc_class_ops puv3_rtcops = { |
| 201 | .open = puv3_rtc_open, | ||
| 202 | .release = puv3_rtc_release, | ||
| 203 | .read_time = puv3_rtc_gettime, | 161 | .read_time = puv3_rtc_gettime, |
| 204 | .set_time = puv3_rtc_settime, | 162 | .set_time = puv3_rtc_settime, |
| 205 | .read_alarm = puv3_rtc_getalarm, | 163 | .read_alarm = puv3_rtc_getalarm, |
| @@ -222,10 +180,6 @@ static void puv3_rtc_enable(struct device *dev, int en) | |||
| 222 | 180 | ||
| 223 | static int puv3_rtc_remove(struct platform_device *dev) | 181 | static int puv3_rtc_remove(struct platform_device *dev) |
| 224 | { | 182 | { |
| 225 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
| 226 | |||
| 227 | rtc_device_unregister(rtc); | ||
| 228 | |||
| 229 | puv3_rtc_setpie(&dev->dev, 0); | 183 | puv3_rtc_setpie(&dev->dev, 0); |
| 230 | puv3_rtc_setaie(&dev->dev, 0); | 184 | puv3_rtc_setaie(&dev->dev, 0); |
| 231 | 185 | ||
| @@ -259,6 +213,24 @@ static int puv3_rtc_probe(struct platform_device *pdev) | |||
| 259 | dev_dbg(&pdev->dev, "PKUnity_rtc: tick irq %d, alarm irq %d\n", | 213 | dev_dbg(&pdev->dev, "PKUnity_rtc: tick irq %d, alarm irq %d\n", |
| 260 | puv3_rtc_tickno, puv3_rtc_alarmno); | 214 | puv3_rtc_tickno, puv3_rtc_alarmno); |
| 261 | 215 | ||
| 216 | rtc = devm_rtc_allocate_device(&pdev->dev); | ||
| 217 | if (IS_ERR(rtc)) | ||
| 218 | return PTR_ERR(rtc); | ||
| 219 | |||
| 220 | ret = devm_request_irq(&pdev->dev, puv3_rtc_alarmno, puv3_rtc_alarmirq, | ||
| 221 | 0, "pkunity-rtc alarm", rtc); | ||
| 222 | if (ret) { | ||
| 223 | dev_err(&pdev->dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret); | ||
| 224 | return ret; | ||
| 225 | } | ||
| 226 | |||
| 227 | ret = devm_request_irq(&pdev->dev, puv3_rtc_tickno, puv3_rtc_tickirq, | ||
| 228 | 0, "pkunity-rtc tick", rtc); | ||
| 229 | if (ret) { | ||
| 230 | dev_err(&pdev->dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret); | ||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 262 | /* get the memory region */ | 234 | /* get the memory region */ |
| 263 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 235 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 264 | if (res == NULL) { | 236 | if (res == NULL) { |
| @@ -278,12 +250,10 @@ static int puv3_rtc_probe(struct platform_device *pdev) | |||
| 278 | puv3_rtc_enable(&pdev->dev, 1); | 250 | puv3_rtc_enable(&pdev->dev, 1); |
| 279 | 251 | ||
| 280 | /* register RTC and exit */ | 252 | /* register RTC and exit */ |
| 281 | rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops, | 253 | rtc->ops = &puv3_rtcops; |
| 282 | THIS_MODULE); | 254 | ret = rtc_register_device(rtc); |
| 283 | 255 | if (ret) { | |
| 284 | if (IS_ERR(rtc)) { | ||
| 285 | dev_err(&pdev->dev, "cannot attach rtc\n"); | 256 | dev_err(&pdev->dev, "cannot attach rtc\n"); |
| 286 | ret = PTR_ERR(rtc); | ||
| 287 | goto err_nortc; | 257 | goto err_nortc; |
| 288 | } | 258 | } |
| 289 | 259 | ||
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index fe4985b54608..47304f5664d8 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
| @@ -348,7 +348,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) | |||
| 348 | dev_err(dev, "No alarm IRQ resource defined\n"); | 348 | dev_err(dev, "No alarm IRQ resource defined\n"); |
| 349 | return -ENXIO; | 349 | return -ENXIO; |
| 350 | } | 350 | } |
| 351 | pxa_rtc_open(dev); | 351 | |
| 352 | pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start, | 352 | pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start, |
| 353 | resource_size(pxa_rtc->ress)); | 353 | resource_size(pxa_rtc->ress)); |
| 354 | if (!pxa_rtc->base) { | 354 | if (!pxa_rtc->base) { |
| @@ -356,6 +356,8 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) | |||
| 356 | return -ENOMEM; | 356 | return -ENOMEM; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | pxa_rtc_open(dev); | ||
| 360 | |||
| 359 | sa1100_rtc->rcnr = pxa_rtc->base + 0x0; | 361 | sa1100_rtc->rcnr = pxa_rtc->base + 0x0; |
| 360 | sa1100_rtc->rtsr = pxa_rtc->base + 0x8; | 362 | sa1100_rtc->rtsr = pxa_rtc->base + 0x8; |
| 361 | sa1100_rtc->rtar = pxa_rtc->base + 0x4; | 363 | sa1100_rtc->rtar = pxa_rtc->base + 0x4; |
diff --git a/drivers/rtc/rtc-rtd119x.c b/drivers/rtc/rtc-rtd119x.c new file mode 100644 index 000000000000..b233559d950b --- /dev/null +++ b/drivers/rtc/rtc-rtd119x.c | |||
| @@ -0,0 +1,242 @@ | |||
| 1 | /* | ||
| 2 | * Realtek RTD129x RTC | ||
| 3 | * | ||
| 4 | * Copyright (c) 2017 Andreas Färber | ||
| 5 | * | ||
| 6 | * SPDX-License-Identifier: GPL-2.0+ | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/clk.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_address.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | |||
| 18 | #define RTD_RTCSEC 0x00 | ||
| 19 | #define RTD_RTCMIN 0x04 | ||
| 20 | #define RTD_RTCHR 0x08 | ||
| 21 | #define RTD_RTCDATE1 0x0c | ||
| 22 | #define RTD_RTCDATE2 0x10 | ||
| 23 | #define RTD_RTCACR 0x28 | ||
| 24 | #define RTD_RTCEN 0x2c | ||
| 25 | #define RTD_RTCCR 0x30 | ||
| 26 | |||
| 27 | #define RTD_RTCSEC_RTCSEC_MASK 0x7f | ||
| 28 | |||
| 29 | #define RTD_RTCMIN_RTCMIN_MASK 0x3f | ||
| 30 | |||
| 31 | #define RTD_RTCHR_RTCHR_MASK 0x1f | ||
| 32 | |||
| 33 | #define RTD_RTCDATE1_RTCDATE1_MASK 0xff | ||
| 34 | |||
| 35 | #define RTD_RTCDATE2_RTCDATE2_MASK 0x7f | ||
| 36 | |||
| 37 | #define RTD_RTCACR_RTCPWR BIT(7) | ||
| 38 | |||
| 39 | #define RTD_RTCEN_RTCEN_MASK 0xff | ||
| 40 | |||
| 41 | #define RTD_RTCCR_RTCRST BIT(6) | ||
| 42 | |||
| 43 | struct rtd119x_rtc { | ||
| 44 | void __iomem *base; | ||
| 45 | struct clk *clk; | ||
| 46 | struct rtc_device *rtcdev; | ||
| 47 | unsigned int base_year; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static inline int rtd119x_rtc_days_in_year(int year) | ||
| 51 | { | ||
| 52 | return 365 + (is_leap_year(year) ? 1 : 0); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void rtd119x_rtc_reset(struct device *dev) | ||
| 56 | { | ||
| 57 | struct rtd119x_rtc *data = dev_get_drvdata(dev); | ||
| 58 | u32 val; | ||
| 59 | |||
| 60 | val = readl_relaxed(data->base + RTD_RTCCR); | ||
| 61 | val |= RTD_RTCCR_RTCRST; | ||
| 62 | writel_relaxed(val, data->base + RTD_RTCCR); | ||
| 63 | |||
| 64 | val &= ~RTD_RTCCR_RTCRST; | ||
| 65 | writel(val, data->base + RTD_RTCCR); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void rtd119x_rtc_set_enabled(struct device *dev, bool enable) | ||
| 69 | { | ||
| 70 | struct rtd119x_rtc *data = dev_get_drvdata(dev); | ||
| 71 | u32 val; | ||
| 72 | |||
| 73 | val = readl_relaxed(data->base + RTD_RTCEN); | ||
| 74 | if (enable) { | ||
| 75 | if ((val & RTD_RTCEN_RTCEN_MASK) == 0x5a) | ||
| 76 | return; | ||
| 77 | writel_relaxed(0x5a, data->base + RTD_RTCEN); | ||
| 78 | } else { | ||
| 79 | writel_relaxed(0, data->base + RTD_RTCEN); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | static int rtd119x_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 84 | { | ||
| 85 | struct rtd119x_rtc *data = dev_get_drvdata(dev); | ||
| 86 | s32 day; | ||
| 87 | u32 sec; | ||
| 88 | unsigned int year; | ||
| 89 | int tries = 0; | ||
| 90 | |||
| 91 | while (true) { | ||
| 92 | tm->tm_sec = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1; | ||
| 93 | tm->tm_min = readl_relaxed(data->base + RTD_RTCMIN) & RTD_RTCMIN_RTCMIN_MASK; | ||
| 94 | tm->tm_hour = readl_relaxed(data->base + RTD_RTCHR) & RTD_RTCHR_RTCHR_MASK; | ||
| 95 | day = readl_relaxed(data->base + RTD_RTCDATE1) & RTD_RTCDATE1_RTCDATE1_MASK; | ||
| 96 | day |= (readl_relaxed(data->base + RTD_RTCDATE2) & RTD_RTCDATE2_RTCDATE2_MASK) << 8; | ||
| 97 | sec = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1; | ||
| 98 | tries++; | ||
| 99 | |||
| 100 | if (sec == tm->tm_sec) | ||
| 101 | break; | ||
| 102 | |||
| 103 | if (tries >= 3) | ||
| 104 | return -EINVAL; | ||
| 105 | } | ||
| 106 | if (tries > 1) | ||
| 107 | dev_dbg(dev, "%s: needed %i tries\n", __func__, tries); | ||
| 108 | |||
| 109 | year = data->base_year; | ||
| 110 | while (day >= rtd119x_rtc_days_in_year(year)) { | ||
| 111 | day -= rtd119x_rtc_days_in_year(year); | ||
| 112 | year++; | ||
| 113 | } | ||
| 114 | tm->tm_year = year - 1900; | ||
| 115 | tm->tm_yday = day; | ||
| 116 | |||
| 117 | tm->tm_mon = 0; | ||
| 118 | while (day >= rtc_month_days(tm->tm_mon, year)) { | ||
| 119 | day -= rtc_month_days(tm->tm_mon, year); | ||
| 120 | tm->tm_mon++; | ||
| 121 | } | ||
| 122 | tm->tm_mday = day + 1; | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int rtd119x_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 128 | { | ||
| 129 | struct rtd119x_rtc *data = dev_get_drvdata(dev); | ||
| 130 | unsigned int day; | ||
| 131 | int i; | ||
| 132 | |||
| 133 | if (1900 + tm->tm_year < data->base_year) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 136 | day = 0; | ||
| 137 | for (i = data->base_year; i < 1900 + tm->tm_year; i++) | ||
| 138 | day += rtd119x_rtc_days_in_year(i); | ||
| 139 | |||
| 140 | day += tm->tm_yday; | ||
| 141 | if (day > 0x7fff) | ||
| 142 | return -EINVAL; | ||
| 143 | |||
| 144 | rtd119x_rtc_set_enabled(dev, false); | ||
| 145 | |||
| 146 | writel_relaxed((tm->tm_sec << 1) & RTD_RTCSEC_RTCSEC_MASK, data->base + RTD_RTCSEC); | ||
| 147 | writel_relaxed(tm->tm_min & RTD_RTCMIN_RTCMIN_MASK, data->base + RTD_RTCMIN); | ||
| 148 | writel_relaxed(tm->tm_hour & RTD_RTCHR_RTCHR_MASK, data->base + RTD_RTCHR); | ||
| 149 | writel_relaxed(day & RTD_RTCDATE1_RTCDATE1_MASK, data->base + RTD_RTCDATE1); | ||
| 150 | writel_relaxed((day >> 8) & RTD_RTCDATE2_RTCDATE2_MASK, data->base + RTD_RTCDATE2); | ||
| 151 | |||
| 152 | rtd119x_rtc_set_enabled(dev, true); | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | static const struct rtc_class_ops rtd119x_rtc_ops = { | ||
| 158 | .read_time = rtd119x_rtc_read_time, | ||
| 159 | .set_time = rtd119x_rtc_set_time, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static const struct of_device_id rtd119x_rtc_dt_ids[] = { | ||
| 163 | { .compatible = "realtek,rtd1295-rtc" }, | ||
| 164 | { } | ||
| 165 | }; | ||
| 166 | |||
| 167 | static int rtd119x_rtc_probe(struct platform_device *pdev) | ||
| 168 | { | ||
| 169 | struct rtd119x_rtc *data; | ||
| 170 | struct resource *res; | ||
| 171 | u32 val; | ||
| 172 | int ret; | ||
| 173 | |||
| 174 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
| 175 | if (!data) | ||
| 176 | return -ENOMEM; | ||
| 177 | |||
| 178 | platform_set_drvdata(pdev, data); | ||
| 179 | data->base_year = 2014; | ||
| 180 | |||
| 181 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 182 | data->base = devm_ioremap_resource(&pdev->dev, res); | ||
| 183 | if (IS_ERR(data->base)) | ||
| 184 | return PTR_ERR(data->base); | ||
| 185 | |||
| 186 | data->clk = of_clk_get(pdev->dev.of_node, 0); | ||
| 187 | if (IS_ERR(data->clk)) | ||
| 188 | return PTR_ERR(data->clk); | ||
| 189 | |||
| 190 | ret = clk_prepare_enable(data->clk); | ||
| 191 | if (ret) { | ||
| 192 | clk_put(data->clk); | ||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | val = readl_relaxed(data->base + RTD_RTCACR); | ||
| 197 | if (!(val & RTD_RTCACR_RTCPWR)) { | ||
| 198 | writel_relaxed(RTD_RTCACR_RTCPWR, data->base + RTD_RTCACR); | ||
| 199 | |||
| 200 | rtd119x_rtc_reset(&pdev->dev); | ||
| 201 | |||
| 202 | writel_relaxed(0, data->base + RTD_RTCMIN); | ||
| 203 | writel_relaxed(0, data->base + RTD_RTCHR); | ||
| 204 | writel_relaxed(0, data->base + RTD_RTCDATE1); | ||
| 205 | writel_relaxed(0, data->base + RTD_RTCDATE2); | ||
| 206 | } | ||
| 207 | |||
| 208 | rtd119x_rtc_set_enabled(&pdev->dev, true); | ||
| 209 | |||
| 210 | data->rtcdev = devm_rtc_device_register(&pdev->dev, "rtc", | ||
| 211 | &rtd119x_rtc_ops, THIS_MODULE); | ||
| 212 | if (IS_ERR(data->rtcdev)) { | ||
| 213 | dev_err(&pdev->dev, "failed to register rtc device"); | ||
| 214 | clk_disable_unprepare(data->clk); | ||
| 215 | clk_put(data->clk); | ||
| 216 | return PTR_ERR(data->rtcdev); | ||
| 217 | } | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int rtd119x_rtc_remove(struct platform_device *pdev) | ||
| 223 | { | ||
| 224 | struct rtd119x_rtc *data = platform_get_drvdata(pdev); | ||
| 225 | |||
| 226 | rtd119x_rtc_set_enabled(&pdev->dev, false); | ||
| 227 | |||
| 228 | clk_disable_unprepare(data->clk); | ||
| 229 | clk_put(data->clk); | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static struct platform_driver rtd119x_rtc_driver = { | ||
| 235 | .probe = rtd119x_rtc_probe, | ||
| 236 | .remove = rtd119x_rtc_remove, | ||
| 237 | .driver = { | ||
| 238 | .name = "rtd1295-rtc", | ||
| 239 | .of_match_table = rtd119x_rtc_dt_ids, | ||
| 240 | }, | ||
| 241 | }; | ||
| 242 | builtin_platform_driver(rtd119x_rtc_driver); | ||
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 85fa1da03762..aa09771de04f 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c | |||
| @@ -868,7 +868,7 @@ static int rv3029_i2c_probe(struct i2c_client *client, | |||
| 868 | return rv3029_probe(&client->dev, regmap, client->irq, client->name); | 868 | return rv3029_probe(&client->dev, regmap, client->irq, client->name); |
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | static struct i2c_device_id rv3029_id[] = { | 871 | static const struct i2c_device_id rv3029_id[] = { |
| 872 | { "rv3029", 0 }, | 872 | { "rv3029", 0 }, |
| 873 | { "rv3029c2", 0 }, | 873 | { "rv3029c2", 0 }, |
| 874 | { } | 874 | { } |
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 449820eeefe8..7067bca5c20d 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c | |||
| @@ -106,33 +106,12 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) | |||
| 106 | return 0; | 106 | return 0; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | /* | 109 | static int s35390a_init(struct s35390a *s35390a) |
| 110 | * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset. | ||
| 111 | * To keep the information if an irq is pending, pass the value read from | ||
| 112 | * STATUS1 to the caller. | ||
| 113 | */ | ||
| 114 | static int s35390a_reset(struct s35390a *s35390a, char *status1) | ||
| 115 | { | 110 | { |
| 116 | char buf; | 111 | char buf; |
| 117 | int ret; | 112 | int ret; |
| 118 | unsigned initcount = 0; | 113 | unsigned initcount = 0; |
| 119 | 114 | ||
| 120 | ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1); | ||
| 121 | if (ret < 0) | ||
| 122 | return ret; | ||
| 123 | |||
| 124 | if (*status1 & S35390A_FLAG_POC) | ||
| 125 | /* | ||
| 126 | * Do not communicate for 0.5 seconds since the power-on | ||
| 127 | * detection circuit is in operation. | ||
| 128 | */ | ||
| 129 | msleep(500); | ||
| 130 | else if (!(*status1 & S35390A_FLAG_BLD)) | ||
| 131 | /* | ||
| 132 | * If both POC and BLD are unset everything is fine. | ||
| 133 | */ | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | /* | 115 | /* |
| 137 | * At least one of POC and BLD are set, so reinitialise chip. Keeping | 116 | * At least one of POC and BLD are set, so reinitialise chip. Keeping |
| 138 | * this information in the hardware to know later that the time isn't | 117 | * this information in the hardware to know later that the time isn't |
| @@ -142,7 +121,6 @@ static int s35390a_reset(struct s35390a *s35390a, char *status1) | |||
| 142 | * The 24H bit is kept over reset, so set it already here. | 121 | * The 24H bit is kept over reset, so set it already here. |
| 143 | */ | 122 | */ |
| 144 | initialize: | 123 | initialize: |
| 145 | *status1 = S35390A_FLAG_24H; | ||
| 146 | buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; | 124 | buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; |
| 147 | ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); | 125 | ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); |
| 148 | 126 | ||
| @@ -165,6 +143,34 @@ initialize: | |||
| 165 | return 1; | 143 | return 1; |
| 166 | } | 144 | } |
| 167 | 145 | ||
| 146 | /* | ||
| 147 | * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset. | ||
| 148 | * To keep the information if an irq is pending, pass the value read from | ||
| 149 | * STATUS1 to the caller. | ||
| 150 | */ | ||
| 151 | static int s35390a_read_status(struct s35390a *s35390a, char *status1) | ||
| 152 | { | ||
| 153 | int ret; | ||
| 154 | |||
| 155 | ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1); | ||
| 156 | if (ret < 0) | ||
| 157 | return ret; | ||
| 158 | |||
| 159 | if (*status1 & S35390A_FLAG_POC) { | ||
| 160 | /* | ||
| 161 | * Do not communicate for 0.5 seconds since the power-on | ||
| 162 | * detection circuit is in operation. | ||
| 163 | */ | ||
| 164 | msleep(500); | ||
| 165 | return 1; | ||
| 166 | } else if (*status1 & S35390A_FLAG_BLD) | ||
| 167 | return 1; | ||
| 168 | /* | ||
| 169 | * If both POC and BLD are unset everything is fine. | ||
| 170 | */ | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 168 | static int s35390a_disable_test_mode(struct s35390a *s35390a) | 174 | static int s35390a_disable_test_mode(struct s35390a *s35390a) |
| 169 | { | 175 | { |
| 170 | char buf[1]; | 176 | char buf[1]; |
| @@ -208,13 +214,16 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 208 | { | 214 | { |
| 209 | struct s35390a *s35390a = i2c_get_clientdata(client); | 215 | struct s35390a *s35390a = i2c_get_clientdata(client); |
| 210 | int i, err; | 216 | int i, err; |
| 211 | char buf[7]; | 217 | char buf[7], status; |
| 212 | 218 | ||
| 213 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " | 219 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " |
| 214 | "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, | 220 | "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec, |
| 215 | tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, | 221 | tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, |
| 216 | tm->tm_wday); | 222 | tm->tm_wday); |
| 217 | 223 | ||
| 224 | if (s35390a_read_status(s35390a, &status) == 1) | ||
| 225 | s35390a_init(s35390a); | ||
| 226 | |||
| 218 | buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); | 227 | buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); |
| 219 | buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); | 228 | buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); |
| 220 | buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); | 229 | buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); |
| @@ -235,9 +244,12 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 235 | static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) | 244 | static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) |
| 236 | { | 245 | { |
| 237 | struct s35390a *s35390a = i2c_get_clientdata(client); | 246 | struct s35390a *s35390a = i2c_get_clientdata(client); |
| 238 | char buf[7]; | 247 | char buf[7], status; |
| 239 | int i, err; | 248 | int i, err; |
| 240 | 249 | ||
| 250 | if (s35390a_read_status(s35390a, &status) == 1) | ||
| 251 | return -EINVAL; | ||
| 252 | |||
| 241 | err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); | 253 | err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); |
| 242 | if (err < 0) | 254 | if (err < 0) |
| 243 | return err; | 255 | return err; |
| @@ -392,12 +404,42 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 392 | return s35390a_set_datetime(to_i2c_client(dev), tm); | 404 | return s35390a_set_datetime(to_i2c_client(dev), tm); |
| 393 | } | 405 | } |
| 394 | 406 | ||
| 407 | static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 408 | unsigned long arg) | ||
| 409 | { | ||
| 410 | struct i2c_client *client = to_i2c_client(dev); | ||
| 411 | struct s35390a *s35390a = i2c_get_clientdata(client); | ||
| 412 | char sts; | ||
| 413 | int err; | ||
| 414 | |||
| 415 | switch (cmd) { | ||
| 416 | case RTC_VL_READ: | ||
| 417 | /* s35390a_reset set lowvoltage flag and init RTC if needed */ | ||
| 418 | err = s35390a_read_status(s35390a, &sts); | ||
| 419 | if (err < 0) | ||
| 420 | return err; | ||
| 421 | if (copy_to_user((void __user *)arg, &err, sizeof(int))) | ||
| 422 | return -EFAULT; | ||
| 423 | break; | ||
| 424 | case RTC_VL_CLR: | ||
| 425 | /* update flag and clear register */ | ||
| 426 | err = s35390a_init(s35390a); | ||
| 427 | if (err < 0) | ||
| 428 | return err; | ||
| 429 | break; | ||
| 430 | default: | ||
| 431 | return -ENOIOCTLCMD; | ||
| 432 | } | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | |||
| 395 | static const struct rtc_class_ops s35390a_rtc_ops = { | 437 | static const struct rtc_class_ops s35390a_rtc_ops = { |
| 396 | .read_time = s35390a_rtc_read_time, | 438 | .read_time = s35390a_rtc_read_time, |
| 397 | .set_time = s35390a_rtc_set_time, | 439 | .set_time = s35390a_rtc_set_time, |
| 398 | .set_alarm = s35390a_rtc_set_alarm, | 440 | .set_alarm = s35390a_rtc_set_alarm, |
| 399 | .read_alarm = s35390a_rtc_read_alarm, | 441 | .read_alarm = s35390a_rtc_read_alarm, |
| 400 | 442 | .ioctl = s35390a_rtc_ioctl, | |
| 401 | }; | 443 | }; |
| 402 | 444 | ||
| 403 | static struct i2c_driver s35390a_driver; | 445 | static struct i2c_driver s35390a_driver; |
| @@ -405,7 +447,7 @@ static struct i2c_driver s35390a_driver; | |||
| 405 | static int s35390a_probe(struct i2c_client *client, | 447 | static int s35390a_probe(struct i2c_client *client, |
| 406 | const struct i2c_device_id *id) | 448 | const struct i2c_device_id *id) |
| 407 | { | 449 | { |
| 408 | int err, err_reset; | 450 | int err, err_read; |
| 409 | unsigned int i; | 451 | unsigned int i; |
| 410 | struct s35390a *s35390a; | 452 | struct s35390a *s35390a; |
| 411 | struct rtc_time tm; | 453 | struct rtc_time tm; |
| @@ -438,9 +480,9 @@ static int s35390a_probe(struct i2c_client *client, | |||
| 438 | } | 480 | } |
| 439 | } | 481 | } |
| 440 | 482 | ||
| 441 | err_reset = s35390a_reset(s35390a, &status1); | 483 | err_read = s35390a_read_status(s35390a, &status1); |
| 442 | if (err_reset < 0) { | 484 | if (err_read < 0) { |
| 443 | err = err_reset; | 485 | err = err_read; |
| 444 | dev_err(&client->dev, "error resetting chip\n"); | 486 | dev_err(&client->dev, "error resetting chip\n"); |
| 445 | goto exit_dummy; | 487 | goto exit_dummy; |
| 446 | } | 488 | } |
| @@ -466,7 +508,7 @@ static int s35390a_probe(struct i2c_client *client, | |||
| 466 | } | 508 | } |
| 467 | } | 509 | } |
| 468 | 510 | ||
| 469 | if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0) | 511 | if (err_read > 0 || s35390a_get_datetime(client, &tm) < 0) |
| 470 | dev_warn(&client->dev, "clock needs to be set\n"); | 512 | dev_warn(&client->dev, "clock needs to be set\n"); |
| 471 | 513 | ||
| 472 | device_set_wakeup_capable(&client->dev, 1); | 514 | device_set_wakeup_capable(&client->dev, 1); |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index c2187bf6c7e4..ed71d1113627 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -95,46 +95,6 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
| 95 | return IRQ_HANDLED; | 95 | return IRQ_HANDLED; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static int sa1100_rtc_open(struct device *dev) | ||
| 99 | { | ||
| 100 | struct sa1100_rtc *info = dev_get_drvdata(dev); | ||
| 101 | struct rtc_device *rtc = info->rtc; | ||
| 102 | int ret; | ||
| 103 | |||
| 104 | ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, 0, "rtc 1Hz", dev); | ||
| 105 | if (ret) { | ||
| 106 | dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz); | ||
| 107 | goto fail_ui; | ||
| 108 | } | ||
| 109 | ret = request_irq(info->irq_alarm, sa1100_rtc_interrupt, 0, "rtc Alrm", dev); | ||
| 110 | if (ret) { | ||
| 111 | dev_err(dev, "IRQ %d already in use.\n", info->irq_alarm); | ||
| 112 | goto fail_ai; | ||
| 113 | } | ||
| 114 | rtc->max_user_freq = RTC_FREQ; | ||
| 115 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | |||
| 119 | fail_ai: | ||
| 120 | free_irq(info->irq_1hz, dev); | ||
| 121 | fail_ui: | ||
| 122 | clk_disable_unprepare(info->clk); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | static void sa1100_rtc_release(struct device *dev) | ||
| 127 | { | ||
| 128 | struct sa1100_rtc *info = dev_get_drvdata(dev); | ||
| 129 | |||
| 130 | spin_lock_irq(&info->lock); | ||
| 131 | writel_relaxed(0, info->rtsr); | ||
| 132 | spin_unlock_irq(&info->lock); | ||
| 133 | |||
| 134 | free_irq(info->irq_alarm, dev); | ||
| 135 | free_irq(info->irq_1hz, dev); | ||
| 136 | } | ||
| 137 | |||
| 138 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 98 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| 139 | { | 99 | { |
| 140 | u32 rtsr; | 100 | u32 rtsr; |
| @@ -216,8 +176,6 @@ static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 216 | } | 176 | } |
| 217 | 177 | ||
| 218 | static const struct rtc_class_ops sa1100_rtc_ops = { | 178 | static const struct rtc_class_ops sa1100_rtc_ops = { |
| 219 | .open = sa1100_rtc_open, | ||
| 220 | .release = sa1100_rtc_release, | ||
| 221 | .read_time = sa1100_rtc_read_time, | 179 | .read_time = sa1100_rtc_read_time, |
| 222 | .set_time = sa1100_rtc_set_time, | 180 | .set_time = sa1100_rtc_set_time, |
| 223 | .read_alarm = sa1100_rtc_read_alarm, | 181 | .read_alarm = sa1100_rtc_read_alarm, |
| @@ -265,6 +223,9 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info) | |||
| 265 | } | 223 | } |
| 266 | info->rtc = rtc; | 224 | info->rtc = rtc; |
| 267 | 225 | ||
| 226 | rtc->max_user_freq = RTC_FREQ; | ||
| 227 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); | ||
| 228 | |||
| 268 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 229 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
| 269 | * See also the comments in sa1100_rtc_interrupt(). | 230 | * See also the comments in sa1100_rtc_interrupt(). |
| 270 | * | 231 | * |
| @@ -299,6 +260,7 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
| 299 | struct resource *iores; | 260 | struct resource *iores; |
| 300 | void __iomem *base; | 261 | void __iomem *base; |
| 301 | int irq_1hz, irq_alarm; | 262 | int irq_1hz, irq_alarm; |
| 263 | int ret; | ||
| 302 | 264 | ||
| 303 | irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz"); | 265 | irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz"); |
| 304 | irq_alarm = platform_get_irq_byname(pdev, "rtc alarm"); | 266 | irq_alarm = platform_get_irq_byname(pdev, "rtc alarm"); |
| @@ -311,6 +273,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
| 311 | info->irq_1hz = irq_1hz; | 273 | info->irq_1hz = irq_1hz; |
| 312 | info->irq_alarm = irq_alarm; | 274 | info->irq_alarm = irq_alarm; |
| 313 | 275 | ||
| 276 | ret = devm_request_irq(&pdev->dev, irq_1hz, sa1100_rtc_interrupt, 0, | ||
| 277 | "rtc 1Hz", &pdev->dev); | ||
| 278 | if (ret) { | ||
| 279 | dev_err(&pdev->dev, "IRQ %d already in use.\n", irq_1hz); | ||
| 280 | return ret; | ||
| 281 | } | ||
| 282 | ret = devm_request_irq(&pdev->dev, irq_alarm, sa1100_rtc_interrupt, 0, | ||
| 283 | "rtc Alrm", &pdev->dev); | ||
| 284 | if (ret) { | ||
| 285 | dev_err(&pdev->dev, "IRQ %d already in use.\n", irq_alarm); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 314 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 289 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 315 | base = devm_ioremap_resource(&pdev->dev, iores); | 290 | base = devm_ioremap_resource(&pdev->dev, iores); |
| 316 | if (IS_ERR(base)) | 291 | if (IS_ERR(base)) |
| @@ -339,8 +314,12 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
| 339 | { | 314 | { |
| 340 | struct sa1100_rtc *info = platform_get_drvdata(pdev); | 315 | struct sa1100_rtc *info = platform_get_drvdata(pdev); |
| 341 | 316 | ||
| 342 | if (info) | 317 | if (info) { |
| 318 | spin_lock_irq(&info->lock); | ||
| 319 | writel_relaxed(0, info->rtsr); | ||
| 320 | spin_unlock_irq(&info->lock); | ||
| 343 | clk_disable_unprepare(info->clk); | 321 | clk_disable_unprepare(info->clk); |
| 322 | } | ||
| 344 | 323 | ||
| 345 | return 0; | 324 | return 0; |
| 346 | } | 325 | } |
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 39cbc1238b92..3d2216ccd860 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c | |||
| @@ -73,6 +73,9 @@ | |||
| 73 | #define SUN6I_ALARM_CONFIG 0x0050 | 73 | #define SUN6I_ALARM_CONFIG 0x0050 |
| 74 | #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) | 74 | #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) |
| 75 | 75 | ||
| 76 | #define SUN6I_LOSC_OUT_GATING 0x0060 | ||
| 77 | #define SUN6I_LOSC_OUT_GATING_EN BIT(0) | ||
| 78 | |||
| 76 | /* | 79 | /* |
| 77 | * Get date values | 80 | * Get date values |
| 78 | */ | 81 | */ |
| @@ -125,6 +128,7 @@ struct sun6i_rtc_dev { | |||
| 125 | struct clk_hw hw; | 128 | struct clk_hw hw; |
| 126 | struct clk_hw *int_osc; | 129 | struct clk_hw *int_osc; |
| 127 | struct clk *losc; | 130 | struct clk *losc; |
| 131 | struct clk *ext_losc; | ||
| 128 | 132 | ||
| 129 | spinlock_t lock; | 133 | spinlock_t lock; |
| 130 | }; | 134 | }; |
| @@ -188,23 +192,24 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) | |||
| 188 | struct clk_init_data init = { | 192 | struct clk_init_data init = { |
| 189 | .ops = &sun6i_rtc_osc_ops, | 193 | .ops = &sun6i_rtc_osc_ops, |
| 190 | }; | 194 | }; |
| 195 | const char *clkout_name = "osc32k-out"; | ||
| 191 | const char *parents[2]; | 196 | const char *parents[2]; |
| 192 | 197 | ||
| 193 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 198 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
| 194 | if (!rtc) | 199 | if (!rtc) |
| 195 | return; | 200 | return; |
| 196 | spin_lock_init(&rtc->lock); | ||
| 197 | 201 | ||
| 198 | clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws), | 202 | clk_data = kzalloc(sizeof(*clk_data) + (sizeof(*clk_data->hws) * 2), |
| 199 | GFP_KERNEL); | 203 | GFP_KERNEL); |
| 200 | if (!clk_data) | 204 | if (!clk_data) |
| 201 | return; | 205 | return; |
| 206 | |||
| 202 | spin_lock_init(&rtc->lock); | 207 | spin_lock_init(&rtc->lock); |
| 203 | 208 | ||
| 204 | rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node)); | 209 | rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 205 | if (IS_ERR(rtc->base)) { | 210 | if (IS_ERR(rtc->base)) { |
| 206 | pr_crit("Can't map RTC registers"); | 211 | pr_crit("Can't map RTC registers"); |
| 207 | return; | 212 | goto err; |
| 208 | } | 213 | } |
| 209 | 214 | ||
| 210 | /* Switch to the external, more precise, oscillator */ | 215 | /* Switch to the external, more precise, oscillator */ |
| @@ -216,7 +221,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) | |||
| 216 | 221 | ||
| 217 | /* Deal with old DTs */ | 222 | /* Deal with old DTs */ |
| 218 | if (!of_get_property(node, "clocks", NULL)) | 223 | if (!of_get_property(node, "clocks", NULL)) |
| 219 | return; | 224 | goto err; |
| 220 | 225 | ||
| 221 | rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, | 226 | rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL, |
| 222 | "rtc-int-osc", | 227 | "rtc-int-osc", |
| @@ -235,7 +240,8 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) | |||
| 235 | 240 | ||
| 236 | init.parent_names = parents; | 241 | init.parent_names = parents; |
| 237 | init.num_parents = of_clk_get_parent_count(node) + 1; | 242 | init.num_parents = of_clk_get_parent_count(node) + 1; |
| 238 | of_property_read_string(node, "clock-output-names", &init.name); | 243 | of_property_read_string_index(node, "clock-output-names", 0, |
| 244 | &init.name); | ||
| 239 | 245 | ||
| 240 | rtc->losc = clk_register(NULL, &rtc->hw); | 246 | rtc->losc = clk_register(NULL, &rtc->hw); |
| 241 | if (IS_ERR(rtc->losc)) { | 247 | if (IS_ERR(rtc->losc)) { |
| @@ -243,9 +249,25 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) | |||
| 243 | return; | 249 | return; |
| 244 | } | 250 | } |
| 245 | 251 | ||
| 246 | clk_data->num = 1; | 252 | of_property_read_string_index(node, "clock-output-names", 1, |
| 253 | &clkout_name); | ||
| 254 | rtc->ext_losc = clk_register_gate(NULL, clkout_name, rtc->hw.init->name, | ||
| 255 | 0, rtc->base + SUN6I_LOSC_OUT_GATING, | ||
| 256 | SUN6I_LOSC_OUT_GATING_EN, 0, | ||
| 257 | &rtc->lock); | ||
| 258 | if (IS_ERR(rtc->ext_losc)) { | ||
| 259 | pr_crit("Couldn't register the LOSC external gate\n"); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | clk_data->num = 2; | ||
| 247 | clk_data->hws[0] = &rtc->hw; | 264 | clk_data->hws[0] = &rtc->hw; |
| 265 | clk_data->hws[1] = __clk_get_hw(rtc->ext_losc); | ||
| 248 | of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); | 266 | of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); |
| 267 | return; | ||
| 268 | |||
| 269 | err: | ||
| 270 | kfree(clk_data); | ||
| 249 | } | 271 | } |
| 250 | CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc", | 272 | CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc", |
| 251 | sun6i_rtc_clk_init); | 273 | sun6i_rtc_clk_init); |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index e1b86bb01062..7ce22967fd16 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
| @@ -119,23 +119,6 @@ static inline void write_elapsed_second(unsigned long sec) | |||
| 119 | spin_unlock_irq(&rtc_lock); | 119 | spin_unlock_irq(&rtc_lock); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static void vr41xx_rtc_release(struct device *dev) | ||
| 123 | { | ||
| 124 | |||
| 125 | spin_lock_irq(&rtc_lock); | ||
| 126 | |||
| 127 | rtc1_write(ECMPLREG, 0); | ||
| 128 | rtc1_write(ECMPMREG, 0); | ||
| 129 | rtc1_write(ECMPHREG, 0); | ||
| 130 | rtc1_write(RTCL1LREG, 0); | ||
| 131 | rtc1_write(RTCL1HREG, 0); | ||
| 132 | |||
| 133 | spin_unlock_irq(&rtc_lock); | ||
| 134 | |||
| 135 | disable_irq(aie_irq); | ||
| 136 | disable_irq(pie_irq); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time) | 122 | static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time) |
| 140 | { | 123 | { |
| 141 | unsigned long epoch_sec, elapsed_sec; | 124 | unsigned long epoch_sec, elapsed_sec; |
| @@ -272,7 +255,6 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id) | |||
| 272 | } | 255 | } |
| 273 | 256 | ||
| 274 | static const struct rtc_class_ops vr41xx_rtc_ops = { | 257 | static const struct rtc_class_ops vr41xx_rtc_ops = { |
| 275 | .release = vr41xx_rtc_release, | ||
| 276 | .ioctl = vr41xx_rtc_ioctl, | 258 | .ioctl = vr41xx_rtc_ioctl, |
| 277 | .read_time = vr41xx_rtc_read_time, | 259 | .read_time = vr41xx_rtc_read_time, |
| 278 | .set_time = vr41xx_rtc_set_time, | 260 | .set_time = vr41xx_rtc_set_time, |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d145e0d90227..41366339b950 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -283,7 +283,7 @@ config SCSI_ISCSI_ATTRS | |||
| 283 | config SCSI_SAS_ATTRS | 283 | config SCSI_SAS_ATTRS |
| 284 | tristate "SAS Transport Attributes" | 284 | tristate "SAS Transport Attributes" |
| 285 | depends on SCSI | 285 | depends on SCSI |
| 286 | select BLK_DEV_BSG | 286 | select BLK_DEV_BSGLIB |
| 287 | help | 287 | help |
| 288 | If you wish to export transport-specific information about | 288 | If you wish to export transport-specific information about |
| 289 | each attached SAS device to sysfs, say Y. | 289 | each attached SAS device to sysfs, say Y. |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 831a1c8b9f89..fe3a0da3ec97 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
| @@ -315,8 +315,6 @@ static void scsi_host_dev_release(struct device *dev) | |||
| 315 | { | 315 | { |
| 316 | struct Scsi_Host *shost = dev_to_shost(dev); | 316 | struct Scsi_Host *shost = dev_to_shost(dev); |
| 317 | struct device *parent = dev->parent; | 317 | struct device *parent = dev->parent; |
| 318 | struct request_queue *q; | ||
| 319 | void *queuedata; | ||
| 320 | 318 | ||
| 321 | scsi_proc_hostdir_rm(shost->hostt); | 319 | scsi_proc_hostdir_rm(shost->hostt); |
| 322 | 320 | ||
| @@ -326,12 +324,6 @@ static void scsi_host_dev_release(struct device *dev) | |||
| 326 | kthread_stop(shost->ehandler); | 324 | kthread_stop(shost->ehandler); |
| 327 | if (shost->work_q) | 325 | if (shost->work_q) |
| 328 | destroy_workqueue(shost->work_q); | 326 | destroy_workqueue(shost->work_q); |
| 329 | q = shost->uspace_req_q; | ||
| 330 | if (q) { | ||
| 331 | queuedata = q->queuedata; | ||
| 332 | blk_cleanup_queue(q); | ||
| 333 | kfree(queuedata); | ||
| 334 | } | ||
| 335 | 327 | ||
| 336 | if (shost->shost_state == SHOST_CREATED) { | 328 | if (shost->shost_state == SHOST_CREATED) { |
| 337 | /* | 329 | /* |
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index c5b6b7165489..e9e97803442a 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
| @@ -90,7 +90,7 @@ static struct list_head *cuse_conntbl_head(dev_t devt) | |||
| 90 | 90 | ||
| 91 | static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to) | 91 | static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to) |
| 92 | { | 92 | { |
| 93 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp); | 93 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb); |
| 94 | loff_t pos = 0; | 94 | loff_t pos = 0; |
| 95 | 95 | ||
| 96 | return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE); | 96 | return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE); |
| @@ -98,7 +98,7 @@ static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to) | |||
| 98 | 98 | ||
| 99 | static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from) | 99 | static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from) |
| 100 | { | 100 | { |
| 101 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp); | 101 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb); |
| 102 | loff_t pos = 0; | 102 | loff_t pos = 0; |
| 103 | /* | 103 | /* |
| 104 | * No locking or generic_write_checks(), the server is | 104 | * No locking or generic_write_checks(), the server is |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c16d00e53264..13c65dd2d37d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -1222,9 +1222,6 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1222 | struct fuse_in *in; | 1222 | struct fuse_in *in; |
| 1223 | unsigned reqsize; | 1223 | unsigned reqsize; |
| 1224 | 1224 | ||
| 1225 | if (task_active_pid_ns(current) != fc->pid_ns) | ||
| 1226 | return -EIO; | ||
| 1227 | |||
| 1228 | restart: | 1225 | restart: |
| 1229 | spin_lock(&fiq->waitq.lock); | 1226 | spin_lock(&fiq->waitq.lock); |
| 1230 | err = -EAGAIN; | 1227 | err = -EAGAIN; |
| @@ -1262,6 +1259,13 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1262 | 1259 | ||
| 1263 | in = &req->in; | 1260 | in = &req->in; |
| 1264 | reqsize = in->h.len; | 1261 | reqsize = in->h.len; |
| 1262 | |||
| 1263 | if (task_active_pid_ns(current) != fc->pid_ns) { | ||
| 1264 | rcu_read_lock(); | ||
| 1265 | in->h.pid = pid_vnr(find_pid_ns(in->h.pid, fc->pid_ns)); | ||
| 1266 | rcu_read_unlock(); | ||
| 1267 | } | ||
| 1268 | |||
| 1265 | /* If request is too large, reply with an error and restart the read */ | 1269 | /* If request is too large, reply with an error and restart the read */ |
| 1266 | if (nbytes < reqsize) { | 1270 | if (nbytes < reqsize) { |
| 1267 | req->out.h.error = -EIO; | 1271 | req->out.h.error = -EIO; |
| @@ -1823,9 +1827,6 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, | |||
| 1823 | struct fuse_req *req; | 1827 | struct fuse_req *req; |
| 1824 | struct fuse_out_header oh; | 1828 | struct fuse_out_header oh; |
| 1825 | 1829 | ||
| 1826 | if (task_active_pid_ns(current) != fc->pid_ns) | ||
| 1827 | return -EIO; | ||
| 1828 | |||
| 1829 | if (nbytes < sizeof(struct fuse_out_header)) | 1830 | if (nbytes < sizeof(struct fuse_out_header)) |
| 1830 | return -EINVAL; | 1831 | return -EINVAL; |
| 1831 | 1832 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 00800c07ba1c..622081b97426 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -923,33 +923,29 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
| 923 | return err; | 923 | return err; |
| 924 | } | 924 | } |
| 925 | 925 | ||
| 926 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | 926 | static int fuse_update_get_attr(struct inode *inode, struct file *file, |
| 927 | struct file *file, bool *refreshed) | 927 | struct kstat *stat) |
| 928 | { | 928 | { |
| 929 | struct fuse_inode *fi = get_fuse_inode(inode); | 929 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 930 | int err; | 930 | int err = 0; |
| 931 | bool r; | ||
| 932 | 931 | ||
| 933 | if (time_before64(fi->i_time, get_jiffies_64())) { | 932 | if (time_before64(fi->i_time, get_jiffies_64())) { |
| 934 | r = true; | ||
| 935 | forget_all_cached_acls(inode); | 933 | forget_all_cached_acls(inode); |
| 936 | err = fuse_do_getattr(inode, stat, file); | 934 | err = fuse_do_getattr(inode, stat, file); |
| 937 | } else { | 935 | } else if (stat) { |
| 938 | r = false; | 936 | generic_fillattr(inode, stat); |
| 939 | err = 0; | 937 | stat->mode = fi->orig_i_mode; |
| 940 | if (stat) { | 938 | stat->ino = fi->orig_ino; |
| 941 | generic_fillattr(inode, stat); | ||
| 942 | stat->mode = fi->orig_i_mode; | ||
| 943 | stat->ino = fi->orig_ino; | ||
| 944 | } | ||
| 945 | } | 939 | } |
| 946 | 940 | ||
| 947 | if (refreshed != NULL) | ||
| 948 | *refreshed = r; | ||
| 949 | |||
| 950 | return err; | 941 | return err; |
| 951 | } | 942 | } |
| 952 | 943 | ||
| 944 | int fuse_update_attributes(struct inode *inode, struct file *file) | ||
| 945 | { | ||
| 946 | return fuse_update_get_attr(inode, file, NULL); | ||
| 947 | } | ||
| 948 | |||
| 953 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | 949 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, |
| 954 | u64 child_nodeid, struct qstr *name) | 950 | u64 child_nodeid, struct qstr *name) |
| 955 | { | 951 | { |
| @@ -1786,7 +1782,7 @@ static int fuse_getattr(const struct path *path, struct kstat *stat, | |||
| 1786 | if (!fuse_allow_current_process(fc)) | 1782 | if (!fuse_allow_current_process(fc)) |
| 1787 | return -EACCES; | 1783 | return -EACCES; |
| 1788 | 1784 | ||
| 1789 | return fuse_update_attributes(inode, stat, NULL, NULL); | 1785 | return fuse_update_get_attr(inode, NULL, stat); |
| 1790 | } | 1786 | } |
| 1791 | 1787 | ||
| 1792 | static const struct inode_operations fuse_dir_inode_operations = { | 1788 | static const struct inode_operations fuse_dir_inode_operations = { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d66789804287..cb7dff5c45d7 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -645,7 +645,7 @@ static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req, | |||
| 645 | static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io, | 645 | static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io, |
| 646 | loff_t pos, size_t count, fl_owner_t owner) | 646 | loff_t pos, size_t count, fl_owner_t owner) |
| 647 | { | 647 | { |
| 648 | struct file *file = io->file; | 648 | struct file *file = io->iocb->ki_filp; |
| 649 | struct fuse_file *ff = file->private_data; | 649 | struct fuse_file *ff = file->private_data; |
| 650 | struct fuse_conn *fc = ff->fc; | 650 | struct fuse_conn *fc = ff->fc; |
| 651 | 651 | ||
| @@ -707,7 +707,8 @@ static void fuse_short_read(struct fuse_req *req, struct inode *inode, | |||
| 707 | 707 | ||
| 708 | static int fuse_do_readpage(struct file *file, struct page *page) | 708 | static int fuse_do_readpage(struct file *file, struct page *page) |
| 709 | { | 709 | { |
| 710 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file); | 710 | struct kiocb iocb; |
| 711 | struct fuse_io_priv io; | ||
| 711 | struct inode *inode = page->mapping->host; | 712 | struct inode *inode = page->mapping->host; |
| 712 | struct fuse_conn *fc = get_fuse_conn(inode); | 713 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 713 | struct fuse_req *req; | 714 | struct fuse_req *req; |
| @@ -735,6 +736,8 @@ static int fuse_do_readpage(struct file *file, struct page *page) | |||
| 735 | req->num_pages = 1; | 736 | req->num_pages = 1; |
| 736 | req->pages[0] = page; | 737 | req->pages[0] = page; |
| 737 | req->page_descs[0].length = count; | 738 | req->page_descs[0].length = count; |
| 739 | init_sync_kiocb(&iocb, file); | ||
| 740 | io = (struct fuse_io_priv) FUSE_IO_PRIV_SYNC(&iocb); | ||
| 738 | num_read = fuse_send_read(req, &io, pos, count, NULL); | 741 | num_read = fuse_send_read(req, &io, pos, count, NULL); |
| 739 | err = req->out.h.error; | 742 | err = req->out.h.error; |
| 740 | 743 | ||
| @@ -923,7 +926,7 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
| 923 | if (fc->auto_inval_data || | 926 | if (fc->auto_inval_data || |
| 924 | (iocb->ki_pos + iov_iter_count(to) > i_size_read(inode))) { | 927 | (iocb->ki_pos + iov_iter_count(to) > i_size_read(inode))) { |
| 925 | int err; | 928 | int err; |
| 926 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | 929 | err = fuse_update_attributes(inode, iocb->ki_filp); |
| 927 | if (err) | 930 | if (err) |
| 928 | return err; | 931 | return err; |
| 929 | } | 932 | } |
| @@ -957,13 +960,18 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | |||
| 957 | static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io, | 960 | static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io, |
| 958 | loff_t pos, size_t count, fl_owner_t owner) | 961 | loff_t pos, size_t count, fl_owner_t owner) |
| 959 | { | 962 | { |
| 960 | struct file *file = io->file; | 963 | struct kiocb *iocb = io->iocb; |
| 964 | struct file *file = iocb->ki_filp; | ||
| 961 | struct fuse_file *ff = file->private_data; | 965 | struct fuse_file *ff = file->private_data; |
| 962 | struct fuse_conn *fc = ff->fc; | 966 | struct fuse_conn *fc = ff->fc; |
| 963 | struct fuse_write_in *inarg = &req->misc.write.in; | 967 | struct fuse_write_in *inarg = &req->misc.write.in; |
| 964 | 968 | ||
| 965 | fuse_write_fill(req, ff, pos, count); | 969 | fuse_write_fill(req, ff, pos, count); |
| 966 | inarg->flags = file->f_flags; | 970 | inarg->flags = file->f_flags; |
| 971 | if (iocb->ki_flags & IOCB_DSYNC) | ||
| 972 | inarg->flags |= O_DSYNC; | ||
| 973 | if (iocb->ki_flags & IOCB_SYNC) | ||
| 974 | inarg->flags |= O_SYNC; | ||
| 967 | if (owner != NULL) { | 975 | if (owner != NULL) { |
| 968 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 976 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
| 969 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | 977 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); |
| @@ -993,14 +1001,14 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos) | |||
| 993 | return ret; | 1001 | return ret; |
| 994 | } | 1002 | } |
| 995 | 1003 | ||
| 996 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | 1004 | static size_t fuse_send_write_pages(struct fuse_req *req, struct kiocb *iocb, |
| 997 | struct inode *inode, loff_t pos, | 1005 | struct inode *inode, loff_t pos, |
| 998 | size_t count) | 1006 | size_t count) |
| 999 | { | 1007 | { |
| 1000 | size_t res; | 1008 | size_t res; |
| 1001 | unsigned offset; | 1009 | unsigned offset; |
| 1002 | unsigned i; | 1010 | unsigned i; |
| 1003 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file); | 1011 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); |
| 1004 | 1012 | ||
| 1005 | for (i = 0; i < req->num_pages; i++) | 1013 | for (i = 0; i < req->num_pages; i++) |
| 1006 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); | 1014 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); |
| @@ -1100,7 +1108,7 @@ static inline unsigned fuse_wr_pages(loff_t pos, size_t len) | |||
| 1100 | FUSE_MAX_PAGES_PER_REQ); | 1108 | FUSE_MAX_PAGES_PER_REQ); |
| 1101 | } | 1109 | } |
| 1102 | 1110 | ||
| 1103 | static ssize_t fuse_perform_write(struct file *file, | 1111 | static ssize_t fuse_perform_write(struct kiocb *iocb, |
| 1104 | struct address_space *mapping, | 1112 | struct address_space *mapping, |
| 1105 | struct iov_iter *ii, loff_t pos) | 1113 | struct iov_iter *ii, loff_t pos) |
| 1106 | { | 1114 | { |
| @@ -1133,7 +1141,7 @@ static ssize_t fuse_perform_write(struct file *file, | |||
| 1133 | } else { | 1141 | } else { |
| 1134 | size_t num_written; | 1142 | size_t num_written; |
| 1135 | 1143 | ||
| 1136 | num_written = fuse_send_write_pages(req, file, inode, | 1144 | num_written = fuse_send_write_pages(req, iocb, inode, |
| 1137 | pos, count); | 1145 | pos, count); |
| 1138 | err = req->out.h.error; | 1146 | err = req->out.h.error; |
| 1139 | if (!err) { | 1147 | if (!err) { |
| @@ -1169,7 +1177,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 1169 | 1177 | ||
| 1170 | if (get_fuse_conn(inode)->writeback_cache) { | 1178 | if (get_fuse_conn(inode)->writeback_cache) { |
| 1171 | /* Update size (EOF optimization) and mode (SUID clearing) */ | 1179 | /* Update size (EOF optimization) and mode (SUID clearing) */ |
| 1172 | err = fuse_update_attributes(mapping->host, NULL, file, NULL); | 1180 | err = fuse_update_attributes(mapping->host, file); |
| 1173 | if (err) | 1181 | if (err) |
| 1174 | return err; | 1182 | return err; |
| 1175 | 1183 | ||
| @@ -1201,7 +1209,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 1201 | 1209 | ||
| 1202 | pos += written; | 1210 | pos += written; |
| 1203 | 1211 | ||
| 1204 | written_buffered = fuse_perform_write(file, mapping, from, pos); | 1212 | written_buffered = fuse_perform_write(iocb, mapping, from, pos); |
| 1205 | if (written_buffered < 0) { | 1213 | if (written_buffered < 0) { |
| 1206 | err = written_buffered; | 1214 | err = written_buffered; |
| 1207 | goto out; | 1215 | goto out; |
| @@ -1220,13 +1228,15 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 1220 | written += written_buffered; | 1228 | written += written_buffered; |
| 1221 | iocb->ki_pos = pos + written_buffered; | 1229 | iocb->ki_pos = pos + written_buffered; |
| 1222 | } else { | 1230 | } else { |
| 1223 | written = fuse_perform_write(file, mapping, from, iocb->ki_pos); | 1231 | written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos); |
| 1224 | if (written >= 0) | 1232 | if (written >= 0) |
| 1225 | iocb->ki_pos += written; | 1233 | iocb->ki_pos += written; |
| 1226 | } | 1234 | } |
| 1227 | out: | 1235 | out: |
| 1228 | current->backing_dev_info = NULL; | 1236 | current->backing_dev_info = NULL; |
| 1229 | inode_unlock(inode); | 1237 | inode_unlock(inode); |
| 1238 | if (written > 0) | ||
| 1239 | written = generic_write_sync(iocb, written); | ||
| 1230 | 1240 | ||
| 1231 | return written ? written : err; | 1241 | return written ? written : err; |
| 1232 | } | 1242 | } |
| @@ -1317,7 +1327,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, | |||
| 1317 | { | 1327 | { |
| 1318 | int write = flags & FUSE_DIO_WRITE; | 1328 | int write = flags & FUSE_DIO_WRITE; |
| 1319 | int cuse = flags & FUSE_DIO_CUSE; | 1329 | int cuse = flags & FUSE_DIO_CUSE; |
| 1320 | struct file *file = io->file; | 1330 | struct file *file = io->iocb->ki_filp; |
| 1321 | struct inode *inode = file->f_mapping->host; | 1331 | struct inode *inode = file->f_mapping->host; |
| 1322 | struct fuse_file *ff = file->private_data; | 1332 | struct fuse_file *ff = file->private_data; |
| 1323 | struct fuse_conn *fc = ff->fc; | 1333 | struct fuse_conn *fc = ff->fc; |
| @@ -1399,8 +1409,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, | |||
| 1399 | loff_t *ppos) | 1409 | loff_t *ppos) |
| 1400 | { | 1410 | { |
| 1401 | ssize_t res; | 1411 | ssize_t res; |
| 1402 | struct file *file = io->file; | 1412 | struct inode *inode = file_inode(io->iocb->ki_filp); |
| 1403 | struct inode *inode = file_inode(file); | ||
| 1404 | 1413 | ||
| 1405 | if (is_bad_inode(inode)) | 1414 | if (is_bad_inode(inode)) |
| 1406 | return -EIO; | 1415 | return -EIO; |
| @@ -1414,15 +1423,14 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, | |||
| 1414 | 1423 | ||
| 1415 | static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) | 1424 | static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) |
| 1416 | { | 1425 | { |
| 1417 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb->ki_filp); | 1426 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); |
| 1418 | return __fuse_direct_read(&io, to, &iocb->ki_pos); | 1427 | return __fuse_direct_read(&io, to, &iocb->ki_pos); |
| 1419 | } | 1428 | } |
| 1420 | 1429 | ||
| 1421 | static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | 1430 | static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) |
| 1422 | { | 1431 | { |
| 1423 | struct file *file = iocb->ki_filp; | 1432 | struct inode *inode = file_inode(iocb->ki_filp); |
| 1424 | struct inode *inode = file_inode(file); | 1433 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); |
| 1425 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file); | ||
| 1426 | ssize_t res; | 1434 | ssize_t res; |
| 1427 | 1435 | ||
| 1428 | if (is_bad_inode(inode)) | 1436 | if (is_bad_inode(inode)) |
| @@ -2181,9 +2189,6 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
| 2181 | if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX) | 2189 | if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX) |
| 2182 | return 0; | 2190 | return 0; |
| 2183 | 2191 | ||
| 2184 | if (pid && pid_nr == 0) | ||
| 2185 | return -EOVERFLOW; | ||
| 2186 | |||
| 2187 | fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg); | 2192 | fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg); |
| 2188 | err = fuse_simple_request(fc, &args); | 2193 | err = fuse_simple_request(fc, &args); |
| 2189 | 2194 | ||
| @@ -2303,7 +2308,7 @@ static loff_t fuse_lseek(struct file *file, loff_t offset, int whence) | |||
| 2303 | return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes); | 2308 | return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes); |
| 2304 | 2309 | ||
| 2305 | fallback: | 2310 | fallback: |
| 2306 | err = fuse_update_attributes(inode, NULL, file, NULL); | 2311 | err = fuse_update_attributes(inode, file); |
| 2307 | if (!err) | 2312 | if (!err) |
| 2308 | return generic_file_llseek(file, offset, whence); | 2313 | return generic_file_llseek(file, offset, whence); |
| 2309 | else | 2314 | else |
| @@ -2323,7 +2328,7 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence) | |||
| 2323 | break; | 2328 | break; |
| 2324 | case SEEK_END: | 2329 | case SEEK_END: |
| 2325 | inode_lock(inode); | 2330 | inode_lock(inode); |
| 2326 | retval = fuse_update_attributes(inode, NULL, file, NULL); | 2331 | retval = fuse_update_attributes(inode, file); |
| 2327 | if (!retval) | 2332 | if (!retval) |
| 2328 | retval = generic_file_llseek(file, offset, whence); | 2333 | retval = generic_file_llseek(file, offset, whence); |
| 2329 | inode_unlock(inode); | 2334 | inode_unlock(inode); |
| @@ -2874,7 +2879,6 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
| 2874 | io->offset = offset; | 2879 | io->offset = offset; |
| 2875 | io->write = (iov_iter_rw(iter) == WRITE); | 2880 | io->write = (iov_iter_rw(iter) == WRITE); |
| 2876 | io->err = 0; | 2881 | io->err = 0; |
| 2877 | io->file = file; | ||
| 2878 | /* | 2882 | /* |
| 2879 | * By default, we want to optimize all I/Os with async request | 2883 | * By default, we want to optimize all I/Os with async request |
| 2880 | * submission to the client filesystem if supported. | 2884 | * submission to the client filesystem if supported. |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index bd4d2a3e1ec1..d5773ca67ad2 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -252,16 +252,15 @@ struct fuse_io_priv { | |||
| 252 | bool should_dirty; | 252 | bool should_dirty; |
| 253 | int err; | 253 | int err; |
| 254 | struct kiocb *iocb; | 254 | struct kiocb *iocb; |
| 255 | struct file *file; | ||
| 256 | struct completion *done; | 255 | struct completion *done; |
| 257 | bool blocking; | 256 | bool blocking; |
| 258 | }; | 257 | }; |
| 259 | 258 | ||
| 260 | #define FUSE_IO_PRIV_SYNC(f) \ | 259 | #define FUSE_IO_PRIV_SYNC(i) \ |
| 261 | { \ | 260 | { \ |
| 262 | .refcnt = KREF_INIT(1), \ | 261 | .refcnt = KREF_INIT(1), \ |
| 263 | .async = 0, \ | 262 | .async = 0, \ |
| 264 | .file = f, \ | 263 | .iocb = i, \ |
| 265 | } | 264 | } |
| 266 | 265 | ||
| 267 | /** | 266 | /** |
| @@ -905,8 +904,7 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | |||
| 905 | 904 | ||
| 906 | void fuse_update_ctime(struct inode *inode); | 905 | void fuse_update_ctime(struct inode *inode); |
| 907 | 906 | ||
| 908 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | 907 | int fuse_update_attributes(struct inode *inode, struct file *file); |
| 909 | struct file *file, bool *refreshed); | ||
| 910 | 908 | ||
| 911 | void fuse_flush_writepages(struct inode *inode); | 909 | void fuse_flush_writepages(struct inode *inode); |
| 912 | 910 | ||
diff --git a/fs/inode.c b/fs/inode.c index 210054157a49..d1e35b53bb23 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1570,11 +1570,24 @@ EXPORT_SYMBOL(bmap); | |||
| 1570 | static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode, | 1570 | static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode, |
| 1571 | bool rcu) | 1571 | bool rcu) |
| 1572 | { | 1572 | { |
| 1573 | if (!rcu) { | 1573 | struct dentry *upperdentry; |
| 1574 | struct inode *realinode = d_real_inode(dentry); | ||
| 1575 | 1574 | ||
| 1576 | if (unlikely(inode != realinode) && | 1575 | /* |
| 1577 | (!timespec_equal(&inode->i_mtime, &realinode->i_mtime) || | 1576 | * Nothing to do if in rcu or if non-overlayfs |
| 1577 | */ | ||
| 1578 | if (rcu || likely(!(dentry->d_flags & DCACHE_OP_REAL))) | ||
| 1579 | return; | ||
| 1580 | |||
| 1581 | upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER); | ||
| 1582 | |||
| 1583 | /* | ||
| 1584 | * If file is on lower then we can't update atime, so no worries about | ||
| 1585 | * stale mtime/ctime. | ||
| 1586 | */ | ||
| 1587 | if (upperdentry) { | ||
| 1588 | struct inode *realinode = d_inode(upperdentry); | ||
| 1589 | |||
| 1590 | if ((!timespec_equal(&inode->i_mtime, &realinode->i_mtime) || | ||
| 1578 | !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) { | 1591 | !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) { |
| 1579 | inode->i_mtime = realinode->i_mtime; | 1592 | inode->i_mtime = realinode->i_mtime; |
| 1580 | inode->i_ctime = realinode->i_ctime; | 1593 | inode->i_ctime = realinode->i_ctime; |
diff --git a/fs/internal.h b/fs/internal.h index fedfe94d84ba..48cee21b4f14 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -71,8 +71,10 @@ extern void __init mnt_init(void); | |||
| 71 | 71 | ||
| 72 | extern int __mnt_want_write(struct vfsmount *); | 72 | extern int __mnt_want_write(struct vfsmount *); |
| 73 | extern int __mnt_want_write_file(struct file *); | 73 | extern int __mnt_want_write_file(struct file *); |
| 74 | extern int mnt_want_write_file_path(struct file *); | ||
| 74 | extern void __mnt_drop_write(struct vfsmount *); | 75 | extern void __mnt_drop_write(struct vfsmount *); |
| 75 | extern void __mnt_drop_write_file(struct file *); | 76 | extern void __mnt_drop_write_file(struct file *); |
| 77 | extern void mnt_drop_write_file_path(struct file *); | ||
| 76 | 78 | ||
| 77 | /* | 79 | /* |
| 78 | * fs_struct.c | 80 | * fs_struct.c |
diff --git a/fs/namespace.c b/fs/namespace.c index f8893dc6a989..df0f7521979a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -431,13 +431,18 @@ int __mnt_want_write_file(struct file *file) | |||
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | /** | 433 | /** |
| 434 | * mnt_want_write_file - get write access to a file's mount | 434 | * mnt_want_write_file_path - get write access to a file's mount |
| 435 | * @file: the file who's mount on which to take a write | 435 | * @file: the file who's mount on which to take a write |
| 436 | * | 436 | * |
| 437 | * This is like mnt_want_write, but it takes a file and can | 437 | * This is like mnt_want_write, but it takes a file and can |
| 438 | * do some optimisations if the file is open for write already | 438 | * do some optimisations if the file is open for write already |
| 439 | * | ||
| 440 | * Called by the vfs for cases when we have an open file at hand, but will do an | ||
| 441 | * inode operation on it (important distinction for files opened on overlayfs, | ||
| 442 | * since the file operations will come from the real underlying file, while | ||
| 443 | * inode operations come from the overlay). | ||
| 439 | */ | 444 | */ |
| 440 | int mnt_want_write_file(struct file *file) | 445 | int mnt_want_write_file_path(struct file *file) |
| 441 | { | 446 | { |
| 442 | int ret; | 447 | int ret; |
| 443 | 448 | ||
| @@ -447,6 +452,53 @@ int mnt_want_write_file(struct file *file) | |||
| 447 | sb_end_write(file->f_path.mnt->mnt_sb); | 452 | sb_end_write(file->f_path.mnt->mnt_sb); |
| 448 | return ret; | 453 | return ret; |
| 449 | } | 454 | } |
| 455 | |||
| 456 | static inline int may_write_real(struct file *file) | ||
| 457 | { | ||
| 458 | struct dentry *dentry = file->f_path.dentry; | ||
| 459 | struct dentry *upperdentry; | ||
| 460 | |||
| 461 | /* Writable file? */ | ||
| 462 | if (file->f_mode & FMODE_WRITER) | ||
| 463 | return 0; | ||
| 464 | |||
| 465 | /* Not overlayfs? */ | ||
| 466 | if (likely(!(dentry->d_flags & DCACHE_OP_REAL))) | ||
| 467 | return 0; | ||
| 468 | |||
| 469 | /* File refers to upper, writable layer? */ | ||
| 470 | upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER); | ||
| 471 | if (upperdentry && file_inode(file) == d_inode(upperdentry)) | ||
| 472 | return 0; | ||
| 473 | |||
| 474 | /* Lower layer: can't write to real file, sorry... */ | ||
| 475 | return -EPERM; | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * mnt_want_write_file - get write access to a file's mount | ||
| 480 | * @file: the file who's mount on which to take a write | ||
| 481 | * | ||
| 482 | * This is like mnt_want_write, but it takes a file and can | ||
| 483 | * do some optimisations if the file is open for write already | ||
| 484 | * | ||
| 485 | * Mostly called by filesystems from their ioctl operation before performing | ||
| 486 | * modification. On overlayfs this needs to check if the file is on a read-only | ||
| 487 | * lower layer and deny access in that case. | ||
| 488 | */ | ||
| 489 | int mnt_want_write_file(struct file *file) | ||
| 490 | { | ||
| 491 | int ret; | ||
| 492 | |||
| 493 | ret = may_write_real(file); | ||
| 494 | if (!ret) { | ||
| 495 | sb_start_write(file_inode(file)->i_sb); | ||
| 496 | ret = __mnt_want_write_file(file); | ||
| 497 | if (ret) | ||
| 498 | sb_end_write(file_inode(file)->i_sb); | ||
| 499 | } | ||
| 500 | return ret; | ||
| 501 | } | ||
| 450 | EXPORT_SYMBOL_GPL(mnt_want_write_file); | 502 | EXPORT_SYMBOL_GPL(mnt_want_write_file); |
| 451 | 503 | ||
| 452 | /** | 504 | /** |
| @@ -484,10 +536,16 @@ void __mnt_drop_write_file(struct file *file) | |||
| 484 | __mnt_drop_write(file->f_path.mnt); | 536 | __mnt_drop_write(file->f_path.mnt); |
| 485 | } | 537 | } |
| 486 | 538 | ||
| 487 | void mnt_drop_write_file(struct file *file) | 539 | void mnt_drop_write_file_path(struct file *file) |
| 488 | { | 540 | { |
| 489 | mnt_drop_write(file->f_path.mnt); | 541 | mnt_drop_write(file->f_path.mnt); |
| 490 | } | 542 | } |
| 543 | |||
| 544 | void mnt_drop_write_file(struct file *file) | ||
| 545 | { | ||
| 546 | __mnt_drop_write(file->f_path.mnt); | ||
| 547 | sb_end_write(file_inode(file)->i_sb); | ||
| 548 | } | ||
| 491 | EXPORT_SYMBOL(mnt_drop_write_file); | 549 | EXPORT_SYMBOL(mnt_drop_write_file); |
| 492 | 550 | ||
| 493 | static int mnt_make_readonly(struct mount *mnt) | 551 | static int mnt_make_readonly(struct mount *mnt) |
| @@ -96,7 +96,7 @@ long vfs_truncate(const struct path *path, loff_t length) | |||
| 96 | * write access on the upper inode, not on the overlay inode. For | 96 | * write access on the upper inode, not on the overlay inode. For |
| 97 | * non-overlay filesystems d_real() is an identity function. | 97 | * non-overlay filesystems d_real() is an identity function. |
| 98 | */ | 98 | */ |
| 99 | upperdentry = d_real(path->dentry, NULL, O_WRONLY); | 99 | upperdentry = d_real(path->dentry, NULL, O_WRONLY, 0); |
| 100 | error = PTR_ERR(upperdentry); | 100 | error = PTR_ERR(upperdentry); |
| 101 | if (IS_ERR(upperdentry)) | 101 | if (IS_ERR(upperdentry)) |
| 102 | goto mnt_drop_write_and_out; | 102 | goto mnt_drop_write_and_out; |
| @@ -670,12 +670,12 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
| 670 | if (!f.file) | 670 | if (!f.file) |
| 671 | goto out; | 671 | goto out; |
| 672 | 672 | ||
| 673 | error = mnt_want_write_file(f.file); | 673 | error = mnt_want_write_file_path(f.file); |
| 674 | if (error) | 674 | if (error) |
| 675 | goto out_fput; | 675 | goto out_fput; |
| 676 | audit_file(f.file); | 676 | audit_file(f.file); |
| 677 | error = chown_common(&f.file->f_path, user, group); | 677 | error = chown_common(&f.file->f_path, user, group); |
| 678 | mnt_drop_write_file(f.file); | 678 | mnt_drop_write_file_path(f.file); |
| 679 | out_fput: | 679 | out_fput: |
| 680 | fdput(f); | 680 | fdput(f); |
| 681 | out: | 681 | out: |
| @@ -857,7 +857,7 @@ EXPORT_SYMBOL(file_path); | |||
| 857 | int vfs_open(const struct path *path, struct file *file, | 857 | int vfs_open(const struct path *path, struct file *file, |
| 858 | const struct cred *cred) | 858 | const struct cred *cred) |
| 859 | { | 859 | { |
| 860 | struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags); | 860 | struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags, 0); |
| 861 | 861 | ||
| 862 | if (IS_ERR(dentry)) | 862 | if (IS_ERR(dentry)) |
| 863 | return PTR_ERR(dentry); | 863 | return PTR_ERR(dentry); |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 48b70e6490f3..9cb0c80e5967 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
| @@ -155,7 +155,7 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) | |||
| 155 | static void ovl_instantiate(struct dentry *dentry, struct inode *inode, | 155 | static void ovl_instantiate(struct dentry *dentry, struct inode *inode, |
| 156 | struct dentry *newdentry, bool hardlink) | 156 | struct dentry *newdentry, bool hardlink) |
| 157 | { | 157 | { |
| 158 | ovl_dentry_version_inc(dentry->d_parent); | 158 | ovl_dentry_version_inc(dentry->d_parent, false); |
| 159 | ovl_dentry_set_upper_alias(dentry); | 159 | ovl_dentry_set_upper_alias(dentry); |
| 160 | if (!hardlink) { | 160 | if (!hardlink) { |
| 161 | ovl_inode_update(inode, newdentry); | 161 | ovl_inode_update(inode, newdentry); |
| @@ -692,7 +692,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) | |||
| 692 | if (flags) | 692 | if (flags) |
| 693 | ovl_cleanup(wdir, upper); | 693 | ovl_cleanup(wdir, upper); |
| 694 | 694 | ||
| 695 | ovl_dentry_version_inc(dentry->d_parent); | 695 | ovl_dentry_version_inc(dentry->d_parent, true); |
| 696 | out_d_drop: | 696 | out_d_drop: |
| 697 | d_drop(dentry); | 697 | d_drop(dentry); |
| 698 | dput(whiteout); | 698 | dput(whiteout); |
| @@ -742,7 +742,7 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) | |||
| 742 | err = vfs_rmdir(dir, upper); | 742 | err = vfs_rmdir(dir, upper); |
| 743 | else | 743 | else |
| 744 | err = vfs_unlink(dir, upper, NULL); | 744 | err = vfs_unlink(dir, upper, NULL); |
| 745 | ovl_dentry_version_inc(dentry->d_parent); | 745 | ovl_dentry_version_inc(dentry->d_parent, ovl_type_origin(dentry)); |
| 746 | 746 | ||
| 747 | /* | 747 | /* |
| 748 | * Keeping this dentry hashed would mean having to release | 748 | * Keeping this dentry hashed would mean having to release |
| @@ -1089,8 +1089,9 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, | |||
| 1089 | drop_nlink(d_inode(new)); | 1089 | drop_nlink(d_inode(new)); |
| 1090 | } | 1090 | } |
| 1091 | 1091 | ||
| 1092 | ovl_dentry_version_inc(old->d_parent); | 1092 | ovl_dentry_version_inc(old->d_parent, |
| 1093 | ovl_dentry_version_inc(new->d_parent); | 1093 | !overwrite && ovl_type_origin(new)); |
| 1094 | ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old)); | ||
| 1094 | 1095 | ||
| 1095 | out_dput: | 1096 | out_dput: |
| 1096 | dput(newdentry); | 1097 | dput(newdentry); |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 5bc71642b226..a619addecafc 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
| @@ -498,6 +498,9 @@ static int ovl_set_nlink_common(struct dentry *dentry, | |||
| 498 | len = snprintf(buf, sizeof(buf), format, | 498 | len = snprintf(buf, sizeof(buf), format, |
| 499 | (int) (inode->i_nlink - realinode->i_nlink)); | 499 | (int) (inode->i_nlink - realinode->i_nlink)); |
| 500 | 500 | ||
| 501 | if (WARN_ON(len >= sizeof(buf))) | ||
| 502 | return -EIO; | ||
| 503 | |||
| 501 | return ovl_do_setxattr(ovl_dentry_upper(dentry), | 504 | return ovl_do_setxattr(ovl_dentry_upper(dentry), |
| 502 | OVL_XATTR_NLINK, buf, len, 0); | 505 | OVL_XATTR_NLINK, buf, len, 0); |
| 503 | } | 506 | } |
| @@ -576,10 +579,13 @@ static int ovl_inode_set(struct inode *inode, void *data) | |||
| 576 | static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, | 579 | static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, |
| 577 | struct dentry *upperdentry) | 580 | struct dentry *upperdentry) |
| 578 | { | 581 | { |
| 579 | struct inode *lowerinode = lowerdentry ? d_inode(lowerdentry) : NULL; | 582 | /* |
| 580 | 583 | * Allow non-NULL lower inode in ovl_inode even if lowerdentry is NULL. | |
| 581 | /* Lower (origin) inode must match, even if NULL */ | 584 | * This happens when finding a copied up overlay inode for a renamed |
| 582 | if (ovl_inode_lower(inode) != lowerinode) | 585 | * or hardlinked overlay dentry and lower dentry cannot be followed |
| 586 | * by origin because lower fs does not support file handles. | ||
| 587 | */ | ||
| 588 | if (lowerdentry && ovl_inode_lower(inode) != d_inode(lowerdentry)) | ||
| 583 | return false; | 589 | return false; |
| 584 | 590 | ||
| 585 | /* | 591 | /* |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index e927a62c97ae..d4e8c1a08fb0 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
| @@ -204,8 +204,8 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode); | |||
| 204 | struct inode *ovl_inode_upper(struct inode *inode); | 204 | struct inode *ovl_inode_upper(struct inode *inode); |
| 205 | struct inode *ovl_inode_lower(struct inode *inode); | 205 | struct inode *ovl_inode_lower(struct inode *inode); |
| 206 | struct inode *ovl_inode_real(struct inode *inode); | 206 | struct inode *ovl_inode_real(struct inode *inode); |
| 207 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); | 207 | struct ovl_dir_cache *ovl_dir_cache(struct inode *inode); |
| 208 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); | 208 | void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache); |
| 209 | bool ovl_dentry_is_opaque(struct dentry *dentry); | 209 | bool ovl_dentry_is_opaque(struct dentry *dentry); |
| 210 | bool ovl_dentry_is_whiteout(struct dentry *dentry); | 210 | bool ovl_dentry_is_whiteout(struct dentry *dentry); |
| 211 | void ovl_dentry_set_opaque(struct dentry *dentry); | 211 | void ovl_dentry_set_opaque(struct dentry *dentry); |
| @@ -217,7 +217,7 @@ void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); | |||
| 217 | void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, | 217 | void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, |
| 218 | struct dentry *lowerdentry); | 218 | struct dentry *lowerdentry); |
| 219 | void ovl_inode_update(struct inode *inode, struct dentry *upperdentry); | 219 | void ovl_inode_update(struct inode *inode, struct dentry *upperdentry); |
| 220 | void ovl_dentry_version_inc(struct dentry *dentry); | 220 | void ovl_dentry_version_inc(struct dentry *dentry, bool impurity); |
| 221 | u64 ovl_dentry_version_get(struct dentry *dentry); | 221 | u64 ovl_dentry_version_get(struct dentry *dentry); |
| 222 | bool ovl_is_whiteout(struct dentry *dentry); | 222 | bool ovl_is_whiteout(struct dentry *dentry); |
| 223 | struct file *ovl_path_open(struct path *path, int flags); | 223 | struct file *ovl_path_open(struct path *path, int flags); |
| @@ -229,6 +229,7 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, | |||
| 229 | int xerr); | 229 | int xerr); |
| 230 | int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry); | 230 | int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry); |
| 231 | void ovl_set_flag(unsigned long flag, struct inode *inode); | 231 | void ovl_set_flag(unsigned long flag, struct inode *inode); |
| 232 | void ovl_clear_flag(unsigned long flag, struct inode *inode); | ||
| 232 | bool ovl_test_flag(unsigned long flag, struct inode *inode); | 233 | bool ovl_test_flag(unsigned long flag, struct inode *inode); |
| 233 | bool ovl_inuse_trylock(struct dentry *dentry); | 234 | bool ovl_inuse_trylock(struct dentry *dentry); |
| 234 | void ovl_inuse_unlock(struct dentry *dentry); | 235 | void ovl_inuse_unlock(struct dentry *dentry); |
| @@ -256,6 +257,7 @@ extern const struct file_operations ovl_dir_operations; | |||
| 256 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); | 257 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); |
| 257 | void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); | 258 | void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); |
| 258 | void ovl_cache_free(struct list_head *list); | 259 | void ovl_cache_free(struct list_head *list); |
| 260 | void ovl_dir_cache_free(struct inode *inode); | ||
| 259 | int ovl_check_d_type_supported(struct path *realpath); | 261 | int ovl_check_d_type_supported(struct path *realpath); |
| 260 | void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, | 262 | void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, |
| 261 | struct dentry *dentry, int level); | 263 | struct dentry *dentry, int level); |
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index f0fd3adb1693..62e9b22a2077 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
| @@ -15,11 +15,13 @@ | |||
| 15 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
| 16 | #include <linux/security.h> | 16 | #include <linux/security.h> |
| 17 | #include <linux/cred.h> | 17 | #include <linux/cred.h> |
| 18 | #include <linux/ratelimit.h> | ||
| 18 | #include "overlayfs.h" | 19 | #include "overlayfs.h" |
| 19 | 20 | ||
| 20 | struct ovl_cache_entry { | 21 | struct ovl_cache_entry { |
| 21 | unsigned int len; | 22 | unsigned int len; |
| 22 | unsigned int type; | 23 | unsigned int type; |
| 24 | u64 real_ino; | ||
| 23 | u64 ino; | 25 | u64 ino; |
| 24 | struct list_head l_node; | 26 | struct list_head l_node; |
| 25 | struct rb_node node; | 27 | struct rb_node node; |
| @@ -32,18 +34,20 @@ struct ovl_dir_cache { | |||
| 32 | long refcount; | 34 | long refcount; |
| 33 | u64 version; | 35 | u64 version; |
| 34 | struct list_head entries; | 36 | struct list_head entries; |
| 37 | struct rb_root root; | ||
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| 37 | struct ovl_readdir_data { | 40 | struct ovl_readdir_data { |
| 38 | struct dir_context ctx; | 41 | struct dir_context ctx; |
| 39 | struct dentry *dentry; | 42 | struct dentry *dentry; |
| 40 | bool is_lowest; | 43 | bool is_lowest; |
| 41 | struct rb_root root; | 44 | struct rb_root *root; |
| 42 | struct list_head *list; | 45 | struct list_head *list; |
| 43 | struct list_head middle; | 46 | struct list_head middle; |
| 44 | struct ovl_cache_entry *first_maybe_whiteout; | 47 | struct ovl_cache_entry *first_maybe_whiteout; |
| 45 | int count; | 48 | int count; |
| 46 | int err; | 49 | int err; |
| 50 | bool is_upper; | ||
| 47 | bool d_type_supported; | 51 | bool d_type_supported; |
| 48 | }; | 52 | }; |
| 49 | 53 | ||
| @@ -58,7 +62,33 @@ struct ovl_dir_file { | |||
| 58 | 62 | ||
| 59 | static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n) | 63 | static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n) |
| 60 | { | 64 | { |
| 61 | return container_of(n, struct ovl_cache_entry, node); | 65 | return rb_entry(n, struct ovl_cache_entry, node); |
| 66 | } | ||
| 67 | |||
| 68 | static bool ovl_cache_entry_find_link(const char *name, int len, | ||
| 69 | struct rb_node ***link, | ||
| 70 | struct rb_node **parent) | ||
| 71 | { | ||
| 72 | bool found = false; | ||
| 73 | struct rb_node **newp = *link; | ||
| 74 | |||
| 75 | while (!found && *newp) { | ||
| 76 | int cmp; | ||
| 77 | struct ovl_cache_entry *tmp; | ||
| 78 | |||
| 79 | *parent = *newp; | ||
| 80 | tmp = ovl_cache_entry_from_node(*newp); | ||
| 81 | cmp = strncmp(name, tmp->name, len); | ||
| 82 | if (cmp > 0) | ||
| 83 | newp = &tmp->node.rb_right; | ||
| 84 | else if (cmp < 0 || len < tmp->len) | ||
| 85 | newp = &tmp->node.rb_left; | ||
| 86 | else | ||
| 87 | found = true; | ||
| 88 | } | ||
| 89 | *link = newp; | ||
| 90 | |||
| 91 | return found; | ||
| 62 | } | 92 | } |
| 63 | 93 | ||
| 64 | static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, | 94 | static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, |
| @@ -82,6 +112,32 @@ static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, | |||
| 82 | return NULL; | 112 | return NULL; |
| 83 | } | 113 | } |
| 84 | 114 | ||
| 115 | static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd, | ||
| 116 | struct ovl_cache_entry *p) | ||
| 117 | { | ||
| 118 | /* Don't care if not doing ovl_iter() */ | ||
| 119 | if (!rdd->dentry) | ||
| 120 | return false; | ||
| 121 | |||
| 122 | /* Always recalc d_ino for parent */ | ||
| 123 | if (strcmp(p->name, "..") == 0) | ||
| 124 | return true; | ||
| 125 | |||
| 126 | /* If this is lower, then native d_ino will do */ | ||
| 127 | if (!rdd->is_upper) | ||
| 128 | return false; | ||
| 129 | |||
| 130 | /* | ||
| 131 | * Recalc d_ino for '.' and for all entries if dir is impure (contains | ||
| 132 | * copied up entries) | ||
| 133 | */ | ||
| 134 | if ((p->name[0] == '.' && p->len == 1) || | ||
| 135 | ovl_test_flag(OVL_IMPURE, d_inode(rdd->dentry))) | ||
| 136 | return true; | ||
| 137 | |||
| 138 | return false; | ||
| 139 | } | ||
| 140 | |||
| 85 | static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd, | 141 | static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd, |
| 86 | const char *name, int len, | 142 | const char *name, int len, |
| 87 | u64 ino, unsigned int d_type) | 143 | u64 ino, unsigned int d_type) |
| @@ -97,7 +153,11 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd, | |||
| 97 | p->name[len] = '\0'; | 153 | p->name[len] = '\0'; |
| 98 | p->len = len; | 154 | p->len = len; |
| 99 | p->type = d_type; | 155 | p->type = d_type; |
| 156 | p->real_ino = ino; | ||
| 100 | p->ino = ino; | 157 | p->ino = ino; |
| 158 | /* Defer setting d_ino for upper entry to ovl_iterate() */ | ||
| 159 | if (ovl_calc_d_ino(rdd, p)) | ||
| 160 | p->ino = 0; | ||
| 101 | p->is_whiteout = false; | 161 | p->is_whiteout = false; |
| 102 | 162 | ||
| 103 | if (d_type == DT_CHR) { | 163 | if (d_type == DT_CHR) { |
| @@ -111,32 +171,22 @@ static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, | |||
| 111 | const char *name, int len, u64 ino, | 171 | const char *name, int len, u64 ino, |
| 112 | unsigned int d_type) | 172 | unsigned int d_type) |
| 113 | { | 173 | { |
| 114 | struct rb_node **newp = &rdd->root.rb_node; | 174 | struct rb_node **newp = &rdd->root->rb_node; |
| 115 | struct rb_node *parent = NULL; | 175 | struct rb_node *parent = NULL; |
| 116 | struct ovl_cache_entry *p; | 176 | struct ovl_cache_entry *p; |
| 117 | 177 | ||
| 118 | while (*newp) { | 178 | if (ovl_cache_entry_find_link(name, len, &newp, &parent)) |
| 119 | int cmp; | 179 | return 0; |
| 120 | struct ovl_cache_entry *tmp; | ||
| 121 | |||
| 122 | parent = *newp; | ||
| 123 | tmp = ovl_cache_entry_from_node(*newp); | ||
| 124 | cmp = strncmp(name, tmp->name, len); | ||
| 125 | if (cmp > 0) | ||
| 126 | newp = &tmp->node.rb_right; | ||
| 127 | else if (cmp < 0 || len < tmp->len) | ||
| 128 | newp = &tmp->node.rb_left; | ||
| 129 | else | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | 180 | ||
| 133 | p = ovl_cache_entry_new(rdd, name, len, ino, d_type); | 181 | p = ovl_cache_entry_new(rdd, name, len, ino, d_type); |
| 134 | if (p == NULL) | 182 | if (p == NULL) { |
| 183 | rdd->err = -ENOMEM; | ||
| 135 | return -ENOMEM; | 184 | return -ENOMEM; |
| 185 | } | ||
| 136 | 186 | ||
| 137 | list_add_tail(&p->l_node, rdd->list); | 187 | list_add_tail(&p->l_node, rdd->list); |
| 138 | rb_link_node(&p->node, parent, newp); | 188 | rb_link_node(&p->node, parent, newp); |
| 139 | rb_insert_color(&p->node, &rdd->root); | 189 | rb_insert_color(&p->node, rdd->root); |
| 140 | 190 | ||
| 141 | return 0; | 191 | return 0; |
| 142 | } | 192 | } |
| @@ -147,7 +197,7 @@ static int ovl_fill_lowest(struct ovl_readdir_data *rdd, | |||
| 147 | { | 197 | { |
| 148 | struct ovl_cache_entry *p; | 198 | struct ovl_cache_entry *p; |
| 149 | 199 | ||
| 150 | p = ovl_cache_entry_find(&rdd->root, name, namelen); | 200 | p = ovl_cache_entry_find(rdd->root, name, namelen); |
| 151 | if (p) { | 201 | if (p) { |
| 152 | list_move_tail(&p->l_node, &rdd->middle); | 202 | list_move_tail(&p->l_node, &rdd->middle); |
| 153 | } else { | 203 | } else { |
| @@ -172,6 +222,16 @@ void ovl_cache_free(struct list_head *list) | |||
| 172 | INIT_LIST_HEAD(list); | 222 | INIT_LIST_HEAD(list); |
| 173 | } | 223 | } |
| 174 | 224 | ||
| 225 | void ovl_dir_cache_free(struct inode *inode) | ||
| 226 | { | ||
| 227 | struct ovl_dir_cache *cache = ovl_dir_cache(inode); | ||
| 228 | |||
| 229 | if (cache) { | ||
| 230 | ovl_cache_free(&cache->entries); | ||
| 231 | kfree(cache); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 175 | static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) | 235 | static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) |
| 176 | { | 236 | { |
| 177 | struct ovl_dir_cache *cache = od->cache; | 237 | struct ovl_dir_cache *cache = od->cache; |
| @@ -179,8 +239,8 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) | |||
| 179 | WARN_ON(cache->refcount <= 0); | 239 | WARN_ON(cache->refcount <= 0); |
| 180 | cache->refcount--; | 240 | cache->refcount--; |
| 181 | if (!cache->refcount) { | 241 | if (!cache->refcount) { |
| 182 | if (ovl_dir_cache(dentry) == cache) | 242 | if (ovl_dir_cache(d_inode(dentry)) == cache) |
| 183 | ovl_set_dir_cache(dentry, NULL); | 243 | ovl_set_dir_cache(d_inode(dentry), NULL); |
| 184 | 244 | ||
| 185 | ovl_cache_free(&cache->entries); | 245 | ovl_cache_free(&cache->entries); |
| 186 | kfree(cache); | 246 | kfree(cache); |
| @@ -273,7 +333,8 @@ static void ovl_dir_reset(struct file *file) | |||
| 273 | od->is_real = false; | 333 | od->is_real = false; |
| 274 | } | 334 | } |
| 275 | 335 | ||
| 276 | static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) | 336 | static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list, |
| 337 | struct rb_root *root) | ||
| 277 | { | 338 | { |
| 278 | int err; | 339 | int err; |
| 279 | struct path realpath; | 340 | struct path realpath; |
| @@ -281,13 +342,14 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) | |||
| 281 | .ctx.actor = ovl_fill_merge, | 342 | .ctx.actor = ovl_fill_merge, |
| 282 | .dentry = dentry, | 343 | .dentry = dentry, |
| 283 | .list = list, | 344 | .list = list, |
| 284 | .root = RB_ROOT, | 345 | .root = root, |
| 285 | .is_lowest = false, | 346 | .is_lowest = false, |
| 286 | }; | 347 | }; |
| 287 | int idx, next; | 348 | int idx, next; |
| 288 | 349 | ||
| 289 | for (idx = 0; idx != -1; idx = next) { | 350 | for (idx = 0; idx != -1; idx = next) { |
| 290 | next = ovl_path_next(idx, dentry, &realpath); | 351 | next = ovl_path_next(idx, dentry, &realpath); |
| 352 | rdd.is_upper = ovl_dentry_upper(dentry) == realpath.dentry; | ||
| 291 | 353 | ||
| 292 | if (next != -1) { | 354 | if (next != -1) { |
| 293 | err = ovl_dir_read(&realpath, &rdd); | 355 | err = ovl_dir_read(&realpath, &rdd); |
| @@ -326,12 +388,13 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | |||
| 326 | int res; | 388 | int res; |
| 327 | struct ovl_dir_cache *cache; | 389 | struct ovl_dir_cache *cache; |
| 328 | 390 | ||
| 329 | cache = ovl_dir_cache(dentry); | 391 | cache = ovl_dir_cache(d_inode(dentry)); |
| 330 | if (cache && ovl_dentry_version_get(dentry) == cache->version) { | 392 | if (cache && ovl_dentry_version_get(dentry) == cache->version) { |
| 393 | WARN_ON(!cache->refcount); | ||
| 331 | cache->refcount++; | 394 | cache->refcount++; |
| 332 | return cache; | 395 | return cache; |
| 333 | } | 396 | } |
| 334 | ovl_set_dir_cache(dentry, NULL); | 397 | ovl_set_dir_cache(d_inode(dentry), NULL); |
| 335 | 398 | ||
| 336 | cache = kzalloc(sizeof(struct ovl_dir_cache), GFP_KERNEL); | 399 | cache = kzalloc(sizeof(struct ovl_dir_cache), GFP_KERNEL); |
| 337 | if (!cache) | 400 | if (!cache) |
| @@ -339,8 +402,9 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | |||
| 339 | 402 | ||
| 340 | cache->refcount = 1; | 403 | cache->refcount = 1; |
| 341 | INIT_LIST_HEAD(&cache->entries); | 404 | INIT_LIST_HEAD(&cache->entries); |
| 405 | cache->root = RB_ROOT; | ||
| 342 | 406 | ||
| 343 | res = ovl_dir_read_merged(dentry, &cache->entries); | 407 | res = ovl_dir_read_merged(dentry, &cache->entries, &cache->root); |
| 344 | if (res) { | 408 | if (res) { |
| 345 | ovl_cache_free(&cache->entries); | 409 | ovl_cache_free(&cache->entries); |
| 346 | kfree(cache); | 410 | kfree(cache); |
| @@ -348,22 +412,266 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | |||
| 348 | } | 412 | } |
| 349 | 413 | ||
| 350 | cache->version = ovl_dentry_version_get(dentry); | 414 | cache->version = ovl_dentry_version_get(dentry); |
| 351 | ovl_set_dir_cache(dentry, cache); | 415 | ovl_set_dir_cache(d_inode(dentry), cache); |
| 352 | 416 | ||
| 353 | return cache; | 417 | return cache; |
| 354 | } | 418 | } |
| 355 | 419 | ||
| 420 | /* | ||
| 421 | * Set d_ino for upper entries. Non-upper entries should always report | ||
| 422 | * the uppermost real inode ino and should not call this function. | ||
| 423 | * | ||
| 424 | * When not all layer are on same fs, report real ino also for upper. | ||
| 425 | * | ||
| 426 | * When all layers are on the same fs, and upper has a reference to | ||
| 427 | * copy up origin, call vfs_getattr() on the overlay entry to make | ||
| 428 | * sure that d_ino will be consistent with st_ino from stat(2). | ||
| 429 | */ | ||
| 430 | static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p) | ||
| 431 | |||
| 432 | { | ||
| 433 | struct dentry *dir = path->dentry; | ||
| 434 | struct dentry *this = NULL; | ||
| 435 | enum ovl_path_type type; | ||
| 436 | u64 ino = p->real_ino; | ||
| 437 | int err = 0; | ||
| 438 | |||
| 439 | if (!ovl_same_sb(dir->d_sb)) | ||
| 440 | goto out; | ||
| 441 | |||
| 442 | if (p->name[0] == '.') { | ||
| 443 | if (p->len == 1) { | ||
| 444 | this = dget(dir); | ||
| 445 | goto get; | ||
| 446 | } | ||
| 447 | if (p->len == 2 && p->name[1] == '.') { | ||
| 448 | /* we shall not be moved */ | ||
| 449 | this = dget(dir->d_parent); | ||
| 450 | goto get; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | this = lookup_one_len(p->name, dir, p->len); | ||
| 454 | if (IS_ERR_OR_NULL(this) || !this->d_inode) { | ||
| 455 | if (IS_ERR(this)) { | ||
| 456 | err = PTR_ERR(this); | ||
| 457 | this = NULL; | ||
| 458 | goto fail; | ||
| 459 | } | ||
| 460 | goto out; | ||
| 461 | } | ||
| 462 | |||
| 463 | get: | ||
| 464 | type = ovl_path_type(this); | ||
| 465 | if (OVL_TYPE_ORIGIN(type)) { | ||
| 466 | struct kstat stat; | ||
| 467 | struct path statpath = *path; | ||
| 468 | |||
| 469 | statpath.dentry = this; | ||
| 470 | err = vfs_getattr(&statpath, &stat, STATX_INO, 0); | ||
| 471 | if (err) | ||
| 472 | goto fail; | ||
| 473 | |||
| 474 | WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev); | ||
| 475 | ino = stat.ino; | ||
| 476 | } | ||
| 477 | |||
| 478 | out: | ||
| 479 | p->ino = ino; | ||
| 480 | dput(this); | ||
| 481 | return err; | ||
| 482 | |||
| 483 | fail: | ||
| 484 | pr_warn_ratelimited("overlay: failed to look up (%s) for ino (%i)\n", | ||
| 485 | p->name, err); | ||
| 486 | goto out; | ||
| 487 | } | ||
| 488 | |||
| 489 | static int ovl_fill_plain(struct dir_context *ctx, const char *name, | ||
| 490 | int namelen, loff_t offset, u64 ino, | ||
| 491 | unsigned int d_type) | ||
| 492 | { | ||
| 493 | struct ovl_cache_entry *p; | ||
| 494 | struct ovl_readdir_data *rdd = | ||
| 495 | container_of(ctx, struct ovl_readdir_data, ctx); | ||
| 496 | |||
| 497 | rdd->count++; | ||
| 498 | p = ovl_cache_entry_new(rdd, name, namelen, ino, d_type); | ||
| 499 | if (p == NULL) { | ||
| 500 | rdd->err = -ENOMEM; | ||
| 501 | return -ENOMEM; | ||
| 502 | } | ||
| 503 | list_add_tail(&p->l_node, rdd->list); | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static int ovl_dir_read_impure(struct path *path, struct list_head *list, | ||
| 509 | struct rb_root *root) | ||
| 510 | { | ||
| 511 | int err; | ||
| 512 | struct path realpath; | ||
| 513 | struct ovl_cache_entry *p, *n; | ||
| 514 | struct ovl_readdir_data rdd = { | ||
| 515 | .ctx.actor = ovl_fill_plain, | ||
| 516 | .list = list, | ||
| 517 | .root = root, | ||
| 518 | }; | ||
| 519 | |||
| 520 | INIT_LIST_HEAD(list); | ||
| 521 | *root = RB_ROOT; | ||
| 522 | ovl_path_upper(path->dentry, &realpath); | ||
| 523 | |||
| 524 | err = ovl_dir_read(&realpath, &rdd); | ||
| 525 | if (err) | ||
| 526 | return err; | ||
| 527 | |||
| 528 | list_for_each_entry_safe(p, n, list, l_node) { | ||
| 529 | if (strcmp(p->name, ".") != 0 && | ||
| 530 | strcmp(p->name, "..") != 0) { | ||
| 531 | err = ovl_cache_update_ino(path, p); | ||
| 532 | if (err) | ||
| 533 | return err; | ||
| 534 | } | ||
| 535 | if (p->ino == p->real_ino) { | ||
| 536 | list_del(&p->l_node); | ||
| 537 | kfree(p); | ||
| 538 | } else { | ||
| 539 | struct rb_node **newp = &root->rb_node; | ||
| 540 | struct rb_node *parent = NULL; | ||
| 541 | |||
| 542 | if (WARN_ON(ovl_cache_entry_find_link(p->name, p->len, | ||
| 543 | &newp, &parent))) | ||
| 544 | return -EIO; | ||
| 545 | |||
| 546 | rb_link_node(&p->node, parent, newp); | ||
| 547 | rb_insert_color(&p->node, root); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) | ||
| 554 | { | ||
| 555 | int res; | ||
| 556 | struct dentry *dentry = path->dentry; | ||
| 557 | struct ovl_dir_cache *cache; | ||
| 558 | |||
| 559 | cache = ovl_dir_cache(d_inode(dentry)); | ||
| 560 | if (cache && ovl_dentry_version_get(dentry) == cache->version) | ||
| 561 | return cache; | ||
| 562 | |||
| 563 | /* Impure cache is not refcounted, free it here */ | ||
| 564 | ovl_dir_cache_free(d_inode(dentry)); | ||
| 565 | ovl_set_dir_cache(d_inode(dentry), NULL); | ||
| 566 | |||
| 567 | cache = kzalloc(sizeof(struct ovl_dir_cache), GFP_KERNEL); | ||
| 568 | if (!cache) | ||
| 569 | return ERR_PTR(-ENOMEM); | ||
| 570 | |||
| 571 | res = ovl_dir_read_impure(path, &cache->entries, &cache->root); | ||
| 572 | if (res) { | ||
| 573 | ovl_cache_free(&cache->entries); | ||
| 574 | kfree(cache); | ||
| 575 | return ERR_PTR(res); | ||
| 576 | } | ||
| 577 | if (list_empty(&cache->entries)) { | ||
| 578 | /* Good oportunity to get rid of an unnecessary "impure" flag */ | ||
| 579 | ovl_do_removexattr(ovl_dentry_upper(dentry), OVL_XATTR_IMPURE); | ||
| 580 | ovl_clear_flag(OVL_IMPURE, d_inode(dentry)); | ||
| 581 | kfree(cache); | ||
| 582 | return NULL; | ||
| 583 | } | ||
| 584 | |||
| 585 | cache->version = ovl_dentry_version_get(dentry); | ||
| 586 | ovl_set_dir_cache(d_inode(dentry), cache); | ||
| 587 | |||
| 588 | return cache; | ||
| 589 | } | ||
| 590 | |||
| 591 | struct ovl_readdir_translate { | ||
| 592 | struct dir_context *orig_ctx; | ||
| 593 | struct ovl_dir_cache *cache; | ||
| 594 | struct dir_context ctx; | ||
| 595 | u64 parent_ino; | ||
| 596 | }; | ||
| 597 | |||
| 598 | static int ovl_fill_real(struct dir_context *ctx, const char *name, | ||
| 599 | int namelen, loff_t offset, u64 ino, | ||
| 600 | unsigned int d_type) | ||
| 601 | { | ||
| 602 | struct ovl_readdir_translate *rdt = | ||
| 603 | container_of(ctx, struct ovl_readdir_translate, ctx); | ||
| 604 | struct dir_context *orig_ctx = rdt->orig_ctx; | ||
| 605 | |||
| 606 | if (rdt->parent_ino && strcmp(name, "..") == 0) | ||
| 607 | ino = rdt->parent_ino; | ||
| 608 | else if (rdt->cache) { | ||
| 609 | struct ovl_cache_entry *p; | ||
| 610 | |||
| 611 | p = ovl_cache_entry_find(&rdt->cache->root, name, namelen); | ||
| 612 | if (p) | ||
| 613 | ino = p->ino; | ||
| 614 | } | ||
| 615 | |||
| 616 | return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type); | ||
| 617 | } | ||
| 618 | |||
| 619 | static int ovl_iterate_real(struct file *file, struct dir_context *ctx) | ||
| 620 | { | ||
| 621 | int err; | ||
| 622 | struct ovl_dir_file *od = file->private_data; | ||
| 623 | struct dentry *dir = file->f_path.dentry; | ||
| 624 | struct ovl_readdir_translate rdt = { | ||
| 625 | .ctx.actor = ovl_fill_real, | ||
| 626 | .orig_ctx = ctx, | ||
| 627 | }; | ||
| 628 | |||
| 629 | if (OVL_TYPE_MERGE(ovl_path_type(dir->d_parent))) { | ||
| 630 | struct kstat stat; | ||
| 631 | struct path statpath = file->f_path; | ||
| 632 | |||
| 633 | statpath.dentry = dir->d_parent; | ||
| 634 | err = vfs_getattr(&statpath, &stat, STATX_INO, 0); | ||
| 635 | if (err) | ||
| 636 | return err; | ||
| 637 | |||
| 638 | WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev); | ||
| 639 | rdt.parent_ino = stat.ino; | ||
| 640 | } | ||
| 641 | |||
| 642 | if (ovl_test_flag(OVL_IMPURE, d_inode(dir))) { | ||
| 643 | rdt.cache = ovl_cache_get_impure(&file->f_path); | ||
| 644 | if (IS_ERR(rdt.cache)) | ||
| 645 | return PTR_ERR(rdt.cache); | ||
| 646 | } | ||
| 647 | |||
| 648 | return iterate_dir(od->realfile, &rdt.ctx); | ||
| 649 | } | ||
| 650 | |||
| 651 | |||
| 356 | static int ovl_iterate(struct file *file, struct dir_context *ctx) | 652 | static int ovl_iterate(struct file *file, struct dir_context *ctx) |
| 357 | { | 653 | { |
| 358 | struct ovl_dir_file *od = file->private_data; | 654 | struct ovl_dir_file *od = file->private_data; |
| 359 | struct dentry *dentry = file->f_path.dentry; | 655 | struct dentry *dentry = file->f_path.dentry; |
| 360 | struct ovl_cache_entry *p; | 656 | struct ovl_cache_entry *p; |
| 657 | int err; | ||
| 361 | 658 | ||
| 362 | if (!ctx->pos) | 659 | if (!ctx->pos) |
| 363 | ovl_dir_reset(file); | 660 | ovl_dir_reset(file); |
| 364 | 661 | ||
| 365 | if (od->is_real) | 662 | if (od->is_real) { |
| 663 | /* | ||
| 664 | * If parent is merge, then need to adjust d_ino for '..', if | ||
| 665 | * dir is impure then need to adjust d_ino for copied up | ||
| 666 | * entries. | ||
| 667 | */ | ||
| 668 | if (ovl_same_sb(dentry->d_sb) && | ||
| 669 | (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) || | ||
| 670 | OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent)))) { | ||
| 671 | return ovl_iterate_real(file, ctx); | ||
| 672 | } | ||
| 366 | return iterate_dir(od->realfile, ctx); | 673 | return iterate_dir(od->realfile, ctx); |
| 674 | } | ||
| 367 | 675 | ||
| 368 | if (!od->cache) { | 676 | if (!od->cache) { |
| 369 | struct ovl_dir_cache *cache; | 677 | struct ovl_dir_cache *cache; |
| @@ -378,9 +686,15 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
| 378 | 686 | ||
| 379 | while (od->cursor != &od->cache->entries) { | 687 | while (od->cursor != &od->cache->entries) { |
| 380 | p = list_entry(od->cursor, struct ovl_cache_entry, l_node); | 688 | p = list_entry(od->cursor, struct ovl_cache_entry, l_node); |
| 381 | if (!p->is_whiteout) | 689 | if (!p->is_whiteout) { |
| 690 | if (!p->ino) { | ||
| 691 | err = ovl_cache_update_ino(&file->f_path, p); | ||
| 692 | if (err) | ||
| 693 | return err; | ||
| 694 | } | ||
| 382 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) | 695 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) |
| 383 | break; | 696 | break; |
| 697 | } | ||
| 384 | od->cursor = p->l_node.next; | 698 | od->cursor = p->l_node.next; |
| 385 | ctx->pos++; | 699 | ctx->pos++; |
| 386 | } | 700 | } |
| @@ -522,8 +836,9 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) | |||
| 522 | { | 836 | { |
| 523 | int err; | 837 | int err; |
| 524 | struct ovl_cache_entry *p; | 838 | struct ovl_cache_entry *p; |
| 839 | struct rb_root root = RB_ROOT; | ||
| 525 | 840 | ||
| 526 | err = ovl_dir_read_merged(dentry, list); | 841 | err = ovl_dir_read_merged(dentry, list, &root); |
| 527 | if (err) | 842 | if (err) |
| 528 | return err; | 843 | return err; |
| 529 | 844 | ||
| @@ -612,12 +927,13 @@ static void ovl_workdir_cleanup_recurse(struct path *path, int level) | |||
| 612 | int err; | 927 | int err; |
| 613 | struct inode *dir = path->dentry->d_inode; | 928 | struct inode *dir = path->dentry->d_inode; |
| 614 | LIST_HEAD(list); | 929 | LIST_HEAD(list); |
| 930 | struct rb_root root = RB_ROOT; | ||
| 615 | struct ovl_cache_entry *p; | 931 | struct ovl_cache_entry *p; |
| 616 | struct ovl_readdir_data rdd = { | 932 | struct ovl_readdir_data rdd = { |
| 617 | .ctx.actor = ovl_fill_merge, | 933 | .ctx.actor = ovl_fill_merge, |
| 618 | .dentry = NULL, | 934 | .dentry = NULL, |
| 619 | .list = &list, | 935 | .list = &list, |
| 620 | .root = RB_ROOT, | 936 | .root = &root, |
| 621 | .is_lowest = false, | 937 | .is_lowest = false, |
| 622 | }; | 938 | }; |
| 623 | 939 | ||
| @@ -675,12 +991,13 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, | |||
| 675 | struct inode *dir = dentry->d_inode; | 991 | struct inode *dir = dentry->d_inode; |
| 676 | struct path path = { .mnt = mnt, .dentry = dentry }; | 992 | struct path path = { .mnt = mnt, .dentry = dentry }; |
| 677 | LIST_HEAD(list); | 993 | LIST_HEAD(list); |
| 994 | struct rb_root root = RB_ROOT; | ||
| 678 | struct ovl_cache_entry *p; | 995 | struct ovl_cache_entry *p; |
| 679 | struct ovl_readdir_data rdd = { | 996 | struct ovl_readdir_data rdd = { |
| 680 | .ctx.actor = ovl_fill_merge, | 997 | .ctx.actor = ovl_fill_merge, |
| 681 | .dentry = NULL, | 998 | .dentry = NULL, |
| 682 | .list = &list, | 999 | .list = &list, |
| 683 | .root = RB_ROOT, | 1000 | .root = &root, |
| 684 | .is_lowest = false, | 1001 | .is_lowest = false, |
| 685 | }; | 1002 | }; |
| 686 | 1003 | ||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index d86e89f97201..cd49c0298ddf 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
| @@ -70,20 +70,20 @@ static int ovl_check_append_only(struct inode *inode, int flag) | |||
| 70 | 70 | ||
| 71 | static struct dentry *ovl_d_real(struct dentry *dentry, | 71 | static struct dentry *ovl_d_real(struct dentry *dentry, |
| 72 | const struct inode *inode, | 72 | const struct inode *inode, |
| 73 | unsigned int open_flags) | 73 | unsigned int open_flags, unsigned int flags) |
| 74 | { | 74 | { |
| 75 | struct dentry *real; | 75 | struct dentry *real; |
| 76 | int err; | 76 | int err; |
| 77 | 77 | ||
| 78 | if (flags & D_REAL_UPPER) | ||
| 79 | return ovl_dentry_upper(dentry); | ||
| 80 | |||
| 78 | if (!d_is_reg(dentry)) { | 81 | if (!d_is_reg(dentry)) { |
| 79 | if (!inode || inode == d_inode(dentry)) | 82 | if (!inode || inode == d_inode(dentry)) |
| 80 | return dentry; | 83 | return dentry; |
| 81 | goto bug; | 84 | goto bug; |
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | if (d_is_negative(dentry)) | ||
| 85 | return dentry; | ||
| 86 | |||
| 87 | if (open_flags) { | 87 | if (open_flags) { |
| 88 | err = ovl_open_maybe_copy_up(dentry, open_flags); | 88 | err = ovl_open_maybe_copy_up(dentry, open_flags); |
| 89 | if (err) | 89 | if (err) |
| @@ -105,7 +105,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, | |||
| 105 | goto bug; | 105 | goto bug; |
| 106 | 106 | ||
| 107 | /* Handle recursion */ | 107 | /* Handle recursion */ |
| 108 | real = d_real(real, inode, open_flags); | 108 | real = d_real(real, inode, open_flags, 0); |
| 109 | 109 | ||
| 110 | if (!inode || inode == d_inode(real)) | 110 | if (!inode || inode == d_inode(real)) |
| 111 | return real; | 111 | return real; |
| @@ -198,6 +198,7 @@ static void ovl_destroy_inode(struct inode *inode) | |||
| 198 | 198 | ||
| 199 | dput(oi->__upperdentry); | 199 | dput(oi->__upperdentry); |
| 200 | kfree(oi->redirect); | 200 | kfree(oi->redirect); |
| 201 | ovl_dir_cache_free(inode); | ||
| 201 | mutex_destroy(&oi->lock); | 202 | mutex_destroy(&oi->lock); |
| 202 | 203 | ||
| 203 | call_rcu(&inode->i_rcu, ovl_i_callback); | 204 | call_rcu(&inode->i_rcu, ovl_i_callback); |
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index f46ad75dc96a..117794582f9f 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c | |||
| @@ -180,14 +180,14 @@ struct inode *ovl_inode_real(struct inode *inode) | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | 182 | ||
| 183 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry) | 183 | struct ovl_dir_cache *ovl_dir_cache(struct inode *inode) |
| 184 | { | 184 | { |
| 185 | return OVL_I(d_inode(dentry))->cache; | 185 | return OVL_I(inode)->cache; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) | 188 | void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache) |
| 189 | { | 189 | { |
| 190 | OVL_I(d_inode(dentry))->cache = cache; | 190 | OVL_I(inode)->cache = cache; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | bool ovl_dentry_is_opaque(struct dentry *dentry) | 193 | bool ovl_dentry_is_opaque(struct dentry *dentry) |
| @@ -275,12 +275,19 @@ void ovl_inode_update(struct inode *inode, struct dentry *upperdentry) | |||
| 275 | } | 275 | } |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | void ovl_dentry_version_inc(struct dentry *dentry) | 278 | void ovl_dentry_version_inc(struct dentry *dentry, bool impurity) |
| 279 | { | 279 | { |
| 280 | struct inode *inode = d_inode(dentry); | 280 | struct inode *inode = d_inode(dentry); |
| 281 | 281 | ||
| 282 | WARN_ON(!inode_is_locked(inode)); | 282 | WARN_ON(!inode_is_locked(inode)); |
| 283 | OVL_I(inode)->version++; | 283 | /* |
| 284 | * Version is used by readdir code to keep cache consistent. For merge | ||
| 285 | * dirs all changes need to be noted. For non-merge dirs, cache only | ||
| 286 | * contains impure (ones which have been copied up and have origins) | ||
| 287 | * entries, so only need to note changes to impure entries. | ||
| 288 | */ | ||
| 289 | if (OVL_TYPE_MERGE(ovl_path_type(dentry)) || impurity) | ||
| 290 | OVL_I(inode)->version++; | ||
| 284 | } | 291 | } |
| 285 | 292 | ||
| 286 | u64 ovl_dentry_version_get(struct dentry *dentry) | 293 | u64 ovl_dentry_version_get(struct dentry *dentry) |
| @@ -382,6 +389,11 @@ void ovl_set_flag(unsigned long flag, struct inode *inode) | |||
| 382 | set_bit(flag, &OVL_I(inode)->flags); | 389 | set_bit(flag, &OVL_I(inode)->flags); |
| 383 | } | 390 | } |
| 384 | 391 | ||
| 392 | void ovl_clear_flag(unsigned long flag, struct inode *inode) | ||
| 393 | { | ||
| 394 | clear_bit(flag, &OVL_I(inode)->flags); | ||
| 395 | } | ||
| 396 | |||
| 385 | bool ovl_test_flag(unsigned long flag, struct inode *inode) | 397 | bool ovl_test_flag(unsigned long flag, struct inode *inode) |
| 386 | { | 398 | { |
| 387 | return test_bit(flag, &OVL_I(inode)->flags); | 399 | return test_bit(flag, &OVL_I(inode)->flags); |
diff --git a/fs/xattr.c b/fs/xattr.c index 7b03df6b8be2..4424f7fecf14 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/posix_acl_xattr.h> | 23 | #include <linux/posix_acl_xattr.h> |
| 24 | 24 | ||
| 25 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
| 26 | #include "internal.h" | ||
| 26 | 27 | ||
| 27 | static const char * | 28 | static const char * |
| 28 | strcmp_prefix(const char *a, const char *a_prefix) | 29 | strcmp_prefix(const char *a, const char *a_prefix) |
| @@ -502,10 +503,10 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | |||
| 502 | if (!f.file) | 503 | if (!f.file) |
| 503 | return error; | 504 | return error; |
| 504 | audit_file(f.file); | 505 | audit_file(f.file); |
| 505 | error = mnt_want_write_file(f.file); | 506 | error = mnt_want_write_file_path(f.file); |
| 506 | if (!error) { | 507 | if (!error) { |
| 507 | error = setxattr(f.file->f_path.dentry, name, value, size, flags); | 508 | error = setxattr(f.file->f_path.dentry, name, value, size, flags); |
| 508 | mnt_drop_write_file(f.file); | 509 | mnt_drop_write_file_path(f.file); |
| 509 | } | 510 | } |
| 510 | fdput(f); | 511 | fdput(f); |
| 511 | return error; | 512 | return error; |
| @@ -734,10 +735,10 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | |||
| 734 | if (!f.file) | 735 | if (!f.file) |
| 735 | return error; | 736 | return error; |
| 736 | audit_file(f.file); | 737 | audit_file(f.file); |
| 737 | error = mnt_want_write_file(f.file); | 738 | error = mnt_want_write_file_path(f.file); |
| 738 | if (!error) { | 739 | if (!error) { |
| 739 | error = removexattr(f.file->f_path.dentry, name); | 740 | error = removexattr(f.file->f_path.dentry, name); |
| 740 | mnt_drop_write_file(f.file); | 741 | mnt_drop_write_file_path(f.file); |
| 741 | } | 742 | } |
| 742 | fdput(f); | 743 | fdput(f); |
| 743 | return error; | 744 | return error; |
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8996.h b/include/dt-bindings/clock/qcom,gcc-msm8996.h index 1f5c42254798..75b07cf5eed0 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8996.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8996.h | |||
| @@ -233,6 +233,8 @@ | |||
| 233 | #define GCC_PCIE_CLKREF_CLK 216 | 233 | #define GCC_PCIE_CLKREF_CLK 216 |
| 234 | #define GCC_RX2_USB2_CLKREF_CLK 217 | 234 | #define GCC_RX2_USB2_CLKREF_CLK 217 |
| 235 | #define GCC_RX1_USB2_CLKREF_CLK 218 | 235 | #define GCC_RX1_USB2_CLKREF_CLK 218 |
| 236 | #define GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK 219 | ||
| 237 | #define GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 220 | ||
| 236 | 238 | ||
| 237 | #define GCC_SYSTEM_NOC_BCR 0 | 239 | #define GCC_SYSTEM_NOC_BCR 0 |
| 238 | #define GCC_CONFIG_NOC_BCR 1 | 240 | #define GCC_CONFIG_NOC_BCR 1 |
diff --git a/include/dt-bindings/clock/r8a77995-cpg-mssr.h b/include/dt-bindings/clock/r8a77995-cpg-mssr.h new file mode 100644 index 000000000000..4e8ae3dee590 --- /dev/null +++ b/include/dt-bindings/clock/r8a77995-cpg-mssr.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Glider bvba | ||
| 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 | #ifndef __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ | ||
| 10 | #define __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ | ||
| 11 | |||
| 12 | #include <dt-bindings/clock/renesas-cpg-mssr.h> | ||
| 13 | |||
| 14 | /* r8a77995 CPG Core Clocks */ | ||
| 15 | #define R8A77995_CLK_Z2 0 | ||
| 16 | #define R8A77995_CLK_ZG 1 | ||
| 17 | #define R8A77995_CLK_ZTR 2 | ||
| 18 | #define R8A77995_CLK_ZT 3 | ||
| 19 | #define R8A77995_CLK_ZX 4 | ||
| 20 | #define R8A77995_CLK_S0D1 5 | ||
| 21 | #define R8A77995_CLK_S1D1 6 | ||
| 22 | #define R8A77995_CLK_S1D2 7 | ||
| 23 | #define R8A77995_CLK_S1D4 8 | ||
| 24 | #define R8A77995_CLK_S2D1 9 | ||
| 25 | #define R8A77995_CLK_S2D2 10 | ||
| 26 | #define R8A77995_CLK_S2D4 11 | ||
| 27 | #define R8A77995_CLK_S3D1 12 | ||
| 28 | #define R8A77995_CLK_S3D2 13 | ||
| 29 | #define R8A77995_CLK_S3D4 14 | ||
| 30 | #define R8A77995_CLK_S1D4C 15 | ||
| 31 | #define R8A77995_CLK_S3D1C 16 | ||
| 32 | #define R8A77995_CLK_S3D2C 17 | ||
| 33 | #define R8A77995_CLK_S3D4C 18 | ||
| 34 | #define R8A77995_CLK_LB 19 | ||
| 35 | #define R8A77995_CLK_CL 20 | ||
| 36 | #define R8A77995_CLK_ZB3 21 | ||
| 37 | #define R8A77995_CLK_ZB3D2 22 | ||
| 38 | #define R8A77995_CLK_CR 23 | ||
| 39 | #define R8A77995_CLK_CRD2 24 | ||
| 40 | #define R8A77995_CLK_SD0H 25 | ||
| 41 | #define R8A77995_CLK_SD0 26 | ||
| 42 | #define R8A77995_CLK_SSP2 27 | ||
| 43 | #define R8A77995_CLK_SSP1 28 | ||
| 44 | #define R8A77995_CLK_RPC 29 | ||
| 45 | #define R8A77995_CLK_RPCD2 30 | ||
| 46 | #define R8A77995_CLK_ZA2 31 | ||
| 47 | #define R8A77995_CLK_ZA8 32 | ||
| 48 | #define R8A77995_CLK_Z2D 33 | ||
| 49 | #define R8A77995_CLK_CANFD 34 | ||
| 50 | #define R8A77995_CLK_MSO 35 | ||
| 51 | #define R8A77995_CLK_R 36 | ||
| 52 | #define R8A77995_CLK_OSC 37 | ||
| 53 | #define R8A77995_CLK_LV0 38 | ||
| 54 | #define R8A77995_CLK_LV1 39 | ||
| 55 | #define R8A77995_CLK_CP 40 | ||
| 56 | |||
| 57 | #endif /* __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ */ | ||
diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index 56f841c22801..55655ab0a4c4 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define SCLK_EMMC_DRV 117 | 49 | #define SCLK_EMMC_DRV 117 |
| 50 | #define SCLK_SDMMC_SAMPLE 118 | 50 | #define SCLK_SDMMC_SAMPLE 118 |
| 51 | #define SCLK_SDIO_SAMPLE 119 | 51 | #define SCLK_SDIO_SAMPLE 119 |
| 52 | #define SCLK_SDIO_SRC 120 | ||
| 52 | #define SCLK_EMMC_SAMPLE 121 | 53 | #define SCLK_EMMC_SAMPLE 121 |
| 53 | #define SCLK_VOP 122 | 54 | #define SCLK_VOP 122 |
| 54 | #define SCLK_HDMI_HDCP 123 | 55 | #define SCLK_HDMI_HDCP 123 |
diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h index f269d833e41a..d8d0e0456dc2 100644 --- a/include/dt-bindings/clock/rv1108-cru.h +++ b/include/dt-bindings/clock/rv1108-cru.h | |||
| @@ -67,9 +67,9 @@ | |||
| 67 | #define SCLK_SPI 108 | 67 | #define SCLK_SPI 108 |
| 68 | #define SCLK_SARADC 109 | 68 | #define SCLK_SARADC 109 |
| 69 | #define SCLK_TSADC 110 | 69 | #define SCLK_TSADC 110 |
| 70 | #define SCLK_MACPHY_PRE 111 | 70 | #define SCLK_MAC_PRE 111 |
| 71 | #define SCLK_MACPHY 112 | 71 | #define SCLK_MAC 112 |
| 72 | #define SCLK_MACPHY_RX 113 | 72 | #define SCLK_MAC_RX 113 |
| 73 | #define SCLK_MAC_REF 114 | 73 | #define SCLK_MAC_REF 114 |
| 74 | #define SCLK_MAC_REFOUT 115 | 74 | #define SCLK_MAC_REFOUT 115 |
| 75 | #define SCLK_DSP_PFM 116 | 75 | #define SCLK_DSP_PFM 116 |
| @@ -110,6 +110,7 @@ | |||
| 110 | #define ACLK_CIF2 207 | 110 | #define ACLK_CIF2 207 |
| 111 | #define ACLK_CIF3 208 | 111 | #define ACLK_CIF3 208 |
| 112 | #define ACLK_PERI 209 | 112 | #define ACLK_PERI 209 |
| 113 | #define ACLK_GMAC 210 | ||
| 113 | 114 | ||
| 114 | /* pclk gates */ | 115 | /* pclk gates */ |
| 115 | #define PCLK_GPIO1 256 | 116 | #define PCLK_GPIO1 256 |
| @@ -141,6 +142,7 @@ | |||
| 141 | #define PCLK_EFUSE0 282 | 142 | #define PCLK_EFUSE0 282 |
| 142 | #define PCLK_EFUSE1 283 | 143 | #define PCLK_EFUSE1 283 |
| 143 | #define PCLK_WDT 284 | 144 | #define PCLK_WDT 284 |
| 145 | #define PCLK_GMAC 285 | ||
| 144 | 146 | ||
| 145 | /* hclk gates */ | 147 | /* hclk gates */ |
| 146 | #define HCLK_I2S0_8CH 320 | 148 | #define HCLK_I2S0_8CH 320 |
diff --git a/include/dt-bindings/clock/stm32h7-clks.h b/include/dt-bindings/clock/stm32h7-clks.h new file mode 100644 index 000000000000..6637272b3242 --- /dev/null +++ b/include/dt-bindings/clock/stm32h7-clks.h | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* SYS, CORE AND BUS CLOCKS */ | ||
| 2 | #define SYS_D1CPRE 0 | ||
| 3 | #define HCLK 1 | ||
| 4 | #define PCLK1 2 | ||
| 5 | #define PCLK2 3 | ||
| 6 | #define PCLK3 4 | ||
| 7 | #define PCLK4 5 | ||
| 8 | #define HSI_DIV 6 | ||
| 9 | #define HSE_1M 7 | ||
| 10 | #define I2S_CKIN 8 | ||
| 11 | #define CK_DSI_PHY 9 | ||
| 12 | #define HSE_CK 10 | ||
| 13 | #define LSE_CK 11 | ||
| 14 | #define CSI_KER_DIV122 12 | ||
| 15 | #define RTC_CK 13 | ||
| 16 | #define CPU_SYSTICK 14 | ||
| 17 | |||
| 18 | /* OSCILLATOR BANK */ | ||
| 19 | #define OSC_BANK 18 | ||
| 20 | #define HSI_CK 18 | ||
| 21 | #define HSI_KER_CK 19 | ||
| 22 | #define CSI_CK 20 | ||
| 23 | #define CSI_KER_CK 21 | ||
| 24 | #define RC48_CK 22 | ||
| 25 | #define LSI_CK 23 | ||
| 26 | |||
| 27 | /* MCLOCK BANK */ | ||
| 28 | #define MCLK_BANK 28 | ||
| 29 | #define PER_CK 28 | ||
| 30 | #define PLLSRC 29 | ||
| 31 | #define SYS_CK 30 | ||
| 32 | #define TRACEIN_CK 31 | ||
| 33 | |||
| 34 | /* ODF BANK */ | ||
| 35 | #define ODF_BANK 32 | ||
| 36 | #define PLL1_P 32 | ||
| 37 | #define PLL1_Q 33 | ||
| 38 | #define PLL1_R 34 | ||
| 39 | #define PLL2_P 35 | ||
| 40 | #define PLL2_Q 36 | ||
| 41 | #define PLL2_R 37 | ||
| 42 | #define PLL3_P 38 | ||
| 43 | #define PLL3_Q 39 | ||
| 44 | #define PLL3_R 40 | ||
| 45 | |||
| 46 | /* MCO BANK */ | ||
| 47 | #define MCO_BANK 41 | ||
| 48 | #define MCO1 41 | ||
| 49 | #define MCO2 42 | ||
| 50 | |||
| 51 | /* PERIF BANK */ | ||
| 52 | #define PERIF_BANK 50 | ||
| 53 | #define D1SRAM1_CK 50 | ||
| 54 | #define ITCM_CK 51 | ||
| 55 | #define DTCM2_CK 52 | ||
| 56 | #define DTCM1_CK 53 | ||
| 57 | #define FLITF_CK 54 | ||
| 58 | #define JPGDEC_CK 55 | ||
| 59 | #define DMA2D_CK 56 | ||
| 60 | #define MDMA_CK 57 | ||
| 61 | #define USB2ULPI_CK 58 | ||
| 62 | #define USB1ULPI_CK 59 | ||
| 63 | #define ETH1RX_CK 60 | ||
| 64 | #define ETH1TX_CK 61 | ||
| 65 | #define ETH1MAC_CK 62 | ||
| 66 | #define ART_CK 63 | ||
| 67 | #define DMA2_CK 64 | ||
| 68 | #define DMA1_CK 65 | ||
| 69 | #define D2SRAM3_CK 66 | ||
| 70 | #define D2SRAM2_CK 67 | ||
| 71 | #define D2SRAM1_CK 68 | ||
| 72 | #define HASH_CK 69 | ||
| 73 | #define CRYPT_CK 70 | ||
| 74 | #define CAMITF_CK 71 | ||
| 75 | #define BKPRAM_CK 72 | ||
| 76 | #define HSEM_CK 73 | ||
| 77 | #define BDMA_CK 74 | ||
| 78 | #define CRC_CK 75 | ||
| 79 | #define GPIOK_CK 76 | ||
| 80 | #define GPIOJ_CK 77 | ||
| 81 | #define GPIOI_CK 78 | ||
| 82 | #define GPIOH_CK 79 | ||
| 83 | #define GPIOG_CK 80 | ||
| 84 | #define GPIOF_CK 81 | ||
| 85 | #define GPIOE_CK 82 | ||
| 86 | #define GPIOD_CK 83 | ||
| 87 | #define GPIOC_CK 84 | ||
| 88 | #define GPIOB_CK 85 | ||
| 89 | #define GPIOA_CK 86 | ||
| 90 | #define WWDG1_CK 87 | ||
| 91 | #define DAC12_CK 88 | ||
| 92 | #define WWDG2_CK 89 | ||
| 93 | #define TIM14_CK 90 | ||
| 94 | #define TIM13_CK 91 | ||
| 95 | #define TIM12_CK 92 | ||
| 96 | #define TIM7_CK 93 | ||
| 97 | #define TIM6_CK 94 | ||
| 98 | #define TIM5_CK 95 | ||
| 99 | #define TIM4_CK 96 | ||
| 100 | #define TIM3_CK 97 | ||
| 101 | #define TIM2_CK 98 | ||
| 102 | #define MDIOS_CK 99 | ||
| 103 | #define OPAMP_CK 100 | ||
| 104 | #define CRS_CK 101 | ||
| 105 | #define TIM17_CK 102 | ||
| 106 | #define TIM16_CK 103 | ||
| 107 | #define TIM15_CK 104 | ||
| 108 | #define TIM8_CK 105 | ||
| 109 | #define TIM1_CK 106 | ||
| 110 | #define TMPSENS_CK 107 | ||
| 111 | #define RTCAPB_CK 108 | ||
| 112 | #define VREF_CK 109 | ||
| 113 | #define COMP12_CK 110 | ||
| 114 | #define SYSCFG_CK 111 | ||
| 115 | |||
| 116 | /* KERNEL BANK */ | ||
| 117 | #define KERN_BANK 120 | ||
| 118 | #define SDMMC1_CK 120 | ||
| 119 | #define QUADSPI_CK 121 | ||
| 120 | #define FMC_CK 122 | ||
| 121 | #define USB2OTG_CK 123 | ||
| 122 | #define USB1OTG_CK 124 | ||
| 123 | #define ADC12_CK 125 | ||
| 124 | #define SDMMC2_CK 126 | ||
| 125 | #define RNG_CK 127 | ||
| 126 | #define ADC3_CK 128 | ||
| 127 | #define DSI_CK 129 | ||
| 128 | #define LTDC_CK 130 | ||
| 129 | #define USART8_CK 131 | ||
| 130 | #define USART7_CK 132 | ||
| 131 | #define HDMICEC_CK 133 | ||
| 132 | #define I2C3_CK 134 | ||
| 133 | #define I2C2_CK 135 | ||
| 134 | #define I2C1_CK 136 | ||
| 135 | #define UART5_CK 137 | ||
| 136 | #define UART4_CK 138 | ||
| 137 | #define USART3_CK 139 | ||
| 138 | #define USART2_CK 140 | ||
| 139 | #define SPDIFRX_CK 141 | ||
| 140 | #define SPI3_CK 142 | ||
| 141 | #define SPI2_CK 143 | ||
| 142 | #define LPTIM1_CK 144 | ||
| 143 | #define FDCAN_CK 145 | ||
| 144 | #define SWP_CK 146 | ||
| 145 | #define HRTIM_CK 147 | ||
| 146 | #define DFSDM1_CK 148 | ||
| 147 | #define SAI3_CK 149 | ||
| 148 | #define SAI2_CK 150 | ||
| 149 | #define SAI1_CK 151 | ||
| 150 | #define SPI5_CK 152 | ||
| 151 | #define SPI4_CK 153 | ||
| 152 | #define SPI1_CK 154 | ||
| 153 | #define USART6_CK 155 | ||
| 154 | #define USART1_CK 156 | ||
| 155 | #define SAI4B_CK 157 | ||
| 156 | #define SAI4A_CK 158 | ||
| 157 | #define LPTIM5_CK 159 | ||
| 158 | #define LPTIM4_CK 160 | ||
| 159 | #define LPTIM3_CK 161 | ||
| 160 | #define LPTIM2_CK 162 | ||
| 161 | #define I2C4_CK 163 | ||
| 162 | #define SPI6_CK 164 | ||
| 163 | #define LPUART1_CK 165 | ||
| 164 | |||
| 165 | #define STM32H7_MAX_CLKS 166 | ||
diff --git a/include/dt-bindings/clock/sun4i-a10-ccu.h b/include/dt-bindings/clock/sun4i-a10-ccu.h new file mode 100644 index 000000000000..c5a53f38d654 --- /dev/null +++ b/include/dt-bindings/clock/sun4i-a10-ccu.h | |||
| @@ -0,0 +1,200 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | ||
| 3 | * | ||
| 4 | * This file is dual-licensed: you can use it either under the terms | ||
| 5 | * of the GPL or the X11 license, at your option. Note that this dual | ||
| 6 | * licensing only applies to this file, and not this project as a | ||
| 7 | * whole. | ||
| 8 | * | ||
| 9 | * a) This file is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation; either version 2 of the | ||
| 12 | * License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This file is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * Or, alternatively, | ||
| 20 | * | ||
| 21 | * b) Permission is hereby granted, free of charge, to any person | ||
| 22 | * obtaining a copy of this software and associated documentation | ||
| 23 | * files (the "Software"), to deal in the Software without | ||
| 24 | * restriction, including without limitation the rights to use, | ||
| 25 | * copy, modify, merge, publish, distribute, sublicense, and/or | ||
| 26 | * sell copies of the Software, and to permit persons to whom the | ||
| 27 | * Software is furnished to do so, subject to the following | ||
| 28 | * conditions: | ||
| 29 | * | ||
| 30 | * The above copyright notice and this permission notice shall be | ||
| 31 | * included in all copies or substantial portions of the Software. | ||
| 32 | * | ||
| 33 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 34 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
| 35 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 36 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
| 37 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 38 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 39 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 40 | */ | ||
| 41 | |||
| 42 | #ifndef _DT_BINDINGS_CLK_SUN4I_A10_H_ | ||
| 43 | #define _DT_BINDINGS_CLK_SUN4I_A10_H_ | ||
| 44 | |||
| 45 | #define CLK_HOSC 1 | ||
| 46 | #define CLK_CPU 20 | ||
| 47 | |||
| 48 | /* AHB Gates */ | ||
| 49 | #define CLK_AHB_OTG 26 | ||
| 50 | #define CLK_AHB_EHCI0 27 | ||
| 51 | #define CLK_AHB_OHCI0 28 | ||
| 52 | #define CLK_AHB_EHCI1 29 | ||
| 53 | #define CLK_AHB_OHCI1 30 | ||
| 54 | #define CLK_AHB_SS 31 | ||
| 55 | #define CLK_AHB_DMA 32 | ||
| 56 | #define CLK_AHB_BIST 33 | ||
| 57 | #define CLK_AHB_MMC0 34 | ||
| 58 | #define CLK_AHB_MMC1 35 | ||
| 59 | #define CLK_AHB_MMC2 36 | ||
| 60 | #define CLK_AHB_MMC3 37 | ||
| 61 | #define CLK_AHB_MS 38 | ||
| 62 | #define CLK_AHB_NAND 39 | ||
| 63 | #define CLK_AHB_SDRAM 40 | ||
| 64 | #define CLK_AHB_ACE 41 | ||
| 65 | #define CLK_AHB_EMAC 42 | ||
| 66 | #define CLK_AHB_TS 43 | ||
| 67 | #define CLK_AHB_SPI0 44 | ||
| 68 | #define CLK_AHB_SPI1 45 | ||
| 69 | #define CLK_AHB_SPI2 46 | ||
| 70 | #define CLK_AHB_SPI3 47 | ||
| 71 | #define CLK_AHB_PATA 48 | ||
| 72 | #define CLK_AHB_SATA 49 | ||
| 73 | #define CLK_AHB_GPS 50 | ||
| 74 | #define CLK_AHB_HSTIMER 51 | ||
| 75 | #define CLK_AHB_VE 52 | ||
| 76 | #define CLK_AHB_TVD 53 | ||
| 77 | #define CLK_AHB_TVE0 54 | ||
| 78 | #define CLK_AHB_TVE1 55 | ||
| 79 | #define CLK_AHB_LCD0 56 | ||
| 80 | #define CLK_AHB_LCD1 57 | ||
| 81 | #define CLK_AHB_CSI0 58 | ||
| 82 | #define CLK_AHB_CSI1 59 | ||
| 83 | #define CLK_AHB_HDMI0 60 | ||
| 84 | #define CLK_AHB_HDMI1 61 | ||
| 85 | #define CLK_AHB_DE_BE0 62 | ||
| 86 | #define CLK_AHB_DE_BE1 63 | ||
| 87 | #define CLK_AHB_DE_FE0 64 | ||
| 88 | #define CLK_AHB_DE_FE1 65 | ||
| 89 | #define CLK_AHB_GMAC 66 | ||
| 90 | #define CLK_AHB_MP 67 | ||
| 91 | #define CLK_AHB_GPU 68 | ||
| 92 | |||
| 93 | /* APB0 Gates */ | ||
| 94 | #define CLK_APB0_CODEC 69 | ||
| 95 | #define CLK_APB0_SPDIF 70 | ||
| 96 | #define CLK_APB0_I2S0 71 | ||
| 97 | #define CLK_APB0_AC97 72 | ||
| 98 | #define CLK_APB0_I2S1 73 | ||
| 99 | #define CLK_APB0_PIO 74 | ||
| 100 | #define CLK_APB0_IR0 75 | ||
| 101 | #define CLK_APB0_IR1 76 | ||
| 102 | #define CLK_APB0_I2S2 77 | ||
| 103 | #define CLK_APB0_KEYPAD 78 | ||
| 104 | |||
| 105 | /* APB1 Gates */ | ||
| 106 | #define CLK_APB1_I2C0 79 | ||
| 107 | #define CLK_APB1_I2C1 80 | ||
| 108 | #define CLK_APB1_I2C2 81 | ||
| 109 | #define CLK_APB1_I2C3 82 | ||
| 110 | #define CLK_APB1_CAN 83 | ||
| 111 | #define CLK_APB1_SCR 84 | ||
| 112 | #define CLK_APB1_PS20 85 | ||
| 113 | #define CLK_APB1_PS21 86 | ||
| 114 | #define CLK_APB1_I2C4 87 | ||
| 115 | #define CLK_APB1_UART0 88 | ||
| 116 | #define CLK_APB1_UART1 89 | ||
| 117 | #define CLK_APB1_UART2 90 | ||
| 118 | #define CLK_APB1_UART3 91 | ||
| 119 | #define CLK_APB1_UART4 92 | ||
| 120 | #define CLK_APB1_UART5 93 | ||
| 121 | #define CLK_APB1_UART6 94 | ||
| 122 | #define CLK_APB1_UART7 95 | ||
| 123 | |||
| 124 | /* IP clocks */ | ||
| 125 | #define CLK_NAND 96 | ||
| 126 | #define CLK_MS 97 | ||
| 127 | #define CLK_MMC0 98 | ||
| 128 | #define CLK_MMC0_OUTPUT 99 | ||
| 129 | #define CLK_MMC0_SAMPLE 100 | ||
| 130 | #define CLK_MMC1 101 | ||
| 131 | #define CLK_MMC1_OUTPUT 102 | ||
| 132 | #define CLK_MMC1_SAMPLE 103 | ||
| 133 | #define CLK_MMC2 104 | ||
| 134 | #define CLK_MMC2_OUTPUT 105 | ||
| 135 | #define CLK_MMC2_SAMPLE 106 | ||
| 136 | #define CLK_MMC3 107 | ||
| 137 | #define CLK_MMC3_OUTPUT 108 | ||
| 138 | #define CLK_MMC3_SAMPLE 109 | ||
| 139 | #define CLK_TS 110 | ||
| 140 | #define CLK_SS 111 | ||
| 141 | #define CLK_SPI0 112 | ||
| 142 | #define CLK_SPI1 113 | ||
| 143 | #define CLK_SPI2 114 | ||
| 144 | #define CLK_PATA 115 | ||
| 145 | #define CLK_IR0 116 | ||
| 146 | #define CLK_IR1 117 | ||
| 147 | #define CLK_I2S0 118 | ||
| 148 | #define CLK_AC97 119 | ||
| 149 | #define CLK_SPDIF 120 | ||
| 150 | #define CLK_KEYPAD 121 | ||
| 151 | #define CLK_SATA 122 | ||
| 152 | #define CLK_USB_OHCI0 123 | ||
| 153 | #define CLK_USB_OHCI1 124 | ||
| 154 | #define CLK_USB_PHY 125 | ||
| 155 | #define CLK_GPS 126 | ||
| 156 | #define CLK_SPI3 127 | ||
| 157 | #define CLK_I2S1 128 | ||
| 158 | #define CLK_I2S2 129 | ||
| 159 | |||
| 160 | /* DRAM Gates */ | ||
| 161 | #define CLK_DRAM_VE 130 | ||
| 162 | #define CLK_DRAM_CSI0 131 | ||
| 163 | #define CLK_DRAM_CSI1 132 | ||
| 164 | #define CLK_DRAM_TS 133 | ||
| 165 | #define CLK_DRAM_TVD 134 | ||
| 166 | #define CLK_DRAM_TVE0 135 | ||
| 167 | #define CLK_DRAM_TVE1 136 | ||
| 168 | #define CLK_DRAM_OUT 137 | ||
| 169 | #define CLK_DRAM_DE_FE1 138 | ||
| 170 | #define CLK_DRAM_DE_FE0 139 | ||
| 171 | #define CLK_DRAM_DE_BE0 140 | ||
| 172 | #define CLK_DRAM_DE_BE1 141 | ||
| 173 | #define CLK_DRAM_MP 142 | ||
| 174 | #define CLK_DRAM_ACE 143 | ||
| 175 | |||
| 176 | /* Display Engine Clocks */ | ||
| 177 | #define CLK_DE_BE0 144 | ||
| 178 | #define CLK_DE_BE1 145 | ||
| 179 | #define CLK_DE_FE0 146 | ||
| 180 | #define CLK_DE_FE1 147 | ||
| 181 | #define CLK_DE_MP 148 | ||
| 182 | #define CLK_TCON0_CH0 149 | ||
| 183 | #define CLK_TCON1_CH0 150 | ||
| 184 | #define CLK_CSI_SCLK 151 | ||
| 185 | #define CLK_TVD_SCLK2 152 | ||
| 186 | #define CLK_TVD 153 | ||
| 187 | #define CLK_TCON0_CH1_SCLK2 154 | ||
| 188 | #define CLK_TCON0_CH1 155 | ||
| 189 | #define CLK_TCON1_CH1_SCLK2 156 | ||
| 190 | #define CLK_TCON1_CH1 157 | ||
| 191 | #define CLK_CSI0 158 | ||
| 192 | #define CLK_CSI1 159 | ||
| 193 | #define CLK_CODEC 160 | ||
| 194 | #define CLK_VE 161 | ||
| 195 | #define CLK_AVS 162 | ||
| 196 | #define CLK_ACE 163 | ||
| 197 | #define CLK_HDMI 164 | ||
| 198 | #define CLK_GPU 165 | ||
| 199 | |||
| 200 | #endif /* _DT_BINDINGS_CLK_SUN4I_A10_H_ */ | ||
diff --git a/include/dt-bindings/clock/sun7i-a20-ccu.h b/include/dt-bindings/clock/sun7i-a20-ccu.h new file mode 100644 index 000000000000..045a5178da0c --- /dev/null +++ b/include/dt-bindings/clock/sun7i-a20-ccu.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | ||
| 3 | * | ||
| 4 | * This file is dual-licensed: you can use it either under the terms | ||
| 5 | * of the GPL or the X11 license, at your option. Note that this dual | ||
| 6 | * licensing only applies to this file, and not this project as a | ||
| 7 | * whole. | ||
| 8 | * | ||
| 9 | * a) This file is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation; either version 2 of the | ||
| 12 | * License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This file is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * Or, alternatively, | ||
| 20 | * | ||
| 21 | * b) Permission is hereby granted, free of charge, to any person | ||
| 22 | * obtaining a copy of this software and associated documentation | ||
| 23 | * files (the "Software"), to deal in the Software without | ||
| 24 | * restriction, including without limitation the rights to use, | ||
| 25 | * copy, modify, merge, publish, distribute, sublicense, and/or | ||
| 26 | * sell copies of the Software, and to permit persons to whom the | ||
| 27 | * Software is furnished to do so, subject to the following | ||
| 28 | * conditions: | ||
| 29 | * | ||
| 30 | * The above copyright notice and this permission notice shall be | ||
| 31 | * included in all copies or substantial portions of the Software. | ||
| 32 | * | ||
| 33 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 34 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
| 35 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 36 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
| 37 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 38 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 39 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 40 | */ | ||
| 41 | |||
| 42 | #ifndef _DT_BINDINGS_CLK_SUN7I_A20_H_ | ||
| 43 | #define _DT_BINDINGS_CLK_SUN7I_A20_H_ | ||
| 44 | |||
| 45 | #include <dt-bindings/clock/sun4i-a10-ccu.h> | ||
| 46 | |||
| 47 | #define CLK_MBUS 166 | ||
| 48 | #define CLK_HDMI1_SLOW 167 | ||
| 49 | #define CLK_HDMI1 168 | ||
| 50 | #define CLK_OUT_A 169 | ||
| 51 | #define CLK_OUT_B 170 | ||
| 52 | |||
| 53 | #endif /* _DT_BINDINGS_CLK_SUN7I_A20_H_ */ | ||
diff --git a/include/dt-bindings/clock/sun8i-r40-ccu.h b/include/dt-bindings/clock/sun8i-r40-ccu.h new file mode 100644 index 000000000000..4fa5f69fc297 --- /dev/null +++ b/include/dt-bindings/clock/sun8i-r40-ccu.h | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io> | ||
| 3 | * | ||
| 4 | * This file is dual-licensed: you can use it either under the terms | ||
| 5 | * of the GPL or the X11 license, at your option. Note that this dual | ||
| 6 | * licensing only applies to this file, and not this project as a | ||
| 7 | * whole. | ||
| 8 | * | ||
| 9 | * a) This file is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation; either version 2 of the | ||
| 12 | * License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This file is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * Or, alternatively, | ||
| 20 | * | ||
| 21 | * b) Permission is hereby granted, free of charge, to any person | ||
| 22 | * obtaining a copy of this software and associated documentation | ||
| 23 | * files (the "Software"), to deal in the Software without | ||
| 24 | * restriction, including without limitation the rights to use, | ||
| 25 | * copy, modify, merge, publish, distribute, sublicense, and/or | ||
| 26 | * sell copies of the Software, and to permit persons to whom the | ||
| 27 | * Software is furnished to do so, subject to the following | ||
| 28 | * conditions: | ||
| 29 | * | ||
| 30 | * The above copyright notice and this permission notice shall be | ||
| 31 | * included in all copies or substantial portions of the Software. | ||
| 32 | * | ||
| 33 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 34 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
| 35 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 36 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
| 37 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 38 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 39 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 40 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #ifndef _DT_BINDINGS_CLK_SUN8I_R40_H_ | ||
| 44 | #define _DT_BINDINGS_CLK_SUN8I_R40_H_ | ||
| 45 | |||
| 46 | #define CLK_CPU 24 | ||
| 47 | |||
| 48 | #define CLK_BUS_MIPI_DSI 29 | ||
| 49 | #define CLK_BUS_CE 30 | ||
| 50 | #define CLK_BUS_DMA 31 | ||
| 51 | #define CLK_BUS_MMC0 32 | ||
| 52 | #define CLK_BUS_MMC1 33 | ||
| 53 | #define CLK_BUS_MMC2 34 | ||
| 54 | #define CLK_BUS_MMC3 35 | ||
| 55 | #define CLK_BUS_NAND 36 | ||
| 56 | #define CLK_BUS_DRAM 37 | ||
| 57 | #define CLK_BUS_EMAC 38 | ||
| 58 | #define CLK_BUS_TS 39 | ||
| 59 | #define CLK_BUS_HSTIMER 40 | ||
| 60 | #define CLK_BUS_SPI0 41 | ||
| 61 | #define CLK_BUS_SPI1 42 | ||
| 62 | #define CLK_BUS_SPI2 43 | ||
| 63 | #define CLK_BUS_SPI3 44 | ||
| 64 | #define CLK_BUS_SATA 45 | ||
| 65 | #define CLK_BUS_OTG 46 | ||
| 66 | #define CLK_BUS_EHCI0 47 | ||
| 67 | #define CLK_BUS_EHCI1 48 | ||
| 68 | #define CLK_BUS_EHCI2 49 | ||
| 69 | #define CLK_BUS_OHCI0 50 | ||
| 70 | #define CLK_BUS_OHCI1 51 | ||
| 71 | #define CLK_BUS_OHCI2 52 | ||
| 72 | #define CLK_BUS_VE 53 | ||
| 73 | #define CLK_BUS_MP 54 | ||
| 74 | #define CLK_BUS_DEINTERLACE 55 | ||
| 75 | #define CLK_BUS_CSI0 56 | ||
| 76 | #define CLK_BUS_CSI1 57 | ||
| 77 | #define CLK_BUS_HDMI1 58 | ||
| 78 | #define CLK_BUS_HDMI0 59 | ||
| 79 | #define CLK_BUS_DE 60 | ||
| 80 | #define CLK_BUS_TVE0 61 | ||
| 81 | #define CLK_BUS_TVE1 62 | ||
| 82 | #define CLK_BUS_TVE_TOP 63 | ||
| 83 | #define CLK_BUS_GMAC 64 | ||
| 84 | #define CLK_BUS_GPU 65 | ||
| 85 | #define CLK_BUS_TVD0 66 | ||
| 86 | #define CLK_BUS_TVD1 67 | ||
| 87 | #define CLK_BUS_TVD2 68 | ||
| 88 | #define CLK_BUS_TVD3 69 | ||
| 89 | #define CLK_BUS_TVD_TOP 70 | ||
| 90 | #define CLK_BUS_TCON_LCD0 71 | ||
| 91 | #define CLK_BUS_TCON_LCD1 72 | ||
| 92 | #define CLK_BUS_TCON_TV0 73 | ||
| 93 | #define CLK_BUS_TCON_TV1 74 | ||
| 94 | #define CLK_BUS_TCON_TOP 75 | ||
| 95 | #define CLK_BUS_CODEC 76 | ||
| 96 | #define CLK_BUS_SPDIF 77 | ||
| 97 | #define CLK_BUS_AC97 78 | ||
| 98 | #define CLK_BUS_PIO 79 | ||
| 99 | #define CLK_BUS_IR0 80 | ||
| 100 | #define CLK_BUS_IR1 81 | ||
| 101 | #define CLK_BUS_THS 82 | ||
| 102 | #define CLK_BUS_KEYPAD 83 | ||
| 103 | #define CLK_BUS_I2S0 84 | ||
| 104 | #define CLK_BUS_I2S1 85 | ||
| 105 | #define CLK_BUS_I2S2 86 | ||
| 106 | #define CLK_BUS_I2C0 87 | ||
| 107 | #define CLK_BUS_I2C1 88 | ||
| 108 | #define CLK_BUS_I2C2 89 | ||
| 109 | #define CLK_BUS_I2C3 90 | ||
| 110 | #define CLK_BUS_CAN 91 | ||
| 111 | #define CLK_BUS_SCR 92 | ||
| 112 | #define CLK_BUS_PS20 93 | ||
| 113 | #define CLK_BUS_PS21 94 | ||
| 114 | #define CLK_BUS_I2C4 95 | ||
| 115 | #define CLK_BUS_UART0 96 | ||
| 116 | #define CLK_BUS_UART1 97 | ||
| 117 | #define CLK_BUS_UART2 98 | ||
| 118 | #define CLK_BUS_UART3 99 | ||
| 119 | #define CLK_BUS_UART4 100 | ||
| 120 | #define CLK_BUS_UART5 101 | ||
| 121 | #define CLK_BUS_UART6 102 | ||
| 122 | #define CLK_BUS_UART7 103 | ||
| 123 | #define CLK_BUS_DBG 104 | ||
| 124 | |||
| 125 | #define CLK_THS 105 | ||
| 126 | #define CLK_NAND 106 | ||
| 127 | #define CLK_MMC0 107 | ||
| 128 | #define CLK_MMC1 108 | ||
| 129 | #define CLK_MMC2 109 | ||
| 130 | #define CLK_MMC3 110 | ||
| 131 | #define CLK_TS 111 | ||
| 132 | #define CLK_CE 112 | ||
| 133 | #define CLK_SPI0 113 | ||
| 134 | #define CLK_SPI1 114 | ||
| 135 | #define CLK_SPI2 115 | ||
| 136 | #define CLK_SPI3 116 | ||
| 137 | #define CLK_I2S0 117 | ||
| 138 | #define CLK_I2S1 118 | ||
| 139 | #define CLK_I2S2 119 | ||
| 140 | #define CLK_AC97 120 | ||
| 141 | #define CLK_SPDIF 121 | ||
| 142 | #define CLK_KEYPAD 122 | ||
| 143 | #define CLK_SATA 123 | ||
| 144 | #define CLK_USB_PHY0 124 | ||
| 145 | #define CLK_USB_PHY1 125 | ||
| 146 | #define CLK_USB_PHY2 126 | ||
| 147 | #define CLK_USB_OHCI0 127 | ||
| 148 | #define CLK_USB_OHCI1 128 | ||
| 149 | #define CLK_USB_OHCI2 129 | ||
| 150 | #define CLK_IR0 130 | ||
| 151 | #define CLK_IR1 131 | ||
| 152 | |||
| 153 | #define CLK_DRAM_VE 133 | ||
| 154 | #define CLK_DRAM_CSI0 134 | ||
| 155 | #define CLK_DRAM_CSI1 135 | ||
| 156 | #define CLK_DRAM_TS 136 | ||
| 157 | #define CLK_DRAM_TVD 137 | ||
| 158 | #define CLK_DRAM_MP 138 | ||
| 159 | #define CLK_DRAM_DEINTERLACE 139 | ||
| 160 | #define CLK_DE 140 | ||
| 161 | #define CLK_MP 141 | ||
| 162 | #define CLK_TCON_LCD0 142 | ||
| 163 | #define CLK_TCON_LCD1 143 | ||
| 164 | #define CLK_TCON_TV0 144 | ||
| 165 | #define CLK_TCON_TV1 145 | ||
| 166 | #define CLK_DEINTERLACE 146 | ||
| 167 | #define CLK_CSI1_MCLK 147 | ||
| 168 | #define CLK_CSI_SCLK 148 | ||
| 169 | #define CLK_CSI0_MCLK 149 | ||
| 170 | #define CLK_VE 150 | ||
| 171 | #define CLK_CODEC 151 | ||
| 172 | #define CLK_AVS 152 | ||
| 173 | #define CLK_HDMI 153 | ||
| 174 | #define CLK_HDMI_SLOW 154 | ||
| 175 | |||
| 176 | #define CLK_DSI_DPHY 156 | ||
| 177 | #define CLK_TVE0 157 | ||
| 178 | #define CLK_TVE1 158 | ||
| 179 | #define CLK_TVD0 159 | ||
| 180 | #define CLK_TVD1 160 | ||
| 181 | #define CLK_TVD2 161 | ||
| 182 | #define CLK_TVD3 162 | ||
| 183 | #define CLK_GPU 163 | ||
| 184 | #define CLK_OUTA 164 | ||
| 185 | #define CLK_OUTB 165 | ||
| 186 | |||
| 187 | #endif /* _DT_BINDINGS_CLK_SUN8I_R40_H_ */ | ||
diff --git a/include/dt-bindings/mfd/stm32h7-rcc.h b/include/dt-bindings/mfd/stm32h7-rcc.h new file mode 100644 index 000000000000..461a8e04453a --- /dev/null +++ b/include/dt-bindings/mfd/stm32h7-rcc.h | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * This header provides constants for the STM32H7 RCC IP | ||
| 3 | */ | ||
| 4 | |||
| 5 | #ifndef _DT_BINDINGS_MFD_STM32H7_RCC_H | ||
| 6 | #define _DT_BINDINGS_MFD_STM32H7_RCC_H | ||
| 7 | |||
| 8 | /* AHB3 */ | ||
| 9 | #define STM32H7_RCC_AHB3_MDMA 0 | ||
| 10 | #define STM32H7_RCC_AHB3_DMA2D 4 | ||
| 11 | #define STM32H7_RCC_AHB3_JPGDEC 5 | ||
| 12 | #define STM32H7_RCC_AHB3_FMC 12 | ||
| 13 | #define STM32H7_RCC_AHB3_QUADSPI 14 | ||
| 14 | #define STM32H7_RCC_AHB3_SDMMC1 16 | ||
| 15 | #define STM32H7_RCC_AHB3_CPU 31 | ||
| 16 | |||
| 17 | #define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8)) | ||
| 18 | |||
| 19 | /* AHB1 */ | ||
| 20 | #define STM32H7_RCC_AHB1_DMA1 0 | ||
| 21 | #define STM32H7_RCC_AHB1_DMA2 1 | ||
| 22 | #define STM32H7_RCC_AHB1_ADC12 5 | ||
| 23 | #define STM32H7_RCC_AHB1_ART 14 | ||
| 24 | #define STM32H7_RCC_AHB1_ETH1MAC 15 | ||
| 25 | #define STM32H7_RCC_AHB1_USB1OTG 25 | ||
| 26 | #define STM32H7_RCC_AHB1_USB2OTG 27 | ||
| 27 | |||
| 28 | #define STM32H7_AHB1_RESET(bit) (STM32H7_RCC_AHB1_##bit + (0x80 * 8)) | ||
| 29 | |||
| 30 | /* AHB2 */ | ||
| 31 | #define STM32H7_RCC_AHB2_CAMITF 0 | ||
| 32 | #define STM32H7_RCC_AHB2_CRYPT 4 | ||
| 33 | #define STM32H7_RCC_AHB2_HASH 5 | ||
| 34 | #define STM32H7_RCC_AHB2_RNG 6 | ||
| 35 | #define STM32H7_RCC_AHB2_SDMMC2 9 | ||
| 36 | |||
| 37 | #define STM32H7_AHB2_RESET(bit) (STM32H7_RCC_AHB2_##bit + (0x84 * 8)) | ||
| 38 | |||
| 39 | /* AHB4 */ | ||
| 40 | #define STM32H7_RCC_AHB4_GPIOA 0 | ||
| 41 | #define STM32H7_RCC_AHB4_GPIOB 1 | ||
| 42 | #define STM32H7_RCC_AHB4_GPIOC 2 | ||
| 43 | #define STM32H7_RCC_AHB4_GPIOD 3 | ||
| 44 | #define STM32H7_RCC_AHB4_GPIOE 4 | ||
| 45 | #define STM32H7_RCC_AHB4_GPIOF 5 | ||
| 46 | #define STM32H7_RCC_AHB4_GPIOG 6 | ||
| 47 | #define STM32H7_RCC_AHB4_GPIOH 7 | ||
| 48 | #define STM32H7_RCC_AHB4_GPIOI 8 | ||
| 49 | #define STM32H7_RCC_AHB4_GPIOJ 9 | ||
| 50 | #define STM32H7_RCC_AHB4_GPIOK 10 | ||
| 51 | #define STM32H7_RCC_AHB4_CRC 19 | ||
| 52 | #define STM32H7_RCC_AHB4_BDMA 21 | ||
| 53 | #define STM32H7_RCC_AHB4_ADC3 24 | ||
| 54 | #define STM32H7_RCC_AHB4_HSEM 25 | ||
| 55 | |||
| 56 | #define STM32H7_AHB4_RESET(bit) (STM32H7_RCC_AHB4_##bit + (0x88 * 8)) | ||
| 57 | |||
| 58 | /* APB3 */ | ||
| 59 | #define STM32H7_RCC_APB3_LTDC 3 | ||
| 60 | #define STM32H7_RCC_APB3_DSI 4 | ||
| 61 | |||
| 62 | #define STM32H7_APB3_RESET(bit) (STM32H7_RCC_APB3_##bit + (0x8C * 8)) | ||
| 63 | |||
| 64 | /* APB1L */ | ||
| 65 | #define STM32H7_RCC_APB1L_TIM2 0 | ||
| 66 | #define STM32H7_RCC_APB1L_TIM3 1 | ||
| 67 | #define STM32H7_RCC_APB1L_TIM4 2 | ||
| 68 | #define STM32H7_RCC_APB1L_TIM5 3 | ||
| 69 | #define STM32H7_RCC_APB1L_TIM6 4 | ||
| 70 | #define STM32H7_RCC_APB1L_TIM7 5 | ||
| 71 | #define STM32H7_RCC_APB1L_TIM12 6 | ||
| 72 | #define STM32H7_RCC_APB1L_TIM13 7 | ||
| 73 | #define STM32H7_RCC_APB1L_TIM14 8 | ||
| 74 | #define STM32H7_RCC_APB1L_LPTIM1 9 | ||
| 75 | #define STM32H7_RCC_APB1L_SPI2 14 | ||
| 76 | #define STM32H7_RCC_APB1L_SPI3 15 | ||
| 77 | #define STM32H7_RCC_APB1L_SPDIF_RX 16 | ||
| 78 | #define STM32H7_RCC_APB1L_USART2 17 | ||
| 79 | #define STM32H7_RCC_APB1L_USART3 18 | ||
| 80 | #define STM32H7_RCC_APB1L_UART4 19 | ||
| 81 | #define STM32H7_RCC_APB1L_UART5 20 | ||
| 82 | #define STM32H7_RCC_APB1L_I2C1 21 | ||
| 83 | #define STM32H7_RCC_APB1L_I2C2 22 | ||
| 84 | #define STM32H7_RCC_APB1L_I2C3 23 | ||
| 85 | #define STM32H7_RCC_APB1L_HDMICEC 27 | ||
| 86 | #define STM32H7_RCC_APB1L_DAC12 29 | ||
| 87 | #define STM32H7_RCC_APB1L_USART7 30 | ||
| 88 | #define STM32H7_RCC_APB1L_USART8 31 | ||
| 89 | |||
| 90 | #define STM32H7_APB1L_RESET(bit) (STM32H7_RCC_APB1L_##bit + (0x90 * 8)) | ||
| 91 | |||
| 92 | /* APB1H */ | ||
| 93 | #define STM32H7_RCC_APB1H_CRS 1 | ||
| 94 | #define STM32H7_RCC_APB1H_SWP 2 | ||
| 95 | #define STM32H7_RCC_APB1H_OPAMP 4 | ||
| 96 | #define STM32H7_RCC_APB1H_MDIOS 5 | ||
| 97 | #define STM32H7_RCC_APB1H_FDCAN 8 | ||
| 98 | |||
| 99 | #define STM32H7_APB1H_RESET(bit) (STM32H7_RCC_APB1H_##bit + (0x94 * 8)) | ||
| 100 | |||
| 101 | /* APB2 */ | ||
| 102 | #define STM32H7_RCC_APB2_TIM1 0 | ||
| 103 | #define STM32H7_RCC_APB2_TIM8 1 | ||
| 104 | #define STM32H7_RCC_APB2_USART1 4 | ||
| 105 | #define STM32H7_RCC_APB2_USART6 5 | ||
| 106 | #define STM32H7_RCC_APB2_SPI1 12 | ||
| 107 | #define STM32H7_RCC_APB2_SPI4 13 | ||
| 108 | #define STM32H7_RCC_APB2_TIM15 16 | ||
| 109 | #define STM32H7_RCC_APB2_TIM16 17 | ||
| 110 | #define STM32H7_RCC_APB2_TIM17 18 | ||
| 111 | #define STM32H7_RCC_APB2_SPI5 20 | ||
| 112 | #define STM32H7_RCC_APB2_SAI1 22 | ||
| 113 | #define STM32H7_RCC_APB2_SAI2 23 | ||
| 114 | #define STM32H7_RCC_APB2_SAI3 24 | ||
| 115 | #define STM32H7_RCC_APB2_DFSDM1 28 | ||
| 116 | #define STM32H7_RCC_APB2_HRTIM 29 | ||
| 117 | |||
| 118 | #define STM32H7_APB2_RESET(bit) (STM32H7_RCC_APB2_##bit + (0x98 * 8)) | ||
| 119 | |||
| 120 | /* APB4 */ | ||
| 121 | #define STM32H7_RCC_APB4_SYSCFG 1 | ||
| 122 | #define STM32H7_RCC_APB4_LPUART1 3 | ||
| 123 | #define STM32H7_RCC_APB4_SPI6 5 | ||
| 124 | #define STM32H7_RCC_APB4_I2C4 7 | ||
| 125 | #define STM32H7_RCC_APB4_LPTIM2 9 | ||
| 126 | #define STM32H7_RCC_APB4_LPTIM3 10 | ||
| 127 | #define STM32H7_RCC_APB4_LPTIM4 11 | ||
| 128 | #define STM32H7_RCC_APB4_LPTIM5 12 | ||
| 129 | #define STM32H7_RCC_APB4_COMP12 14 | ||
| 130 | #define STM32H7_RCC_APB4_VREF 15 | ||
| 131 | #define STM32H7_RCC_APB4_SAI4 21 | ||
| 132 | #define STM32H7_RCC_APB4_TMPSENS 26 | ||
| 133 | |||
| 134 | #define STM32H7_APB4_RESET(bit) (STM32H7_RCC_APB4_##bit + (0x9C * 8)) | ||
| 135 | |||
| 136 | #endif /* _DT_BINDINGS_MFD_STM32H7_RCC_H */ | ||
diff --git a/include/dt-bindings/reset/sun4i-a10-ccu.h b/include/dt-bindings/reset/sun4i-a10-ccu.h new file mode 100644 index 000000000000..5f4480bedc8a --- /dev/null +++ b/include/dt-bindings/reset/sun4i-a10-ccu.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | ||
| 3 | * | ||
| 4 | * This file is dual-licensed: you can use it either under the terms | ||
| 5 | * of the GPL or the X11 license, at your option. Note that this dual | ||
| 6 | * licensing only applies to this file, and not this project as a | ||
| 7 | * whole. | ||
| 8 | * | ||
| 9 | * a) This file is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation; either version 2 of the | ||
| 12 | * License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This file is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * Or, alternatively, | ||
| 20 | * | ||
| 21 | * b) Permission is hereby granted, free of charge, to any person | ||
| 22 | * obtaining a copy of this software and associated documentation | ||
| 23 | * files (the "Software"), to deal in the Software without | ||
| 24 | * restriction, including without limitation the rights to use, | ||
| 25 | * copy, modify, merge, publish, distribute, sublicense, and/or | ||
| 26 | * sell copies of the Software, and to permit persons to whom the | ||
| 27 | * Software is furnished to do so, subject to the following | ||
| 28 | * conditions: | ||
| 29 | * | ||
| 30 | * The above copyright notice and this permission notice shall be | ||
| 31 | * included in all copies or substantial portions of the Software. | ||
| 32 | * | ||
| 33 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 34 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
| 35 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 36 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
| 37 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 38 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 39 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 40 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #ifndef _DT_BINDINGS_RST_SUN4I_A10_H | ||
| 44 | #define _DT_BINDINGS_RST_SUN4I_A10_H | ||
| 45 | |||
| 46 | #define RST_USB_PHY0 1 | ||
| 47 | #define RST_USB_PHY1 2 | ||
| 48 | #define RST_USB_PHY2 3 | ||
| 49 | #define RST_GPS 4 | ||
| 50 | #define RST_DE_BE0 5 | ||
| 51 | #define RST_DE_BE1 6 | ||
| 52 | #define RST_DE_FE0 7 | ||
| 53 | #define RST_DE_FE1 8 | ||
| 54 | #define RST_DE_MP 9 | ||
| 55 | #define RST_TVE0 10 | ||
| 56 | #define RST_TCON0 11 | ||
| 57 | #define RST_TVE1 12 | ||
| 58 | #define RST_TCON1 13 | ||
| 59 | #define RST_CSI0 14 | ||
| 60 | #define RST_CSI1 15 | ||
| 61 | #define RST_VE 16 | ||
| 62 | #define RST_ACE 17 | ||
| 63 | #define RST_LVDS 18 | ||
| 64 | #define RST_GPU 19 | ||
| 65 | #define RST_HDMI_H 20 | ||
| 66 | #define RST_HDMI_SYS 21 | ||
| 67 | #define RST_HDMI_AUDIO_DMA 22 | ||
| 68 | |||
| 69 | #endif /* DT_BINDINGS_RST_SUN4I_A10_H */ | ||
diff --git a/include/dt-bindings/reset/sun8i-r40-ccu.h b/include/dt-bindings/reset/sun8i-r40-ccu.h new file mode 100644 index 000000000000..c5ebcf6672e4 --- /dev/null +++ b/include/dt-bindings/reset/sun8i-r40-ccu.h | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io> | ||
| 3 | * | ||
| 4 | * This file is dual-licensed: you can use it either under the terms | ||
| 5 | * of the GPL or the X11 license, at your option. Note that this dual | ||
| 6 | * licensing only applies to this file, and not this project as a | ||
| 7 | * whole. | ||
| 8 | * | ||
| 9 | * a) This file is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation; either version 2 of the | ||
| 12 | * License, or (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This file is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * Or, alternatively, | ||
| 20 | * | ||
| 21 | * b) Permission is hereby granted, free of charge, to any person | ||
| 22 | * obtaining a copy of this software and associated documentation | ||
| 23 | * files (the "Software"), to deal in the Software without | ||
| 24 | * restriction, including without limitation the rights to use, | ||
| 25 | * copy, modify, merge, publish, distribute, sublicense, and/or | ||
| 26 | * sell copies of the Software, and to permit persons to whom the | ||
| 27 | * Software is furnished to do so, subject to the following | ||
| 28 | * conditions: | ||
| 29 | * | ||
| 30 | * The above copyright notice and this permission notice shall be | ||
| 31 | * included in all copies or substantial portions of the Software. | ||
| 32 | * | ||
| 33 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 34 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
| 35 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 36 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
| 37 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 38 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 39 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 40 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #ifndef _DT_BINDINGS_RST_SUN8I_R40_H_ | ||
| 44 | #define _DT_BINDINGS_RST_SUN8I_R40_H_ | ||
| 45 | |||
| 46 | #define RST_USB_PHY0 0 | ||
| 47 | #define RST_USB_PHY1 1 | ||
| 48 | #define RST_USB_PHY2 2 | ||
| 49 | |||
| 50 | #define RST_DRAM 3 | ||
| 51 | #define RST_MBUS 4 | ||
| 52 | |||
| 53 | #define RST_BUS_MIPI_DSI 5 | ||
| 54 | #define RST_BUS_CE 6 | ||
| 55 | #define RST_BUS_DMA 7 | ||
| 56 | #define RST_BUS_MMC0 8 | ||
| 57 | #define RST_BUS_MMC1 9 | ||
| 58 | #define RST_BUS_MMC2 10 | ||
| 59 | #define RST_BUS_MMC3 11 | ||
| 60 | #define RST_BUS_NAND 12 | ||
| 61 | #define RST_BUS_DRAM 13 | ||
| 62 | #define RST_BUS_EMAC 14 | ||
| 63 | #define RST_BUS_TS 15 | ||
| 64 | #define RST_BUS_HSTIMER 16 | ||
| 65 | #define RST_BUS_SPI0 17 | ||
| 66 | #define RST_BUS_SPI1 18 | ||
| 67 | #define RST_BUS_SPI2 19 | ||
| 68 | #define RST_BUS_SPI3 20 | ||
| 69 | #define RST_BUS_SATA 21 | ||
| 70 | #define RST_BUS_OTG 22 | ||
| 71 | #define RST_BUS_EHCI0 23 | ||
| 72 | #define RST_BUS_EHCI1 24 | ||
| 73 | #define RST_BUS_EHCI2 25 | ||
| 74 | #define RST_BUS_OHCI0 26 | ||
| 75 | #define RST_BUS_OHCI1 27 | ||
| 76 | #define RST_BUS_OHCI2 28 | ||
| 77 | #define RST_BUS_VE 29 | ||
| 78 | #define RST_BUS_MP 30 | ||
| 79 | #define RST_BUS_DEINTERLACE 31 | ||
| 80 | #define RST_BUS_CSI0 32 | ||
| 81 | #define RST_BUS_CSI1 33 | ||
| 82 | #define RST_BUS_HDMI0 34 | ||
| 83 | #define RST_BUS_HDMI1 35 | ||
| 84 | #define RST_BUS_DE 36 | ||
| 85 | #define RST_BUS_TVE0 37 | ||
| 86 | #define RST_BUS_TVE1 38 | ||
| 87 | #define RST_BUS_TVE_TOP 39 | ||
| 88 | #define RST_BUS_GMAC 40 | ||
| 89 | #define RST_BUS_GPU 41 | ||
| 90 | #define RST_BUS_TVD0 42 | ||
| 91 | #define RST_BUS_TVD1 43 | ||
| 92 | #define RST_BUS_TVD2 44 | ||
| 93 | #define RST_BUS_TVD3 45 | ||
| 94 | #define RST_BUS_TVD_TOP 46 | ||
| 95 | #define RST_BUS_TCON_LCD0 47 | ||
| 96 | #define RST_BUS_TCON_LCD1 48 | ||
| 97 | #define RST_BUS_TCON_TV0 49 | ||
| 98 | #define RST_BUS_TCON_TV1 50 | ||
| 99 | #define RST_BUS_TCON_TOP 51 | ||
| 100 | #define RST_BUS_DBG 52 | ||
| 101 | #define RST_BUS_LVDS 53 | ||
| 102 | #define RST_BUS_CODEC 54 | ||
| 103 | #define RST_BUS_SPDIF 55 | ||
| 104 | #define RST_BUS_AC97 56 | ||
| 105 | #define RST_BUS_IR0 57 | ||
| 106 | #define RST_BUS_IR1 58 | ||
| 107 | #define RST_BUS_THS 59 | ||
| 108 | #define RST_BUS_KEYPAD 60 | ||
| 109 | #define RST_BUS_I2S0 61 | ||
| 110 | #define RST_BUS_I2S1 62 | ||
| 111 | #define RST_BUS_I2S2 63 | ||
| 112 | #define RST_BUS_I2C0 64 | ||
| 113 | #define RST_BUS_I2C1 65 | ||
| 114 | #define RST_BUS_I2C2 66 | ||
| 115 | #define RST_BUS_I2C3 67 | ||
| 116 | #define RST_BUS_CAN 68 | ||
| 117 | #define RST_BUS_SCR 69 | ||
| 118 | #define RST_BUS_PS20 70 | ||
| 119 | #define RST_BUS_PS21 71 | ||
| 120 | #define RST_BUS_I2C4 72 | ||
| 121 | #define RST_BUS_UART0 73 | ||
| 122 | #define RST_BUS_UART1 74 | ||
| 123 | #define RST_BUS_UART2 75 | ||
| 124 | #define RST_BUS_UART3 76 | ||
| 125 | #define RST_BUS_UART4 77 | ||
| 126 | #define RST_BUS_UART5 78 | ||
| 127 | #define RST_BUS_UART6 79 | ||
| 128 | #define RST_BUS_UART7 80 | ||
| 129 | |||
| 130 | #endif /* _DT_BINDINGS_RST_SUN8I_R40_H_ */ | ||
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c59c62571e4f..5100ec1b5d55 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
| @@ -343,6 +343,7 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, | |||
| 343 | u8 clk_gate_flags, spinlock_t *lock); | 343 | u8 clk_gate_flags, spinlock_t *lock); |
| 344 | void clk_unregister_gate(struct clk *clk); | 344 | void clk_unregister_gate(struct clk *clk); |
| 345 | void clk_hw_unregister_gate(struct clk_hw *hw); | 345 | void clk_hw_unregister_gate(struct clk_hw *hw); |
| 346 | int clk_gate_is_enabled(struct clk_hw *hw); | ||
| 346 | 347 | ||
| 347 | struct clk_div_table { | 348 | struct clk_div_table { |
| 348 | unsigned int val; | 349 | unsigned int val; |
| @@ -565,6 +566,9 @@ struct clk_fractional_divider { | |||
| 565 | u8 nwidth; | 566 | u8 nwidth; |
| 566 | u32 nmask; | 567 | u32 nmask; |
| 567 | u8 flags; | 568 | u8 flags; |
| 569 | void (*approximation)(struct clk_hw *hw, | ||
| 570 | unsigned long rate, unsigned long *parent_rate, | ||
| 571 | unsigned long *m, unsigned long *n); | ||
| 568 | spinlock_t *lock; | 572 | spinlock_t *lock; |
| 569 | }; | 573 | }; |
| 570 | 574 | ||
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index 17f413bbbedf..6aca5ce8a99a 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h | |||
| @@ -185,4 +185,29 @@ | |||
| 185 | #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ | 185 | #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ |
| 186 | #define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */ | 186 | #define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */ |
| 187 | 187 | ||
| 188 | #define AT91_PMC_AUDIO_PLL0 0x14c | ||
| 189 | #define AT91_PMC_AUDIO_PLL_PLLEN (1 << 0) | ||
| 190 | #define AT91_PMC_AUDIO_PLL_PADEN (1 << 1) | ||
| 191 | #define AT91_PMC_AUDIO_PLL_PMCEN (1 << 2) | ||
| 192 | #define AT91_PMC_AUDIO_PLL_RESETN (1 << 3) | ||
| 193 | #define AT91_PMC_AUDIO_PLL_ND_OFFSET 8 | ||
| 194 | #define AT91_PMC_AUDIO_PLL_ND_MASK (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET) | ||
| 195 | #define AT91_PMC_AUDIO_PLL_ND(n) ((n) << AT91_PMC_AUDIO_PLL_ND_OFFSET) | ||
| 196 | #define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16 | ||
| 197 | #define AT91_PMC_AUDIO_PLL_QDPMC_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | ||
| 198 | #define AT91_PMC_AUDIO_PLL_QDPMC(n) ((n) << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | ||
| 199 | |||
| 200 | #define AT91_PMC_AUDIO_PLL1 0x150 | ||
| 201 | #define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff | ||
| 202 | #define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24 | ||
| 203 | #define AT91_PMC_AUDIO_PLL_QDPAD_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) | ||
| 204 | #define AT91_PMC_AUDIO_PLL_QDPAD(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) | ||
| 205 | #define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET AT91_PMC_AUDIO_PLL_QDPAD_OFFSET | ||
| 206 | #define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) | ||
| 207 | #define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) | ||
| 208 | #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26 | ||
| 209 | #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f | ||
| 210 | #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) | ||
| 211 | #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) | ||
| 212 | |||
| 188 | #endif | 213 | #endif |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index aae1cdb76851..ed1a7cf6923a 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
| @@ -147,7 +147,7 @@ struct dentry_operations { | |||
| 147 | struct vfsmount *(*d_automount)(struct path *); | 147 | struct vfsmount *(*d_automount)(struct path *); |
| 148 | int (*d_manage)(const struct path *, bool); | 148 | int (*d_manage)(const struct path *, bool); |
| 149 | struct dentry *(*d_real)(struct dentry *, const struct inode *, | 149 | struct dentry *(*d_real)(struct dentry *, const struct inode *, |
| 150 | unsigned int); | 150 | unsigned int, unsigned int); |
| 151 | } ____cacheline_aligned; | 151 | } ____cacheline_aligned; |
| 152 | 152 | ||
| 153 | /* | 153 | /* |
| @@ -562,11 +562,15 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper) | |||
| 562 | return upper; | 562 | return upper; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | /* d_real() flags */ | ||
| 566 | #define D_REAL_UPPER 0x2 /* return upper dentry or NULL if non-upper */ | ||
| 567 | |||
| 565 | /** | 568 | /** |
| 566 | * d_real - Return the real dentry | 569 | * d_real - Return the real dentry |
| 567 | * @dentry: the dentry to query | 570 | * @dentry: the dentry to query |
| 568 | * @inode: inode to select the dentry from multiple layers (can be NULL) | 571 | * @inode: inode to select the dentry from multiple layers (can be NULL) |
| 569 | * @flags: open flags to control copy-up behavior | 572 | * @open_flags: open flags to control copy-up behavior |
| 573 | * @flags: flags to control what is returned by this function | ||
| 570 | * | 574 | * |
| 571 | * If dentry is on a union/overlay, then return the underlying, real dentry. | 575 | * If dentry is on a union/overlay, then return the underlying, real dentry. |
| 572 | * Otherwise return the dentry itself. | 576 | * Otherwise return the dentry itself. |
| @@ -575,10 +579,10 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper) | |||
| 575 | */ | 579 | */ |
| 576 | static inline struct dentry *d_real(struct dentry *dentry, | 580 | static inline struct dentry *d_real(struct dentry *dentry, |
| 577 | const struct inode *inode, | 581 | const struct inode *inode, |
| 578 | unsigned int flags) | 582 | unsigned int open_flags, unsigned int flags) |
| 579 | { | 583 | { |
| 580 | if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) | 584 | if (unlikely(dentry->d_flags & DCACHE_OP_REAL)) |
| 581 | return dentry->d_op->d_real(dentry, inode, flags); | 585 | return dentry->d_op->d_real(dentry, inode, open_flags, flags); |
| 582 | else | 586 | else |
| 583 | return dentry; | 587 | return dentry; |
| 584 | } | 588 | } |
| @@ -593,7 +597,7 @@ static inline struct dentry *d_real(struct dentry *dentry, | |||
| 593 | static inline struct inode *d_real_inode(const struct dentry *dentry) | 597 | static inline struct inode *d_real_inode(const struct dentry *dentry) |
| 594 | { | 598 | { |
| 595 | /* This usage of d_real() results in const dentry */ | 599 | /* This usage of d_real() results in const dentry */ |
| 596 | return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0)); | 600 | return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0, 0)); |
| 597 | } | 601 | } |
| 598 | 602 | ||
| 599 | struct name_snapshot { | 603 | struct name_snapshot { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 2d0e6748e46e..33d8e45cd874 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1235,7 +1235,7 @@ static inline struct inode *file_inode(const struct file *f) | |||
| 1235 | 1235 | ||
| 1236 | static inline struct dentry *file_dentry(const struct file *file) | 1236 | static inline struct dentry *file_dentry(const struct file *file) |
| 1237 | { | 1237 | { |
| 1238 | return d_real(file->f_path.dentry, file_inode(file), 0); | 1238 | return d_real(file->f_path.dentry, file_inode(file), 0, 0); |
| 1239 | } | 1239 | } |
| 1240 | 1240 | ||
| 1241 | static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) | 1241 | static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl) |
diff --git a/include/linux/module.h b/include/linux/module.h index e7bdd549e527..fe5aa3736707 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -209,7 +209,7 @@ extern void cleanup_module(void); | |||
| 209 | #ifdef MODULE | 209 | #ifdef MODULE |
| 210 | /* Creates an alias so file2alias.c can find device table. */ | 210 | /* Creates an alias so file2alias.c can find device table. */ |
| 211 | #define MODULE_DEVICE_TABLE(type, name) \ | 211 | #define MODULE_DEVICE_TABLE(type, name) \ |
| 212 | extern const typeof(name) __mod_##type##__##name##_device_table \ | 212 | extern typeof(name) __mod_##type##__##name##_device_table \ |
| 213 | __attribute__ ((unused, alias(__stringify(name)))) | 213 | __attribute__ ((unused, alias(__stringify(name)))) |
| 214 | #else /* !MODULE */ | 214 | #else /* !MODULE */ |
| 215 | #define MODULE_DEVICE_TABLE(type, name) | 215 | #define MODULE_DEVICE_TABLE(type, name) |
diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 5144f9103723..87723c86f136 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h | |||
| @@ -226,7 +226,9 @@ struct nvme_id_ctrl { | |||
| 226 | __le16 mntmt; | 226 | __le16 mntmt; |
| 227 | __le16 mxtmt; | 227 | __le16 mxtmt; |
| 228 | __le32 sanicap; | 228 | __le32 sanicap; |
| 229 | __u8 rsvd332[180]; | 229 | __le32 hmminds; |
| 230 | __le16 hmmaxd; | ||
| 231 | __u8 rsvd338[174]; | ||
| 230 | __u8 sqes; | 232 | __u8 sqes; |
| 231 | __u8 cqes; | 233 | __u8 cqes; |
| 232 | __le16 maxcmd; | 234 | __le16 maxcmd; |
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 0a0f0d14a5fb..e6d0f9c1cafd 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
| @@ -72,8 +72,6 @@ extern struct class *rtc_class; | |||
| 72 | * issued through ioctl() ... | 72 | * issued through ioctl() ... |
| 73 | */ | 73 | */ |
| 74 | struct rtc_class_ops { | 74 | struct rtc_class_ops { |
| 75 | int (*open)(struct device *); | ||
| 76 | void (*release)(struct device *); | ||
| 77 | int (*ioctl)(struct device *, unsigned int, unsigned long); | 75 | int (*ioctl)(struct device *, unsigned int, unsigned long); |
| 78 | int (*read_time)(struct device *, struct rtc_time *); | 76 | int (*read_time)(struct device *, struct rtc_time *); |
| 79 | int (*set_time)(struct device *, struct rtc_time *); | 77 | int (*set_time)(struct device *, struct rtc_time *); |
diff --git a/include/linux/string.h b/include/linux/string.h index e1eeb0a8a969..54d21783e18d 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
| @@ -434,20 +434,9 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) | |||
| 434 | * @count: The number of bytes to copy | 434 | * @count: The number of bytes to copy |
| 435 | * @pad: Character to use for padding if space is left in destination. | 435 | * @pad: Character to use for padding if space is left in destination. |
| 436 | */ | 436 | */ |
| 437 | __FORTIFY_INLINE void memcpy_and_pad(void *dest, size_t dest_len, | 437 | static inline void memcpy_and_pad(void *dest, size_t dest_len, |
| 438 | const void *src, size_t count, int pad) | 438 | const void *src, size_t count, int pad) |
| 439 | { | 439 | { |
| 440 | size_t dest_size = __builtin_object_size(dest, 0); | ||
| 441 | size_t src_size = __builtin_object_size(src, 0); | ||
| 442 | |||
| 443 | if (__builtin_constant_p(dest_len) && __builtin_constant_p(count)) { | ||
| 444 | if (dest_size < dest_len && dest_size < count) | ||
| 445 | __write_overflow(); | ||
| 446 | else if (src_size < dest_len && src_size < count) | ||
| 447 | __read_overflow3(); | ||
| 448 | } | ||
| 449 | if (dest_size < dest_len) | ||
| 450 | fortify_panic(__func__); | ||
| 451 | if (dest_len > count) { | 440 | if (dest_len > count) { |
| 452 | memcpy(dest, src, count); | 441 | memcpy(dest, src, count); |
| 453 | memset(dest + count, pad, dest_len - count); | 442 | memset(dest + count, pad, dest_len - count); |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index afb04811b7b9..0a804b1a4726 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
| @@ -691,12 +691,6 @@ struct Scsi_Host { | |||
| 691 | unsigned int prot_capabilities; | 691 | unsigned int prot_capabilities; |
| 692 | unsigned char prot_guard_type; | 692 | unsigned char prot_guard_type; |
| 693 | 693 | ||
| 694 | /* | ||
| 695 | * q used for scsi_tgt msgs, async events or any other requests that | ||
| 696 | * need to be processed in userspace | ||
| 697 | */ | ||
| 698 | struct request_queue *uspace_req_q; | ||
| 699 | |||
| 700 | /* legacy crap */ | 694 | /* legacy crap */ |
| 701 | unsigned long base; | 695 | unsigned long base; |
| 702 | unsigned long io_port; | 696 | unsigned long io_port; |
diff --git a/include/trace/events/block.h b/include/trace/events/block.h index f815aaaef755..1fd7ff1a46f7 100644 --- a/include/trace/events/block.h +++ b/include/trace/events/block.h | |||
| @@ -397,7 +397,6 @@ DECLARE_EVENT_CLASS(block_get_rq, | |||
| 397 | 397 | ||
| 398 | TP_fast_assign( | 398 | TP_fast_assign( |
| 399 | __entry->dev = bio ? bio_dev(bio) : 0; | 399 | __entry->dev = bio ? bio_dev(bio) : 0; |
| 400 | __entry->dev = bio_dev(bio); | ||
| 401 | __entry->sector = bio ? bio->bi_iter.bi_sector : 0; | 400 | __entry->sector = bio ? bio->bi_iter.bi_sector : 0; |
| 402 | __entry->nr_sector = bio ? bio_sectors(bio) : 0; | 401 | __entry->nr_sector = bio ? bio_sectors(bio) : 0; |
| 403 | blk_fill_rwbs(__entry->rwbs, | 402 | blk_fill_rwbs(__entry->rwbs, |
| @@ -414,7 +413,7 @@ DECLARE_EVENT_CLASS(block_get_rq, | |||
| 414 | /** | 413 | /** |
| 415 | * block_getrq - get a free request entry in queue for block IO operations | 414 | * block_getrq - get a free request entry in queue for block IO operations |
| 416 | * @q: queue for operations | 415 | * @q: queue for operations |
| 417 | * @bio: pending block IO operation | 416 | * @bio: pending block IO operation (can be %NULL) |
| 418 | * @rw: low bit indicates a read (%0) or a write (%1) | 417 | * @rw: low bit indicates a read (%0) or a write (%1) |
| 419 | * | 418 | * |
| 420 | * A request struct for queue @q has been allocated to handle the | 419 | * A request struct for queue @q has been allocated to handle the |
| @@ -430,7 +429,7 @@ DEFINE_EVENT(block_get_rq, block_getrq, | |||
| 430 | /** | 429 | /** |
| 431 | * block_sleeprq - waiting to get a free request entry in queue for block IO operation | 430 | * block_sleeprq - waiting to get a free request entry in queue for block IO operation |
| 432 | * @q: queue for operation | 431 | * @q: queue for operation |
| 433 | * @bio: pending block IO operation | 432 | * @bio: pending block IO operation (can be %NULL) |
| 434 | * @rw: low bit indicates a read (%0) or a write (%1) | 433 | * @rw: low bit indicates a read (%0) or a write (%1) |
| 435 | * | 434 | * |
| 436 | * In the case where a request struct cannot be provided for queue @q | 435 | * In the case where a request struct cannot be provided for queue @q |
diff --git a/kernel/module.c b/kernel/module.c index 40f983cbea81..de66ec825992 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -2707,21 +2707,21 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
| 2707 | } | 2707 | } |
| 2708 | #endif /* CONFIG_KALLSYMS */ | 2708 | #endif /* CONFIG_KALLSYMS */ |
| 2709 | 2709 | ||
| 2710 | static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) | 2710 | static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num) |
| 2711 | { | 2711 | { |
| 2712 | if (!debug) | 2712 | if (!debug) |
| 2713 | return; | 2713 | return; |
| 2714 | #ifdef CONFIG_DYNAMIC_DEBUG | 2714 | #ifdef CONFIG_DYNAMIC_DEBUG |
| 2715 | if (ddebug_add_module(debug, num, debug->modname)) | 2715 | if (ddebug_add_module(debug, num, mod->name)) |
| 2716 | pr_err("dynamic debug error adding module: %s\n", | 2716 | pr_err("dynamic debug error adding module: %s\n", |
| 2717 | debug->modname); | 2717 | debug->modname); |
| 2718 | #endif | 2718 | #endif |
| 2719 | } | 2719 | } |
| 2720 | 2720 | ||
| 2721 | static void dynamic_debug_remove(struct _ddebug *debug) | 2721 | static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug) |
| 2722 | { | 2722 | { |
| 2723 | if (debug) | 2723 | if (debug) |
| 2724 | ddebug_remove_module(debug->modname); | 2724 | ddebug_remove_module(mod->name); |
| 2725 | } | 2725 | } |
| 2726 | 2726 | ||
| 2727 | void * __weak module_alloc(unsigned long size) | 2727 | void * __weak module_alloc(unsigned long size) |
| @@ -3715,7 +3715,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3715 | goto free_arch_cleanup; | 3715 | goto free_arch_cleanup; |
| 3716 | } | 3716 | } |
| 3717 | 3717 | ||
| 3718 | dynamic_debug_setup(info->debug, info->num_debug); | 3718 | dynamic_debug_setup(mod, info->debug, info->num_debug); |
| 3719 | 3719 | ||
| 3720 | /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */ | 3720 | /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */ |
| 3721 | ftrace_module_init(mod); | 3721 | ftrace_module_init(mod); |
| @@ -3779,7 +3779,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3779 | module_disable_nx(mod); | 3779 | module_disable_nx(mod); |
| 3780 | 3780 | ||
| 3781 | ddebug_cleanup: | 3781 | ddebug_cleanup: |
| 3782 | dynamic_debug_remove(info->debug); | 3782 | dynamic_debug_remove(mod, info->debug); |
| 3783 | synchronize_sched(); | 3783 | synchronize_sched(); |
| 3784 | kfree(mod->args); | 3784 | kfree(mod->args); |
| 3785 | free_arch_cleanup: | 3785 | free_arch_cleanup: |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index f028a9a472fd..e19606bb41a0 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
| @@ -569,8 +569,10 @@ static int cgwb_create(struct backing_dev_info *bdi, | |||
| 569 | 569 | ||
| 570 | /* need to create a new one */ | 570 | /* need to create a new one */ |
| 571 | wb = kmalloc(sizeof(*wb), gfp); | 571 | wb = kmalloc(sizeof(*wb), gfp); |
| 572 | if (!wb) | 572 | if (!wb) { |
| 573 | return -ENOMEM; | 573 | ret = -ENOMEM; |
| 574 | goto out_put; | ||
| 575 | } | ||
| 574 | 576 | ||
| 575 | ret = wb_init(wb, bdi, blkcg_css->id, gfp); | 577 | ret = wb_init(wb, bdi, blkcg_css->id, gfp); |
| 576 | if (ret) | 578 | if (ret) |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index b920d186ad4a..98314b400a95 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -47,6 +47,12 @@ enum export { | |||
| 47 | export_unused_gpl, export_gpl_future, export_unknown | 47 | export_unused_gpl, export_gpl_future, export_unknown |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | /* In kernel, this size is defined in linux/module.h; | ||
| 51 | * here we use Elf_Addr instead of long for covering cross-compile | ||
| 52 | */ | ||
| 53 | |||
| 54 | #define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) | ||
| 55 | |||
| 50 | #define PRINTF __attribute__ ((format (printf, 1, 2))) | 56 | #define PRINTF __attribute__ ((format (printf, 1, 2))) |
| 51 | 57 | ||
| 52 | PRINTF void fatal(const char *fmt, ...) | 58 | PRINTF void fatal(const char *fmt, ...) |
| @@ -2111,6 +2117,23 @@ static void check_exports(struct module *mod) | |||
| 2111 | } | 2117 | } |
| 2112 | } | 2118 | } |
| 2113 | 2119 | ||
| 2120 | static int check_modname_len(struct module *mod) | ||
| 2121 | { | ||
| 2122 | const char *mod_name; | ||
| 2123 | |||
| 2124 | mod_name = strrchr(mod->name, '/'); | ||
| 2125 | if (mod_name == NULL) | ||
| 2126 | mod_name = mod->name; | ||
| 2127 | else | ||
| 2128 | mod_name++; | ||
| 2129 | if (strlen(mod_name) >= MODULE_NAME_LEN) { | ||
| 2130 | merror("module name is too long [%s.ko]\n", mod->name); | ||
| 2131 | return 1; | ||
| 2132 | } | ||
| 2133 | |||
| 2134 | return 0; | ||
| 2135 | } | ||
| 2136 | |||
| 2114 | /** | 2137 | /** |
| 2115 | * Header for the generated file | 2138 | * Header for the generated file |
| 2116 | **/ | 2139 | **/ |
| @@ -2150,11 +2173,6 @@ static void add_staging_flag(struct buffer *b, const char *name) | |||
| 2150 | buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); | 2173 | buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); |
| 2151 | } | 2174 | } |
| 2152 | 2175 | ||
| 2153 | /* In kernel, this size is defined in linux/module.h; | ||
| 2154 | * here we use Elf_Addr instead of long for covering cross-compile | ||
| 2155 | */ | ||
| 2156 | #define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) | ||
| 2157 | |||
| 2158 | /** | 2176 | /** |
| 2159 | * Record CRCs for unresolved symbols | 2177 | * Record CRCs for unresolved symbols |
| 2160 | **/ | 2178 | **/ |
| @@ -2485,6 +2503,7 @@ int main(int argc, char **argv) | |||
| 2485 | 2503 | ||
| 2486 | buf.pos = 0; | 2504 | buf.pos = 0; |
| 2487 | 2505 | ||
| 2506 | err |= check_modname_len(mod); | ||
| 2488 | add_header(&buf, mod); | 2507 | add_header(&buf, mod); |
| 2489 | add_intree_flag(&buf, !external_module); | 2508 | add_intree_flag(&buf, !external_module); |
| 2490 | add_staging_flag(&buf, mod->name); | 2509 | add_staging_flag(&buf, mod->name); |
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install index 677756ae34c9..067459760a7b 100755 --- a/scripts/sphinx-pre-install +++ b/scripts/sphinx-pre-install | |||
| @@ -40,7 +40,6 @@ my $virtualenv = 1; | |||
| 40 | # | 40 | # |
| 41 | 41 | ||
| 42 | my %texlive = ( | 42 | my %texlive = ( |
| 43 | 'adjustbox.sty' => 'texlive-adjustbox', | ||
| 44 | 'amsfonts.sty' => 'texlive-amsfonts', | 43 | 'amsfonts.sty' => 'texlive-amsfonts', |
| 45 | 'amsmath.sty' => 'texlive-amsmath', | 44 | 'amsmath.sty' => 'texlive-amsmath', |
| 46 | 'amssymb.sty' => 'texlive-amsfonts', | 45 | 'amssymb.sty' => 'texlive-amsfonts', |
diff --git a/sound/core/device.c b/sound/core/device.c index 8918838b1999..cb0e46f66cc9 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
| @@ -128,7 +128,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data) | |||
| 128 | if (dev) | 128 | if (dev) |
| 129 | __snd_device_disconnect(dev); | 129 | __snd_device_disconnect(dev); |
| 130 | else | 130 | else |
| 131 | dev_dbg(card->dev, "device disconnect %p (from %pF), not found\n", | 131 | dev_dbg(card->dev, "device disconnect %p (from %pS), not found\n", |
| 132 | device_data, __builtin_return_address(0)); | 132 | device_data, __builtin_return_address(0)); |
| 133 | } | 133 | } |
| 134 | EXPORT_SYMBOL_GPL(snd_device_disconnect); | 134 | EXPORT_SYMBOL_GPL(snd_device_disconnect); |
| @@ -152,7 +152,7 @@ void snd_device_free(struct snd_card *card, void *device_data) | |||
| 152 | if (dev) | 152 | if (dev) |
| 153 | __snd_device_free(dev); | 153 | __snd_device_free(dev); |
| 154 | else | 154 | else |
| 155 | dev_dbg(card->dev, "device free %p (from %pF), not found\n", | 155 | dev_dbg(card->dev, "device free %p (from %pS), not found\n", |
| 156 | device_data, __builtin_return_address(0)); | 156 | device_data, __builtin_return_address(0)); |
| 157 | } | 157 | } |
| 158 | EXPORT_SYMBOL(snd_device_free); | 158 | EXPORT_SYMBOL(snd_device_free); |
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c index c4acf17e9f5e..e40a2cba5002 100644 --- a/sound/core/seq_device.c +++ b/sound/core/seq_device.c | |||
| @@ -148,8 +148,10 @@ void snd_seq_device_load_drivers(void) | |||
| 148 | flush_work(&autoload_work); | 148 | flush_work(&autoload_work); |
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL(snd_seq_device_load_drivers); | 150 | EXPORT_SYMBOL(snd_seq_device_load_drivers); |
| 151 | #define cancel_autoload_drivers() cancel_work_sync(&autoload_work) | ||
| 151 | #else | 152 | #else |
| 152 | #define queue_autoload_drivers() /* NOP */ | 153 | #define queue_autoload_drivers() /* NOP */ |
| 154 | #define cancel_autoload_drivers() /* NOP */ | ||
| 153 | #endif | 155 | #endif |
| 154 | 156 | ||
| 155 | /* | 157 | /* |
| @@ -159,6 +161,7 @@ static int snd_seq_device_dev_free(struct snd_device *device) | |||
| 159 | { | 161 | { |
| 160 | struct snd_seq_device *dev = device->device_data; | 162 | struct snd_seq_device *dev = device->device_data; |
| 161 | 163 | ||
| 164 | cancel_autoload_drivers(); | ||
| 162 | put_device(&dev->dev); | 165 | put_device(&dev->dev); |
| 163 | return 0; | 166 | return 0; |
| 164 | } | 167 | } |
diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index dc5541c8b359..73e7a5e527fc 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c | |||
| @@ -253,24 +253,21 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) | |||
| 253 | if (err < 0) { | 253 | if (err < 0) { |
| 254 | dev_err(&motu->unit->device, | 254 | dev_err(&motu->unit->device, |
| 255 | "fail to start isochronous comm: %d\n", err); | 255 | "fail to start isochronous comm: %d\n", err); |
| 256 | stop_both_streams(motu); | 256 | goto stop_streams; |
| 257 | return err; | ||
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | err = start_isoc_ctx(motu, &motu->rx_stream); | 259 | err = start_isoc_ctx(motu, &motu->rx_stream); |
| 261 | if (err < 0) { | 260 | if (err < 0) { |
| 262 | dev_err(&motu->unit->device, | 261 | dev_err(&motu->unit->device, |
| 263 | "fail to start IT context: %d\n", err); | 262 | "fail to start IT context: %d\n", err); |
| 264 | stop_both_streams(motu); | 263 | goto stop_streams; |
| 265 | return err; | ||
| 266 | } | 264 | } |
| 267 | 265 | ||
| 268 | err = protocol->switch_fetching_mode(motu, true); | 266 | err = protocol->switch_fetching_mode(motu, true); |
| 269 | if (err < 0) { | 267 | if (err < 0) { |
| 270 | dev_err(&motu->unit->device, | 268 | dev_err(&motu->unit->device, |
| 271 | "fail to enable frame fetching: %d\n", err); | 269 | "fail to enable frame fetching: %d\n", err); |
| 272 | stop_both_streams(motu); | 270 | goto stop_streams; |
| 273 | return err; | ||
| 274 | } | 271 | } |
| 275 | } | 272 | } |
| 276 | 273 | ||
| @@ -281,12 +278,15 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu, unsigned int rate) | |||
| 281 | dev_err(&motu->unit->device, | 278 | dev_err(&motu->unit->device, |
| 282 | "fail to start IR context: %d", err); | 279 | "fail to start IR context: %d", err); |
| 283 | amdtp_stream_stop(&motu->rx_stream); | 280 | amdtp_stream_stop(&motu->rx_stream); |
| 284 | stop_both_streams(motu); | 281 | goto stop_streams; |
| 285 | return err; | ||
| 286 | } | 282 | } |
| 287 | } | 283 | } |
| 288 | 284 | ||
| 289 | return 0; | 285 | return 0; |
| 286 | |||
| 287 | stop_streams: | ||
| 288 | stop_both_streams(motu); | ||
| 289 | return err; | ||
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void snd_motu_stream_stop_duplex(struct snd_motu *motu) | 292 | void snd_motu_stream_stop_duplex(struct snd_motu *motu) |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 976a3d23557e..70d023a85bf5 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
| @@ -558,12 +558,10 @@ static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream) | |||
| 558 | struct snd_card_asihpi_pcm *dpcm; | 558 | struct snd_card_asihpi_pcm *dpcm; |
| 559 | struct snd_card_asihpi *card; | 559 | struct snd_card_asihpi *card; |
| 560 | 560 | ||
| 561 | BUG_ON(!substream); | ||
| 562 | |||
| 563 | dpcm = (struct snd_card_asihpi_pcm *)substream->runtime->private_data; | 561 | dpcm = (struct snd_card_asihpi_pcm *)substream->runtime->private_data; |
| 564 | card = snd_pcm_substream_chip(substream); | 562 | card = snd_pcm_substream_chip(substream); |
| 565 | 563 | ||
| 566 | BUG_ON(in_interrupt()); | 564 | WARN_ON(in_interrupt()); |
| 567 | tasklet_disable(&card->t); | 565 | tasklet_disable(&card->t); |
| 568 | card->llmode_streampriv = dpcm; | 566 | card->llmode_streampriv = dpcm; |
| 569 | tasklet_enable(&card->t); | 567 | tasklet_enable(&card->t); |
| @@ -578,8 +576,6 @@ static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream) | |||
| 578 | struct snd_card_asihpi_pcm *dpcm; | 576 | struct snd_card_asihpi_pcm *dpcm; |
| 579 | struct snd_card_asihpi *card; | 577 | struct snd_card_asihpi *card; |
| 580 | 578 | ||
| 581 | BUG_ON(!substream); | ||
| 582 | |||
| 583 | dpcm = (struct snd_card_asihpi_pcm *)substream->runtime->private_data; | 579 | dpcm = (struct snd_card_asihpi_pcm *)substream->runtime->private_data; |
| 584 | card = snd_pcm_substream_chip(substream); | 580 | card = snd_pcm_substream_chip(substream); |
| 585 | 581 | ||
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 97ac80af4447..8f20dec97843 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
| @@ -2622,22 +2622,18 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2622 | 2622 | ||
| 2623 | err = request_firmware(&chip->assp_kernel_image, | 2623 | err = request_firmware(&chip->assp_kernel_image, |
| 2624 | "ess/maestro3_assp_kernel.fw", &pci->dev); | 2624 | "ess/maestro3_assp_kernel.fw", &pci->dev); |
| 2625 | if (err < 0) { | 2625 | if (err < 0) |
| 2626 | snd_m3_free(chip); | 2626 | goto free_chip; |
| 2627 | return err; | ||
| 2628 | } | ||
| 2629 | 2627 | ||
| 2630 | err = request_firmware(&chip->assp_minisrc_image, | 2628 | err = request_firmware(&chip->assp_minisrc_image, |
| 2631 | "ess/maestro3_assp_minisrc.fw", &pci->dev); | 2629 | "ess/maestro3_assp_minisrc.fw", &pci->dev); |
| 2632 | if (err < 0) { | 2630 | if (err < 0) |
| 2633 | snd_m3_free(chip); | 2631 | goto free_chip; |
| 2634 | return err; | 2632 | |
| 2635 | } | 2633 | err = pci_request_regions(pci, card->driver); |
| 2634 | if (err < 0) | ||
| 2635 | goto free_chip; | ||
| 2636 | 2636 | ||
| 2637 | if ((err = pci_request_regions(pci, card->driver)) < 0) { | ||
| 2638 | snd_m3_free(chip); | ||
| 2639 | return err; | ||
| 2640 | } | ||
| 2641 | chip->iobase = pci_resource_start(pci, 0); | 2637 | chip->iobase = pci_resource_start(pci, 0); |
| 2642 | 2638 | ||
| 2643 | /* just to be sure */ | 2639 | /* just to be sure */ |
| @@ -2655,8 +2651,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2655 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, | 2651 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, |
| 2656 | KBUILD_MODNAME, chip)) { | 2652 | KBUILD_MODNAME, chip)) { |
| 2657 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); | 2653 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); |
| 2658 | snd_m3_free(chip); | 2654 | err = -ENOMEM; |
| 2659 | return -ENOMEM; | 2655 | goto free_chip; |
| 2660 | } | 2656 | } |
| 2661 | chip->irq = pci->irq; | 2657 | chip->irq = pci->irq; |
| 2662 | 2658 | ||
| @@ -2666,10 +2662,9 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2666 | dev_warn(card->dev, "can't allocate apm buffer\n"); | 2662 | dev_warn(card->dev, "can't allocate apm buffer\n"); |
| 2667 | #endif | 2663 | #endif |
| 2668 | 2664 | ||
| 2669 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 2665 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
| 2670 | snd_m3_free(chip); | 2666 | if (err < 0) |
| 2671 | return err; | 2667 | goto free_chip; |
| 2672 | } | ||
| 2673 | 2668 | ||
| 2674 | if ((err = snd_m3_mixer(chip)) < 0) | 2669 | if ((err = snd_m3_mixer(chip)) < 0) |
| 2675 | return err; | 2670 | return err; |
| @@ -2699,6 +2694,10 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2699 | *chip_ret = chip; | 2694 | *chip_ret = chip; |
| 2700 | 2695 | ||
| 2701 | return 0; | 2696 | return 0; |
| 2697 | |||
| 2698 | free_chip: | ||
| 2699 | snd_m3_free(chip); | ||
| 2700 | return err; | ||
| 2702 | } | 2701 | } |
| 2703 | 2702 | ||
| 2704 | /* | 2703 | /* |
| @@ -2741,23 +2740,19 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
| 2741 | break; | 2740 | break; |
| 2742 | } | 2741 | } |
| 2743 | 2742 | ||
| 2744 | if ((err = snd_m3_create(card, pci, | 2743 | err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev], &chip); |
| 2745 | external_amp[dev], | 2744 | if (err < 0) |
| 2746 | amp_gpio[dev], | 2745 | goto free_card; |
| 2747 | &chip)) < 0) { | 2746 | |
| 2748 | snd_card_free(card); | ||
| 2749 | return err; | ||
| 2750 | } | ||
| 2751 | card->private_data = chip; | 2747 | card->private_data = chip; |
| 2752 | 2748 | ||
| 2753 | sprintf(card->shortname, "ESS %s PCI", card->driver); | 2749 | sprintf(card->shortname, "ESS %s PCI", card->driver); |
| 2754 | sprintf(card->longname, "%s at 0x%lx, irq %d", | 2750 | sprintf(card->longname, "%s at 0x%lx, irq %d", |
| 2755 | card->shortname, chip->iobase, chip->irq); | 2751 | card->shortname, chip->iobase, chip->irq); |
| 2756 | 2752 | ||
| 2757 | if ((err = snd_card_register(card)) < 0) { | 2753 | err = snd_card_register(card); |
| 2758 | snd_card_free(card); | 2754 | if (err < 0) |
| 2759 | return err; | 2755 | goto free_card; |
| 2760 | } | ||
| 2761 | 2756 | ||
| 2762 | #if 0 /* TODO: not supported yet */ | 2757 | #if 0 /* TODO: not supported yet */ |
| 2763 | /* TODO enable MIDI IRQ and I/O */ | 2758 | /* TODO enable MIDI IRQ and I/O */ |
| @@ -2772,6 +2767,10 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
| 2772 | pci_set_drvdata(pci, card); | 2767 | pci_set_drvdata(pci, card); |
| 2773 | dev++; | 2768 | dev++; |
| 2774 | return 0; | 2769 | return 0; |
| 2770 | |||
| 2771 | free_card: | ||
| 2772 | snd_card_free(card); | ||
| 2773 | return err; | ||
| 2775 | } | 2774 | } |
| 2776 | 2775 | ||
| 2777 | static void snd_m3_remove(struct pci_dev *pci) | 2776 | static void snd_m3_remove(struct pci_dev *pci) |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 0ff41f9ab434..9f0f73875f01 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
| @@ -793,11 +793,8 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
| 793 | 793 | ||
| 794 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM); | 794 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM); |
| 795 | hdsp_write (hdsp, HDSP_fifoData, 0); | 795 | hdsp_write (hdsp, HDSP_fifoData, 0); |
| 796 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { | 796 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) |
| 797 | hdsp->io_type = Multiface; | 797 | goto set_multi; |
| 798 | dev_info(hdsp->card->dev, "Multiface found\n"); | ||
| 799 | return 0; | ||
| 800 | } | ||
| 801 | 798 | ||
| 802 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 799 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
| 803 | hdsp_write(hdsp, HDSP_fifoData, 0); | 800 | hdsp_write(hdsp, HDSP_fifoData, 0); |
| @@ -810,20 +807,14 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
| 810 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); | 807 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); |
| 811 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 808 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
| 812 | hdsp_write(hdsp, HDSP_fifoData, 0); | 809 | hdsp_write(hdsp, HDSP_fifoData, 0); |
| 813 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) { | 810 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) |
| 814 | hdsp->io_type = Multiface; | 811 | goto set_multi; |
| 815 | dev_info(hdsp->card->dev, "Multiface found\n"); | ||
| 816 | return 0; | ||
| 817 | } | ||
| 818 | 812 | ||
| 819 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); | 813 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); |
| 820 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 814 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
| 821 | hdsp_write(hdsp, HDSP_fifoData, 0); | 815 | hdsp_write(hdsp, HDSP_fifoData, 0); |
| 822 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { | 816 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) |
| 823 | hdsp->io_type = Multiface; | 817 | goto set_multi; |
| 824 | dev_info(hdsp->card->dev, "Multiface found\n"); | ||
| 825 | return 0; | ||
| 826 | } | ||
| 827 | 818 | ||
| 828 | hdsp->io_type = RPM; | 819 | hdsp->io_type = RPM; |
| 829 | dev_info(hdsp->card->dev, "RPM found\n"); | 820 | dev_info(hdsp->card->dev, "RPM found\n"); |
| @@ -838,6 +829,11 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
| 838 | hdsp->io_type = Digiface; | 829 | hdsp->io_type = Digiface; |
| 839 | } | 830 | } |
| 840 | return 0; | 831 | return 0; |
| 832 | |||
| 833 | set_multi: | ||
| 834 | hdsp->io_type = Multiface; | ||
| 835 | dev_info(hdsp->card->dev, "Multiface found\n"); | ||
| 836 | return 0; | ||
| 841 | } | 837 | } |
| 842 | 838 | ||
| 843 | 839 | ||
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 25284d8d9758..f20d42714e4d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
| @@ -6949,10 +6949,8 @@ static int snd_hdspm_probe(struct pci_dev *pci, | |||
| 6949 | hdspm->pci = pci; | 6949 | hdspm->pci = pci; |
| 6950 | 6950 | ||
| 6951 | err = snd_hdspm_create(card, hdspm); | 6951 | err = snd_hdspm_create(card, hdspm); |
| 6952 | if (err < 0) { | 6952 | if (err < 0) |
| 6953 | snd_card_free(card); | 6953 | goto free_card; |
| 6954 | return err; | ||
| 6955 | } | ||
| 6956 | 6954 | ||
| 6957 | if (hdspm->io_type != MADIface) { | 6955 | if (hdspm->io_type != MADIface) { |
| 6958 | snprintf(card->shortname, sizeof(card->shortname), "%s_%x", | 6956 | snprintf(card->shortname, sizeof(card->shortname), "%s_%x", |
| @@ -6970,15 +6968,17 @@ static int snd_hdspm_probe(struct pci_dev *pci, | |||
| 6970 | } | 6968 | } |
| 6971 | 6969 | ||
| 6972 | err = snd_card_register(card); | 6970 | err = snd_card_register(card); |
| 6973 | if (err < 0) { | 6971 | if (err < 0) |
| 6974 | snd_card_free(card); | 6972 | goto free_card; |
| 6975 | return err; | ||
| 6976 | } | ||
| 6977 | 6973 | ||
| 6978 | pci_set_drvdata(pci, card); | 6974 | pci_set_drvdata(pci, card); |
| 6979 | 6975 | ||
| 6980 | dev++; | 6976 | dev++; |
| 6981 | return 0; | 6977 | return 0; |
| 6978 | |||
| 6979 | free_card: | ||
| 6980 | snd_card_free(card); | ||
| 6981 | return err; | ||
| 6982 | } | 6982 | } |
| 6983 | 6983 | ||
| 6984 | static void snd_hdspm_remove(struct pci_dev *pci) | 6984 | static void snd_hdspm_remove(struct pci_dev *pci) |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 4faf3e1ed06a..eafdee384059 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
| @@ -268,10 +268,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
| 268 | if ((err = snd_ymfpci_create(card, pci, | 268 | if ((err = snd_ymfpci_create(card, pci, |
| 269 | old_legacy_ctrl, | 269 | old_legacy_ctrl, |
| 270 | &chip)) < 0) { | 270 | &chip)) < 0) { |
| 271 | snd_card_free(card); | ||
| 272 | release_and_free_resource(mpu_res); | 271 | release_and_free_resource(mpu_res); |
| 273 | release_and_free_resource(fm_res); | 272 | release_and_free_resource(fm_res); |
| 274 | return err; | 273 | goto free_card; |
| 275 | } | 274 | } |
| 276 | chip->fm_res = fm_res; | 275 | chip->fm_res = fm_res; |
| 277 | chip->mpu_res = mpu_res; | 276 | chip->mpu_res = mpu_res; |
| @@ -283,35 +282,31 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
| 283 | card->shortname, | 282 | card->shortname, |
| 284 | chip->reg_area_phys, | 283 | chip->reg_area_phys, |
| 285 | chip->irq); | 284 | chip->irq); |
| 286 | if ((err = snd_ymfpci_pcm(chip, 0)) < 0) { | 285 | err = snd_ymfpci_pcm(chip, 0); |
| 287 | snd_card_free(card); | 286 | if (err < 0) |
| 288 | return err; | 287 | goto free_card; |
| 289 | } | 288 | |
| 290 | if ((err = snd_ymfpci_pcm_spdif(chip, 1)) < 0) { | 289 | err = snd_ymfpci_pcm_spdif(chip, 1); |
| 291 | snd_card_free(card); | 290 | if (err < 0) |
| 292 | return err; | 291 | goto free_card; |
| 293 | } | 292 | |
| 294 | err = snd_ymfpci_mixer(chip, rear_switch[dev]); | 293 | err = snd_ymfpci_mixer(chip, rear_switch[dev]); |
| 295 | if (err < 0) { | 294 | if (err < 0) |
| 296 | snd_card_free(card); | 295 | goto free_card; |
| 297 | return err; | 296 | |
| 298 | } | ||
| 299 | if (chip->ac97->ext_id & AC97_EI_SDAC) { | 297 | if (chip->ac97->ext_id & AC97_EI_SDAC) { |
| 300 | err = snd_ymfpci_pcm_4ch(chip, 2); | 298 | err = snd_ymfpci_pcm_4ch(chip, 2); |
| 301 | if (err < 0) { | 299 | if (err < 0) |
| 302 | snd_card_free(card); | 300 | goto free_card; |
| 303 | return err; | 301 | |
| 304 | } | ||
| 305 | err = snd_ymfpci_pcm2(chip, 3); | 302 | err = snd_ymfpci_pcm2(chip, 3); |
| 306 | if (err < 0) { | 303 | if (err < 0) |
| 307 | snd_card_free(card); | 304 | goto free_card; |
| 308 | return err; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | if ((err = snd_ymfpci_timer(chip, 0)) < 0) { | ||
| 312 | snd_card_free(card); | ||
| 313 | return err; | ||
| 314 | } | 305 | } |
| 306 | err = snd_ymfpci_timer(chip, 0); | ||
| 307 | if (err < 0) | ||
| 308 | goto free_card; | ||
| 309 | |||
| 315 | if (chip->mpu_res) { | 310 | if (chip->mpu_res) { |
| 316 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, | 311 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, |
| 317 | mpu_port[dev], | 312 | mpu_port[dev], |
| @@ -336,21 +331,24 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
| 336 | legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; | 331 | legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; |
| 337 | pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); | 332 | pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); |
| 338 | } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { | 333 | } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { |
| 339 | snd_card_free(card); | ||
| 340 | dev_err(card->dev, "cannot create opl3 hwdep\n"); | 334 | dev_err(card->dev, "cannot create opl3 hwdep\n"); |
| 341 | return err; | 335 | goto free_card; |
| 342 | } | 336 | } |
| 343 | } | 337 | } |
| 344 | 338 | ||
| 345 | snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2); | 339 | snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2); |
| 346 | 340 | ||
| 347 | if ((err = snd_card_register(card)) < 0) { | 341 | err = snd_card_register(card); |
| 348 | snd_card_free(card); | 342 | if (err < 0) |
| 349 | return err; | 343 | goto free_card; |
| 350 | } | 344 | |
| 351 | pci_set_drvdata(pci, card); | 345 | pci_set_drvdata(pci, card); |
| 352 | dev++; | 346 | dev++; |
| 353 | return 0; | 347 | return 0; |
| 348 | |||
| 349 | free_card: | ||
| 350 | snd_card_free(card); | ||
| 351 | return err; | ||
| 354 | } | 352 | } |
| 355 | 353 | ||
| 356 | static void snd_card_ymfpci_remove(struct pci_dev *pci) | 354 | static void snd_card_ymfpci_remove(struct pci_dev *pci) |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index edfd58248082..8ca2e41e5827 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
| @@ -2399,59 +2399,60 @@ int snd_ymfpci_create(struct snd_card *card, | |||
| 2399 | dev_err(chip->card->dev, | 2399 | dev_err(chip->card->dev, |
| 2400 | "unable to grab memory region 0x%lx-0x%lx\n", | 2400 | "unable to grab memory region 0x%lx-0x%lx\n", |
| 2401 | chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); | 2401 | chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); |
| 2402 | snd_ymfpci_free(chip); | 2402 | err = -EBUSY; |
| 2403 | return -EBUSY; | 2403 | goto free_chip; |
| 2404 | } | 2404 | } |
| 2405 | if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, | 2405 | if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, |
| 2406 | KBUILD_MODNAME, chip)) { | 2406 | KBUILD_MODNAME, chip)) { |
| 2407 | dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); | 2407 | dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq); |
| 2408 | snd_ymfpci_free(chip); | 2408 | err = -EBUSY; |
| 2409 | return -EBUSY; | 2409 | goto free_chip; |
| 2410 | } | 2410 | } |
| 2411 | chip->irq = pci->irq; | 2411 | chip->irq = pci->irq; |
| 2412 | 2412 | ||
| 2413 | snd_ymfpci_aclink_reset(pci); | 2413 | snd_ymfpci_aclink_reset(pci); |
| 2414 | if (snd_ymfpci_codec_ready(chip, 0) < 0) { | 2414 | if (snd_ymfpci_codec_ready(chip, 0) < 0) { |
| 2415 | snd_ymfpci_free(chip); | 2415 | err = -EIO; |
| 2416 | return -EIO; | 2416 | goto free_chip; |
| 2417 | } | 2417 | } |
| 2418 | 2418 | ||
| 2419 | err = snd_ymfpci_request_firmware(chip); | 2419 | err = snd_ymfpci_request_firmware(chip); |
| 2420 | if (err < 0) { | 2420 | if (err < 0) { |
| 2421 | dev_err(chip->card->dev, "firmware request failed: %d\n", err); | 2421 | dev_err(chip->card->dev, "firmware request failed: %d\n", err); |
| 2422 | snd_ymfpci_free(chip); | 2422 | goto free_chip; |
| 2423 | return err; | ||
| 2424 | } | 2423 | } |
| 2425 | snd_ymfpci_download_image(chip); | 2424 | snd_ymfpci_download_image(chip); |
| 2426 | 2425 | ||
| 2427 | udelay(100); /* seems we need a delay after downloading image.. */ | 2426 | udelay(100); /* seems we need a delay after downloading image.. */ |
| 2428 | 2427 | ||
| 2429 | if (snd_ymfpci_memalloc(chip) < 0) { | 2428 | if (snd_ymfpci_memalloc(chip) < 0) { |
| 2430 | snd_ymfpci_free(chip); | 2429 | err = -EIO; |
| 2431 | return -EIO; | 2430 | goto free_chip; |
| 2432 | } | 2431 | } |
| 2433 | 2432 | ||
| 2434 | if ((err = snd_ymfpci_ac3_init(chip)) < 0) { | 2433 | err = snd_ymfpci_ac3_init(chip); |
| 2435 | snd_ymfpci_free(chip); | 2434 | if (err < 0) |
| 2436 | return err; | 2435 | goto free_chip; |
| 2437 | } | ||
| 2438 | 2436 | ||
| 2439 | #ifdef CONFIG_PM_SLEEP | 2437 | #ifdef CONFIG_PM_SLEEP |
| 2440 | chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32), | 2438 | chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32), |
| 2441 | GFP_KERNEL); | 2439 | GFP_KERNEL); |
| 2442 | if (chip->saved_regs == NULL) { | 2440 | if (chip->saved_regs == NULL) { |
| 2443 | snd_ymfpci_free(chip); | 2441 | err = -ENOMEM; |
| 2444 | return -ENOMEM; | 2442 | goto free_chip; |
| 2445 | } | 2443 | } |
| 2446 | #endif | 2444 | #endif |
| 2447 | 2445 | ||
| 2448 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 2446 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
| 2449 | snd_ymfpci_free(chip); | 2447 | if (err < 0) |
| 2450 | return err; | 2448 | goto free_chip; |
| 2451 | } | ||
| 2452 | 2449 | ||
| 2453 | snd_ymfpci_proc_init(card, chip); | 2450 | snd_ymfpci_proc_init(card, chip); |
| 2454 | 2451 | ||
| 2455 | *rchip = chip; | 2452 | *rchip = chip; |
| 2456 | return 0; | 2453 | return 0; |
| 2454 | |||
| 2455 | free_chip: | ||
| 2456 | snd_ymfpci_free(chip); | ||
| 2457 | return err; | ||
| 2457 | } | 2458 | } |
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 0cd7caaed9c4..8445edd06737 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c | |||
| @@ -32,7 +32,6 @@ struct atmel_classd { | |||
| 32 | struct regmap *regmap; | 32 | struct regmap *regmap; |
| 33 | struct clk *pclk; | 33 | struct clk *pclk; |
| 34 | struct clk *gclk; | 34 | struct clk *gclk; |
| 35 | struct clk *aclk; | ||
| 36 | int irq; | 35 | int irq; |
| 37 | const struct atmel_classd_pdata *pdata; | 36 | const struct atmel_classd_pdata *pdata; |
| 38 | }; | 37 | }; |
| @@ -330,11 +329,6 @@ static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream, | |||
| 330 | { | 329 | { |
| 331 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 330 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 332 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); | 331 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); |
| 333 | int ret; | ||
| 334 | |||
| 335 | ret = clk_prepare_enable(dd->aclk); | ||
| 336 | if (ret) | ||
| 337 | return ret; | ||
| 338 | 332 | ||
| 339 | return clk_prepare_enable(dd->gclk); | 333 | return clk_prepare_enable(dd->gclk); |
| 340 | } | 334 | } |
| @@ -357,31 +351,31 @@ static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai, | |||
| 357 | return 0; | 351 | return 0; |
| 358 | } | 352 | } |
| 359 | 353 | ||
| 360 | #define CLASSD_ACLK_RATE_11M2896_MPY_8 (112896 * 100 * 8) | 354 | #define CLASSD_GCLK_RATE_11M2896_MPY_8 (112896 * 100 * 8) |
| 361 | #define CLASSD_ACLK_RATE_12M288_MPY_8 (12288 * 1000 * 8) | 355 | #define CLASSD_GCLK_RATE_12M288_MPY_8 (12288 * 1000 * 8) |
| 362 | 356 | ||
| 363 | static struct { | 357 | static struct { |
| 364 | int rate; | 358 | int rate; |
| 365 | int sample_rate; | 359 | int sample_rate; |
| 366 | int dsp_clk; | 360 | int dsp_clk; |
| 367 | unsigned long aclk_rate; | 361 | unsigned long gclk_rate; |
| 368 | } const sample_rates[] = { | 362 | } const sample_rates[] = { |
| 369 | { 8000, CLASSD_INTPMR_FRAME_8K, | 363 | { 8000, CLASSD_INTPMR_FRAME_8K, |
| 370 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | 364 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, |
| 371 | { 16000, CLASSD_INTPMR_FRAME_16K, | 365 | { 16000, CLASSD_INTPMR_FRAME_16K, |
| 372 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | 366 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, |
| 373 | { 32000, CLASSD_INTPMR_FRAME_32K, | 367 | { 32000, CLASSD_INTPMR_FRAME_32K, |
| 374 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | 368 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, |
| 375 | { 48000, CLASSD_INTPMR_FRAME_48K, | 369 | { 48000, CLASSD_INTPMR_FRAME_48K, |
| 376 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | 370 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, |
| 377 | { 96000, CLASSD_INTPMR_FRAME_96K, | 371 | { 96000, CLASSD_INTPMR_FRAME_96K, |
| 378 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | 372 | CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, |
| 379 | { 22050, CLASSD_INTPMR_FRAME_22K, | 373 | { 22050, CLASSD_INTPMR_FRAME_22K, |
| 380 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | 374 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, |
| 381 | { 44100, CLASSD_INTPMR_FRAME_44K, | 375 | { 44100, CLASSD_INTPMR_FRAME_44K, |
| 382 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | 376 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, |
| 383 | { 88200, CLASSD_INTPMR_FRAME_88K, | 377 | { 88200, CLASSD_INTPMR_FRAME_88K, |
| 384 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | 378 | CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, |
| 385 | }; | 379 | }; |
| 386 | 380 | ||
| 387 | static int | 381 | static int |
| @@ -410,13 +404,12 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 410 | } | 404 | } |
| 411 | 405 | ||
| 412 | dev_dbg(codec->dev, | 406 | dev_dbg(codec->dev, |
| 413 | "Selected SAMPLE_RATE of %dHz, ACLK_RATE of %ldHz\n", | 407 | "Selected SAMPLE_RATE of %dHz, GCLK_RATE of %ldHz\n", |
| 414 | sample_rates[best].rate, sample_rates[best].aclk_rate); | 408 | sample_rates[best].rate, sample_rates[best].gclk_rate); |
| 415 | 409 | ||
| 416 | clk_disable_unprepare(dd->gclk); | 410 | clk_disable_unprepare(dd->gclk); |
| 417 | clk_disable_unprepare(dd->aclk); | ||
| 418 | 411 | ||
| 419 | ret = clk_set_rate(dd->aclk, sample_rates[best].aclk_rate); | 412 | ret = clk_set_rate(dd->gclk, sample_rates[best].gclk_rate); |
| 420 | if (ret) | 413 | if (ret) |
| 421 | return ret; | 414 | return ret; |
| 422 | 415 | ||
| @@ -426,10 +419,6 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 426 | 419 | ||
| 427 | snd_soc_update_bits(codec, CLASSD_INTPMR, mask, val); | 420 | snd_soc_update_bits(codec, CLASSD_INTPMR, mask, val); |
| 428 | 421 | ||
| 429 | ret = clk_prepare_enable(dd->aclk); | ||
| 430 | if (ret) | ||
| 431 | return ret; | ||
| 432 | |||
| 433 | return clk_prepare_enable(dd->gclk); | 422 | return clk_prepare_enable(dd->gclk); |
| 434 | } | 423 | } |
| 435 | 424 | ||
| @@ -441,7 +430,6 @@ atmel_classd_codec_dai_shutdown(struct snd_pcm_substream *substream, | |||
| 441 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); | 430 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); |
| 442 | 431 | ||
| 443 | clk_disable_unprepare(dd->gclk); | 432 | clk_disable_unprepare(dd->gclk); |
| 444 | clk_disable_unprepare(dd->aclk); | ||
| 445 | } | 433 | } |
| 446 | 434 | ||
| 447 | static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, | 435 | static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, |
| @@ -596,13 +584,6 @@ static int atmel_classd_probe(struct platform_device *pdev) | |||
| 596 | return ret; | 584 | return ret; |
| 597 | } | 585 | } |
| 598 | 586 | ||
| 599 | dd->aclk = devm_clk_get(dev, "aclk"); | ||
| 600 | if (IS_ERR(dd->aclk)) { | ||
| 601 | ret = PTR_ERR(dd->aclk); | ||
| 602 | dev_err(dev, "failed to get audio clock: %d\n", ret); | ||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 606 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 587 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 607 | io_base = devm_ioremap_resource(dev, res); | 588 | io_base = devm_ioremap_resource(dev, res); |
| 608 | if (IS_ERR(io_base)) { | 589 | if (IS_ERR(io_base)) { |
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index bc2a24f7a791..c7641cb50616 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c | |||
| @@ -143,37 +143,32 @@ static int usb6fire_chip_probe(struct usb_interface *intf, | |||
| 143 | chip->card = card; | 143 | chip->card = card; |
| 144 | 144 | ||
| 145 | ret = usb6fire_comm_init(chip); | 145 | ret = usb6fire_comm_init(chip); |
| 146 | if (ret < 0) { | 146 | if (ret < 0) |
| 147 | usb6fire_chip_destroy(chip); | 147 | goto destroy_chip; |
| 148 | return ret; | ||
| 149 | } | ||
| 150 | 148 | ||
| 151 | ret = usb6fire_midi_init(chip); | 149 | ret = usb6fire_midi_init(chip); |
| 152 | if (ret < 0) { | 150 | if (ret < 0) |
| 153 | usb6fire_chip_destroy(chip); | 151 | goto destroy_chip; |
| 154 | return ret; | ||
| 155 | } | ||
| 156 | 152 | ||
| 157 | ret = usb6fire_pcm_init(chip); | 153 | ret = usb6fire_pcm_init(chip); |
| 158 | if (ret < 0) { | 154 | if (ret < 0) |
| 159 | usb6fire_chip_destroy(chip); | 155 | goto destroy_chip; |
| 160 | return ret; | ||
| 161 | } | ||
| 162 | 156 | ||
| 163 | ret = usb6fire_control_init(chip); | 157 | ret = usb6fire_control_init(chip); |
| 164 | if (ret < 0) { | 158 | if (ret < 0) |
| 165 | usb6fire_chip_destroy(chip); | 159 | goto destroy_chip; |
| 166 | return ret; | ||
| 167 | } | ||
| 168 | 160 | ||
| 169 | ret = snd_card_register(card); | 161 | ret = snd_card_register(card); |
| 170 | if (ret < 0) { | 162 | if (ret < 0) { |
| 171 | dev_err(&intf->dev, "cannot register card."); | 163 | dev_err(&intf->dev, "cannot register card."); |
| 172 | usb6fire_chip_destroy(chip); | 164 | goto destroy_chip; |
| 173 | return ret; | ||
| 174 | } | 165 | } |
| 175 | usb_set_intfdata(intf, chip); | 166 | usb_set_intfdata(intf, chip); |
| 176 | return 0; | 167 | return 0; |
| 168 | |||
| 169 | destroy_chip: | ||
| 170 | usb6fire_chip_destroy(chip); | ||
| 171 | return ret; | ||
| 177 | } | 172 | } |
| 178 | 173 | ||
| 179 | static void usb6fire_chip_disconnect(struct usb_interface *intf) | 174 | static void usb6fire_chip_disconnect(struct usb_interface *intf) |
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index b49d6e953d52..159da1f3924e 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c | |||
| @@ -508,8 +508,7 @@ static bool us122l_create_card(struct snd_card *card) | |||
| 508 | err = us122l_create_usbmidi(card); | 508 | err = us122l_create_usbmidi(card); |
| 509 | if (err < 0) { | 509 | if (err < 0) { |
| 510 | snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); | 510 | snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); |
| 511 | us122l_stop(us122l); | 511 | goto stop; |
| 512 | return false; | ||
| 513 | } | 512 | } |
| 514 | err = usb_stream_hwdep_new(card); | 513 | err = usb_stream_hwdep_new(card); |
| 515 | if (err < 0) { | 514 | if (err < 0) { |
| @@ -518,10 +517,13 @@ static bool us122l_create_card(struct snd_card *card) | |||
| 518 | list_for_each(p, &us122l->midi_list) | 517 | list_for_each(p, &us122l->midi_list) |
| 519 | snd_usbmidi_disconnect(p); | 518 | snd_usbmidi_disconnect(p); |
| 520 | 519 | ||
| 521 | us122l_stop(us122l); | 520 | goto stop; |
| 522 | return false; | ||
| 523 | } | 521 | } |
| 524 | return true; | 522 | return true; |
| 523 | |||
| 524 | stop: | ||
| 525 | us122l_stop(us122l); | ||
| 526 | return false; | ||
| 525 | } | 527 | } |
| 526 | 528 | ||
| 527 | static void snd_us122l_free(struct snd_card *card) | 529 | static void snd_us122l_free(struct snd_card *card) |
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index fe926cb9192e..4dab49080700 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c | |||
| @@ -352,20 +352,22 @@ static int submit_urbs(struct usb_stream_kernel *sk, | |||
| 352 | int err; | 352 | int err; |
| 353 | prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb); | 353 | prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb); |
| 354 | err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC); | 354 | err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC); |
| 355 | if (err < 0) { | 355 | if (err < 0) |
| 356 | snd_printk(KERN_ERR "%i\n", err); | 356 | goto report_failure; |
| 357 | return err; | 357 | |
| 358 | } | ||
| 359 | sk->idle_inurb = sk->completed_inurb; | 358 | sk->idle_inurb = sk->completed_inurb; |
| 360 | sk->completed_inurb = inurb; | 359 | sk->completed_inurb = inurb; |
| 361 | err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC); | 360 | err = usb_submit_urb(sk->idle_outurb, GFP_ATOMIC); |
| 362 | if (err < 0) { | 361 | if (err < 0) |
| 363 | snd_printk(KERN_ERR "%i\n", err); | 362 | goto report_failure; |
| 364 | return err; | 363 | |
| 365 | } | ||
| 366 | sk->idle_outurb = sk->completed_outurb; | 364 | sk->idle_outurb = sk->completed_outurb; |
| 367 | sk->completed_outurb = outurb; | 365 | sk->completed_outurb = outurb; |
| 368 | return 0; | 366 | return 0; |
| 367 | |||
| 368 | report_failure: | ||
| 369 | snd_printk(KERN_ERR "%i\n", err); | ||
| 370 | return err; | ||
| 369 | } | 371 | } |
| 370 | 372 | ||
| 371 | #ifdef DEBUG_LOOP_BACK | 373 | #ifdef DEBUG_LOOP_BACK |
