diff options
107 files changed, 5490 insertions, 699 deletions
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index bae0d87a38b2..5573c08d3180 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt | |||
| @@ -50,6 +50,11 @@ Optional | |||
| 50 | regions, used when the GIC doesn't have banked registers. The offset is | 50 | regions, used when the GIC doesn't have banked registers. The offset is |
| 51 | cpu-offset * cpu-nr. | 51 | cpu-offset * cpu-nr. |
| 52 | 52 | ||
| 53 | - arm,routable-irqs : Total number of gic irq inputs which are not directly | ||
| 54 | connected from the peripherals, but are routed dynamically | ||
| 55 | by a crossbar/multiplexer preceding the GIC. The GIC irq | ||
| 56 | input line is assigned dynamically when the corresponding | ||
| 57 | peripheral's crossbar line is mapped. | ||
| 53 | Example: | 58 | Example: |
| 54 | 59 | ||
| 55 | intc: interrupt-controller@fff11000 { | 60 | intc: interrupt-controller@fff11000 { |
| @@ -57,6 +62,7 @@ Example: | |||
| 57 | #interrupt-cells = <3>; | 62 | #interrupt-cells = <3>; |
| 58 | #address-cells = <1>; | 63 | #address-cells = <1>; |
| 59 | interrupt-controller; | 64 | interrupt-controller; |
| 65 | arm,routable-irqs = <160>; | ||
| 60 | reg = <0xfff11000 0x1000>, | 66 | reg = <0xfff11000 0x1000>, |
| 61 | <0xfff10100 0x100>; | 67 | <0xfff10100 0x100>; |
| 62 | }; | 68 | }; |
diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt new file mode 100644 index 000000000000..fb88585cfb93 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | Some socs have a large number of interrupts requests to service | ||
| 2 | the needs of its many peripherals and subsystems. All of the | ||
| 3 | interrupt lines from the subsystems are not needed at the same | ||
| 4 | time, so they have to be muxed to the irq-controller appropriately. | ||
| 5 | In such places a interrupt controllers are preceded by an CROSSBAR | ||
| 6 | that provides flexibility in muxing the device requests to the controller | ||
| 7 | inputs. | ||
| 8 | |||
| 9 | Required properties: | ||
| 10 | - compatible : Should be "ti,irq-crossbar" | ||
| 11 | - reg: Base address and the size of the crossbar registers. | ||
| 12 | - ti,max-irqs: Total number of irqs available at the interrupt controller. | ||
| 13 | - ti,reg-size: Size of a individual register in bytes. Every individual | ||
| 14 | register is assumed to be of same size. Valid sizes are 1, 2, 4. | ||
| 15 | - ti,irqs-reserved: List of the reserved irq lines that are not muxed using | ||
| 16 | crossbar. These interrupt lines are reserved in the soc, | ||
| 17 | so crossbar bar driver should not consider them as free | ||
| 18 | lines. | ||
| 19 | |||
| 20 | Examples: | ||
| 21 | crossbar_mpu: @4a020000 { | ||
| 22 | compatible = "ti,irq-crossbar"; | ||
| 23 | reg = <0x4a002a48 0x130>; | ||
| 24 | ti,max-irqs = <160>; | ||
| 25 | ti,reg-size = <2>; | ||
| 26 | ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>; | ||
| 27 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/arm-integrator.txt b/Documentation/devicetree/bindings/clock/arm-integrator.txt new file mode 100644 index 000000000000..652914b17b95 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/arm-integrator.txt | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | Clock bindings for ARM Integrator Core Module clocks | ||
| 2 | |||
| 3 | Auxilary Oscillator Clock | ||
| 4 | |||
| 5 | This is a configurable clock fed from a 24 MHz chrystal, | ||
| 6 | used for generating e.g. video clocks. It is located on the | ||
| 7 | core module and there is only one of these. | ||
| 8 | |||
| 9 | This clock node *must* be a subnode of the core module, since | ||
| 10 | it obtains the base address for it's address range from its | ||
| 11 | parent node. | ||
| 12 | |||
| 13 | |||
| 14 | Required properties: | ||
| 15 | - compatible: must be "arm,integrator-cm-auxosc" | ||
| 16 | - #clock-cells: must be <0> | ||
| 17 | |||
| 18 | Optional properties: | ||
| 19 | - clocks: parent clock(s) | ||
| 20 | |||
| 21 | Example: | ||
| 22 | |||
| 23 | core-module@10000000 { | ||
| 24 | xtal24mhz: xtal24mhz@24M { | ||
| 25 | #clock-cells = <0>; | ||
| 26 | compatible = "fixed-clock"; | ||
| 27 | clock-frequency = <24000000>; | ||
| 28 | }; | ||
| 29 | auxosc: cm_aux_osc@25M { | ||
| 30 | #clock-cells = <0>; | ||
| 31 | compatible = "arm,integrator-cm-auxosc"; | ||
| 32 | clocks = <&xtal24mhz>; | ||
| 33 | }; | ||
| 34 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt new file mode 100644 index 000000000000..4897bea7e3f8 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | * Altera SOCFPGA specific extensions to the Synopsys Designware Mobile | ||
| 2 | Storage Host Controller | ||
| 3 | |||
| 4 | The Synopsys designware mobile storage host controller is used to interface | ||
| 5 | a SoC with storage medium such as eMMC or SD/MMC cards. This file documents | ||
| 6 | differences between the core Synopsys dw mshc controller properties described | ||
| 7 | by synopsys-dw-mshc.txt and the properties used by the Altera SOCFPGA specific | ||
| 8 | extensions to the Synopsys Designware Mobile Storage Host Controller. | ||
| 9 | |||
| 10 | Required Properties: | ||
| 11 | |||
| 12 | * compatible: should be | ||
| 13 | - "altr,socfpga-dw-mshc": for Altera's SOCFPGA platform | ||
| 14 | |||
| 15 | Example: | ||
| 16 | |||
| 17 | mmc: dwmmc0@ff704000 { | ||
| 18 | compatible = "altr,socfpga-dw-mshc"; | ||
| 19 | reg = <0xff704000 0x1000>; | ||
| 20 | interrupts = <0 129 4>; | ||
| 21 | #address-cells = <1>; | ||
| 22 | #size-cells = <0>; | ||
| 23 | }; | ||
diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt index 0347d8350d94..af25e77c0e0c 100644 --- a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt +++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | |||
| @@ -6,8 +6,11 @@ Orion5x SoCs. Sending the character 'A', at 19200 baud, tells the | |||
| 6 | microcontroller to turn the power off. This driver adds a handler to | 6 | microcontroller to turn the power off. This driver adds a handler to |
| 7 | pm_power_off which is called to turn the power off. | 7 | pm_power_off which is called to turn the power off. |
| 8 | 8 | ||
| 9 | Synology NAS devices use a similar scheme, but a different baud rate, | ||
| 10 | 9600, and a different character, '1'. | ||
| 11 | |||
| 9 | Required Properties: | 12 | Required Properties: |
| 10 | - compatible: Should be "qnap,power-off" | 13 | - compatible: Should be "qnap,power-off" or "synology,power-off" |
| 11 | 14 | ||
| 12 | - reg: Address and length of the register set for UART1 | 15 | - reg: Address and length of the register set for UART1 |
| 13 | - clocks: tclk clock | 16 | - clocks: tclk clock |
diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt index 5dc8d30061ce..de11eb4c121f 100644 --- a/Documentation/devicetree/bindings/watchdog/marvel.txt +++ b/Documentation/devicetree/bindings/watchdog/marvel.txt | |||
| @@ -3,17 +3,24 @@ | |||
| 3 | Required Properties: | 3 | Required Properties: |
| 4 | 4 | ||
| 5 | - Compatibility : "marvell,orion-wdt" | 5 | - Compatibility : "marvell,orion-wdt" |
| 6 | - reg : Address of the timer registers | 6 | "marvell,armada-370-wdt" |
| 7 | "marvell,armada-xp-wdt" | ||
| 8 | |||
| 9 | - reg : Should contain two entries: first one with the | ||
| 10 | timer control address, second one with the | ||
| 11 | rstout enable address. | ||
| 7 | 12 | ||
| 8 | Optional properties: | 13 | Optional properties: |
| 9 | 14 | ||
| 15 | - interrupts : Contains the IRQ for watchdog expiration | ||
| 10 | - timeout-sec : Contains the watchdog timeout in seconds | 16 | - timeout-sec : Contains the watchdog timeout in seconds |
| 11 | 17 | ||
| 12 | Example: | 18 | Example: |
| 13 | 19 | ||
| 14 | wdt@20300 { | 20 | wdt@20300 { |
| 15 | compatible = "marvell,orion-wdt"; | 21 | compatible = "marvell,orion-wdt"; |
| 16 | reg = <0x20300 0x28>; | 22 | reg = <0x20300 0x28>, <0x20108 0x4>; |
| 23 | interrupts = <3>; | ||
| 17 | timeout-sec = <10>; | 24 | timeout-sec = <10>; |
| 18 | status = "okay"; | 25 | status = "okay"; |
| 19 | }; | 26 | }; |
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts index e6be9315ff0a..b10e6351da53 100644 --- a/arch/arm/boot/dts/integratorap.dts +++ b/arch/arm/boot/dts/integratorap.dts | |||
| @@ -18,6 +18,28 @@ | |||
| 18 | bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk"; | 18 | bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk"; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | /* 24 MHz chrystal on the core module */ | ||
| 22 | xtal24mhz: xtal24mhz@24M { | ||
| 23 | #clock-cells = <0>; | ||
| 24 | compatible = "fixed-clock"; | ||
| 25 | clock-frequency = <24000000>; | ||
| 26 | }; | ||
| 27 | |||
| 28 | pclk: pclk@0 { | ||
| 29 | #clock-cells = <0>; | ||
| 30 | compatible = "fixed-factor-clock"; | ||
| 31 | clock-div = <1>; | ||
| 32 | clock-mult = <1>; | ||
| 33 | clocks = <&xtal24mhz>; | ||
| 34 | }; | ||
| 35 | |||
| 36 | /* The UART clock is 14.74 MHz divided by an ICS525 */ | ||
| 37 | uartclk: uartclk@14.74M { | ||
| 38 | #clock-cells = <0>; | ||
| 39 | compatible = "fixed-clock"; | ||
| 40 | clock-frequency = <14745600>; | ||
| 41 | }; | ||
| 42 | |||
| 21 | syscon { | 43 | syscon { |
| 22 | compatible = "arm,integrator-ap-syscon"; | 44 | compatible = "arm,integrator-ap-syscon"; |
| 23 | reg = <0x11000000 0x100>; | 45 | reg = <0x11000000 0x100>; |
| @@ -28,14 +50,17 @@ | |||
| 28 | 50 | ||
| 29 | timer0: timer@13000000 { | 51 | timer0: timer@13000000 { |
| 30 | compatible = "arm,integrator-timer"; | 52 | compatible = "arm,integrator-timer"; |
| 53 | clocks = <&xtal24mhz>; | ||
| 31 | }; | 54 | }; |
| 32 | 55 | ||
| 33 | timer1: timer@13000100 { | 56 | timer1: timer@13000100 { |
| 34 | compatible = "arm,integrator-timer"; | 57 | compatible = "arm,integrator-timer"; |
| 58 | clocks = <&xtal24mhz>; | ||
| 35 | }; | 59 | }; |
| 36 | 60 | ||
| 37 | timer2: timer@13000200 { | 61 | timer2: timer@13000200 { |
| 38 | compatible = "arm,integrator-timer"; | 62 | compatible = "arm,integrator-timer"; |
| 63 | clocks = <&xtal24mhz>; | ||
| 39 | }; | 64 | }; |
| 40 | 65 | ||
| 41 | pic: pic@14000000 { | 66 | pic: pic@14000000 { |
| @@ -92,26 +117,36 @@ | |||
| 92 | rtc: rtc@15000000 { | 117 | rtc: rtc@15000000 { |
| 93 | compatible = "arm,pl030", "arm,primecell"; | 118 | compatible = "arm,pl030", "arm,primecell"; |
| 94 | arm,primecell-periphid = <0x00041030>; | 119 | arm,primecell-periphid = <0x00041030>; |
| 120 | clocks = <&pclk>; | ||
| 121 | clock-names = "apb_pclk"; | ||
| 95 | }; | 122 | }; |
| 96 | 123 | ||
| 97 | uart0: uart@16000000 { | 124 | uart0: uart@16000000 { |
| 98 | compatible = "arm,pl010", "arm,primecell"; | 125 | compatible = "arm,pl010", "arm,primecell"; |
| 99 | arm,primecell-periphid = <0x00041010>; | 126 | arm,primecell-periphid = <0x00041010>; |
| 127 | clocks = <&uartclk>, <&pclk>; | ||
| 128 | clock-names = "uartclk", "apb_pclk"; | ||
| 100 | }; | 129 | }; |
| 101 | 130 | ||
| 102 | uart1: uart@17000000 { | 131 | uart1: uart@17000000 { |
| 103 | compatible = "arm,pl010", "arm,primecell"; | 132 | compatible = "arm,pl010", "arm,primecell"; |
| 104 | arm,primecell-periphid = <0x00041010>; | 133 | arm,primecell-periphid = <0x00041010>; |
| 134 | clocks = <&uartclk>, <&pclk>; | ||
| 135 | clock-names = "uartclk", "apb_pclk"; | ||
| 105 | }; | 136 | }; |
| 106 | 137 | ||
| 107 | kmi0: kmi@18000000 { | 138 | kmi0: kmi@18000000 { |
| 108 | compatible = "arm,pl050", "arm,primecell"; | 139 | compatible = "arm,pl050", "arm,primecell"; |
| 109 | arm,primecell-periphid = <0x00041050>; | 140 | arm,primecell-periphid = <0x00041050>; |
| 141 | clocks = <&xtal24mhz>, <&pclk>; | ||
| 142 | clock-names = "KMIREFCLK", "apb_pclk"; | ||
| 110 | }; | 143 | }; |
| 111 | 144 | ||
| 112 | kmi1: kmi@19000000 { | 145 | kmi1: kmi@19000000 { |
| 113 | compatible = "arm,pl050", "arm,primecell"; | 146 | compatible = "arm,pl050", "arm,primecell"; |
| 114 | arm,primecell-periphid = <0x00041050>; | 147 | arm,primecell-periphid = <0x00041050>; |
| 148 | clocks = <&xtal24mhz>, <&pclk>; | ||
| 149 | clock-names = "KMIREFCLK", "apb_pclk"; | ||
| 115 | }; | 150 | }; |
| 116 | }; | 151 | }; |
| 117 | }; | 152 | }; |
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts index a21c17de9a5e..d43f15b4f79a 100644 --- a/arch/arm/boot/dts/integratorcp.dts +++ b/arch/arm/boot/dts/integratorcp.dts | |||
| @@ -13,25 +13,107 @@ | |||
| 13 | bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk"; | 13 | bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk"; |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | /* | ||
| 17 | * The Integrator/CP overall clocking architecture can be found in | ||
| 18 | * ARM DUI 0184B page 7-28 "Integrator/CP922T system clocks" which | ||
| 19 | * appear to illustrate the layout used in most configurations. | ||
| 20 | */ | ||
| 21 | |||
| 22 | /* The codec chrystal operates at 24.576 MHz */ | ||
| 23 | xtal_codec: xtal24.576@24.576M { | ||
| 24 | #clock-cells = <0>; | ||
| 25 | compatible = "fixed-clock"; | ||
| 26 | clock-frequency = <24576000>; | ||
| 27 | }; | ||
| 28 | |||
| 29 | /* The chrystal is divided by 2 by the codec for the AACI bit clock */ | ||
| 30 | aaci_bitclk: aaci_bitclk@12.288M { | ||
| 31 | #clock-cells = <0>; | ||
| 32 | compatible = "fixed-factor-clock"; | ||
| 33 | clock-div = <2>; | ||
| 34 | clock-mult = <1>; | ||
| 35 | clocks = <&xtal_codec>; | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* This is a 25MHz chrystal on the base board */ | ||
| 39 | xtal25mhz: xtal25mhz@25M { | ||
| 40 | #clock-cells = <0>; | ||
| 41 | compatible = "fixed-clock"; | ||
| 42 | clock-frequency = <25000000>; | ||
| 43 | }; | ||
| 44 | |||
| 45 | /* The UART clock is 14.74 MHz divided from 25MHz by an ICS525 */ | ||
| 46 | uartclk: uartclk@14.74M { | ||
| 47 | #clock-cells = <0>; | ||
| 48 | compatible = "fixed-clock"; | ||
| 49 | clock-frequency = <14745600>; | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* Actually sysclk I think */ | ||
| 53 | pclk: pclk@0 { | ||
| 54 | #clock-cells = <0>; | ||
| 55 | compatible = "fixed-clock"; | ||
| 56 | clock-frequency = <0>; | ||
| 57 | }; | ||
| 58 | |||
| 59 | core-module@10000000 { | ||
| 60 | /* 24 MHz chrystal on the core module */ | ||
| 61 | xtal24mhz: xtal24mhz@24M { | ||
| 62 | #clock-cells = <0>; | ||
| 63 | compatible = "fixed-clock"; | ||
| 64 | clock-frequency = <24000000>; | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* | ||
| 68 | * External oscillator on the core module, usually used | ||
| 69 | * to drive video circuitry. Driven from the 24MHz clock. | ||
| 70 | */ | ||
| 71 | auxosc: cm_aux_osc@25M { | ||
| 72 | #clock-cells = <0>; | ||
| 73 | compatible = "arm,integrator-cm-auxosc"; | ||
| 74 | clocks = <&xtal24mhz>; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* The KMI clock is the 24 MHz oscillator divided to 8MHz */ | ||
| 78 | kmiclk: kmiclk@1M { | ||
| 79 | #clock-cells = <0>; | ||
| 80 | compatible = "fixed-factor-clock"; | ||
| 81 | clock-div = <3>; | ||
| 82 | clock-mult = <1>; | ||
| 83 | clocks = <&xtal24mhz>; | ||
| 84 | }; | ||
| 85 | |||
| 86 | /* The timer clock is the 24 MHz oscillator divided to 1MHz */ | ||
| 87 | timclk: timclk@1M { | ||
| 88 | #clock-cells = <0>; | ||
| 89 | compatible = "fixed-factor-clock"; | ||
| 90 | clock-div = <24>; | ||
| 91 | clock-mult = <1>; | ||
| 92 | clocks = <&xtal24mhz>; | ||
| 93 | }; | ||
| 94 | }; | ||
| 95 | |||
| 16 | syscon { | 96 | syscon { |
| 17 | compatible = "arm,integrator-cp-syscon"; | 97 | compatible = "arm,integrator-cp-syscon"; |
| 18 | reg = <0xcb000000 0x100>; | 98 | reg = <0xcb000000 0x100>; |
| 19 | }; | 99 | }; |
| 20 | 100 | ||
| 21 | timer0: timer@13000000 { | 101 | timer0: timer@13000000 { |
| 22 | /* TIMER0 runs @ 25MHz */ | 102 | /* TIMER0 runs directly on the 25MHz chrystal */ |
| 23 | compatible = "arm,integrator-cp-timer"; | 103 | compatible = "arm,integrator-cp-timer"; |
| 24 | status = "disabled"; | 104 | clocks = <&xtal25mhz>; |
| 25 | }; | 105 | }; |
| 26 | 106 | ||
| 27 | timer1: timer@13000100 { | 107 | timer1: timer@13000100 { |
| 28 | /* TIMER1 runs @ 1MHz */ | 108 | /* TIMER1 runs @ 1MHz */ |
| 29 | compatible = "arm,integrator-cp-timer"; | 109 | compatible = "arm,integrator-cp-timer"; |
| 110 | clocks = <&timclk>; | ||
| 30 | }; | 111 | }; |
| 31 | 112 | ||
| 32 | timer2: timer@13000200 { | 113 | timer2: timer@13000200 { |
| 33 | /* TIMER2 runs @ 1MHz */ | 114 | /* TIMER2 runs @ 1MHz */ |
| 34 | compatible = "arm,integrator-cp-timer"; | 115 | compatible = "arm,integrator-cp-timer"; |
| 116 | clocks = <&timclk>; | ||
| 35 | }; | 117 | }; |
| 36 | 118 | ||
| 37 | pic: pic@14000000 { | 119 | pic: pic@14000000 { |
| @@ -74,22 +156,32 @@ | |||
| 74 | */ | 156 | */ |
| 75 | rtc@15000000 { | 157 | rtc@15000000 { |
| 76 | compatible = "arm,pl031", "arm,primecell"; | 158 | compatible = "arm,pl031", "arm,primecell"; |
| 159 | clocks = <&pclk>; | ||
| 160 | clock-names = "apb_pclk"; | ||
| 77 | }; | 161 | }; |
| 78 | 162 | ||
| 79 | uart@16000000 { | 163 | uart@16000000 { |
| 80 | compatible = "arm,pl011", "arm,primecell"; | 164 | compatible = "arm,pl011", "arm,primecell"; |
| 165 | clocks = <&uartclk>, <&pclk>; | ||
| 166 | clock-names = "uartclk", "apb_pclk"; | ||
| 81 | }; | 167 | }; |
| 82 | 168 | ||
| 83 | uart@17000000 { | 169 | uart@17000000 { |
| 84 | compatible = "arm,pl011", "arm,primecell"; | 170 | compatible = "arm,pl011", "arm,primecell"; |
| 171 | clocks = <&uartclk>, <&pclk>; | ||
| 172 | clock-names = "uartclk", "apb_pclk"; | ||
| 85 | }; | 173 | }; |
| 86 | 174 | ||
| 87 | kmi@18000000 { | 175 | kmi@18000000 { |
| 88 | compatible = "arm,pl050", "arm,primecell"; | 176 | compatible = "arm,pl050", "arm,primecell"; |
| 177 | clocks = <&kmiclk>, <&pclk>; | ||
| 178 | clock-names = "KMIREFCLK", "apb_pclk"; | ||
| 89 | }; | 179 | }; |
| 90 | 180 | ||
| 91 | kmi@19000000 { | 181 | kmi@19000000 { |
| 92 | compatible = "arm,pl050", "arm,primecell"; | 182 | compatible = "arm,pl050", "arm,primecell"; |
| 183 | clocks = <&kmiclk>, <&pclk>; | ||
| 184 | clock-names = "KMIREFCLK", "apb_pclk"; | ||
| 93 | }; | 185 | }; |
| 94 | 186 | ||
| 95 | /* | 187 | /* |
| @@ -100,18 +192,24 @@ | |||
| 100 | reg = <0x1c000000 0x1000>; | 192 | reg = <0x1c000000 0x1000>; |
| 101 | interrupts = <23 24>; | 193 | interrupts = <23 24>; |
| 102 | max-frequency = <515633>; | 194 | max-frequency = <515633>; |
| 195 | clocks = <&uartclk>, <&pclk>; | ||
| 196 | clock-names = "mclk", "apb_pclk"; | ||
| 103 | }; | 197 | }; |
| 104 | 198 | ||
| 105 | aaci@1d000000 { | 199 | aaci@1d000000 { |
| 106 | compatible = "arm,pl041", "arm,primecell"; | 200 | compatible = "arm,pl041", "arm,primecell"; |
| 107 | reg = <0x1d000000 0x1000>; | 201 | reg = <0x1d000000 0x1000>; |
| 108 | interrupts = <25>; | 202 | interrupts = <25>; |
| 203 | clocks = <&pclk>; | ||
| 204 | clock-names = "apb_pclk"; | ||
| 109 | }; | 205 | }; |
| 110 | 206 | ||
| 111 | clcd@c0000000 { | 207 | clcd@c0000000 { |
| 112 | compatible = "arm,pl110", "arm,primecell"; | 208 | compatible = "arm,pl110", "arm,primecell"; |
| 113 | reg = <0xC0000000 0x1000>; | 209 | reg = <0xC0000000 0x1000>; |
| 114 | interrupts = <22>; | 210 | interrupts = <22>; |
| 211 | clocks = <&auxosc>, <&pclk>; | ||
| 212 | clock-names = "clcd", "apb_pclk"; | ||
| 115 | }; | 213 | }; |
| 116 | }; | 214 | }; |
| 117 | }; | 215 | }; |
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index e22520dff8c6..618e5b537eaf 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi | |||
| @@ -421,6 +421,29 @@ | |||
| 421 | clock-output-names = "extal"; | 421 | clock-output-names = "extal"; |
| 422 | }; | 422 | }; |
| 423 | 423 | ||
| 424 | /* | ||
| 425 | * The external audio clocks are configured as 0 Hz fixed frequency clocks by | ||
| 426 | * default. Boards that provide audio clocks should override them. | ||
| 427 | */ | ||
| 428 | audio_clk_a: audio_clk_a { | ||
| 429 | compatible = "fixed-clock"; | ||
| 430 | #clock-cells = <0>; | ||
| 431 | clock-frequency = <0>; | ||
| 432 | clock-output-names = "audio_clk_a"; | ||
| 433 | }; | ||
| 434 | audio_clk_b: audio_clk_b { | ||
| 435 | compatible = "fixed-clock"; | ||
| 436 | #clock-cells = <0>; | ||
| 437 | clock-frequency = <0>; | ||
| 438 | clock-output-names = "audio_clk_b"; | ||
| 439 | }; | ||
| 440 | audio_clk_c: audio_clk_c { | ||
| 441 | compatible = "fixed-clock"; | ||
| 442 | #clock-cells = <0>; | ||
| 443 | clock-frequency = <0>; | ||
| 444 | clock-output-names = "audio_clk_c"; | ||
| 445 | }; | ||
| 446 | |||
| 424 | /* Special CPG clocks */ | 447 | /* Special CPG clocks */ |
| 425 | cpg_clocks: cpg_clocks@e6150000 { | 448 | cpg_clocks: cpg_clocks@e6150000 { |
| 426 | compatible = "renesas,r8a7790-cpg-clocks", | 449 | compatible = "renesas,r8a7790-cpg-clocks", |
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index ba51d69abbea..4568c9869d44 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi | |||
| @@ -92,7 +92,12 @@ | |||
| 92 | #address-cells = <1>; | 92 | #address-cells = <1>; |
| 93 | #size-cells = <0>; | 93 | #size-cells = <0>; |
| 94 | 94 | ||
| 95 | osc: osc1 { | 95 | osc1: osc1 { |
| 96 | #clock-cells = <0>; | ||
| 97 | compatible = "fixed-clock"; | ||
| 98 | }; | ||
| 99 | |||
| 100 | osc2: osc2 { | ||
| 96 | #clock-cells = <0>; | 101 | #clock-cells = <0>; |
| 97 | compatible = "fixed-clock"; | 102 | compatible = "fixed-clock"; |
| 98 | }; | 103 | }; |
| @@ -100,7 +105,11 @@ | |||
| 100 | f2s_periph_ref_clk: f2s_periph_ref_clk { | 105 | f2s_periph_ref_clk: f2s_periph_ref_clk { |
| 101 | #clock-cells = <0>; | 106 | #clock-cells = <0>; |
| 102 | compatible = "fixed-clock"; | 107 | compatible = "fixed-clock"; |
| 103 | clock-frequency = <10000000>; | 108 | }; |
| 109 | |||
| 110 | f2s_sdram_ref_clk: f2s_sdram_ref_clk { | ||
| 111 | #clock-cells = <0>; | ||
| 112 | compatible = "fixed-clock"; | ||
| 104 | }; | 113 | }; |
| 105 | 114 | ||
| 106 | main_pll: main_pll { | 115 | main_pll: main_pll { |
| @@ -108,7 +117,7 @@ | |||
| 108 | #size-cells = <0>; | 117 | #size-cells = <0>; |
| 109 | #clock-cells = <0>; | 118 | #clock-cells = <0>; |
| 110 | compatible = "altr,socfpga-pll-clock"; | 119 | compatible = "altr,socfpga-pll-clock"; |
| 111 | clocks = <&osc>; | 120 | clocks = <&osc1>; |
| 112 | reg = <0x40>; | 121 | reg = <0x40>; |
| 113 | 122 | ||
| 114 | mpuclk: mpuclk { | 123 | mpuclk: mpuclk { |
| @@ -162,7 +171,7 @@ | |||
| 162 | #size-cells = <0>; | 171 | #size-cells = <0>; |
| 163 | #clock-cells = <0>; | 172 | #clock-cells = <0>; |
| 164 | compatible = "altr,socfpga-pll-clock"; | 173 | compatible = "altr,socfpga-pll-clock"; |
| 165 | clocks = <&osc>; | 174 | clocks = <&osc1>, <&osc2>, <&f2s_periph_ref_clk>; |
| 166 | reg = <0x80>; | 175 | reg = <0x80>; |
| 167 | 176 | ||
| 168 | emac0_clk: emac0_clk { | 177 | emac0_clk: emac0_clk { |
| @@ -213,7 +222,7 @@ | |||
| 213 | #size-cells = <0>; | 222 | #size-cells = <0>; |
| 214 | #clock-cells = <0>; | 223 | #clock-cells = <0>; |
| 215 | compatible = "altr,socfpga-pll-clock"; | 224 | compatible = "altr,socfpga-pll-clock"; |
| 216 | clocks = <&osc>; | 225 | clocks = <&osc1>, <&osc2>, <&f2s_sdram_ref_clk>; |
| 217 | reg = <0xC0>; | 226 | reg = <0xC0>; |
| 218 | 227 | ||
| 219 | ddr_dqs_clk: ddr_dqs_clk { | 228 | ddr_dqs_clk: ddr_dqs_clk { |
| @@ -475,6 +484,17 @@ | |||
| 475 | arm,data-latency = <2 1 1>; | 484 | arm,data-latency = <2 1 1>; |
| 476 | }; | 485 | }; |
| 477 | 486 | ||
| 487 | mmc: dwmmc0@ff704000 { | ||
| 488 | compatible = "altr,socfpga-dw-mshc"; | ||
| 489 | reg = <0xff704000 0x1000>; | ||
| 490 | interrupts = <0 139 4>; | ||
| 491 | fifo-depth = <0x400>; | ||
| 492 | #address-cells = <1>; | ||
| 493 | #size-cells = <0>; | ||
| 494 | clocks = <&l4_mp_clk>, <&sdmmc_clk>; | ||
| 495 | clock-names = "biu", "ciu"; | ||
| 496 | }; | ||
| 497 | |||
| 478 | /* Local timer */ | 498 | /* Local timer */ |
| 479 | timer@fffec600 { | 499 | timer@fffec600 { |
| 480 | compatible = "arm,cortex-a9-twd-timer"; | 500 | compatible = "arm,cortex-a9-twd-timer"; |
| @@ -528,9 +548,9 @@ | |||
| 528 | reg = <0xffd05000 0x1000>; | 548 | reg = <0xffd05000 0x1000>; |
| 529 | }; | 549 | }; |
| 530 | 550 | ||
| 531 | sysmgr@ffd08000 { | 551 | sysmgr: sysmgr@ffd08000 { |
| 532 | compatible = "altr,sys-mgr"; | 552 | compatible = "altr,sys-mgr", "syscon"; |
| 533 | reg = <0xffd08000 0x4000>; | 553 | reg = <0xffd08000 0x4000>; |
| 534 | }; | 554 | }; |
| 535 | }; | 555 | }; |
| 536 | }; | 556 | }; |
diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/socfpga_arria5.dtsi index a85b4043f888..6c87b7070ca7 100644 --- a/arch/arm/boot/dts/socfpga_arria5.dtsi +++ b/arch/arm/boot/dts/socfpga_arria5.dtsi | |||
| @@ -27,6 +27,17 @@ | |||
| 27 | }; | 27 | }; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | dwmmc0@ff704000 { | ||
| 31 | num-slots = <1>; | ||
| 32 | supports-highspeed; | ||
| 33 | broken-cd; | ||
| 34 | |||
| 35 | slot@0 { | ||
| 36 | reg = <0>; | ||
| 37 | bus-width = <4>; | ||
| 38 | }; | ||
| 39 | }; | ||
| 40 | |||
| 30 | serial0@ffc02000 { | 41 | serial0@ffc02000 { |
| 31 | clock-frequency = <100000000>; | 42 | clock-frequency = <100000000>; |
| 32 | }; | 43 | }; |
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi index a8716f6dbe2e..ca41b0ebf461 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi +++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi | |||
| @@ -28,6 +28,17 @@ | |||
| 28 | }; | 28 | }; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | dwmmc0@ff704000 { | ||
| 32 | num-slots = <1>; | ||
| 33 | supports-highspeed; | ||
| 34 | broken-cd; | ||
| 35 | |||
| 36 | slot@0 { | ||
| 37 | reg = <0>; | ||
| 38 | bus-width = <4>; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | |||
| 31 | ethernet@ff702000 { | 42 | ethernet@ff702000 { |
| 32 | phy-mode = "rgmii"; | 43 | phy-mode = "rgmii"; |
| 33 | phy-addr = <0xffffffff>; /* probe for phy addr */ | 44 | phy-addr = <0xffffffff>; /* probe for phy addr */ |
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts index dde2c66c50eb..87d6f759a9c1 100644 --- a/arch/arm/boot/dts/socfpga_vt.dts +++ b/arch/arm/boot/dts/socfpga_vt.dts | |||
| @@ -41,6 +41,17 @@ | |||
| 41 | }; | 41 | }; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | dwmmc0@ff704000 { | ||
| 45 | num-slots = <1>; | ||
| 46 | supports-highspeed; | ||
| 47 | broken-cd; | ||
| 48 | |||
| 49 | slot@0 { | ||
| 50 | reg = <0>; | ||
| 51 | bus-width = <4>; | ||
| 52 | }; | ||
| 53 | }; | ||
| 54 | |||
| 44 | ethernet@ff700000 { | 55 | ethernet@ff700000 { |
| 45 | phy-mode = "gmii"; | 56 | phy-mode = "gmii"; |
| 46 | status = "okay"; | 57 | status = "okay"; |
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 53c6a26b633d..fd6bff0c5b96 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c | |||
| @@ -271,10 +271,14 @@ static void __init integrator_cp_of_init(struct device_node *np) | |||
| 271 | void __iomem *base; | 271 | void __iomem *base; |
| 272 | int irq; | 272 | int irq; |
| 273 | const char *name = of_get_property(np, "compatible", NULL); | 273 | const char *name = of_get_property(np, "compatible", NULL); |
| 274 | struct clk *clk; | ||
| 274 | 275 | ||
| 275 | base = of_iomap(np, 0); | 276 | base = of_iomap(np, 0); |
| 276 | if (WARN_ON(!base)) | 277 | if (WARN_ON(!base)) |
| 277 | return; | 278 | return; |
| 279 | clk = of_clk_get(np, 0); | ||
| 280 | if (WARN_ON(IS_ERR(clk))) | ||
| 281 | return; | ||
| 278 | 282 | ||
| 279 | /* Ensure timer is disabled */ | 283 | /* Ensure timer is disabled */ |
| 280 | writel(0, base + TIMER_CTRL); | 284 | writel(0, base + TIMER_CTRL); |
| @@ -283,13 +287,13 @@ static void __init integrator_cp_of_init(struct device_node *np) | |||
| 283 | goto err; | 287 | goto err; |
| 284 | 288 | ||
| 285 | if (!init_count) | 289 | if (!init_count) |
| 286 | sp804_clocksource_init(base, name); | 290 | __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); |
| 287 | else { | 291 | else { |
| 288 | irq = irq_of_parse_and_map(np, 0); | 292 | irq = irq_of_parse_and_map(np, 0); |
| 289 | if (irq <= 0) | 293 | if (irq <= 0) |
| 290 | goto err; | 294 | goto err; |
| 291 | 295 | ||
| 292 | sp804_clockevents_init(base, irq, name); | 296 | __sp804_clockevents_init(base, irq, clk, name); |
| 293 | } | 297 | } |
| 294 | 298 | ||
| 295 | init_count++; | 299 | init_count++; |
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig index 4e1ce211d43f..e3a05e8801d8 100644 --- a/arch/arm/configs/socfpga_defconfig +++ b/arch/arm/configs/socfpga_defconfig | |||
| @@ -52,6 +52,7 @@ CONFIG_BLK_DEV_SD=y | |||
| 52 | # CONFIG_SCSI_LOWLEVEL is not set | 52 | # CONFIG_SCSI_LOWLEVEL is not set |
| 53 | CONFIG_NETDEVICES=y | 53 | CONFIG_NETDEVICES=y |
| 54 | CONFIG_STMMAC_ETH=y | 54 | CONFIG_STMMAC_ETH=y |
| 55 | CONFIG_MICREL_PHY=y | ||
| 55 | # CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set | 56 | # CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set |
| 56 | CONFIG_INPUT_EVDEV=y | 57 | CONFIG_INPUT_EVDEV=y |
| 57 | # CONFIG_SERIO_SERPORT is not set | 58 | # CONFIG_SERIO_SERPORT is not set |
| @@ -66,6 +67,9 @@ CONFIG_SERIAL_8250_DW=y | |||
| 66 | CONFIG_EXT2_FS=y | 67 | CONFIG_EXT2_FS=y |
| 67 | CONFIG_EXT2_FS_XATTR=y | 68 | CONFIG_EXT2_FS_XATTR=y |
| 68 | CONFIG_EXT2_FS_POSIX_ACL=y | 69 | CONFIG_EXT2_FS_POSIX_ACL=y |
| 70 | CONFIG_EXT3_FS=y | ||
| 71 | CONFIG_NFS_FS=y | ||
| 72 | CONFIG_ROOT_NFS=y | ||
| 69 | # CONFIG_DNOTIFY is not set | 73 | # CONFIG_DNOTIFY is not set |
| 70 | # CONFIG_INOTIFY_USER is not set | 74 | # CONFIG_INOTIFY_USER is not set |
| 71 | CONFIG_VFAT_FS=y | 75 | CONFIG_VFAT_FS=y |
| @@ -82,3 +86,5 @@ CONFIG_DEBUG_INFO=y | |||
| 82 | CONFIG_ENABLE_DEFAULT_TRACERS=y | 86 | CONFIG_ENABLE_DEFAULT_TRACERS=y |
| 83 | CONFIG_DEBUG_USER=y | 87 | CONFIG_DEBUG_USER=y |
| 84 | CONFIG_XZ_DEC=y | 88 | CONFIG_XZ_DEC=y |
| 89 | CONFIG_MMC=y | ||
| 90 | CONFIG_MMC_DW=y | ||
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c index f091a9010c2f..ff8b7e76b6e9 100644 --- a/arch/arm/mach-davinci/aemif.c +++ b/arch/arm/mach-davinci/aemif.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
| 17 | 17 | ||
| 18 | #include <linux/platform_data/mtd-davinci-aemif.h> | 18 | #include <linux/platform_data/mtd-davinci-aemif.h> |
| 19 | #include <linux/platform_data/mtd-davinci.h> | ||
| 19 | 20 | ||
| 20 | /* Timing value configuration */ | 21 | /* Timing value configuration */ |
| 21 | 22 | ||
| @@ -43,6 +44,17 @@ | |||
| 43 | WSTROBE(WSTROBE_MAX) | \ | 44 | WSTROBE(WSTROBE_MAX) | \ |
| 44 | WSETUP(WSETUP_MAX)) | 45 | WSETUP(WSETUP_MAX)) |
| 45 | 46 | ||
| 47 | static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset) | ||
| 48 | { | ||
| 49 | return readl_relaxed(base + offset); | ||
| 50 | } | ||
| 51 | |||
| 52 | static inline void davinci_aemif_writel(void __iomem *base, | ||
| 53 | int offset, unsigned long value) | ||
| 54 | { | ||
| 55 | writel_relaxed(value, base + offset); | ||
| 56 | } | ||
| 57 | |||
| 46 | /* | 58 | /* |
| 47 | * aemif_calc_rate - calculate timing data. | 59 | * aemif_calc_rate - calculate timing data. |
| 48 | * @wanted: The cycle time needed in nanoseconds. | 60 | * @wanted: The cycle time needed in nanoseconds. |
| @@ -76,6 +88,7 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max) | |||
| 76 | * @t: timing values to be progammed | 88 | * @t: timing values to be progammed |
| 77 | * @base: The virtual base address of the AEMIF interface | 89 | * @base: The virtual base address of the AEMIF interface |
| 78 | * @cs: chip-select to program the timing values for | 90 | * @cs: chip-select to program the timing values for |
| 91 | * @clkrate: the AEMIF clkrate | ||
| 79 | * | 92 | * |
| 80 | * This function programs the given timing values (in real clock) into the | 93 | * This function programs the given timing values (in real clock) into the |
| 81 | * AEMIF registers taking the AEMIF clock into account. | 94 | * AEMIF registers taking the AEMIF clock into account. |
| @@ -86,24 +99,17 @@ static int aemif_calc_rate(int wanted, unsigned long clk, int max) | |||
| 86 | * | 99 | * |
| 87 | * Returns 0 on success, else negative errno. | 100 | * Returns 0 on success, else negative errno. |
| 88 | */ | 101 | */ |
| 89 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | 102 | static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, |
| 90 | void __iomem *base, unsigned cs) | 103 | void __iomem *base, unsigned cs, |
| 104 | unsigned long clkrate) | ||
| 91 | { | 105 | { |
| 92 | unsigned set, val; | 106 | unsigned set, val; |
| 93 | int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; | 107 | int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; |
| 94 | unsigned offset = A1CR_OFFSET + cs * 4; | 108 | unsigned offset = A1CR_OFFSET + cs * 4; |
| 95 | struct clk *aemif_clk; | ||
| 96 | unsigned long clkrate; | ||
| 97 | 109 | ||
| 98 | if (!t) | 110 | if (!t) |
| 99 | return 0; /* Nothing to do */ | 111 | return 0; /* Nothing to do */ |
| 100 | 112 | ||
| 101 | aemif_clk = clk_get(NULL, "aemif"); | ||
| 102 | if (IS_ERR(aemif_clk)) | ||
| 103 | return PTR_ERR(aemif_clk); | ||
| 104 | |||
| 105 | clkrate = clk_get_rate(aemif_clk); | ||
| 106 | |||
| 107 | clkrate /= 1000; /* turn clock into kHz for ease of use */ | 113 | clkrate /= 1000; /* turn clock into kHz for ease of use */ |
| 108 | 114 | ||
| 109 | ta = aemif_calc_rate(t->ta, clkrate, TA_MAX); | 115 | ta = aemif_calc_rate(t->ta, clkrate, TA_MAX); |
| @@ -130,4 +136,83 @@ int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | |||
| 130 | 136 | ||
| 131 | return 0; | 137 | return 0; |
| 132 | } | 138 | } |
| 133 | EXPORT_SYMBOL(davinci_aemif_setup_timing); | 139 | |
| 140 | /** | ||
| 141 | * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata | ||
| 142 | * @pdev - link to platform device to setup settings for | ||
| 143 | * | ||
| 144 | * This function does not use any locking while programming the AEMIF | ||
| 145 | * because it is expected that there is only one user of a given | ||
| 146 | * chip-select. | ||
| 147 | * | ||
| 148 | * Returns 0 on success, else negative errno. | ||
| 149 | */ | ||
| 150 | int davinci_aemif_setup(struct platform_device *pdev) | ||
| 151 | { | ||
| 152 | struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
| 153 | uint32_t val; | ||
| 154 | unsigned long clkrate; | ||
| 155 | struct resource *res; | ||
| 156 | void __iomem *base; | ||
| 157 | struct clk *clk; | ||
| 158 | int ret = 0; | ||
| 159 | |||
| 160 | clk = clk_get(&pdev->dev, "aemif"); | ||
| 161 | if (IS_ERR(clk)) { | ||
| 162 | ret = PTR_ERR(clk); | ||
| 163 | dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); | ||
| 164 | return ret; | ||
| 165 | } | ||
| 166 | |||
| 167 | ret = clk_prepare_enable(clk); | ||
| 168 | if (ret < 0) { | ||
| 169 | dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n", | ||
| 170 | ret); | ||
| 171 | goto err_put; | ||
| 172 | } | ||
| 173 | |||
| 174 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 175 | if (!res) { | ||
| 176 | dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n"); | ||
| 177 | ret = -ENOMEM; | ||
| 178 | goto err; | ||
| 179 | } | ||
| 180 | |||
| 181 | base = ioremap(res->start, resource_size(res)); | ||
| 182 | if (!base) { | ||
| 183 | dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res); | ||
| 184 | ret = -ENOMEM; | ||
| 185 | goto err; | ||
| 186 | } | ||
| 187 | |||
| 188 | /* | ||
| 189 | * Setup Async configuration register in case we did not boot | ||
| 190 | * from NAND and so bootloader did not bother to set it up. | ||
| 191 | */ | ||
| 192 | val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4); | ||
| 193 | /* | ||
| 194 | * Extended Wait is not valid and Select Strobe mode is not | ||
| 195 | * used | ||
| 196 | */ | ||
| 197 | val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK); | ||
| 198 | if (pdata->options & NAND_BUSWIDTH_16) | ||
| 199 | val |= 0x1; | ||
| 200 | |||
| 201 | davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val); | ||
| 202 | |||
| 203 | clkrate = clk_get_rate(clk); | ||
| 204 | |||
| 205 | if (pdata->timing) | ||
| 206 | ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id, | ||
| 207 | clkrate); | ||
| 208 | |||
| 209 | if (ret < 0) | ||
| 210 | dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); | ||
| 211 | |||
| 212 | iounmap(base); | ||
| 213 | err: | ||
| 214 | clk_disable_unprepare(clk); | ||
| 215 | err_put: | ||
| 216 | clk_put(clk); | ||
| 217 | return ret; | ||
| 218 | } | ||
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index d1f45af7a530..5623131c4f0b 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c | |||
| @@ -419,6 +419,9 @@ static inline void da830_evm_init_nand(int mux_mode) | |||
| 419 | if (ret) | 419 | if (ret) |
| 420 | pr_warning("da830_evm_init: NAND device not registered.\n"); | 420 | pr_warning("da830_evm_init: NAND device not registered.\n"); |
| 421 | 421 | ||
| 422 | if (davinci_aemif_setup(&da830_evm_nand_device)) | ||
| 423 | pr_warn("%s: Cannot configure AEMIF.\n", __func__); | ||
| 424 | |||
| 422 | gpio_direction_output(mux_mode, 1); | 425 | gpio_direction_output(mux_mode, 1); |
| 423 | } | 426 | } |
| 424 | #else | 427 | #else |
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index e0af0eccde8f..234c5bb091f5 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c | |||
| @@ -358,6 +358,9 @@ static inline void da850_evm_setup_nor_nand(void) | |||
| 358 | 358 | ||
| 359 | platform_add_devices(da850_evm_devices, | 359 | platform_add_devices(da850_evm_devices, |
| 360 | ARRAY_SIZE(da850_evm_devices)); | 360 | ARRAY_SIZE(da850_evm_devices)); |
| 361 | |||
| 362 | if (davinci_aemif_setup(&da850_evm_nandflash_device)) | ||
| 363 | pr_warn("%s: Cannot configure AEMIF.\n", __func__); | ||
| 361 | } | 364 | } |
| 362 | } | 365 | } |
| 363 | 366 | ||
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 3de4dc9a1698..e583e58b5e1e 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c | |||
| @@ -778,6 +778,11 @@ static __init void davinci_evm_init(void) | |||
| 778 | /* only one device will be jumpered and detected */ | 778 | /* only one device will be jumpered and detected */ |
| 779 | if (HAS_NAND) { | 779 | if (HAS_NAND) { |
| 780 | platform_device_register(&davinci_evm_nandflash_device); | 780 | platform_device_register(&davinci_evm_nandflash_device); |
| 781 | |||
| 782 | if (davinci_aemif_setup(&davinci_evm_nandflash_device)) | ||
| 783 | pr_warn("%s: Cannot configure AEMIF.\n", | ||
| 784 | __func__); | ||
| 785 | |||
| 781 | evm_leds[7].default_trigger = "nand-disk"; | 786 | evm_leds[7].default_trigger = "nand-disk"; |
| 782 | if (HAS_NOR) | 787 | if (HAS_NOR) |
| 783 | pr_warning("WARNING: both NAND and NOR flash " | 788 | pr_warning("WARNING: both NAND and NOR flash " |
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 13d0801fd6b1..ae129bc49273 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c | |||
| @@ -805,6 +805,9 @@ static __init void evm_init(void) | |||
| 805 | 805 | ||
| 806 | platform_device_register(&davinci_nand_device); | 806 | platform_device_register(&davinci_nand_device); |
| 807 | 807 | ||
| 808 | if (davinci_aemif_setup(&davinci_nand_device)) | ||
| 809 | pr_warn("%s: Cannot configure AEMIF.\n", __func__); | ||
| 810 | |||
| 808 | dm646x_init_edma(dm646x_edma_rsv); | 811 | dm646x_init_edma(dm646x_edma_rsv); |
| 809 | 812 | ||
| 810 | if (HAS_ATA) | 813 | if (HAS_ATA) |
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 7aa105b1fd0f..96fc00a167f5 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <mach/cp_intc.h> | 27 | #include <mach/cp_intc.h> |
| 28 | #include <mach/da8xx.h> | 28 | #include <mach/da8xx.h> |
| 29 | #include <linux/platform_data/mtd-davinci.h> | 29 | #include <linux/platform_data/mtd-davinci.h> |
| 30 | #include <linux/platform_data/mtd-davinci-aemif.h> | ||
| 30 | #include <mach/mux.h> | 31 | #include <mach/mux.h> |
| 31 | #include <linux/platform_data/spi-davinci.h> | 32 | #include <linux/platform_data/spi-davinci.h> |
| 32 | 33 | ||
| @@ -432,6 +433,9 @@ static void __init mityomapl138_setup_nand(void) | |||
| 432 | { | 433 | { |
| 433 | platform_add_devices(mityomapl138_devices, | 434 | platform_add_devices(mityomapl138_devices, |
| 434 | ARRAY_SIZE(mityomapl138_devices)); | 435 | ARRAY_SIZE(mityomapl138_devices)); |
| 436 | |||
| 437 | if (davinci_aemif_setup(&mityomapl138_nandflash_device)) | ||
| 438 | pr_warn("%s: Cannot configure AEMIF.\n", __func__); | ||
| 435 | } | 439 | } |
| 436 | 440 | ||
| 437 | static const short mityomap_mii_pins[] = { | 441 | static const short mityomap_mii_pins[] = { |
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h index 5362df3df89f..f4a5b34489b7 100644 --- a/arch/arm/mach-dove/include/mach/bridge-regs.h +++ b/arch/arm/mach-dove/include/mach/bridge-regs.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #define CPU_CTRL_PCIE1_LINK 0x00000008 | 21 | #define CPU_CTRL_PCIE1_LINK 0x00000008 |
| 22 | 22 | ||
| 23 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) | 23 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) |
| 24 | #define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108) | ||
| 24 | #define SOFT_RESET_OUT_EN 0x00000004 | 25 | #define SOFT_RESET_OUT_EN 0x00000004 |
| 25 | 26 | ||
| 26 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) | 27 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) |
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index e00025bbbe89..ba18214c9aca 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c | |||
| @@ -35,56 +35,6 @@ | |||
| 35 | #include "common.h" | 35 | #include "common.h" |
| 36 | #include "regs-pmu.h" | 36 | #include "regs-pmu.h" |
| 37 | 37 | ||
| 38 | #define EXYNOS4_EPLL_LOCK (S5P_VA_CMU + 0x0C010) | ||
| 39 | #define EXYNOS4_VPLL_LOCK (S5P_VA_CMU + 0x0C020) | ||
| 40 | |||
| 41 | #define EXYNOS4_EPLL_CON0 (S5P_VA_CMU + 0x0C110) | ||
| 42 | #define EXYNOS4_EPLL_CON1 (S5P_VA_CMU + 0x0C114) | ||
| 43 | #define EXYNOS4_VPLL_CON0 (S5P_VA_CMU + 0x0C120) | ||
| 44 | #define EXYNOS4_VPLL_CON1 (S5P_VA_CMU + 0x0C124) | ||
| 45 | |||
| 46 | #define EXYNOS4_CLKSRC_MASK_TOP (S5P_VA_CMU + 0x0C310) | ||
| 47 | #define EXYNOS4_CLKSRC_MASK_CAM (S5P_VA_CMU + 0x0C320) | ||
| 48 | #define EXYNOS4_CLKSRC_MASK_TV (S5P_VA_CMU + 0x0C324) | ||
| 49 | #define EXYNOS4_CLKSRC_MASK_LCD0 (S5P_VA_CMU + 0x0C334) | ||
| 50 | #define EXYNOS4_CLKSRC_MASK_MAUDIO (S5P_VA_CMU + 0x0C33C) | ||
| 51 | #define EXYNOS4_CLKSRC_MASK_FSYS (S5P_VA_CMU + 0x0C340) | ||
| 52 | #define EXYNOS4_CLKSRC_MASK_PERIL0 (S5P_VA_CMU + 0x0C350) | ||
| 53 | #define EXYNOS4_CLKSRC_MASK_PERIL1 (S5P_VA_CMU + 0x0C354) | ||
| 54 | |||
| 55 | #define EXYNOS4_CLKSRC_MASK_DMC (S5P_VA_CMU + 0x10300) | ||
| 56 | |||
| 57 | #define EXYNOS4_EPLLCON0_LOCKED_SHIFT (29) | ||
| 58 | #define EXYNOS4_VPLLCON0_LOCKED_SHIFT (29) | ||
| 59 | |||
| 60 | #define EXYNOS4210_CLKSRC_MASK_LCD1 (S5P_VA_CMU + 0x0C338) | ||
| 61 | |||
| 62 | static const struct sleep_save exynos4_set_clksrc[] = { | ||
| 63 | { .reg = EXYNOS4_CLKSRC_MASK_TOP , .val = 0x00000001, }, | ||
| 64 | { .reg = EXYNOS4_CLKSRC_MASK_CAM , .val = 0x11111111, }, | ||
| 65 | { .reg = EXYNOS4_CLKSRC_MASK_TV , .val = 0x00000111, }, | ||
| 66 | { .reg = EXYNOS4_CLKSRC_MASK_LCD0 , .val = 0x00001111, }, | ||
| 67 | { .reg = EXYNOS4_CLKSRC_MASK_MAUDIO , .val = 0x00000001, }, | ||
| 68 | { .reg = EXYNOS4_CLKSRC_MASK_FSYS , .val = 0x01011111, }, | ||
| 69 | { .reg = EXYNOS4_CLKSRC_MASK_PERIL0 , .val = 0x01111111, }, | ||
| 70 | { .reg = EXYNOS4_CLKSRC_MASK_PERIL1 , .val = 0x01110111, }, | ||
| 71 | { .reg = EXYNOS4_CLKSRC_MASK_DMC , .val = 0x00010000, }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static const struct sleep_save exynos4210_set_clksrc[] = { | ||
| 75 | { .reg = EXYNOS4210_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct sleep_save exynos4_epll_save[] = { | ||
| 79 | SAVE_ITEM(EXYNOS4_EPLL_CON0), | ||
| 80 | SAVE_ITEM(EXYNOS4_EPLL_CON1), | ||
| 81 | }; | ||
| 82 | |||
| 83 | static struct sleep_save exynos4_vpll_save[] = { | ||
| 84 | SAVE_ITEM(EXYNOS4_VPLL_CON0), | ||
| 85 | SAVE_ITEM(EXYNOS4_VPLL_CON1), | ||
| 86 | }; | ||
| 87 | |||
| 88 | static struct sleep_save exynos5_sys_save[] = { | 38 | static struct sleep_save exynos5_sys_save[] = { |
| 89 | SAVE_ITEM(EXYNOS5_SYS_I2C_CFG), | 39 | SAVE_ITEM(EXYNOS5_SYS_I2C_CFG), |
| 90 | }; | 40 | }; |
| @@ -124,10 +74,7 @@ static void exynos_pm_prepare(void) | |||
| 124 | 74 | ||
| 125 | s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); | 75 | s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); |
| 126 | 76 | ||
| 127 | if (!soc_is_exynos5250()) { | 77 | if (soc_is_exynos5250()) { |
| 128 | s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save)); | ||
| 129 | s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save)); | ||
| 130 | } else { | ||
| 131 | s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save)); | 78 | s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save)); |
| 132 | /* Disable USE_RETENTION of JPEG_MEM_OPTION */ | 79 | /* Disable USE_RETENTION of JPEG_MEM_OPTION */ |
| 133 | tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION); | 80 | tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION); |
| @@ -143,15 +90,6 @@ static void exynos_pm_prepare(void) | |||
| 143 | /* ensure at least INFORM0 has the resume address */ | 90 | /* ensure at least INFORM0 has the resume address */ |
| 144 | 91 | ||
| 145 | __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); | 92 | __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); |
| 146 | |||
| 147 | /* Before enter central sequence mode, clock src register have to set */ | ||
| 148 | |||
| 149 | if (!soc_is_exynos5250()) | ||
| 150 | s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc)); | ||
| 151 | |||
| 152 | if (soc_is_exynos4210()) | ||
| 153 | s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc)); | ||
| 154 | |||
| 155 | } | 93 | } |
| 156 | 94 | ||
| 157 | static int exynos_pm_add(struct device *dev, struct subsys_interface *sif) | 95 | static int exynos_pm_add(struct device *dev, struct subsys_interface *sif) |
| @@ -162,73 +100,6 @@ static int exynos_pm_add(struct device *dev, struct subsys_interface *sif) | |||
| 162 | return 0; | 100 | return 0; |
| 163 | } | 101 | } |
| 164 | 102 | ||
| 165 | static unsigned long pll_base_rate; | ||
| 166 | |||
| 167 | static void exynos4_restore_pll(void) | ||
| 168 | { | ||
| 169 | unsigned long pll_con, locktime, lockcnt; | ||
| 170 | unsigned long pll_in_rate; | ||
| 171 | unsigned int p_div, epll_wait = 0, vpll_wait = 0; | ||
| 172 | |||
| 173 | if (pll_base_rate == 0) | ||
| 174 | return; | ||
| 175 | |||
| 176 | pll_in_rate = pll_base_rate; | ||
| 177 | |||
| 178 | /* EPLL */ | ||
| 179 | pll_con = exynos4_epll_save[0].val; | ||
| 180 | |||
| 181 | if (pll_con & (1 << 31)) { | ||
| 182 | pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT); | ||
| 183 | p_div = (pll_con >> PLL46XX_PDIV_SHIFT); | ||
| 184 | |||
| 185 | pll_in_rate /= 1000000; | ||
| 186 | |||
| 187 | locktime = (3000 / pll_in_rate) * p_div; | ||
| 188 | lockcnt = locktime * 10000 / (10000 / pll_in_rate); | ||
| 189 | |||
| 190 | __raw_writel(lockcnt, EXYNOS4_EPLL_LOCK); | ||
| 191 | |||
| 192 | s3c_pm_do_restore_core(exynos4_epll_save, | ||
| 193 | ARRAY_SIZE(exynos4_epll_save)); | ||
| 194 | epll_wait = 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | pll_in_rate = pll_base_rate; | ||
| 198 | |||
| 199 | /* VPLL */ | ||
| 200 | pll_con = exynos4_vpll_save[0].val; | ||
| 201 | |||
| 202 | if (pll_con & (1 << 31)) { | ||
| 203 | pll_in_rate /= 1000000; | ||
| 204 | /* 750us */ | ||
| 205 | locktime = 750; | ||
| 206 | lockcnt = locktime * 10000 / (10000 / pll_in_rate); | ||
| 207 | |||
| 208 | __raw_writel(lockcnt, EXYNOS4_VPLL_LOCK); | ||
| 209 | |||
| 210 | s3c_pm_do_restore_core(exynos4_vpll_save, | ||
| 211 | ARRAY_SIZE(exynos4_vpll_save)); | ||
| 212 | vpll_wait = 1; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* Wait PLL locking */ | ||
| 216 | |||
| 217 | do { | ||
| 218 | if (epll_wait) { | ||
| 219 | pll_con = __raw_readl(EXYNOS4_EPLL_CON0); | ||
| 220 | if (pll_con & (1 << EXYNOS4_EPLLCON0_LOCKED_SHIFT)) | ||
| 221 | epll_wait = 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | if (vpll_wait) { | ||
| 225 | pll_con = __raw_readl(EXYNOS4_VPLL_CON0); | ||
| 226 | if (pll_con & (1 << EXYNOS4_VPLLCON0_LOCKED_SHIFT)) | ||
| 227 | vpll_wait = 0; | ||
| 228 | } | ||
| 229 | } while (epll_wait || vpll_wait); | ||
| 230 | } | ||
| 231 | |||
| 232 | static struct subsys_interface exynos_pm_interface = { | 103 | static struct subsys_interface exynos_pm_interface = { |
| 233 | .name = "exynos_pm", | 104 | .name = "exynos_pm", |
| 234 | .subsys = &exynos_subsys, | 105 | .subsys = &exynos_subsys, |
| @@ -237,7 +108,6 @@ static struct subsys_interface exynos_pm_interface = { | |||
| 237 | 108 | ||
| 238 | static __init int exynos_pm_drvinit(void) | 109 | static __init int exynos_pm_drvinit(void) |
| 239 | { | 110 | { |
| 240 | struct clk *pll_base; | ||
| 241 | unsigned int tmp; | 111 | unsigned int tmp; |
| 242 | 112 | ||
| 243 | if (soc_is_exynos5440()) | 113 | if (soc_is_exynos5440()) |
| @@ -251,15 +121,6 @@ static __init int exynos_pm_drvinit(void) | |||
| 251 | tmp |= ((0xFF << 8) | (0x1F << 1)); | 121 | tmp |= ((0xFF << 8) | (0x1F << 1)); |
| 252 | __raw_writel(tmp, S5P_WAKEUP_MASK); | 122 | __raw_writel(tmp, S5P_WAKEUP_MASK); |
| 253 | 123 | ||
| 254 | if (!soc_is_exynos5250()) { | ||
| 255 | pll_base = clk_get(NULL, "xtal"); | ||
| 256 | |||
| 257 | if (!IS_ERR(pll_base)) { | ||
| 258 | pll_base_rate = clk_get_rate(pll_base); | ||
| 259 | clk_put(pll_base); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | return subsys_interface_register(&exynos_pm_interface); | 124 | return subsys_interface_register(&exynos_pm_interface); |
| 264 | } | 125 | } |
| 265 | arch_initcall(exynos_pm_drvinit); | 126 | arch_initcall(exynos_pm_drvinit); |
| @@ -343,13 +204,8 @@ static void exynos_pm_resume(void) | |||
| 343 | 204 | ||
| 344 | s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); | 205 | s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); |
| 345 | 206 | ||
| 346 | if (!soc_is_exynos5250()) { | 207 | if (IS_ENABLED(CONFIG_SMP) && !soc_is_exynos5250()) |
| 347 | exynos4_restore_pll(); | ||
| 348 | |||
| 349 | #ifdef CONFIG_SMP | ||
| 350 | scu_enable(S5P_VA_SCU); | 208 | scu_enable(S5P_VA_SCU); |
| 351 | #endif | ||
| 352 | } | ||
| 353 | 209 | ||
| 354 | early_wakeup: | 210 | early_wakeup: |
| 355 | 211 | ||
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index 271a255864d2..ba43321001d8 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig | |||
| @@ -30,6 +30,9 @@ config ARCH_CINTEGRATOR | |||
| 30 | config INTEGRATOR_IMPD1 | 30 | config INTEGRATOR_IMPD1 |
| 31 | tristate "Include support for Integrator/IM-PD1" | 31 | tristate "Include support for Integrator/IM-PD1" |
| 32 | depends on ARCH_INTEGRATOR_AP | 32 | depends on ARCH_INTEGRATOR_AP |
| 33 | select ARCH_REQUIRE_GPIOLIB | ||
| 34 | select ARM_VIC | ||
| 35 | select GPIO_PL061 if GPIOLIB | ||
| 33 | help | 36 | help |
| 34 | The IM-PD1 is an add-on logic module for the Integrator which | 37 | The IM-PD1 is an add-on logic module for the Integrator which |
| 35 | allows ARM(R) Ltd PrimeCells to be developed and evaluated. | 38 | allows ARM(R) Ltd PrimeCells to be developed and evaluated. |
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 9f82f9dcbb98..d9b784824808 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/platform_data/clk-integrator.h> | 24 | #include <linux/platform_data/clk-integrator.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/irqchip/arm-vic.h> | ||
| 26 | 27 | ||
| 27 | #include <mach/lm.h> | 28 | #include <mach/lm.h> |
| 28 | #include <mach/impd1.h> | 29 | #include <mach/impd1.h> |
| @@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position"); | |||
| 35 | 36 | ||
| 36 | struct impd1_module { | 37 | struct impd1_module { |
| 37 | void __iomem *base; | 38 | void __iomem *base; |
| 39 | void __iomem *vic_base; | ||
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | void impd1_tweak_control(struct device *dev, u32 mask, u32 val) | 42 | void impd1_tweak_control(struct device *dev, u32 mask, u32 val) |
| @@ -262,9 +264,6 @@ struct impd1_device { | |||
| 262 | 264 | ||
| 263 | static struct impd1_device impd1_devs[] = { | 265 | static struct impd1_device impd1_devs[] = { |
| 264 | { | 266 | { |
| 265 | .offset = 0x03000000, | ||
| 266 | .id = 0x00041190, | ||
| 267 | }, { | ||
| 268 | .offset = 0x00100000, | 267 | .offset = 0x00100000, |
| 269 | .irq = { 1 }, | 268 | .irq = { 1 }, |
| 270 | .id = 0x00141011, | 269 | .id = 0x00141011, |
| @@ -304,46 +303,72 @@ static struct impd1_device impd1_devs[] = { | |||
| 304 | } | 303 | } |
| 305 | }; | 304 | }; |
| 306 | 305 | ||
| 307 | static int impd1_probe(struct lm_device *dev) | 306 | /* |
| 307 | * Valid IRQs: 0 thru 9 and 11, 10 unused. | ||
| 308 | */ | ||
| 309 | #define IMPD1_VALID_IRQS 0x00000bffU | ||
| 310 | |||
| 311 | static int __init impd1_probe(struct lm_device *dev) | ||
| 308 | { | 312 | { |
| 309 | struct impd1_module *impd1; | 313 | struct impd1_module *impd1; |
| 310 | int i, ret; | 314 | int irq_base; |
| 315 | int i; | ||
| 311 | 316 | ||
| 312 | if (dev->id != module_id) | 317 | if (dev->id != module_id) |
| 313 | return -EINVAL; | 318 | return -EINVAL; |
| 314 | 319 | ||
| 315 | if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers")) | 320 | if (!devm_request_mem_region(&dev->dev, dev->resource.start, |
| 321 | SZ_4K, "LM registers")) | ||
| 316 | return -EBUSY; | 322 | return -EBUSY; |
| 317 | 323 | ||
| 318 | impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL); | 324 | impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module), |
| 319 | if (!impd1) { | 325 | GFP_KERNEL); |
| 320 | ret = -ENOMEM; | 326 | if (!impd1) |
| 321 | goto release_lm; | 327 | return -ENOMEM; |
| 322 | } | ||
| 323 | 328 | ||
| 324 | impd1->base = ioremap(dev->resource.start, SZ_4K); | 329 | impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K); |
| 325 | if (!impd1->base) { | 330 | if (!impd1->base) |
| 326 | ret = -ENOMEM; | 331 | return -ENOMEM; |
| 327 | goto free_impd1; | ||
| 328 | } | ||
| 329 | 332 | ||
| 330 | lm_set_drvdata(dev, impd1); | 333 | integrator_impd1_clk_init(impd1->base, dev->id); |
| 331 | 334 | ||
| 332 | printk("IM-PD1 found at 0x%08lx\n", | 335 | if (!devm_request_mem_region(&dev->dev, |
| 333 | (unsigned long)dev->resource.start); | 336 | dev->resource.start + 0x03000000, |
| 337 | SZ_4K, "VIC")) | ||
| 338 | return -EBUSY; | ||
| 334 | 339 | ||
| 335 | integrator_impd1_clk_init(impd1->base, dev->id); | 340 | impd1->vic_base = devm_ioremap(&dev->dev, |
| 341 | dev->resource.start + 0x03000000, | ||
| 342 | SZ_4K); | ||
| 343 | if (!impd1->vic_base) | ||
| 344 | return -ENOMEM; | ||
| 345 | |||
| 346 | irq_base = vic_init_cascaded(impd1->vic_base, dev->irq, | ||
| 347 | IMPD1_VALID_IRQS, 0); | ||
| 348 | |||
| 349 | lm_set_drvdata(dev, impd1); | ||
| 350 | |||
| 351 | dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n", | ||
| 352 | (unsigned long)dev->resource.start); | ||
| 336 | 353 | ||
| 337 | for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { | 354 | for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { |
| 338 | struct impd1_device *idev = impd1_devs + i; | 355 | struct impd1_device *idev = impd1_devs + i; |
| 339 | struct amba_device *d; | 356 | struct amba_device *d; |
| 340 | unsigned long pc_base; | 357 | unsigned long pc_base; |
| 341 | char devname[32]; | 358 | char devname[32]; |
| 359 | int irq1 = idev->irq[0]; | ||
| 360 | int irq2 = idev->irq[1]; | ||
| 361 | |||
| 362 | /* Translate IRQs to IM-PD1 local numberspace */ | ||
| 363 | if (irq1) | ||
| 364 | irq1 += irq_base; | ||
| 365 | if (irq2) | ||
| 366 | irq2 += irq_base; | ||
| 342 | 367 | ||
| 343 | pc_base = dev->resource.start + idev->offset; | 368 | pc_base = dev->resource.start + idev->offset; |
| 344 | snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12); | 369 | snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12); |
| 345 | d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, | 370 | d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, |
| 346 | dev->irq, dev->irq, | 371 | irq1, irq2, |
| 347 | idev->platform_data, idev->id, | 372 | idev->platform_data, idev->id, |
| 348 | &dev->resource); | 373 | &dev->resource); |
| 349 | if (IS_ERR(d)) { | 374 | if (IS_ERR(d)) { |
| @@ -353,14 +378,6 @@ static int impd1_probe(struct lm_device *dev) | |||
| 353 | } | 378 | } |
| 354 | 379 | ||
| 355 | return 0; | 380 | return 0; |
| 356 | |||
| 357 | free_impd1: | ||
| 358 | if (impd1 && impd1->base) | ||
| 359 | iounmap(impd1->base); | ||
| 360 | kfree(impd1); | ||
| 361 | release_lm: | ||
| 362 | release_mem_region(dev->resource.start, SZ_4K); | ||
| 363 | return ret; | ||
| 364 | } | 381 | } |
| 365 | 382 | ||
| 366 | static int impd1_remove_one(struct device *dev, void *data) | 383 | static int impd1_remove_one(struct device *dev, void *data) |
| @@ -371,16 +388,10 @@ static int impd1_remove_one(struct device *dev, void *data) | |||
| 371 | 388 | ||
| 372 | static void impd1_remove(struct lm_device *dev) | 389 | static void impd1_remove(struct lm_device *dev) |
| 373 | { | 390 | { |
| 374 | struct impd1_module *impd1 = lm_get_drvdata(dev); | ||
| 375 | |||
| 376 | device_for_each_child(&dev->dev, NULL, impd1_remove_one); | 391 | device_for_each_child(&dev->dev, NULL, impd1_remove_one); |
| 377 | integrator_impd1_clk_exit(dev->id); | 392 | integrator_impd1_clk_exit(dev->id); |
| 378 | 393 | ||
| 379 | lm_set_drvdata(dev, NULL); | 394 | lm_set_drvdata(dev, NULL); |
| 380 | |||
| 381 | iounmap(impd1->base); | ||
| 382 | kfree(impd1); | ||
| 383 | release_mem_region(dev->resource.start, SZ_4K); | ||
| 384 | } | 395 | } |
| 385 | 396 | ||
| 386 | static struct lm_driver impd1_driver = { | 397 | static struct lm_driver impd1_driver = { |
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index e4f27f0e56ac..cc0857cab2e1 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/sys_soc.h> | 42 | #include <linux/sys_soc.h> |
| 43 | #include <linux/termios.h> | 43 | #include <linux/termios.h> |
| 44 | #include <linux/sched_clock.h> | 44 | #include <linux/sched_clock.h> |
| 45 | #include <linux/clk-provider.h> | ||
| 45 | 46 | ||
| 46 | #include <mach/hardware.h> | 47 | #include <mach/hardware.h> |
| 47 | #include <mach/platform.h> | 48 | #include <mach/platform.h> |
| @@ -402,10 +403,7 @@ static void __init ap_of_timer_init(void) | |||
| 402 | struct clk *clk; | 403 | struct clk *clk; |
| 403 | unsigned long rate; | 404 | unsigned long rate; |
| 404 | 405 | ||
| 405 | clk = clk_get_sys("ap_timer", NULL); | 406 | of_clk_init(NULL); |
| 406 | BUG_ON(IS_ERR(clk)); | ||
| 407 | clk_prepare_enable(clk); | ||
| 408 | rate = clk_get_rate(clk); | ||
| 409 | 407 | ||
| 410 | err = of_property_read_string(of_aliases, | 408 | err = of_property_read_string(of_aliases, |
| 411 | "arm,timer-primary", &path); | 409 | "arm,timer-primary", &path); |
| @@ -415,6 +413,12 @@ static void __init ap_of_timer_init(void) | |||
| 415 | base = of_iomap(node, 0); | 413 | base = of_iomap(node, 0); |
| 416 | if (WARN_ON(!base)) | 414 | if (WARN_ON(!base)) |
| 417 | return; | 415 | return; |
| 416 | |||
| 417 | clk = of_clk_get(node, 0); | ||
| 418 | BUG_ON(IS_ERR(clk)); | ||
| 419 | clk_prepare_enable(clk); | ||
| 420 | rate = clk_get_rate(clk); | ||
| 421 | |||
| 418 | writel(0, base + TIMER_CTRL); | 422 | writel(0, base + TIMER_CTRL); |
| 419 | integrator_clocksource_init(rate, base); | 423 | integrator_clocksource_init(rate, base); |
| 420 | 424 | ||
| @@ -427,6 +431,12 @@ static void __init ap_of_timer_init(void) | |||
| 427 | if (WARN_ON(!base)) | 431 | if (WARN_ON(!base)) |
| 428 | return; | 432 | return; |
| 429 | irq = irq_of_parse_and_map(node, 0); | 433 | irq = irq_of_parse_and_map(node, 0); |
| 434 | |||
| 435 | clk = of_clk_get(node, 0); | ||
| 436 | BUG_ON(IS_ERR(clk)); | ||
| 437 | clk_prepare_enable(clk); | ||
| 438 | rate = clk_get_rate(clk); | ||
| 439 | |||
| 430 | writel(0, base + TIMER_CTRL); | 440 | writel(0, base + TIMER_CTRL); |
| 431 | integrator_clockevent_init(rate, base, irq); | 441 | integrator_clockevent_init(rate, base, irq); |
| 432 | } | 442 | } |
| @@ -440,7 +450,6 @@ static void __init ap_init_irq_of(void) | |||
| 440 | { | 450 | { |
| 441 | cm_init(); | 451 | cm_init(); |
| 442 | of_irq_init(fpga_irq_of_match); | 452 | of_irq_init(fpga_irq_of_match); |
| 443 | integrator_clk_init(false); | ||
| 444 | } | 453 | } |
| 445 | 454 | ||
| 446 | /* For the Device Tree, add in the UART callbacks as AUXDATA */ | 455 | /* For the Device Tree, add in the UART callbacks as AUXDATA */ |
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index a3ef961e4a93..0ad5f60598c8 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/irqchip/versatile-fpga.h> | 23 | #include <linux/irqchip/versatile-fpga.h> |
| 24 | #include <linux/gfp.h> | 24 | #include <linux/gfp.h> |
| 25 | #include <linux/mtd/physmap.h> | 25 | #include <linux/mtd/physmap.h> |
| 26 | #include <linux/platform_data/clk-integrator.h> | ||
| 27 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
| 28 | #include <linux/of_address.h> | 27 | #include <linux/of_address.h> |
| 29 | #include <linux/of_platform.h> | 28 | #include <linux/of_platform.h> |
| @@ -33,8 +32,6 @@ | |||
| 33 | #include <mach/platform.h> | 32 | #include <mach/platform.h> |
| 34 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
| 35 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
| 36 | #include <asm/hardware/arm_timer.h> | ||
| 37 | #include <asm/hardware/icst.h> | ||
| 38 | 35 | ||
| 39 | #include <mach/lm.h> | 36 | #include <mach/lm.h> |
| 40 | 37 | ||
| @@ -43,8 +40,6 @@ | |||
| 43 | #include <asm/mach/map.h> | 40 | #include <asm/mach/map.h> |
| 44 | #include <asm/mach/time.h> | 41 | #include <asm/mach/time.h> |
| 45 | 42 | ||
| 46 | #include <asm/hardware/timer-sp.h> | ||
| 47 | |||
| 48 | #include <plat/clcd.h> | 43 | #include <plat/clcd.h> |
| 49 | #include <plat/sched_clock.h> | 44 | #include <plat/sched_clock.h> |
| 50 | 45 | ||
| @@ -250,7 +245,6 @@ static void __init intcp_init_irq_of(void) | |||
| 250 | { | 245 | { |
| 251 | cm_init(); | 246 | cm_init(); |
| 252 | of_irq_init(fpga_irq_of_match); | 247 | of_irq_init(fpga_irq_of_match); |
| 253 | integrator_clk_init(true); | ||
| 254 | } | 248 | } |
| 255 | 249 | ||
| 256 | /* | 250 | /* |
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h index 6e5077e2ec26..1c37082c8b39 100644 --- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h +++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #define CPU_RESET 0x00000002 | 22 | #define CPU_RESET 0x00000002 |
| 23 | 23 | ||
| 24 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) | 24 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) |
| 25 | #define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108) | ||
| 25 | #define SOFT_RESET_OUT_EN 0x00000004 | 26 | #define SOFT_RESET_OUT_EN 0x00000004 |
| 26 | 27 | ||
| 27 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) | 28 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) |
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h index 5f03484584d4..e20d6da234a6 100644 --- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h +++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #define L2_WRITETHROUGH 0x00020000 | 15 | #define L2_WRITETHROUGH 0x00020000 |
| 16 | 16 | ||
| 17 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) | 17 | #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) |
| 18 | #define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108) | ||
| 18 | #define SOFT_RESET_OUT_EN 0x00000004 | 19 | #define SOFT_RESET_OUT_EN 0x00000004 |
| 19 | 20 | ||
| 20 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) | 21 | #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 5c22c0899e9c..cb31d4390d52 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
| @@ -74,6 +74,7 @@ config SOC_DRA7XX | |||
| 74 | select ARM_CPU_SUSPEND if PM | 74 | select ARM_CPU_SUSPEND if PM |
| 75 | select ARM_GIC | 75 | select ARM_GIC |
| 76 | select HAVE_ARM_ARCH_TIMER | 76 | select HAVE_ARM_ARCH_TIMER |
| 77 | select IRQ_CROSSBAR | ||
| 77 | 78 | ||
| 78 | config ARCH_OMAP2PLUS | 79 | config ARCH_OMAP2PLUS |
| 79 | bool | 80 | bool |
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 3664562f9148..693fe486e917 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c | |||
| @@ -138,7 +138,7 @@ static void wakeupgen_mask(struct irq_data *d) | |||
| 138 | unsigned long flags; | 138 | unsigned long flags; |
| 139 | 139 | ||
| 140 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); | 140 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); |
| 141 | _wakeupgen_clear(d->irq, irq_target_cpu[d->irq]); | 141 | _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]); |
| 142 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); | 142 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| @@ -150,7 +150,7 @@ static void wakeupgen_unmask(struct irq_data *d) | |||
| 150 | unsigned long flags; | 150 | unsigned long flags; |
| 151 | 151 | ||
| 152 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); | 152 | raw_spin_lock_irqsave(&wakeupgen_lock, flags); |
| 153 | _wakeupgen_set(d->irq, irq_target_cpu[d->irq]); | 153 | _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]); |
| 154 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); | 154 | raw_spin_unlock_irqrestore(&wakeupgen_lock, flags); |
| 155 | } | 155 | } |
| 156 | 156 | ||
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 6cd3f3772ecf..95e171a055f3 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
| 23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
| 24 | #include <linux/irqchip/arm-gic.h> | 24 | #include <linux/irqchip/arm-gic.h> |
| 25 | #include <linux/irqchip/irq-crossbar.h> | ||
| 25 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
| 26 | #include <linux/reboot.h> | 27 | #include <linux/reboot.h> |
| 27 | 28 | ||
| @@ -288,5 +289,8 @@ void __init omap_gic_of_init(void) | |||
| 288 | 289 | ||
| 289 | skip_errata_init: | 290 | skip_errata_init: |
| 290 | omap_wakeupgen_init(); | 291 | omap_wakeupgen_init(); |
| 292 | #ifdef CONFIG_IRQ_CROSSBAR | ||
| 293 | irqcrossbar_init(); | ||
| 294 | #endif | ||
| 291 | irqchip_init(); | 295 | irqchip_init(); |
| 292 | } | 296 | } |
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h index f727d03f1688..5766e3fbff69 100644 --- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h +++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) | 18 | #define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) |
| 19 | 19 | ||
| 20 | #define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) | 20 | #define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) |
| 21 | #define RSTOUTn_MASK_PHYS (ORION5X_BRIDGE_PHYS_BASE + 0x108) | ||
| 21 | 22 | ||
| 22 | #define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) | 23 | #define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) |
| 23 | 24 | ||
diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c index e6ab0cd5b286..bee0073c9b64 100644 --- a/arch/arm/mach-shmobile/clock-r7s72100.c +++ b/arch/arm/mach-shmobile/clock-r7s72100.c | |||
| @@ -22,12 +22,15 @@ | |||
| 22 | #include <mach/common.h> | 22 | #include <mach/common.h> |
| 23 | #include <mach/r7s72100.h> | 23 | #include <mach/r7s72100.h> |
| 24 | 24 | ||
| 25 | /* registers */ | 25 | /* Frequency Control Registers */ |
| 26 | #define FRQCR 0xfcfe0010 | 26 | #define FRQCR 0xfcfe0010 |
| 27 | #define FRQCR2 0xfcfe0014 | 27 | #define FRQCR2 0xfcfe0014 |
| 28 | /* Standby Control Registers */ | ||
| 28 | #define STBCR3 0xfcfe0420 | 29 | #define STBCR3 0xfcfe0420 |
| 29 | #define STBCR4 0xfcfe0424 | 30 | #define STBCR4 0xfcfe0424 |
| 31 | #define STBCR7 0xfcfe0430 | ||
| 30 | #define STBCR9 0xfcfe0438 | 32 | #define STBCR9 0xfcfe0438 |
| 33 | #define STBCR10 0xfcfe043c | ||
| 31 | 34 | ||
| 32 | #define PLL_RATE 30 | 35 | #define PLL_RATE 30 |
| 33 | 36 | ||
| @@ -67,7 +70,7 @@ static struct clk pll_clk = { | |||
| 67 | 70 | ||
| 68 | static unsigned long bus_recalc(struct clk *clk) | 71 | static unsigned long bus_recalc(struct clk *clk) |
| 69 | { | 72 | { |
| 70 | return clk->parent->rate * 2 / 3; | 73 | return clk->parent->rate / 3; |
| 71 | } | 74 | } |
| 72 | 75 | ||
| 73 | static struct sh_clk_ops bus_clk_ops = { | 76 | static struct sh_clk_ops bus_clk_ops = { |
| @@ -145,15 +148,25 @@ struct clk div4_clks[DIV4_NR] = { | |||
| 145 | | CLK_ENABLE_ON_INIT), | 148 | | CLK_ENABLE_ON_INIT), |
| 146 | }; | 149 | }; |
| 147 | 150 | ||
| 148 | enum { MSTP97, MSTP96, MSTP95, MSTP94, | 151 | enum { |
| 152 | MSTP107, MSTP106, MSTP105, MSTP104, MSTP103, | ||
| 153 | MSTP97, MSTP96, MSTP95, MSTP94, | ||
| 154 | MSTP74, | ||
| 149 | MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40, | 155 | MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40, |
| 150 | MSTP33, MSTP_NR }; | 156 | MSTP33, MSTP_NR |
| 157 | }; | ||
| 151 | 158 | ||
| 152 | static struct clk mstp_clks[MSTP_NR] = { | 159 | static struct clk mstp_clks[MSTP_NR] = { |
| 160 | [MSTP107] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 7, 0), /* RSPI0 */ | ||
| 161 | [MSTP106] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 6, 0), /* RSPI1 */ | ||
| 162 | [MSTP105] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 5, 0), /* RSPI2 */ | ||
| 163 | [MSTP104] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 4, 0), /* RSPI3 */ | ||
| 164 | [MSTP103] = SH_CLK_MSTP8(&peripheral1_clk, STBCR10, 3, 0), /* RSPI4 */ | ||
| 153 | [MSTP97] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 7, 0), /* RIIC0 */ | 165 | [MSTP97] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 7, 0), /* RIIC0 */ |
| 154 | [MSTP96] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 6, 0), /* RIIC1 */ | 166 | [MSTP96] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 6, 0), /* RIIC1 */ |
| 155 | [MSTP95] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 5, 0), /* RIIC2 */ | 167 | [MSTP95] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 5, 0), /* RIIC2 */ |
| 156 | [MSTP94] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 4, 0), /* RIIC3 */ | 168 | [MSTP94] = SH_CLK_MSTP8(&peripheral0_clk, STBCR9, 4, 0), /* RIIC3 */ |
| 169 | [MSTP74] = SH_CLK_MSTP8(&peripheral1_clk, STBCR7, 4, 0), /* Ether */ | ||
| 157 | [MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */ | 170 | [MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */ |
| 158 | [MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */ | 171 | [MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */ |
| 159 | [MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */ | 172 | [MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */ |
| @@ -176,6 +189,21 @@ static struct clk_lookup lookups[] = { | |||
| 176 | CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), | 189 | CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), |
| 177 | 190 | ||
| 178 | /* MSTP clocks */ | 191 | /* MSTP clocks */ |
| 192 | CLKDEV_DEV_ID("rspi-rz.0", &mstp_clks[MSTP107]), | ||
| 193 | CLKDEV_DEV_ID("rspi-rz.1", &mstp_clks[MSTP106]), | ||
| 194 | CLKDEV_DEV_ID("rspi-rz.2", &mstp_clks[MSTP105]), | ||
| 195 | CLKDEV_DEV_ID("rspi-rz.3", &mstp_clks[MSTP104]), | ||
| 196 | CLKDEV_DEV_ID("rspi-rz.4", &mstp_clks[MSTP103]), | ||
| 197 | CLKDEV_DEV_ID("e800c800.spi", &mstp_clks[MSTP107]), | ||
| 198 | CLKDEV_DEV_ID("e800d000.spi", &mstp_clks[MSTP106]), | ||
| 199 | CLKDEV_DEV_ID("e800d800.spi", &mstp_clks[MSTP105]), | ||
| 200 | CLKDEV_DEV_ID("e800e000.spi", &mstp_clks[MSTP104]), | ||
| 201 | CLKDEV_DEV_ID("e800e800.spi", &mstp_clks[MSTP103]), | ||
| 202 | CLKDEV_DEV_ID("fcfee000.i2c", &mstp_clks[MSTP97]), | ||
| 203 | CLKDEV_DEV_ID("fcfee400.i2c", &mstp_clks[MSTP96]), | ||
| 204 | CLKDEV_DEV_ID("fcfee800.i2c", &mstp_clks[MSTP95]), | ||
| 205 | CLKDEV_DEV_ID("fcfeec00.i2c", &mstp_clks[MSTP94]), | ||
| 206 | CLKDEV_DEV_ID("r7s72100-ether", &mstp_clks[MSTP74]), | ||
| 179 | CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]), | 207 | CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]), |
| 180 | 208 | ||
| 181 | /* ICK */ | 209 | /* ICK */ |
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c index 9783945f8bc7..2009a9bc6356 100644 --- a/arch/arm/mach-shmobile/clock-r8a7778.c +++ b/arch/arm/mach-shmobile/clock-r8a7778.c | |||
| @@ -221,6 +221,10 @@ static struct clk_lookup lookups[] = { | |||
| 221 | CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */ | 221 | CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */ |
| 222 | CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */ | 222 | CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */ |
| 223 | 223 | ||
| 224 | CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a), | ||
| 225 | CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b), | ||
| 226 | CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c), | ||
| 227 | CLKDEV_ICK_ID("clk_i", "rcar_sound", &s1_clk), | ||
| 224 | CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]), | 228 | CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]), |
| 225 | CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]), | 229 | CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]), |
| 226 | CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]), | 230 | CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]), |
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index cabedebd7648..8e403ae0c7b2 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c | |||
| @@ -120,16 +120,16 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
| 120 | [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */ | 120 | [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */ |
| 121 | [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ | 121 | [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ |
| 122 | [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ | 122 | [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ |
| 123 | [MSTP120] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 20, 0), /* VIN3 */ | 123 | [MSTP120] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 20, MSTPSR1, 0), /* VIN3 */ |
| 124 | [MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */ | 124 | [MSTP116] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 16, MSTPSR1, 0), /* PCIe */ |
| 125 | [MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */ | 125 | [MSTP115] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 15, MSTPSR1, 0), /* SATA */ |
| 126 | [MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */ | 126 | [MSTP114] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 14, MSTPSR1, 0), /* Ether */ |
| 127 | [MSTP110] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 10, 0), /* VIN0 */ | 127 | [MSTP110] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 10, MSTPSR1, 0), /* VIN0 */ |
| 128 | [MSTP109] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 9, 0), /* VIN1 */ | 128 | [MSTP109] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 9, MSTPSR1, 0), /* VIN1 */ |
| 129 | [MSTP108] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 8, 0), /* VIN2 */ | 129 | [MSTP108] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 8, MSTPSR1, 0), /* VIN2 */ |
| 130 | [MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */ | 130 | [MSTP103] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 3, MSTPSR1, 0), /* DU */ |
| 131 | [MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */ | 131 | [MSTP101] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 1, MSTPSR1, 0), /* USB2 */ |
| 132 | [MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */ | 132 | [MSTP100] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 0, MSTPSR1, 0), /* USB0/1 */ |
| 133 | [MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */ | 133 | [MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */ |
| 134 | [MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */ | 134 | [MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */ |
| 135 | [MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */ | 135 | [MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */ |
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c index f44987a92ad4..3f93503f5b96 100644 --- a/arch/arm/mach-shmobile/clock-r8a7790.c +++ b/arch/arm/mach-shmobile/clock-r8a7790.c | |||
| @@ -43,17 +43,26 @@ | |||
| 43 | * see "p1 / 2" on R8A7790_CLOCK_ROOT() below | 43 | * see "p1 / 2" on R8A7790_CLOCK_ROOT() below |
| 44 | */ | 44 | */ |
| 45 | 45 | ||
| 46 | #define CPG_BASE 0xe6150000 | 46 | #define CPG_BASE 0xe6150000 |
| 47 | #define CPG_LEN 0x1000 | 47 | #define CPG_LEN 0x1000 |
| 48 | 48 | ||
| 49 | #define SMSTPCR1 0xe6150134 | 49 | #define SMSTPCR1 0xe6150134 |
| 50 | #define SMSTPCR2 0xe6150138 | 50 | #define SMSTPCR2 0xe6150138 |
| 51 | #define SMSTPCR3 0xe615013c | 51 | #define SMSTPCR3 0xe615013c |
| 52 | #define SMSTPCR5 0xe6150144 | 52 | #define SMSTPCR5 0xe6150144 |
| 53 | #define SMSTPCR7 0xe615014c | 53 | #define SMSTPCR7 0xe615014c |
| 54 | #define SMSTPCR8 0xe6150990 | 54 | #define SMSTPCR8 0xe6150990 |
| 55 | #define SMSTPCR9 0xe6150994 | 55 | #define SMSTPCR9 0xe6150994 |
| 56 | #define SMSTPCR10 0xe6150998 | 56 | #define SMSTPCR10 0xe6150998 |
| 57 | |||
| 58 | #define MSTPSR1 IOMEM(0xe6150038) | ||
| 59 | #define MSTPSR2 IOMEM(0xe6150040) | ||
| 60 | #define MSTPSR3 IOMEM(0xe6150048) | ||
| 61 | #define MSTPSR5 IOMEM(0xe615003c) | ||
| 62 | #define MSTPSR7 IOMEM(0xe61501c4) | ||
| 63 | #define MSTPSR8 IOMEM(0xe61509a0) | ||
| 64 | #define MSTPSR9 IOMEM(0xe61509a4) | ||
| 65 | #define MSTPSR10 IOMEM(0xe61509a8) | ||
| 57 | 66 | ||
| 58 | #define SDCKCR 0xE6150074 | 67 | #define SDCKCR 0xE6150074 |
| 59 | #define SD2CKCR 0xE6150078 | 68 | #define SD2CKCR 0xE6150078 |
| @@ -82,6 +91,15 @@ static struct clk main_clk = { | |||
| 82 | .ops = &followparent_clk_ops, | 91 | .ops = &followparent_clk_ops, |
| 83 | }; | 92 | }; |
| 84 | 93 | ||
| 94 | static struct clk audio_clk_a = { | ||
| 95 | }; | ||
| 96 | |||
| 97 | static struct clk audio_clk_b = { | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct clk audio_clk_c = { | ||
| 101 | }; | ||
| 102 | |||
| 85 | /* | 103 | /* |
| 86 | * clock ratio of these clock will be updated | 104 | * clock ratio of these clock will be updated |
| 87 | * on r8a7790_clock_init() | 105 | * on r8a7790_clock_init() |
| @@ -115,6 +133,9 @@ SH_FIXED_RATIO_CLK_SET(ddr_clk, pll3_clk, 1, 8); | |||
| 115 | SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); | 133 | SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); |
| 116 | 134 | ||
| 117 | static struct clk *main_clks[] = { | 135 | static struct clk *main_clks[] = { |
| 136 | &audio_clk_a, | ||
| 137 | &audio_clk_b, | ||
| 138 | &audio_clk_c, | ||
| 118 | &extal_clk, | 139 | &extal_clk, |
| 119 | &extal_div2_clk, | 140 | &extal_div2_clk, |
| 120 | &main_clk, | 141 | &main_clk, |
| @@ -183,15 +204,22 @@ static struct clk div6_clks[DIV6_NR] = { | |||
| 183 | 204 | ||
| 184 | /* MSTP */ | 205 | /* MSTP */ |
| 185 | enum { | 206 | enum { |
| 207 | MSTP1017, /* parent of SCU */ | ||
| 208 | |||
| 209 | MSTP1031, MSTP1030, | ||
| 210 | MSTP1029, MSTP1028, MSTP1027, MSTP1026, MSTP1025, MSTP1024, MSTP1023, MSTP1022, | ||
| 186 | MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010, | 211 | MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010, |
| 187 | MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005, | 212 | MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005, |
| 188 | MSTP931, MSTP930, MSTP929, MSTP928, | 213 | MSTP931, MSTP930, MSTP929, MSTP928, |
| 189 | MSTP917, | 214 | MSTP917, |
| 215 | MSTP815, MSTP814, | ||
| 190 | MSTP813, | 216 | MSTP813, |
| 217 | MSTP811, MSTP810, MSTP809, MSTP808, | ||
| 191 | MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720, | 218 | MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720, |
| 192 | MSTP717, MSTP716, | 219 | MSTP717, MSTP716, |
| 193 | MSTP704, | 220 | MSTP704, MSTP703, |
| 194 | MSTP522, | 221 | MSTP522, |
| 222 | MSTP502, MSTP501, | ||
| 195 | MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304, | 223 | MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304, |
| 196 | MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, | 224 | MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, |
| 197 | MSTP124, | 225 | MSTP124, |
| @@ -199,53 +227,77 @@ enum { | |||
| 199 | }; | 227 | }; |
| 200 | 228 | ||
| 201 | static struct clk mstp_clks[MSTP_NR] = { | 229 | static struct clk mstp_clks[MSTP_NR] = { |
| 202 | [MSTP1015] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 15, 0), /* SSI0 */ | 230 | [MSTP1031] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 31, MSTPSR10, 0), /* SCU0 */ |
| 203 | [MSTP1014] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 14, 0), /* SSI1 */ | 231 | [MSTP1030] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 30, MSTPSR10, 0), /* SCU1 */ |
| 204 | [MSTP1013] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 13, 0), /* SSI2 */ | 232 | [MSTP1029] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 29, MSTPSR10, 0), /* SCU2 */ |
| 205 | [MSTP1012] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 12, 0), /* SSI3 */ | 233 | [MSTP1028] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 28, MSTPSR10, 0), /* SCU3 */ |
| 206 | [MSTP1011] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 11, 0), /* SSI4 */ | 234 | [MSTP1027] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 27, MSTPSR10, 0), /* SCU4 */ |
| 207 | [MSTP1010] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 10, 0), /* SSI5 */ | 235 | [MSTP1026] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 26, MSTPSR10, 0), /* SCU5 */ |
| 208 | [MSTP1009] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 9, 0), /* SSI6 */ | 236 | [MSTP1025] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 25, MSTPSR10, 0), /* SCU6 */ |
| 209 | [MSTP1008] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 8, 0), /* SSI7 */ | 237 | [MSTP1024] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 24, MSTPSR10, 0), /* SCU7 */ |
| 210 | [MSTP1007] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 7, 0), /* SSI8 */ | 238 | [MSTP1023] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 23, MSTPSR10, 0), /* SCU8 */ |
| 211 | [MSTP1006] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 6, 0), /* SSI9 */ | 239 | [MSTP1022] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 22, MSTPSR10, 0), /* SCU9 */ |
| 212 | [MSTP1005] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 5, 0), /* SSI ALL */ | 240 | [MSTP1017] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 17, MSTPSR10, 0), /* SCU */ |
| 213 | [MSTP931] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 31, 0), /* I2C0 */ | 241 | [MSTP1015] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 15, MSTPSR10, 0), /* SSI0 */ |
| 214 | [MSTP930] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 30, 0), /* I2C1 */ | 242 | [MSTP1014] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 14, MSTPSR10, 0), /* SSI1 */ |
| 215 | [MSTP929] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 29, 0), /* I2C2 */ | 243 | [MSTP1013] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 13, MSTPSR10, 0), /* SSI2 */ |
| 216 | [MSTP928] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 28, 0), /* I2C3 */ | 244 | [MSTP1012] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 12, MSTPSR10, 0), /* SSI3 */ |
| 217 | [MSTP917] = SH_CLK_MSTP32(&qspi_clk, SMSTPCR9, 17, 0), /* QSPI */ | 245 | [MSTP1011] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 11, MSTPSR10, 0), /* SSI4 */ |
| 218 | [MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */ | 246 | [MSTP1010] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 10, MSTPSR10, 0), /* SSI5 */ |
| 219 | [MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */ | 247 | [MSTP1009] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 9, MSTPSR10, 0), /* SSI6 */ |
| 220 | [MSTP725] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 25, 0), /* LVDS1 */ | 248 | [MSTP1008] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 8, MSTPSR10, 0), /* SSI7 */ |
| 221 | [MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */ | 249 | [MSTP1007] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 7, MSTPSR10, 0), /* SSI8 */ |
| 222 | [MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */ | 250 | [MSTP1006] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 6, MSTPSR10, 0), /* SSI9 */ |
| 223 | [MSTP722] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 22, 0), /* DU2 */ | 251 | [MSTP1005] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 5, MSTPSR10, 0), /* SSI ALL */ |
| 224 | [MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */ | 252 | [MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */ |
| 225 | [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */ | 253 | [MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */ |
| 226 | [MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */ | 254 | [MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */ |
| 227 | [MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */ | 255 | [MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */ |
| 228 | [MSTP704] = SH_CLK_MSTP32(&mp_clk, SMSTPCR7, 4, 0), /* HSUSB */ | 256 | [MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */ |
| 229 | [MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */ | 257 | [MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */ |
| 230 | [MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */ | 258 | [MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */ |
| 231 | [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */ | 259 | [MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */ |
| 232 | [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_SD1], SMSTPCR3, 13, 0), /* SDHI1 */ | 260 | [MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */ |
| 233 | [MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SD2], SMSTPCR3, 12, 0), /* SDHI2 */ | 261 | [MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */ |
| 234 | [MSTP311] = SH_CLK_MSTP32(&div6_clks[DIV6_SD3], SMSTPCR3, 11, 0), /* SDHI3 */ | 262 | [MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */ |
| 235 | [MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, 0), /* MMC1 */ | 263 | [MSTP808] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 8, MSTPSR8, 0), /* VIN3 */ |
| 236 | [MSTP304] = SH_CLK_MSTP32(&cp_clk, SMSTPCR3, 4, 0), /* TPU0 */ | 264 | [MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */ |
| 237 | [MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */ | 265 | [MSTP725] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 25, MSTPSR7, 0), /* LVDS1 */ |
| 238 | [MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */ | 266 | [MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */ |
| 239 | [MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */ | 267 | [MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */ |
| 240 | [MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */ | 268 | [MSTP722] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 22, MSTPSR7, 0), /* DU2 */ |
| 241 | [MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */ | 269 | [MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */ |
| 242 | [MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */ | 270 | [MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */ |
| 243 | [MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */ | 271 | [MSTP717] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 17, MSTPSR7, 0), /* HSCIF0 */ |
| 272 | [MSTP716] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 16, MSTPSR7, 0), /* HSCIF1 */ | ||
| 273 | [MSTP704] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 4, MSTPSR7, 0), /* HSUSB */ | ||
| 274 | [MSTP703] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 3, MSTPSR7, 0), /* EHCI */ | ||
| 275 | [MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */ | ||
| 276 | [MSTP502] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 2, MSTPSR5, 0), /* Audio-DMAC low */ | ||
| 277 | [MSTP501] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 1, MSTPSR5, 0), /* Audio-DMAC hi */ | ||
| 278 | [MSTP315] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, MSTPSR3, 0), /* MMC0 */ | ||
| 279 | [MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */ | ||
| 280 | [MSTP313] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD1], SMSTPCR3, 13, MSTPSR3, 0), /* SDHI1 */ | ||
| 281 | [MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI2 */ | ||
| 282 | [MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD3], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI3 */ | ||
| 283 | [MSTP305] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, MSTPSR3, 0), /* MMC1 */ | ||
| 284 | [MSTP304] = SH_CLK_MSTP32_STS(&cp_clk, SMSTPCR3, 4, MSTPSR3, 0), /* TPU0 */ | ||
| 285 | [MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */ | ||
| 286 | [MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */ | ||
| 287 | [MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */ | ||
| 288 | [MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */ | ||
| 289 | [MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */ | ||
| 290 | [MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */ | ||
| 291 | [MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */ | ||
| 244 | }; | 292 | }; |
| 245 | 293 | ||
| 246 | static struct clk_lookup lookups[] = { | 294 | static struct clk_lookup lookups[] = { |
| 247 | 295 | ||
| 248 | /* main clocks */ | 296 | /* main clocks */ |
| 297 | CLKDEV_CON_ID("audio_clk_a", &audio_clk_a), | ||
| 298 | CLKDEV_CON_ID("audio_clk_b", &audio_clk_b), | ||
| 299 | CLKDEV_CON_ID("audio_clk_c", &audio_clk_c), | ||
| 300 | CLKDEV_CON_ID("audio_clk_internal", &m2_clk), | ||
| 249 | CLKDEV_CON_ID("extal", &extal_clk), | 301 | CLKDEV_CON_ID("extal", &extal_clk), |
| 250 | CLKDEV_CON_ID("extal_div2", &extal_div2_clk), | 302 | CLKDEV_CON_ID("extal_div2", &extal_div2_clk), |
| 251 | CLKDEV_CON_ID("main", &main_clk), | 303 | CLKDEV_CON_ID("main", &main_clk), |
| @@ -291,32 +343,32 @@ static struct clk_lookup lookups[] = { | |||
| 291 | CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), | 343 | CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), |
| 292 | CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]), | 344 | CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]), |
| 293 | CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]), | 345 | CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]), |
| 294 | CLKDEV_DEV_ID("e6508000.i2c", &mstp_clks[MSTP931]), | ||
| 295 | CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]), | 346 | CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]), |
| 296 | CLKDEV_DEV_ID("e6518000.i2c", &mstp_clks[MSTP930]), | ||
| 297 | CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]), | 347 | CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]), |
| 298 | CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]), | ||
| 299 | CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]), | 348 | CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]), |
| 300 | CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]), | ||
| 301 | CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]), | 349 | CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]), |
| 302 | CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]), | 350 | CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]), |
| 303 | CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]), | 351 | CLKDEV_DEV_ID("r8a7790-vin.0", &mstp_clks[MSTP811]), |
| 352 | CLKDEV_DEV_ID("r8a7790-vin.1", &mstp_clks[MSTP810]), | ||
| 353 | CLKDEV_DEV_ID("r8a7790-vin.2", &mstp_clks[MSTP809]), | ||
| 354 | CLKDEV_DEV_ID("r8a7790-vin.3", &mstp_clks[MSTP808]), | ||
| 304 | CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), | 355 | CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), |
| 305 | CLKDEV_DEV_ID("ee200000.mmc", &mstp_clks[MSTP315]), | 356 | CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP502]), |
| 357 | CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP501]), | ||
| 306 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]), | 358 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]), |
| 307 | CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]), | ||
| 308 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), | 359 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), |
| 309 | CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]), | ||
| 310 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), | 360 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), |
| 311 | CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP312]), | ||
| 312 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]), | 361 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]), |
| 313 | CLKDEV_DEV_ID("ee160000.sd", &mstp_clks[MSTP311]), | ||
| 314 | CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]), | 362 | CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]), |
| 315 | CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]), | ||
| 316 | CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]), | 363 | CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]), |
| 317 | CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]), | 364 | CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]), |
| 318 | CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]), | 365 | CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]), |
| 319 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]), | 366 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]), |
| 367 | CLKDEV_DEV_ID("pci-rcar-gen2.0", &mstp_clks[MSTP703]), | ||
| 368 | CLKDEV_DEV_ID("pci-rcar-gen2.1", &mstp_clks[MSTP703]), | ||
| 369 | CLKDEV_DEV_ID("pci-rcar-gen2.2", &mstp_clks[MSTP703]), | ||
| 370 | CLKDEV_DEV_ID("sata-r8a7790.0", &mstp_clks[MSTP815]), | ||
| 371 | CLKDEV_DEV_ID("sata-r8a7790.1", &mstp_clks[MSTP814]), | ||
| 320 | 372 | ||
| 321 | /* ICK */ | 373 | /* ICK */ |
| 322 | CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]), | 374 | CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]), |
| @@ -325,6 +377,20 @@ static struct clk_lookup lookups[] = { | |||
| 325 | CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]), | 377 | CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]), |
| 326 | CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]), | 378 | CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]), |
| 327 | CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]), | 379 | CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]), |
| 380 | CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a), | ||
| 381 | CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b), | ||
| 382 | CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c), | ||
| 383 | CLKDEV_ICK_ID("clk_i", "rcar_sound", &m2_clk), | ||
| 384 | CLKDEV_ICK_ID("scu.0", "rcar_sound", &mstp_clks[MSTP1031]), | ||
| 385 | CLKDEV_ICK_ID("scu.1", "rcar_sound", &mstp_clks[MSTP1030]), | ||
| 386 | CLKDEV_ICK_ID("scu.2", "rcar_sound", &mstp_clks[MSTP1029]), | ||
| 387 | CLKDEV_ICK_ID("scu.3", "rcar_sound", &mstp_clks[MSTP1028]), | ||
| 388 | CLKDEV_ICK_ID("scu.4", "rcar_sound", &mstp_clks[MSTP1027]), | ||
| 389 | CLKDEV_ICK_ID("scu.5", "rcar_sound", &mstp_clks[MSTP1026]), | ||
| 390 | CLKDEV_ICK_ID("scu.6", "rcar_sound", &mstp_clks[MSTP1025]), | ||
| 391 | CLKDEV_ICK_ID("scu.7", "rcar_sound", &mstp_clks[MSTP1024]), | ||
| 392 | CLKDEV_ICK_ID("scu.8", "rcar_sound", &mstp_clks[MSTP1023]), | ||
| 393 | CLKDEV_ICK_ID("scu.9", "rcar_sound", &mstp_clks[MSTP1022]), | ||
| 328 | CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]), | 394 | CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]), |
| 329 | CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]), | 395 | CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]), |
| 330 | CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]), | 396 | CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]), |
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c index f5461262ee25..701383fe3267 100644 --- a/arch/arm/mach-shmobile/clock-r8a7791.c +++ b/arch/arm/mach-shmobile/clock-r8a7791.c | |||
| @@ -59,10 +59,19 @@ | |||
| 59 | #define SMSTPCR10 0xE6150998 | 59 | #define SMSTPCR10 0xE6150998 |
| 60 | #define SMSTPCR11 0xE615099C | 60 | #define SMSTPCR11 0xE615099C |
| 61 | 61 | ||
| 62 | #define MSTPSR1 IOMEM(0xe6150038) | ||
| 63 | #define MSTPSR2 IOMEM(0xe6150040) | ||
| 64 | #define MSTPSR3 IOMEM(0xe6150048) | ||
| 65 | #define MSTPSR5 IOMEM(0xe615003c) | ||
| 66 | #define MSTPSR7 IOMEM(0xe61501c4) | ||
| 67 | #define MSTPSR8 IOMEM(0xe61509a0) | ||
| 68 | #define MSTPSR9 IOMEM(0xe61509a4) | ||
| 69 | #define MSTPSR11 IOMEM(0xe61509ac) | ||
| 70 | |||
| 62 | #define MODEMR 0xE6160060 | 71 | #define MODEMR 0xE6160060 |
| 63 | #define SDCKCR 0xE6150074 | 72 | #define SDCKCR 0xE6150074 |
| 64 | #define SD2CKCR 0xE6150078 | 73 | #define SD1CKCR 0xE6150078 |
| 65 | #define SD3CKCR 0xE615007C | 74 | #define SD2CKCR 0xE615026c |
| 66 | #define MMC0CKCR 0xE6150240 | 75 | #define MMC0CKCR 0xE6150240 |
| 67 | #define MMC1CKCR 0xE6150244 | 76 | #define MMC1CKCR 0xE6150244 |
| 68 | #define SSPCKCR 0xE6150248 | 77 | #define SSPCKCR 0xE6150248 |
| @@ -93,6 +102,7 @@ static struct clk main_clk = { | |||
| 93 | */ | 102 | */ |
| 94 | SH_FIXED_RATIO_CLK_SET(pll1_clk, main_clk, 1, 1); | 103 | SH_FIXED_RATIO_CLK_SET(pll1_clk, main_clk, 1, 1); |
| 95 | SH_FIXED_RATIO_CLK_SET(pll3_clk, main_clk, 1, 1); | 104 | SH_FIXED_RATIO_CLK_SET(pll3_clk, main_clk, 1, 1); |
| 105 | SH_FIXED_RATIO_CLK_SET(qspi_clk, pll1_clk, 1, 1); | ||
| 96 | 106 | ||
| 97 | /* fixed ratio clock */ | 107 | /* fixed ratio clock */ |
| 98 | SH_FIXED_RATIO_CLK_SET(extal_div2_clk, extal_clk, 1, 2); | 108 | SH_FIXED_RATIO_CLK_SET(extal_div2_clk, extal_clk, 1, 2); |
| @@ -103,7 +113,9 @@ SH_FIXED_RATIO_CLK_SET(hp_clk, pll1_clk, 1, 12); | |||
| 103 | SH_FIXED_RATIO_CLK_SET(p_clk, pll1_clk, 1, 24); | 113 | SH_FIXED_RATIO_CLK_SET(p_clk, pll1_clk, 1, 24); |
| 104 | SH_FIXED_RATIO_CLK_SET(rclk_clk, pll1_clk, 1, (48 * 1024)); | 114 | SH_FIXED_RATIO_CLK_SET(rclk_clk, pll1_clk, 1, (48 * 1024)); |
| 105 | SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); | 115 | SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); |
| 116 | SH_FIXED_RATIO_CLK_SET(zg_clk, pll1_clk, 1, 3); | ||
| 106 | SH_FIXED_RATIO_CLK_SET(zx_clk, pll1_clk, 1, 3); | 117 | SH_FIXED_RATIO_CLK_SET(zx_clk, pll1_clk, 1, 3); |
| 118 | SH_FIXED_RATIO_CLK_SET(zs_clk, pll1_clk, 1, 6); | ||
| 107 | 119 | ||
| 108 | static struct clk *main_clks[] = { | 120 | static struct clk *main_clks[] = { |
| 109 | &extal_clk, | 121 | &extal_clk, |
| @@ -114,46 +126,103 @@ static struct clk *main_clks[] = { | |||
| 114 | &pll3_clk, | 126 | &pll3_clk, |
| 115 | &hp_clk, | 127 | &hp_clk, |
| 116 | &p_clk, | 128 | &p_clk, |
| 129 | &qspi_clk, | ||
| 117 | &rclk_clk, | 130 | &rclk_clk, |
| 118 | &mp_clk, | 131 | &mp_clk, |
| 119 | &cp_clk, | 132 | &cp_clk, |
| 133 | &zg_clk, | ||
| 120 | &zx_clk, | 134 | &zx_clk, |
| 135 | &zs_clk, | ||
| 136 | }; | ||
| 137 | |||
| 138 | /* SDHI (DIV4) clock */ | ||
| 139 | static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 }; | ||
| 140 | |||
| 141 | static struct clk_div_mult_table div4_div_mult_table = { | ||
| 142 | .divisors = divisors, | ||
| 143 | .nr_divisors = ARRAY_SIZE(divisors), | ||
| 144 | }; | ||
| 145 | |||
| 146 | static struct clk_div4_table div4_table = { | ||
| 147 | .div_mult_table = &div4_div_mult_table, | ||
| 148 | }; | ||
| 149 | |||
| 150 | enum { | ||
| 151 | DIV4_SDH, DIV4_SD0, | ||
| 152 | DIV4_NR | ||
| 153 | }; | ||
| 154 | |||
| 155 | static struct clk div4_clks[DIV4_NR] = { | ||
| 156 | [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT), | ||
| 157 | [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT), | ||
| 158 | }; | ||
| 159 | |||
| 160 | /* DIV6 clocks */ | ||
| 161 | enum { | ||
| 162 | DIV6_SD1, DIV6_SD2, | ||
| 163 | DIV6_NR | ||
| 164 | }; | ||
| 165 | |||
| 166 | static struct clk div6_clks[DIV6_NR] = { | ||
| 167 | [DIV6_SD1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0), | ||
| 168 | [DIV6_SD2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0), | ||
| 121 | }; | 169 | }; |
| 122 | 170 | ||
| 123 | /* MSTP */ | 171 | /* MSTP */ |
| 124 | enum { | 172 | enum { |
| 173 | MSTP1108, MSTP1107, MSTP1106, | ||
| 174 | MSTP931, MSTP930, MSTP929, MSTP928, MSTP927, MSTP925, | ||
| 175 | MSTP917, | ||
| 176 | MSTP815, MSTP814, | ||
| 125 | MSTP813, | 177 | MSTP813, |
| 178 | MSTP811, MSTP810, MSTP809, | ||
| 126 | MSTP726, MSTP724, MSTP723, MSTP721, MSTP720, | 179 | MSTP726, MSTP724, MSTP723, MSTP721, MSTP720, |
| 127 | MSTP719, MSTP718, MSTP715, MSTP714, | 180 | MSTP719, MSTP718, MSTP715, MSTP714, |
| 128 | MSTP522, | 181 | MSTP522, |
| 182 | MSTP314, MSTP312, MSTP311, | ||
| 129 | MSTP216, MSTP207, MSTP206, | 183 | MSTP216, MSTP207, MSTP206, |
| 130 | MSTP204, MSTP203, MSTP202, MSTP1105, MSTP1106, MSTP1107, | 184 | MSTP204, MSTP203, MSTP202, |
| 131 | MSTP124, | 185 | MSTP124, |
| 132 | MSTP_NR | 186 | MSTP_NR |
| 133 | }; | 187 | }; |
| 134 | 188 | ||
| 135 | static struct clk mstp_clks[MSTP_NR] = { | 189 | static struct clk mstp_clks[MSTP_NR] = { |
| 136 | [MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */ | 190 | [MSTP1108] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 8, MSTPSR11, 0), /* SCIFA5 */ |
| 137 | [MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */ | 191 | [MSTP1107] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 7, MSTPSR11, 0), /* SCIFA4 */ |
| 138 | [MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */ | 192 | [MSTP1106] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 6, MSTPSR11, 0), /* SCIFA3 */ |
| 139 | [MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */ | 193 | [MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */ |
| 140 | [MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */ | 194 | [MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */ |
| 141 | [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */ | 195 | [MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */ |
| 142 | [MSTP719] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 19, 0), /* SCIF2 */ | 196 | [MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */ |
| 143 | [MSTP718] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 18, 0), /* SCIF3 */ | 197 | [MSTP927] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */ |
| 144 | [MSTP715] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 15, 0), /* SCIF4 */ | 198 | [MSTP925] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */ |
| 145 | [MSTP714] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 14, 0), /* SCIF5 */ | 199 | [MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */ |
| 146 | [MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */ | 200 | [MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */ |
| 147 | [MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */ | 201 | [MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */ |
| 148 | [MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */ | 202 | [MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */ |
| 149 | [MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */ | 203 | [MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */ |
| 150 | [MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */ | 204 | [MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */ |
| 151 | [MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */ | 205 | [MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */ |
| 152 | [MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */ | 206 | [MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */ |
| 153 | [MSTP1105] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 5, 0), /* SCIFA3 */ | 207 | [MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */ |
| 154 | [MSTP1106] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 6, 0), /* SCIFA4 */ | 208 | [MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */ |
| 155 | [MSTP1107] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 7, 0), /* SCIFA5 */ | 209 | [MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */ |
| 156 | [MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */ | 210 | [MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */ |
| 211 | [MSTP719] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 19, MSTPSR7, 0), /* SCIF2 */ | ||
| 212 | [MSTP718] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 18, MSTPSR7, 0), /* SCIF3 */ | ||
| 213 | [MSTP715] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 15, MSTPSR7, 0), /* SCIF4 */ | ||
| 214 | [MSTP714] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 14, MSTPSR7, 0), /* SCIF5 */ | ||
| 215 | [MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */ | ||
| 216 | [MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */ | ||
| 217 | [MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD1], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI1 */ | ||
| 218 | [MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI2 */ | ||
| 219 | [MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */ | ||
| 220 | [MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */ | ||
| 221 | [MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */ | ||
| 222 | [MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */ | ||
| 223 | [MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */ | ||
| 224 | [MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */ | ||
| 225 | [MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */ | ||
| 157 | }; | 226 | }; |
| 158 | 227 | ||
| 159 | static struct clk_lookup lookups[] = { | 228 | static struct clk_lookup lookups[] = { |
| @@ -165,8 +234,11 @@ static struct clk_lookup lookups[] = { | |||
| 165 | CLKDEV_CON_ID("pll1", &pll1_clk), | 234 | CLKDEV_CON_ID("pll1", &pll1_clk), |
| 166 | CLKDEV_CON_ID("pll1_div2", &pll1_div2_clk), | 235 | CLKDEV_CON_ID("pll1_div2", &pll1_div2_clk), |
| 167 | CLKDEV_CON_ID("pll3", &pll3_clk), | 236 | CLKDEV_CON_ID("pll3", &pll3_clk), |
| 237 | CLKDEV_CON_ID("zg", &zg_clk), | ||
| 238 | CLKDEV_CON_ID("zs", &zs_clk), | ||
| 168 | CLKDEV_CON_ID("hp", &hp_clk), | 239 | CLKDEV_CON_ID("hp", &hp_clk), |
| 169 | CLKDEV_CON_ID("p", &p_clk), | 240 | CLKDEV_CON_ID("p", &p_clk), |
| 241 | CLKDEV_CON_ID("qspi", &qspi_clk), | ||
| 170 | CLKDEV_CON_ID("rclk", &rclk_clk), | 242 | CLKDEV_CON_ID("rclk", &rclk_clk), |
| 171 | CLKDEV_CON_ID("mp", &mp_clk), | 243 | CLKDEV_CON_ID("mp", &mp_clk), |
| 172 | CLKDEV_CON_ID("cp", &cp_clk), | 244 | CLKDEV_CON_ID("cp", &cp_clk), |
| @@ -188,13 +260,27 @@ static struct clk_lookup lookups[] = { | |||
| 188 | CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP718]), /* SCIF3 */ | 260 | CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP718]), /* SCIF3 */ |
| 189 | CLKDEV_DEV_ID("sh-sci.10", &mstp_clks[MSTP715]), /* SCIF4 */ | 261 | CLKDEV_DEV_ID("sh-sci.10", &mstp_clks[MSTP715]), /* SCIF4 */ |
| 190 | CLKDEV_DEV_ID("sh-sci.11", &mstp_clks[MSTP714]), /* SCIF5 */ | 262 | CLKDEV_DEV_ID("sh-sci.11", &mstp_clks[MSTP714]), /* SCIF5 */ |
| 191 | CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1105]), /* SCIFA3 */ | 263 | CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1106]), /* SCIFA3 */ |
| 192 | CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1106]), /* SCIFA4 */ | 264 | CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1107]), /* SCIFA4 */ |
| 193 | CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1107]), /* SCIFA5 */ | 265 | CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1108]), /* SCIFA5 */ |
| 266 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), | ||
| 267 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP312]), | ||
| 268 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), | ||
| 194 | CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]), | 269 | CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]), |
| 195 | CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]), | 270 | CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]), |
| 196 | CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), | 271 | CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), |
| 272 | CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]), | ||
| 273 | CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]), | ||
| 274 | CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]), | ||
| 275 | CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]), | ||
| 276 | CLKDEV_DEV_ID("i2c-rcar_gen2.4", &mstp_clks[MSTP927]), | ||
| 277 | CLKDEV_DEV_ID("i2c-rcar_gen2.5", &mstp_clks[MSTP925]), | ||
| 197 | CLKDEV_DEV_ID("r8a7791-ether", &mstp_clks[MSTP813]), /* Ether */ | 278 | CLKDEV_DEV_ID("r8a7791-ether", &mstp_clks[MSTP813]), /* Ether */ |
| 279 | CLKDEV_DEV_ID("r8a7791-vin.0", &mstp_clks[MSTP811]), | ||
| 280 | CLKDEV_DEV_ID("r8a7791-vin.1", &mstp_clks[MSTP810]), | ||
| 281 | CLKDEV_DEV_ID("r8a7791-vin.2", &mstp_clks[MSTP809]), | ||
| 282 | CLKDEV_DEV_ID("sata-r8a7791.0", &mstp_clks[MSTP815]), | ||
| 283 | CLKDEV_DEV_ID("sata-r8a7791.1", &mstp_clks[MSTP814]), | ||
| 198 | }; | 284 | }; |
| 199 | 285 | ||
| 200 | #define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31) \ | 286 | #define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31) \ |
| @@ -232,10 +318,21 @@ void __init r8a7791_clock_init(void) | |||
| 232 | break; | 318 | break; |
| 233 | } | 319 | } |
| 234 | 320 | ||
| 321 | if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2)) | ||
| 322 | SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16); | ||
| 323 | else | ||
| 324 | SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20); | ||
| 325 | |||
| 235 | for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) | 326 | for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) |
| 236 | ret = clk_register(main_clks[k]); | 327 | ret = clk_register(main_clks[k]); |
| 237 | 328 | ||
| 238 | if (!ret) | 329 | if (!ret) |
| 330 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); | ||
| 331 | |||
| 332 | if (!ret) | ||
| 333 | ret = sh_clk_div6_register(div6_clks, DIV6_NR); | ||
| 334 | |||
| 335 | if (!ret) | ||
| 239 | ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); | 336 | ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); |
| 240 | 337 | ||
| 241 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 338 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); |
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 3389f0775def..0b95babe84ba 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h | |||
| @@ -3,6 +3,31 @@ | |||
| 3 | 3 | ||
| 4 | #include <mach/rcar-gen2.h> | 4 | #include <mach/rcar-gen2.h> |
| 5 | 5 | ||
| 6 | /* DMA slave IDs */ | ||
| 7 | enum { | ||
| 8 | RCAR_DMA_SLAVE_INVALID, | ||
| 9 | AUDIO_DMAC_SLAVE_SSI0_TX, | ||
| 10 | AUDIO_DMAC_SLAVE_SSI0_RX, | ||
| 11 | AUDIO_DMAC_SLAVE_SSI1_TX, | ||
| 12 | AUDIO_DMAC_SLAVE_SSI1_RX, | ||
| 13 | AUDIO_DMAC_SLAVE_SSI2_TX, | ||
| 14 | AUDIO_DMAC_SLAVE_SSI2_RX, | ||
| 15 | AUDIO_DMAC_SLAVE_SSI3_TX, | ||
| 16 | AUDIO_DMAC_SLAVE_SSI3_RX, | ||
| 17 | AUDIO_DMAC_SLAVE_SSI4_TX, | ||
| 18 | AUDIO_DMAC_SLAVE_SSI4_RX, | ||
| 19 | AUDIO_DMAC_SLAVE_SSI5_TX, | ||
| 20 | AUDIO_DMAC_SLAVE_SSI5_RX, | ||
| 21 | AUDIO_DMAC_SLAVE_SSI6_TX, | ||
| 22 | AUDIO_DMAC_SLAVE_SSI6_RX, | ||
| 23 | AUDIO_DMAC_SLAVE_SSI7_TX, | ||
| 24 | AUDIO_DMAC_SLAVE_SSI7_RX, | ||
| 25 | AUDIO_DMAC_SLAVE_SSI8_TX, | ||
| 26 | AUDIO_DMAC_SLAVE_SSI8_RX, | ||
| 27 | AUDIO_DMAC_SLAVE_SSI9_TX, | ||
| 28 | AUDIO_DMAC_SLAVE_SSI9_RX, | ||
| 29 | }; | ||
| 30 | |||
| 6 | void r8a7790_add_standard_devices(void); | 31 | void r8a7790_add_standard_devices(void); |
| 7 | void r8a7790_add_dt_devices(void); | 32 | void r8a7790_add_dt_devices(void); |
| 8 | void r8a7790_clock_init(void); | 33 | void r8a7790_clock_init(void); |
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index 6ab37aa1e919..c4616f0698c6 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c | |||
| @@ -24,12 +24,100 @@ | |||
| 24 | #include <linux/platform_data/gpio-rcar.h> | 24 | #include <linux/platform_data/gpio-rcar.h> |
| 25 | #include <linux/platform_data/irq-renesas-irqc.h> | 25 | #include <linux/platform_data/irq-renesas-irqc.h> |
| 26 | #include <linux/serial_sci.h> | 26 | #include <linux/serial_sci.h> |
| 27 | #include <linux/sh_dma.h> | ||
| 27 | #include <linux/sh_timer.h> | 28 | #include <linux/sh_timer.h> |
| 28 | #include <mach/common.h> | 29 | #include <mach/common.h> |
| 30 | #include <mach/dma-register.h> | ||
| 29 | #include <mach/irqs.h> | 31 | #include <mach/irqs.h> |
| 30 | #include <mach/r8a7790.h> | 32 | #include <mach/r8a7790.h> |
| 31 | #include <asm/mach/arch.h> | 33 | #include <asm/mach/arch.h> |
| 32 | 34 | ||
| 35 | /* Audio-DMAC */ | ||
| 36 | #define AUDIO_DMAC_SLAVE(_id, _addr, t, r) \ | ||
| 37 | { \ | ||
| 38 | .slave_id = AUDIO_DMAC_SLAVE_## _id ##_TX, \ | ||
| 39 | .addr = _addr + 0x8, \ | ||
| 40 | .chcr = CHCR_TX(XMIT_SZ_32BIT), \ | ||
| 41 | .mid_rid = t, \ | ||
| 42 | }, { \ | ||
| 43 | .slave_id = AUDIO_DMAC_SLAVE_## _id ##_RX, \ | ||
| 44 | .addr = _addr + 0xc, \ | ||
| 45 | .chcr = CHCR_RX(XMIT_SZ_32BIT), \ | ||
| 46 | .mid_rid = r, \ | ||
| 47 | } | ||
| 48 | |||
| 49 | static const struct sh_dmae_slave_config r8a7790_audio_dmac_slaves[] = { | ||
| 50 | AUDIO_DMAC_SLAVE(SSI0, 0xec241000, 0x01, 0x02), | ||
| 51 | AUDIO_DMAC_SLAVE(SSI1, 0xec241040, 0x03, 0x04), | ||
| 52 | AUDIO_DMAC_SLAVE(SSI2, 0xec241080, 0x05, 0x06), | ||
| 53 | AUDIO_DMAC_SLAVE(SSI3, 0xec2410c0, 0x07, 0x08), | ||
| 54 | AUDIO_DMAC_SLAVE(SSI4, 0xec241100, 0x09, 0x0a), | ||
| 55 | AUDIO_DMAC_SLAVE(SSI5, 0xec241140, 0x0b, 0x0c), | ||
| 56 | AUDIO_DMAC_SLAVE(SSI6, 0xec241180, 0x0d, 0x0e), | ||
| 57 | AUDIO_DMAC_SLAVE(SSI7, 0xec2411c0, 0x0f, 0x10), | ||
| 58 | AUDIO_DMAC_SLAVE(SSI8, 0xec241200, 0x11, 0x12), | ||
| 59 | AUDIO_DMAC_SLAVE(SSI9, 0xec241240, 0x13, 0x14), | ||
| 60 | }; | ||
| 61 | |||
| 62 | #define DMAE_CHANNEL(a, b) \ | ||
| 63 | { \ | ||
| 64 | .offset = (a) - 0x20, \ | ||
| 65 | .dmars = (a) - 0x20 + 0x40, \ | ||
| 66 | .chclr_bit = (b), \ | ||
| 67 | .chclr_offset = 0x80 - 0x20, \ | ||
| 68 | } | ||
| 69 | |||
| 70 | static const struct sh_dmae_channel r8a7790_audio_dmac_channels[] = { | ||
| 71 | DMAE_CHANNEL(0x8000, 0), | ||
| 72 | DMAE_CHANNEL(0x8080, 1), | ||
| 73 | DMAE_CHANNEL(0x8100, 2), | ||
| 74 | DMAE_CHANNEL(0x8180, 3), | ||
| 75 | DMAE_CHANNEL(0x8200, 4), | ||
| 76 | DMAE_CHANNEL(0x8280, 5), | ||
| 77 | DMAE_CHANNEL(0x8300, 6), | ||
| 78 | DMAE_CHANNEL(0x8380, 7), | ||
| 79 | DMAE_CHANNEL(0x8400, 8), | ||
| 80 | DMAE_CHANNEL(0x8480, 9), | ||
| 81 | DMAE_CHANNEL(0x8500, 10), | ||
| 82 | DMAE_CHANNEL(0x8580, 11), | ||
| 83 | DMAE_CHANNEL(0x8600, 12), | ||
| 84 | }; | ||
| 85 | |||
| 86 | static struct sh_dmae_pdata r8a7790_audio_dmac_platform_data = { | ||
| 87 | .slave = r8a7790_audio_dmac_slaves, | ||
| 88 | .slave_num = ARRAY_SIZE(r8a7790_audio_dmac_slaves), | ||
| 89 | .channel = r8a7790_audio_dmac_channels, | ||
| 90 | .channel_num = ARRAY_SIZE(r8a7790_audio_dmac_channels), | ||
| 91 | .ts_low_shift = TS_LOW_SHIFT, | ||
| 92 | .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, | ||
| 93 | .ts_high_shift = TS_HI_SHIFT, | ||
| 94 | .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, | ||
| 95 | .ts_shift = dma_ts_shift, | ||
| 96 | .ts_shift_num = ARRAY_SIZE(dma_ts_shift), | ||
| 97 | .dmaor_init = DMAOR_DME, | ||
| 98 | .chclr_present = 1, | ||
| 99 | .chclr_bitwise = 1, | ||
| 100 | }; | ||
| 101 | |||
| 102 | static struct resource r8a7790_audio_dmac_resources[] = { | ||
| 103 | /* Channel registers and DMAOR for low */ | ||
| 104 | DEFINE_RES_MEM(0xec700020, 0x8663 - 0x20), | ||
| 105 | DEFINE_RES_IRQ(gic_spi(346)), | ||
| 106 | DEFINE_RES_NAMED(gic_spi(320), 13, NULL, IORESOURCE_IRQ), | ||
| 107 | |||
| 108 | /* Channel registers and DMAOR for hi */ | ||
| 109 | DEFINE_RES_MEM(0xec720020, 0x8663 - 0x20), /* hi */ | ||
| 110 | DEFINE_RES_IRQ(gic_spi(347)), | ||
| 111 | DEFINE_RES_NAMED(gic_spi(333), 13, NULL, IORESOURCE_IRQ), | ||
| 112 | }; | ||
| 113 | |||
| 114 | #define r8a7790_register_audio_dmac(id) \ | ||
| 115 | platform_device_register_resndata( \ | ||
| 116 | &platform_bus, "sh-dma-engine", id, \ | ||
| 117 | &r8a7790_audio_dmac_resources[id * 3], 3, \ | ||
| 118 | &r8a7790_audio_dmac_platform_data, \ | ||
| 119 | sizeof(r8a7790_audio_dmac_platform_data)) | ||
| 120 | |||
| 33 | static const struct resource pfc_resources[] __initconst = { | 121 | static const struct resource pfc_resources[] __initconst = { |
| 34 | DEFINE_RES_MEM(0xe6060000, 0x250), | 122 | DEFINE_RES_MEM(0xe6060000, 0x250), |
| 35 | }; | 123 | }; |
| @@ -101,6 +189,8 @@ void __init r8a7790_pinmux_init(void) | |||
| 101 | r8a7790_register_i2c(1); | 189 | r8a7790_register_i2c(1); |
| 102 | r8a7790_register_i2c(2); | 190 | r8a7790_register_i2c(2); |
| 103 | r8a7790_register_i2c(3); | 191 | r8a7790_register_i2c(3); |
| 192 | r8a7790_register_audio_dmac(0); | ||
| 193 | r8a7790_register_audio_dmac(1); | ||
| 104 | } | 194 | } |
| 105 | 195 | ||
| 106 | #define __R8A7790_SCIF(scif_type, _scscr, index, baseaddr, irq) \ | 196 | #define __R8A7790_SCIF(scif_type, _scscr, index, baseaddr, irq) \ |
diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index d2c13ba1190b..abf9ee9bbc3f 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig | |||
| @@ -5,6 +5,7 @@ menuconfig ARCH_STI | |||
| 5 | select PINCTRL | 5 | select PINCTRL |
| 6 | select PINCTRL_ST | 6 | select PINCTRL_ST |
| 7 | select MFD_SYSCON | 7 | select MFD_SYSCON |
| 8 | select ARCH_HAS_RESET_CONTROLLER | ||
| 8 | select HAVE_ARM_SCU if SMP | 9 | select HAVE_ARM_SCU if SMP |
| 9 | select ARCH_REQUIRE_GPIOLIB | 10 | select ARCH_REQUIRE_GPIOLIB |
| 10 | select ARM_ERRATA_754322 | 11 | select ARM_ERRATA_754322 |
| @@ -24,6 +25,7 @@ if ARCH_STI | |||
| 24 | config SOC_STIH415 | 25 | config SOC_STIH415 |
| 25 | bool "STiH415 STMicroelectronics Consumer Electronics family" | 26 | bool "STiH415 STMicroelectronics Consumer Electronics family" |
| 26 | default y | 27 | default y |
| 28 | select STIH415_RESET | ||
| 27 | help | 29 | help |
| 28 | This enables support for STMicroelectronics Digital Consumer | 30 | This enables support for STMicroelectronics Digital Consumer |
| 29 | Electronics family StiH415 parts, primarily targeted at set-top-box | 31 | Electronics family StiH415 parts, primarily targeted at set-top-box |
| @@ -33,6 +35,7 @@ config SOC_STIH415 | |||
| 33 | config SOC_STIH416 | 35 | config SOC_STIH416 |
| 34 | bool "STiH416 STMicroelectronics Consumer Electronics family" | 36 | bool "STiH416 STMicroelectronics Consumer Electronics family" |
| 35 | default y | 37 | default y |
| 38 | select STIH416_RESET | ||
| 36 | help | 39 | help |
| 37 | This enables support for STMicroelectronics Digital Consumer | 40 | This enables support for STMicroelectronics Digital Consumer |
| 38 | Electronics family StiH416 parts, primarily targeted at set-top-box | 41 | Electronics family StiH416 parts, primarily targeted at set-top-box |
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index a335126ae18f..f2c89fb8fca9 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
| @@ -108,7 +108,7 @@ void __init versatile_init_irq(void) | |||
| 108 | 108 | ||
| 109 | np = of_find_matching_node_by_address(NULL, vic_of_match, | 109 | np = of_find_matching_node_by_address(NULL, vic_of_match, |
| 110 | VERSATILE_VIC_BASE); | 110 | VERSATILE_VIC_BASE); |
| 111 | __vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np); | 111 | __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np); |
| 112 | 112 | ||
| 113 | writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); | 113 | writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); |
| 114 | 114 | ||
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index 830ff07f3385..3ec6e8e8d368 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c | |||
| @@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase) | |||
| 595 | /***************************************************************************** | 595 | /***************************************************************************** |
| 596 | * Watchdog | 596 | * Watchdog |
| 597 | ****************************************************************************/ | 597 | ****************************************************************************/ |
| 598 | static struct resource orion_wdt_resource = | 598 | static struct resource orion_wdt_resource[] = { |
| 599 | DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28); | 599 | DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04), |
| 600 | DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04), | ||
| 601 | }; | ||
| 600 | 602 | ||
| 601 | static struct platform_device orion_wdt_device = { | 603 | static struct platform_device orion_wdt_device = { |
| 602 | .name = "orion_wdt", | 604 | .name = "orion_wdt", |
| 603 | .id = -1, | 605 | .id = -1, |
| 604 | .num_resources = 1, | 606 | .num_resources = ARRAY_SIZE(orion_wdt_resource), |
| 605 | .resource = &orion_wdt_resource, | 607 | .resource = orion_wdt_resource, |
| 606 | }; | 608 | }; |
| 607 | 609 | ||
| 608 | void __init orion_wdt_init(void) | 610 | void __init orion_wdt_init(void) |
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index 1f44e56cc65d..558a239954e8 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c | |||
| @@ -256,8 +256,6 @@ static int tegra_ahb_probe(struct platform_device *pdev) | |||
| 256 | return -ENOMEM; | 256 | return -ENOMEM; |
| 257 | 257 | ||
| 258 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 258 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 259 | if (!res) | ||
| 260 | return -ENODEV; | ||
| 261 | ahb->regs = devm_ioremap_resource(&pdev->dev, res); | 259 | ahb->regs = devm_ioremap_resource(&pdev->dev, res); |
| 262 | if (IS_ERR(ahb->regs)) | 260 | if (IS_ERR(ahb->regs)) |
| 263 | return PTR_ERR(ahb->regs); | 261 | return PTR_ERR(ahb->regs); |
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 962fd35cbd8d..5a86da97a70b 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | 31 | ||
| 32 | #define DRIVER_NAME "CCI-400" | 32 | #define DRIVER_NAME "CCI-400" |
| 33 | #define DRIVER_NAME_PMU DRIVER_NAME " PMU" | 33 | #define DRIVER_NAME_PMU DRIVER_NAME " PMU" |
| 34 | #define PMU_NAME "CCI_400" | ||
| 35 | 34 | ||
| 36 | #define CCI_PORT_CTRL 0x0 | 35 | #define CCI_PORT_CTRL 0x0 |
| 37 | #define CCI_CTRL_STATUS 0xc | 36 | #define CCI_CTRL_STATUS 0xc |
| @@ -88,8 +87,7 @@ static unsigned long cci_ctrl_phys; | |||
| 88 | 87 | ||
| 89 | #define CCI_REV_R0 0 | 88 | #define CCI_REV_R0 0 |
| 90 | #define CCI_REV_R1 1 | 89 | #define CCI_REV_R1 1 |
| 91 | #define CCI_REV_R0_P4 4 | 90 | #define CCI_REV_R1_PX 5 |
| 92 | #define CCI_REV_R1_P2 6 | ||
| 93 | 91 | ||
| 94 | #define CCI_PMU_EVT_SEL 0x000 | 92 | #define CCI_PMU_EVT_SEL 0x000 |
| 95 | #define CCI_PMU_CNTR 0x004 | 93 | #define CCI_PMU_CNTR 0x004 |
| @@ -163,6 +161,15 @@ static struct pmu_port_event_ranges port_event_range[] = { | |||
| 163 | }, | 161 | }, |
| 164 | }; | 162 | }; |
| 165 | 163 | ||
| 164 | /* | ||
| 165 | * Export different PMU names for the different revisions so userspace knows | ||
| 166 | * because the event ids are different | ||
| 167 | */ | ||
| 168 | static char *const pmu_names[] = { | ||
| 169 | [CCI_REV_R0] = "CCI_400", | ||
| 170 | [CCI_REV_R1] = "CCI_400_r1", | ||
| 171 | }; | ||
| 172 | |||
| 166 | struct cci_pmu_drv_data { | 173 | struct cci_pmu_drv_data { |
| 167 | void __iomem *base; | 174 | void __iomem *base; |
| 168 | struct arm_pmu *cci_pmu; | 175 | struct arm_pmu *cci_pmu; |
| @@ -193,21 +200,16 @@ static int probe_cci_revision(void) | |||
| 193 | rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; | 200 | rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; |
| 194 | rev >>= CCI_PID2_REV_SHIFT; | 201 | rev >>= CCI_PID2_REV_SHIFT; |
| 195 | 202 | ||
| 196 | if (rev <= CCI_REV_R0_P4) | 203 | if (rev < CCI_REV_R1_PX) |
| 197 | return CCI_REV_R0; | 204 | return CCI_REV_R0; |
| 198 | else if (rev <= CCI_REV_R1_P2) | 205 | else |
| 199 | return CCI_REV_R1; | 206 | return CCI_REV_R1; |
| 200 | |||
| 201 | return -ENOENT; | ||
| 202 | } | 207 | } |
| 203 | 208 | ||
| 204 | static struct pmu_port_event_ranges *port_range_by_rev(void) | 209 | static struct pmu_port_event_ranges *port_range_by_rev(void) |
| 205 | { | 210 | { |
| 206 | int rev = probe_cci_revision(); | 211 | int rev = probe_cci_revision(); |
| 207 | 212 | ||
| 208 | if (rev < 0) | ||
| 209 | return NULL; | ||
| 210 | |||
| 211 | return &port_event_range[rev]; | 213 | return &port_event_range[rev]; |
| 212 | } | 214 | } |
| 213 | 215 | ||
| @@ -526,7 +528,7 @@ static void pmu_write_counter(struct perf_event *event, u32 value) | |||
| 526 | static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev) | 528 | static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev) |
| 527 | { | 529 | { |
| 528 | *cci_pmu = (struct arm_pmu){ | 530 | *cci_pmu = (struct arm_pmu){ |
| 529 | .name = PMU_NAME, | 531 | .name = pmu_names[probe_cci_revision()], |
| 530 | .max_period = (1LLU << 32) - 1, | 532 | .max_period = (1LLU << 32) - 1, |
| 531 | .get_hw_events = pmu_get_hw_events, | 533 | .get_hw_events = pmu_get_hw_events, |
| 532 | .get_event_idx = pmu_get_event_idx, | 534 | .get_event_idx = pmu_get_event_idx, |
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 2ac754e18bcf..293e2e0a0a87 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c | |||
| @@ -890,13 +890,12 @@ int __init mvebu_mbus_dt_init(void) | |||
| 890 | const __be32 *prop; | 890 | const __be32 *prop; |
| 891 | int ret; | 891 | int ret; |
| 892 | 892 | ||
| 893 | np = of_find_matching_node(NULL, of_mvebu_mbus_ids); | 893 | np = of_find_matching_node_and_match(NULL, of_mvebu_mbus_ids, &of_id); |
| 894 | if (!np) { | 894 | if (!np) { |
| 895 | pr_err("could not find a matching SoC family\n"); | 895 | pr_err("could not find a matching SoC family\n"); |
| 896 | return -ENODEV; | 896 | return -ENODEV; |
| 897 | } | 897 | } |
| 898 | 898 | ||
| 899 | of_id = of_match_node(of_mvebu_mbus_ids, np); | ||
| 900 | mbus_state.soc = of_id->data; | 899 | mbus_state.soc = of_id->data; |
| 901 | 900 | ||
| 902 | prop = of_get_property(np, "controller", NULL); | 901 | prop = of_get_property(np, "controller", NULL); |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 2f2b08457c67..244759bbd7b7 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
| @@ -342,11 +342,11 @@ config HW_RANDOM_TPM | |||
| 342 | If unsure, say Y. | 342 | If unsure, say Y. |
| 343 | 343 | ||
| 344 | config HW_RANDOM_MSM | 344 | config HW_RANDOM_MSM |
| 345 | tristate "Qualcomm MSM Random Number Generator support" | 345 | tristate "Qualcomm SoCs Random Number Generator support" |
| 346 | depends on HW_RANDOM && ARCH_MSM | 346 | depends on HW_RANDOM && ARCH_QCOM |
| 347 | ---help--- | 347 | ---help--- |
| 348 | This driver provides kernel-side support for the Random Number | 348 | This driver provides kernel-side support for the Random Number |
| 349 | Generator hardware found on Qualcomm MSM SoCs. | 349 | Generator hardware found on Qualcomm SoCs. |
| 350 | 350 | ||
| 351 | To compile this driver as a module, choose M here. the | 351 | To compile this driver as a module, choose M here. the |
| 352 | module will be called msm-rng. | 352 | module will be called msm-rng. |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 7641965d208d..f9f605695e40 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
| @@ -111,4 +111,5 @@ source "drivers/clk/qcom/Kconfig" | |||
| 111 | 111 | ||
| 112 | endmenu | 112 | endmenu |
| 113 | 113 | ||
| 114 | source "drivers/clk/bcm/Kconfig" | ||
| 114 | source "drivers/clk/mvebu/Kconfig" | 115 | source "drivers/clk/mvebu/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a367a9831717..88af4a399d6c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o | |||
| 29 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | 29 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o |
| 30 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o | 30 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o |
| 31 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ | 31 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ |
| 32 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ | ||
| 32 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ | 33 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ |
| 33 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ | 34 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ |
| 34 | ifeq ($(CONFIG_COMMON_CLK), y) | 35 | ifeq ($(CONFIG_COMMON_CLK), y) |
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig new file mode 100644 index 000000000000..a7262fb8ce55 --- /dev/null +++ b/drivers/clk/bcm/Kconfig | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | config CLK_BCM_KONA | ||
| 2 | bool "Broadcom Kona CCU clock support" | ||
| 3 | depends on ARCH_BCM_MOBILE | ||
| 4 | depends on COMMON_CLK | ||
| 5 | default y | ||
| 6 | help | ||
| 7 | Enable common clock framework support for Broadcom SoCs | ||
| 8 | using "Kona" style clock control units, including those | ||
| 9 | in the BCM281xx family. | ||
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile new file mode 100644 index 000000000000..cf93359aa862 --- /dev/null +++ b/drivers/clk/bcm/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o | ||
| 2 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o | ||
| 3 | obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o | ||
diff --git a/drivers/clk/bcm/clk-bcm281xx.c b/drivers/clk/bcm/clk-bcm281xx.c new file mode 100644 index 000000000000..3c66de696aeb --- /dev/null +++ b/drivers/clk/bcm/clk-bcm281xx.c | |||
| @@ -0,0 +1,416 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * Copyright 2013 Linaro Limited | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License as | ||
| 7 | * published by the Free Software Foundation version 2. | ||
| 8 | * | ||
| 9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 10 | * kind, whether express or implied; without even the implied warranty | ||
| 11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "clk-kona.h" | ||
| 16 | #include "dt-bindings/clock/bcm281xx.h" | ||
| 17 | |||
| 18 | /* bcm11351 CCU device tree "compatible" strings */ | ||
| 19 | #define BCM11351_DT_ROOT_CCU_COMPAT "brcm,bcm11351-root-ccu" | ||
| 20 | #define BCM11351_DT_AON_CCU_COMPAT "brcm,bcm11351-aon-ccu" | ||
| 21 | #define BCM11351_DT_HUB_CCU_COMPAT "brcm,bcm11351-hub-ccu" | ||
| 22 | #define BCM11351_DT_MASTER_CCU_COMPAT "brcm,bcm11351-master-ccu" | ||
| 23 | #define BCM11351_DT_SLAVE_CCU_COMPAT "brcm,bcm11351-slave-ccu" | ||
| 24 | |||
| 25 | /* Root CCU clocks */ | ||
| 26 | |||
| 27 | static struct peri_clk_data frac_1m_data = { | ||
| 28 | .gate = HW_SW_GATE(0x214, 16, 0, 1), | ||
| 29 | .trig = TRIGGER(0x0e04, 0), | ||
| 30 | .div = FRAC_DIVIDER(0x0e00, 0, 22, 16), | ||
| 31 | .clocks = CLOCKS("ref_crystal"), | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* AON CCU clocks */ | ||
| 35 | |||
| 36 | static struct peri_clk_data hub_timer_data = { | ||
| 37 | .gate = HW_SW_GATE(0x0414, 16, 0, 1), | ||
| 38 | .clocks = CLOCKS("bbl_32k", | ||
| 39 | "frac_1m", | ||
| 40 | "dft_19_5m"), | ||
| 41 | .sel = SELECTOR(0x0a10, 0, 2), | ||
| 42 | .trig = TRIGGER(0x0a40, 4), | ||
| 43 | }; | ||
| 44 | |||
| 45 | static struct peri_clk_data pmu_bsc_data = { | ||
| 46 | .gate = HW_SW_GATE(0x0418, 16, 0, 1), | ||
| 47 | .clocks = CLOCKS("ref_crystal", | ||
| 48 | "pmu_bsc_var", | ||
| 49 | "bbl_32k"), | ||
| 50 | .sel = SELECTOR(0x0a04, 0, 2), | ||
| 51 | .div = DIVIDER(0x0a04, 3, 4), | ||
| 52 | .trig = TRIGGER(0x0a40, 0), | ||
| 53 | }; | ||
| 54 | |||
| 55 | static struct peri_clk_data pmu_bsc_var_data = { | ||
| 56 | .clocks = CLOCKS("var_312m", | ||
| 57 | "ref_312m"), | ||
| 58 | .sel = SELECTOR(0x0a00, 0, 2), | ||
| 59 | .div = DIVIDER(0x0a00, 4, 5), | ||
| 60 | .trig = TRIGGER(0x0a40, 2), | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* Hub CCU clocks */ | ||
| 64 | |||
| 65 | static struct peri_clk_data tmon_1m_data = { | ||
| 66 | .gate = HW_SW_GATE(0x04a4, 18, 2, 3), | ||
| 67 | .clocks = CLOCKS("ref_crystal", | ||
| 68 | "frac_1m"), | ||
| 69 | .sel = SELECTOR(0x0e74, 0, 2), | ||
| 70 | .trig = TRIGGER(0x0e84, 1), | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* Master CCU clocks */ | ||
| 74 | |||
| 75 | static struct peri_clk_data sdio1_data = { | ||
| 76 | .gate = HW_SW_GATE(0x0358, 18, 2, 3), | ||
| 77 | .clocks = CLOCKS("ref_crystal", | ||
| 78 | "var_52m", | ||
| 79 | "ref_52m", | ||
| 80 | "var_96m", | ||
| 81 | "ref_96m"), | ||
| 82 | .sel = SELECTOR(0x0a28, 0, 3), | ||
| 83 | .div = DIVIDER(0x0a28, 4, 14), | ||
| 84 | .trig = TRIGGER(0x0afc, 9), | ||
| 85 | }; | ||
| 86 | |||
| 87 | static struct peri_clk_data sdio2_data = { | ||
| 88 | .gate = HW_SW_GATE(0x035c, 18, 2, 3), | ||
| 89 | .clocks = CLOCKS("ref_crystal", | ||
| 90 | "var_52m", | ||
| 91 | "ref_52m", | ||
| 92 | "var_96m", | ||
| 93 | "ref_96m"), | ||
| 94 | .sel = SELECTOR(0x0a2c, 0, 3), | ||
| 95 | .div = DIVIDER(0x0a2c, 4, 14), | ||
| 96 | .trig = TRIGGER(0x0afc, 10), | ||
| 97 | }; | ||
| 98 | |||
| 99 | static struct peri_clk_data sdio3_data = { | ||
| 100 | .gate = HW_SW_GATE(0x0364, 18, 2, 3), | ||
| 101 | .clocks = CLOCKS("ref_crystal", | ||
| 102 | "var_52m", | ||
| 103 | "ref_52m", | ||
| 104 | "var_96m", | ||
| 105 | "ref_96m"), | ||
| 106 | .sel = SELECTOR(0x0a34, 0, 3), | ||
| 107 | .div = DIVIDER(0x0a34, 4, 14), | ||
| 108 | .trig = TRIGGER(0x0afc, 12), | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct peri_clk_data sdio4_data = { | ||
| 112 | .gate = HW_SW_GATE(0x0360, 18, 2, 3), | ||
| 113 | .clocks = CLOCKS("ref_crystal", | ||
| 114 | "var_52m", | ||
| 115 | "ref_52m", | ||
| 116 | "var_96m", | ||
| 117 | "ref_96m"), | ||
| 118 | .sel = SELECTOR(0x0a30, 0, 3), | ||
| 119 | .div = DIVIDER(0x0a30, 4, 14), | ||
| 120 | .trig = TRIGGER(0x0afc, 11), | ||
| 121 | }; | ||
| 122 | |||
| 123 | static struct peri_clk_data usb_ic_data = { | ||
| 124 | .gate = HW_SW_GATE(0x0354, 18, 2, 3), | ||
| 125 | .clocks = CLOCKS("ref_crystal", | ||
| 126 | "var_96m", | ||
| 127 | "ref_96m"), | ||
| 128 | .div = FIXED_DIVIDER(2), | ||
| 129 | .sel = SELECTOR(0x0a24, 0, 2), | ||
| 130 | .trig = TRIGGER(0x0afc, 7), | ||
| 131 | }; | ||
| 132 | |||
| 133 | /* also called usbh_48m */ | ||
| 134 | static struct peri_clk_data hsic2_48m_data = { | ||
| 135 | .gate = HW_SW_GATE(0x0370, 18, 2, 3), | ||
| 136 | .clocks = CLOCKS("ref_crystal", | ||
| 137 | "var_96m", | ||
| 138 | "ref_96m"), | ||
| 139 | .sel = SELECTOR(0x0a38, 0, 2), | ||
| 140 | .div = FIXED_DIVIDER(2), | ||
| 141 | .trig = TRIGGER(0x0afc, 5), | ||
| 142 | }; | ||
| 143 | |||
| 144 | /* also called usbh_12m */ | ||
| 145 | static struct peri_clk_data hsic2_12m_data = { | ||
| 146 | .gate = HW_SW_GATE(0x0370, 20, 4, 5), | ||
| 147 | .div = DIVIDER(0x0a38, 12, 2), | ||
| 148 | .clocks = CLOCKS("ref_crystal", | ||
| 149 | "var_96m", | ||
| 150 | "ref_96m"), | ||
| 151 | .pre_div = FIXED_DIVIDER(2), | ||
| 152 | .sel = SELECTOR(0x0a38, 0, 2), | ||
| 153 | .trig = TRIGGER(0x0afc, 5), | ||
| 154 | }; | ||
| 155 | |||
| 156 | /* Slave CCU clocks */ | ||
| 157 | |||
| 158 | static struct peri_clk_data uartb_data = { | ||
| 159 | .gate = HW_SW_GATE(0x0400, 18, 2, 3), | ||
| 160 | .clocks = CLOCKS("ref_crystal", | ||
| 161 | "var_156m", | ||
| 162 | "ref_156m"), | ||
| 163 | .sel = SELECTOR(0x0a10, 0, 2), | ||
| 164 | .div = FRAC_DIVIDER(0x0a10, 4, 12, 8), | ||
| 165 | .trig = TRIGGER(0x0afc, 2), | ||
| 166 | }; | ||
| 167 | |||
| 168 | static struct peri_clk_data uartb2_data = { | ||
| 169 | .gate = HW_SW_GATE(0x0404, 18, 2, 3), | ||
| 170 | .clocks = CLOCKS("ref_crystal", | ||
| 171 | "var_156m", | ||
| 172 | "ref_156m"), | ||
| 173 | .sel = SELECTOR(0x0a14, 0, 2), | ||
| 174 | .div = FRAC_DIVIDER(0x0a14, 4, 12, 8), | ||
| 175 | .trig = TRIGGER(0x0afc, 3), | ||
| 176 | }; | ||
| 177 | |||
| 178 | static struct peri_clk_data uartb3_data = { | ||
| 179 | .gate = HW_SW_GATE(0x0408, 18, 2, 3), | ||
| 180 | .clocks = CLOCKS("ref_crystal", | ||
| 181 | "var_156m", | ||
| 182 | "ref_156m"), | ||
| 183 | .sel = SELECTOR(0x0a18, 0, 2), | ||
| 184 | .div = FRAC_DIVIDER(0x0a18, 4, 12, 8), | ||
| 185 | .trig = TRIGGER(0x0afc, 4), | ||
| 186 | }; | ||
| 187 | |||
| 188 | static struct peri_clk_data uartb4_data = { | ||
| 189 | .gate = HW_SW_GATE(0x0408, 18, 2, 3), | ||
| 190 | .clocks = CLOCKS("ref_crystal", | ||
| 191 | "var_156m", | ||
| 192 | "ref_156m"), | ||
| 193 | .sel = SELECTOR(0x0a1c, 0, 2), | ||
| 194 | .div = FRAC_DIVIDER(0x0a1c, 4, 12, 8), | ||
| 195 | .trig = TRIGGER(0x0afc, 5), | ||
| 196 | }; | ||
| 197 | |||
| 198 | static struct peri_clk_data ssp0_data = { | ||
| 199 | .gate = HW_SW_GATE(0x0410, 18, 2, 3), | ||
| 200 | .clocks = CLOCKS("ref_crystal", | ||
| 201 | "var_104m", | ||
| 202 | "ref_104m", | ||
| 203 | "var_96m", | ||
| 204 | "ref_96m"), | ||
| 205 | .sel = SELECTOR(0x0a20, 0, 3), | ||
| 206 | .div = DIVIDER(0x0a20, 4, 14), | ||
| 207 | .trig = TRIGGER(0x0afc, 6), | ||
| 208 | }; | ||
| 209 | |||
| 210 | static struct peri_clk_data ssp2_data = { | ||
| 211 | .gate = HW_SW_GATE(0x0418, 18, 2, 3), | ||
| 212 | .clocks = CLOCKS("ref_crystal", | ||
| 213 | "var_104m", | ||
| 214 | "ref_104m", | ||
| 215 | "var_96m", | ||
| 216 | "ref_96m"), | ||
| 217 | .sel = SELECTOR(0x0a28, 0, 3), | ||
| 218 | .div = DIVIDER(0x0a28, 4, 14), | ||
| 219 | .trig = TRIGGER(0x0afc, 8), | ||
| 220 | }; | ||
| 221 | |||
| 222 | static struct peri_clk_data bsc1_data = { | ||
| 223 | .gate = HW_SW_GATE(0x0458, 18, 2, 3), | ||
| 224 | .clocks = CLOCKS("ref_crystal", | ||
| 225 | "var_104m", | ||
| 226 | "ref_104m", | ||
| 227 | "var_13m", | ||
| 228 | "ref_13m"), | ||
| 229 | .sel = SELECTOR(0x0a64, 0, 3), | ||
| 230 | .trig = TRIGGER(0x0afc, 23), | ||
| 231 | }; | ||
| 232 | |||
| 233 | static struct peri_clk_data bsc2_data = { | ||
| 234 | .gate = HW_SW_GATE(0x045c, 18, 2, 3), | ||
| 235 | .clocks = CLOCKS("ref_crystal", | ||
| 236 | "var_104m", | ||
| 237 | "ref_104m", | ||
| 238 | "var_13m", | ||
| 239 | "ref_13m"), | ||
| 240 | .sel = SELECTOR(0x0a68, 0, 3), | ||
| 241 | .trig = TRIGGER(0x0afc, 24), | ||
| 242 | }; | ||
| 243 | |||
| 244 | static struct peri_clk_data bsc3_data = { | ||
| 245 | .gate = HW_SW_GATE(0x0484, 18, 2, 3), | ||
| 246 | .clocks = CLOCKS("ref_crystal", | ||
| 247 | "var_104m", | ||
| 248 | "ref_104m", | ||
| 249 | "var_13m", | ||
| 250 | "ref_13m"), | ||
| 251 | .sel = SELECTOR(0x0a84, 0, 3), | ||
| 252 | .trig = TRIGGER(0x0b00, 2), | ||
| 253 | }; | ||
| 254 | |||
| 255 | static struct peri_clk_data pwm_data = { | ||
| 256 | .gate = HW_SW_GATE(0x0468, 18, 2, 3), | ||
| 257 | .clocks = CLOCKS("ref_crystal", | ||
| 258 | "var_104m"), | ||
| 259 | .sel = SELECTOR(0x0a70, 0, 2), | ||
| 260 | .div = DIVIDER(0x0a70, 4, 3), | ||
| 261 | .trig = TRIGGER(0x0afc, 15), | ||
| 262 | }; | ||
| 263 | |||
| 264 | /* | ||
| 265 | * CCU setup routines | ||
| 266 | * | ||
| 267 | * These are called from kona_dt_ccu_setup() to initialize the array | ||
| 268 | * of clocks provided by the CCU. Once allocated, the entries in | ||
| 269 | * the array are initialized by calling kona_clk_setup() with the | ||
| 270 | * initialization data for each clock. They return 0 if successful | ||
| 271 | * or an error code otherwise. | ||
| 272 | */ | ||
| 273 | static int __init bcm281xx_root_ccu_clks_setup(struct ccu_data *ccu) | ||
| 274 | { | ||
| 275 | struct clk **clks; | ||
| 276 | size_t count = BCM281XX_ROOT_CCU_CLOCK_COUNT; | ||
| 277 | |||
| 278 | clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); | ||
| 279 | if (!clks) { | ||
| 280 | pr_err("%s: failed to allocate root clocks\n", __func__); | ||
| 281 | return -ENOMEM; | ||
| 282 | } | ||
| 283 | ccu->data.clks = clks; | ||
| 284 | ccu->data.clk_num = count; | ||
| 285 | |||
| 286 | PERI_CLK_SETUP(clks, ccu, BCM281XX_ROOT_CCU_FRAC_1M, frac_1m); | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int __init bcm281xx_aon_ccu_clks_setup(struct ccu_data *ccu) | ||
| 292 | { | ||
| 293 | struct clk **clks; | ||
| 294 | size_t count = BCM281XX_AON_CCU_CLOCK_COUNT; | ||
| 295 | |||
| 296 | clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); | ||
| 297 | if (!clks) { | ||
| 298 | pr_err("%s: failed to allocate aon clocks\n", __func__); | ||
| 299 | return -ENOMEM; | ||
| 300 | } | ||
| 301 | ccu->data.clks = clks; | ||
| 302 | ccu->data.clk_num = count; | ||
| 303 | |||
| 304 | PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_HUB_TIMER, hub_timer); | ||
| 305 | PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_PMU_BSC, pmu_bsc); | ||
| 306 | PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_PMU_BSC_VAR, pmu_bsc_var); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int __init bcm281xx_hub_ccu_clks_setup(struct ccu_data *ccu) | ||
| 312 | { | ||
| 313 | struct clk **clks; | ||
| 314 | size_t count = BCM281XX_HUB_CCU_CLOCK_COUNT; | ||
| 315 | |||
| 316 | clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); | ||
| 317 | if (!clks) { | ||
| 318 | pr_err("%s: failed to allocate hub clocks\n", __func__); | ||
| 319 | return -ENOMEM; | ||
| 320 | } | ||
| 321 | ccu->data.clks = clks; | ||
| 322 | ccu->data.clk_num = count; | ||
| 323 | |||
| 324 | PERI_CLK_SETUP(clks, ccu, BCM281XX_HUB_CCU_TMON_1M, tmon_1m); | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int __init bcm281xx_master_ccu_clks_setup(struct ccu_data *ccu) | ||
| 330 | { | ||
| 331 | struct clk **clks; | ||
| 332 | size_t count = BCM281XX_MASTER_CCU_CLOCK_COUNT; | ||
| 333 | |||
| 334 | clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); | ||
| 335 | if (!clks) { | ||
| 336 | pr_err("%s: failed to allocate master clocks\n", __func__); | ||
| 337 | return -ENOMEM; | ||
| 338 | } | ||
| 339 | ccu->data.clks = clks; | ||
| 340 | ccu->data.clk_num = count; | ||
| 341 | |||
| 342 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO1, sdio1); | ||
| 343 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO2, sdio2); | ||
| 344 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO3, sdio3); | ||
| 345 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO4, sdio4); | ||
| 346 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_USB_IC, usb_ic); | ||
| 347 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_HSIC2_48M, hsic2_48m); | ||
| 348 | PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_HSIC2_12M, hsic2_12m); | ||
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int __init bcm281xx_slave_ccu_clks_setup(struct ccu_data *ccu) | ||
| 354 | { | ||
| 355 | struct clk **clks; | ||
| 356 | size_t count = BCM281XX_SLAVE_CCU_CLOCK_COUNT; | ||
| 357 | |||
| 358 | clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); | ||
| 359 | if (!clks) { | ||
| 360 | pr_err("%s: failed to allocate slave clocks\n", __func__); | ||
| 361 | return -ENOMEM; | ||
| 362 | } | ||
| 363 | ccu->data.clks = clks; | ||
| 364 | ccu->data.clk_num = count; | ||
| 365 | |||
| 366 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB, uartb); | ||
| 367 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB2, uartb2); | ||
| 368 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB3, uartb3); | ||
| 369 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB4, uartb4); | ||
| 370 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_SSP0, ssp0); | ||
| 371 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_SSP2, ssp2); | ||
| 372 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC1, bsc1); | ||
| 373 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC2, bsc2); | ||
| 374 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC3, bsc3); | ||
| 375 | PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_PWM, pwm); | ||
| 376 | |||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* Device tree match table callback functions */ | ||
| 381 | |||
| 382 | static void __init kona_dt_root_ccu_setup(struct device_node *node) | ||
| 383 | { | ||
| 384 | kona_dt_ccu_setup(node, bcm281xx_root_ccu_clks_setup); | ||
| 385 | } | ||
| 386 | |||
| 387 | static void __init kona_dt_aon_ccu_setup(struct device_node *node) | ||
| 388 | { | ||
| 389 | kona_dt_ccu_setup(node, bcm281xx_aon_ccu_clks_setup); | ||
| 390 | } | ||
| 391 | |||
| 392 | static void __init kona_dt_hub_ccu_setup(struct device_node *node) | ||
| 393 | { | ||
| 394 | kona_dt_ccu_setup(node, bcm281xx_hub_ccu_clks_setup); | ||
| 395 | } | ||
| 396 | |||
| 397 | static void __init kona_dt_master_ccu_setup(struct device_node *node) | ||
| 398 | { | ||
| 399 | kona_dt_ccu_setup(node, bcm281xx_master_ccu_clks_setup); | ||
| 400 | } | ||
| 401 | |||
| 402 | static void __init kona_dt_slave_ccu_setup(struct device_node *node) | ||
| 403 | { | ||
| 404 | kona_dt_ccu_setup(node, bcm281xx_slave_ccu_clks_setup); | ||
| 405 | } | ||
| 406 | |||
| 407 | CLK_OF_DECLARE(bcm11351_root_ccu, BCM11351_DT_ROOT_CCU_COMPAT, | ||
| 408 | kona_dt_root_ccu_setup); | ||
| 409 | CLK_OF_DECLARE(bcm11351_aon_ccu, BCM11351_DT_AON_CCU_COMPAT, | ||
| 410 | kona_dt_aon_ccu_setup); | ||
| 411 | CLK_OF_DECLARE(bcm11351_hub_ccu, BCM11351_DT_HUB_CCU_COMPAT, | ||
| 412 | kona_dt_hub_ccu_setup); | ||
| 413 | CLK_OF_DECLARE(bcm11351_master_ccu, BCM11351_DT_MASTER_CCU_COMPAT, | ||
| 414 | kona_dt_master_ccu_setup); | ||
| 415 | CLK_OF_DECLARE(bcm11351_slave_ccu, BCM11351_DT_SLAVE_CCU_COMPAT, | ||
| 416 | kona_dt_slave_ccu_setup); | ||
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c new file mode 100644 index 000000000000..c7607feb18dd --- /dev/null +++ b/drivers/clk/bcm/clk-kona-setup.c | |||
| @@ -0,0 +1,769 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * Copyright 2013 Linaro Limited | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License as | ||
| 7 | * published by the Free Software Foundation version 2. | ||
| 8 | * | ||
| 9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 10 | * kind, whether express or implied; without even the implied warranty | ||
| 11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/of_address.h> | ||
| 17 | |||
| 18 | #include "clk-kona.h" | ||
| 19 | |||
| 20 | /* These are used when a selector or trigger is found to be unneeded */ | ||
| 21 | #define selector_clear_exists(sel) ((sel)->width = 0) | ||
| 22 | #define trigger_clear_exists(trig) FLAG_CLEAR(trig, TRIG, EXISTS) | ||
| 23 | |||
| 24 | LIST_HEAD(ccu_list); /* The list of set up CCUs */ | ||
| 25 | |||
| 26 | /* Validity checking */ | ||
| 27 | |||
| 28 | static bool clk_requires_trigger(struct kona_clk *bcm_clk) | ||
| 29 | { | ||
| 30 | struct peri_clk_data *peri = bcm_clk->peri; | ||
| 31 | struct bcm_clk_sel *sel; | ||
| 32 | struct bcm_clk_div *div; | ||
| 33 | |||
| 34 | if (bcm_clk->type != bcm_clk_peri) | ||
| 35 | return false; | ||
| 36 | |||
| 37 | sel = &peri->sel; | ||
| 38 | if (sel->parent_count && selector_exists(sel)) | ||
| 39 | return true; | ||
| 40 | |||
| 41 | div = &peri->div; | ||
| 42 | if (!divider_exists(div)) | ||
| 43 | return false; | ||
| 44 | |||
| 45 | /* Fixed dividers don't need triggers */ | ||
| 46 | if (!divider_is_fixed(div)) | ||
| 47 | return true; | ||
| 48 | |||
| 49 | div = &peri->pre_div; | ||
| 50 | |||
| 51 | return divider_exists(div) && !divider_is_fixed(div); | ||
| 52 | } | ||
| 53 | |||
| 54 | static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) | ||
| 55 | { | ||
| 56 | struct peri_clk_data *peri; | ||
| 57 | struct bcm_clk_gate *gate; | ||
| 58 | struct bcm_clk_div *div; | ||
| 59 | struct bcm_clk_sel *sel; | ||
| 60 | struct bcm_clk_trig *trig; | ||
| 61 | const char *name; | ||
| 62 | u32 range; | ||
| 63 | u32 limit; | ||
| 64 | |||
| 65 | BUG_ON(bcm_clk->type != bcm_clk_peri); | ||
| 66 | peri = bcm_clk->peri; | ||
| 67 | name = bcm_clk->name; | ||
| 68 | range = bcm_clk->ccu->range; | ||
| 69 | |||
| 70 | limit = range - sizeof(u32); | ||
| 71 | limit = round_down(limit, sizeof(u32)); | ||
| 72 | |||
| 73 | gate = &peri->gate; | ||
| 74 | if (gate_exists(gate)) { | ||
| 75 | if (gate->offset > limit) { | ||
| 76 | pr_err("%s: bad gate offset for %s (%u > %u)\n", | ||
| 77 | __func__, name, gate->offset, limit); | ||
| 78 | return false; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | div = &peri->div; | ||
| 83 | if (divider_exists(div)) { | ||
| 84 | if (div->offset > limit) { | ||
| 85 | pr_err("%s: bad divider offset for %s (%u > %u)\n", | ||
| 86 | __func__, name, div->offset, limit); | ||
| 87 | return false; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | div = &peri->pre_div; | ||
| 92 | if (divider_exists(div)) { | ||
| 93 | if (div->offset > limit) { | ||
| 94 | pr_err("%s: bad pre-divider offset for %s " | ||
| 95 | "(%u > %u)\n", | ||
| 96 | __func__, name, div->offset, limit); | ||
| 97 | return false; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | sel = &peri->sel; | ||
| 102 | if (selector_exists(sel)) { | ||
| 103 | if (sel->offset > limit) { | ||
| 104 | pr_err("%s: bad selector offset for %s (%u > %u)\n", | ||
| 105 | __func__, name, sel->offset, limit); | ||
| 106 | return false; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | trig = &peri->trig; | ||
| 111 | if (trigger_exists(trig)) { | ||
| 112 | if (trig->offset > limit) { | ||
| 113 | pr_err("%s: bad trigger offset for %s (%u > %u)\n", | ||
| 114 | __func__, name, trig->offset, limit); | ||
| 115 | return false; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | trig = &peri->pre_trig; | ||
| 120 | if (trigger_exists(trig)) { | ||
| 121 | if (trig->offset > limit) { | ||
| 122 | pr_err("%s: bad pre-trigger offset for %s (%u > %u)\n", | ||
| 123 | __func__, name, trig->offset, limit); | ||
| 124 | return false; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | return true; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* A bit position must be less than the number of bits in a 32-bit register. */ | ||
| 132 | static bool bit_posn_valid(u32 bit_posn, const char *field_name, | ||
| 133 | const char *clock_name) | ||
| 134 | { | ||
| 135 | u32 limit = BITS_PER_BYTE * sizeof(u32) - 1; | ||
| 136 | |||
| 137 | if (bit_posn > limit) { | ||
| 138 | pr_err("%s: bad %s bit for %s (%u > %u)\n", __func__, | ||
| 139 | field_name, clock_name, bit_posn, limit); | ||
| 140 | return false; | ||
| 141 | } | ||
| 142 | return true; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 146 | * A bitfield must be at least 1 bit wide. Both the low-order and | ||
| 147 | * high-order bits must lie within a 32-bit register. We require | ||
| 148 | * fields to be less than 32 bits wide, mainly because we use | ||
| 149 | * shifting to produce field masks, and shifting a full word width | ||
| 150 | * is not well-defined by the C standard. | ||
| 151 | */ | ||
| 152 | static bool bitfield_valid(u32 shift, u32 width, const char *field_name, | ||
| 153 | const char *clock_name) | ||
| 154 | { | ||
| 155 | u32 limit = BITS_PER_BYTE * sizeof(u32); | ||
| 156 | |||
| 157 | if (!width) { | ||
| 158 | pr_err("%s: bad %s field width 0 for %s\n", __func__, | ||
| 159 | field_name, clock_name); | ||
| 160 | return false; | ||
| 161 | } | ||
| 162 | if (shift + width > limit) { | ||
| 163 | pr_err("%s: bad %s for %s (%u + %u > %u)\n", __func__, | ||
| 164 | field_name, clock_name, shift, width, limit); | ||
| 165 | return false; | ||
| 166 | } | ||
| 167 | return true; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* | ||
| 171 | * All gates, if defined, have a status bit, and for hardware-only | ||
| 172 | * gates, that's it. Gates that can be software controlled also | ||
| 173 | * have an enable bit. And a gate that can be hardware or software | ||
| 174 | * controlled will have a hardware/software select bit. | ||
| 175 | */ | ||
| 176 | static bool gate_valid(struct bcm_clk_gate *gate, const char *field_name, | ||
| 177 | const char *clock_name) | ||
| 178 | { | ||
| 179 | if (!bit_posn_valid(gate->status_bit, "gate status", clock_name)) | ||
| 180 | return false; | ||
| 181 | |||
| 182 | if (gate_is_sw_controllable(gate)) { | ||
| 183 | if (!bit_posn_valid(gate->en_bit, "gate enable", clock_name)) | ||
| 184 | return false; | ||
| 185 | |||
| 186 | if (gate_is_hw_controllable(gate)) { | ||
| 187 | if (!bit_posn_valid(gate->hw_sw_sel_bit, | ||
| 188 | "gate hw/sw select", | ||
| 189 | clock_name)) | ||
| 190 | return false; | ||
| 191 | } | ||
| 192 | } else { | ||
| 193 | BUG_ON(!gate_is_hw_controllable(gate)); | ||
| 194 | } | ||
| 195 | |||
| 196 | return true; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * A selector bitfield must be valid. Its parent_sel array must | ||
| 201 | * also be reasonable for the field. | ||
| 202 | */ | ||
| 203 | static bool sel_valid(struct bcm_clk_sel *sel, const char *field_name, | ||
| 204 | const char *clock_name) | ||
| 205 | { | ||
| 206 | if (!bitfield_valid(sel->shift, sel->width, field_name, clock_name)) | ||
| 207 | return false; | ||
| 208 | |||
| 209 | if (sel->parent_count) { | ||
| 210 | u32 max_sel; | ||
| 211 | u32 limit; | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Make sure the selector field can hold all the | ||
| 215 | * selector values we expect to be able to use. A | ||
| 216 | * clock only needs to have a selector defined if it | ||
| 217 | * has more than one parent. And in that case the | ||
| 218 | * highest selector value will be in the last entry | ||
| 219 | * in the array. | ||
| 220 | */ | ||
| 221 | max_sel = sel->parent_sel[sel->parent_count - 1]; | ||
| 222 | limit = (1 << sel->width) - 1; | ||
| 223 | if (max_sel > limit) { | ||
| 224 | pr_err("%s: bad selector for %s " | ||
| 225 | "(%u needs > %u bits)\n", | ||
| 226 | __func__, clock_name, max_sel, | ||
| 227 | sel->width); | ||
| 228 | return false; | ||
| 229 | } | ||
| 230 | } else { | ||
| 231 | pr_warn("%s: ignoring selector for %s (no parents)\n", | ||
| 232 | __func__, clock_name); | ||
| 233 | selector_clear_exists(sel); | ||
| 234 | kfree(sel->parent_sel); | ||
| 235 | sel->parent_sel = NULL; | ||
| 236 | } | ||
| 237 | |||
| 238 | return true; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* | ||
| 242 | * A fixed divider just needs to be non-zero. A variable divider | ||
| 243 | * has to have a valid divider bitfield, and if it has a fraction, | ||
| 244 | * the width of the fraction must not be no more than the width of | ||
| 245 | * the divider as a whole. | ||
| 246 | */ | ||
| 247 | static bool div_valid(struct bcm_clk_div *div, const char *field_name, | ||
| 248 | const char *clock_name) | ||
| 249 | { | ||
| 250 | if (divider_is_fixed(div)) { | ||
| 251 | /* Any fixed divider value but 0 is OK */ | ||
| 252 | if (div->fixed == 0) { | ||
| 253 | pr_err("%s: bad %s fixed value 0 for %s\n", __func__, | ||
| 254 | field_name, clock_name); | ||
| 255 | return false; | ||
| 256 | } | ||
| 257 | return true; | ||
| 258 | } | ||
| 259 | if (!bitfield_valid(div->shift, div->width, field_name, clock_name)) | ||
| 260 | return false; | ||
| 261 | |||
| 262 | if (divider_has_fraction(div)) | ||
| 263 | if (div->frac_width > div->width) { | ||
| 264 | pr_warn("%s: bad %s fraction width for %s (%u > %u)\n", | ||
| 265 | __func__, field_name, clock_name, | ||
| 266 | div->frac_width, div->width); | ||
| 267 | return false; | ||
| 268 | } | ||
| 269 | |||
| 270 | return true; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* | ||
| 274 | * If a clock has two dividers, the combined number of fractional | ||
| 275 | * bits must be representable in a 32-bit unsigned value. This | ||
| 276 | * is because we scale up a dividend using both dividers before | ||
| 277 | * dividing to improve accuracy, and we need to avoid overflow. | ||
| 278 | */ | ||
| 279 | static bool kona_dividers_valid(struct kona_clk *bcm_clk) | ||
| 280 | { | ||
| 281 | struct peri_clk_data *peri = bcm_clk->peri; | ||
| 282 | struct bcm_clk_div *div; | ||
| 283 | struct bcm_clk_div *pre_div; | ||
| 284 | u32 limit; | ||
| 285 | |||
| 286 | BUG_ON(bcm_clk->type != bcm_clk_peri); | ||
| 287 | |||
| 288 | if (!divider_exists(&peri->div) || !divider_exists(&peri->pre_div)) | ||
| 289 | return true; | ||
| 290 | |||
| 291 | div = &peri->div; | ||
| 292 | pre_div = &peri->pre_div; | ||
| 293 | if (divider_is_fixed(div) || divider_is_fixed(pre_div)) | ||
| 294 | return true; | ||
| 295 | |||
| 296 | limit = BITS_PER_BYTE * sizeof(u32); | ||
| 297 | |||
| 298 | return div->frac_width + pre_div->frac_width <= limit; | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | /* A trigger just needs to represent a valid bit position */ | ||
| 303 | static bool trig_valid(struct bcm_clk_trig *trig, const char *field_name, | ||
| 304 | const char *clock_name) | ||
| 305 | { | ||
| 306 | return bit_posn_valid(trig->bit, field_name, clock_name); | ||
| 307 | } | ||
| 308 | |||
| 309 | /* Determine whether the set of peripheral clock registers are valid. */ | ||
| 310 | static bool | ||
| 311 | peri_clk_data_valid(struct kona_clk *bcm_clk) | ||
| 312 | { | ||
| 313 | struct peri_clk_data *peri; | ||
| 314 | struct bcm_clk_gate *gate; | ||
| 315 | struct bcm_clk_sel *sel; | ||
| 316 | struct bcm_clk_div *div; | ||
| 317 | struct bcm_clk_div *pre_div; | ||
| 318 | struct bcm_clk_trig *trig; | ||
| 319 | const char *name; | ||
| 320 | |||
| 321 | BUG_ON(bcm_clk->type != bcm_clk_peri); | ||
| 322 | |||
| 323 | /* | ||
| 324 | * First validate register offsets. This is the only place | ||
| 325 | * where we need something from the ccu, so we do these | ||
| 326 | * together. | ||
| 327 | */ | ||
| 328 | if (!peri_clk_data_offsets_valid(bcm_clk)) | ||
| 329 | return false; | ||
| 330 | |||
| 331 | peri = bcm_clk->peri; | ||
| 332 | name = bcm_clk->name; | ||
| 333 | gate = &peri->gate; | ||
| 334 | if (gate_exists(gate) && !gate_valid(gate, "gate", name)) | ||
| 335 | return false; | ||
| 336 | |||
| 337 | sel = &peri->sel; | ||
| 338 | if (selector_exists(sel)) { | ||
| 339 | if (!sel_valid(sel, "selector", name)) | ||
| 340 | return false; | ||
| 341 | |||
| 342 | } else if (sel->parent_count > 1) { | ||
| 343 | pr_err("%s: multiple parents but no selector for %s\n", | ||
| 344 | __func__, name); | ||
| 345 | |||
| 346 | return false; | ||
| 347 | } | ||
| 348 | |||
| 349 | div = &peri->div; | ||
| 350 | pre_div = &peri->pre_div; | ||
| 351 | if (divider_exists(div)) { | ||
| 352 | if (!div_valid(div, "divider", name)) | ||
| 353 | return false; | ||
| 354 | |||
| 355 | if (divider_exists(pre_div)) | ||
| 356 | if (!div_valid(pre_div, "pre-divider", name)) | ||
| 357 | return false; | ||
| 358 | } else if (divider_exists(pre_div)) { | ||
| 359 | pr_err("%s: pre-divider but no divider for %s\n", __func__, | ||
| 360 | name); | ||
| 361 | return false; | ||
| 362 | } | ||
| 363 | |||
| 364 | trig = &peri->trig; | ||
| 365 | if (trigger_exists(trig)) { | ||
| 366 | if (!trig_valid(trig, "trigger", name)) | ||
| 367 | return false; | ||
| 368 | |||
| 369 | if (trigger_exists(&peri->pre_trig)) { | ||
| 370 | if (!trig_valid(trig, "pre-trigger", name)) { | ||
| 371 | return false; | ||
| 372 | } | ||
| 373 | } | ||
| 374 | if (!clk_requires_trigger(bcm_clk)) { | ||
| 375 | pr_warn("%s: ignoring trigger for %s (not needed)\n", | ||
| 376 | __func__, name); | ||
| 377 | trigger_clear_exists(trig); | ||
| 378 | } | ||
| 379 | } else if (trigger_exists(&peri->pre_trig)) { | ||
| 380 | pr_err("%s: pre-trigger but no trigger for %s\n", __func__, | ||
| 381 | name); | ||
| 382 | return false; | ||
| 383 | } else if (clk_requires_trigger(bcm_clk)) { | ||
| 384 | pr_err("%s: required trigger missing for %s\n", __func__, | ||
| 385 | name); | ||
| 386 | return false; | ||
| 387 | } | ||
| 388 | |||
| 389 | return kona_dividers_valid(bcm_clk); | ||
| 390 | } | ||
| 391 | |||
| 392 | static bool kona_clk_valid(struct kona_clk *bcm_clk) | ||
| 393 | { | ||
| 394 | switch (bcm_clk->type) { | ||
| 395 | case bcm_clk_peri: | ||
| 396 | if (!peri_clk_data_valid(bcm_clk)) | ||
| 397 | return false; | ||
| 398 | break; | ||
| 399 | default: | ||
| 400 | pr_err("%s: unrecognized clock type (%d)\n", __func__, | ||
| 401 | (int)bcm_clk->type); | ||
| 402 | return false; | ||
| 403 | } | ||
| 404 | return true; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* | ||
| 408 | * Scan an array of parent clock names to determine whether there | ||
| 409 | * are any entries containing BAD_CLK_NAME. Such entries are | ||
| 410 | * placeholders for non-supported clocks. Keep track of the | ||
| 411 | * position of each clock name in the original array. | ||
| 412 | * | ||
| 413 | * Allocates an array of pointers to to hold the names of all | ||
| 414 | * non-null entries in the original array, and returns a pointer to | ||
| 415 | * that array in *names. This will be used for registering the | ||
| 416 | * clock with the common clock code. On successful return, | ||
| 417 | * *count indicates how many entries are in that names array. | ||
| 418 | * | ||
| 419 | * If there is more than one entry in the resulting names array, | ||
| 420 | * another array is allocated to record the parent selector value | ||
| 421 | * for each (defined) parent clock. This is the value that | ||
| 422 | * represents this parent clock in the clock's source selector | ||
| 423 | * register. The position of the clock in the original parent array | ||
| 424 | * defines that selector value. The number of entries in this array | ||
| 425 | * is the same as the number of entries in the parent names array. | ||
| 426 | * | ||
| 427 | * The array of selector values is returned. If the clock has no | ||
| 428 | * parents, no selector is required and a null pointer is returned. | ||
| 429 | * | ||
| 430 | * Returns a null pointer if the clock names array supplied was | ||
| 431 | * null. (This is not an error.) | ||
| 432 | * | ||
| 433 | * Returns a pointer-coded error if an error occurs. | ||
| 434 | */ | ||
| 435 | static u32 *parent_process(const char *clocks[], | ||
| 436 | u32 *count, const char ***names) | ||
| 437 | { | ||
| 438 | static const char **parent_names; | ||
| 439 | static u32 *parent_sel; | ||
| 440 | const char **clock; | ||
| 441 | u32 parent_count; | ||
| 442 | u32 bad_count = 0; | ||
| 443 | u32 orig_count; | ||
| 444 | u32 i; | ||
| 445 | u32 j; | ||
| 446 | |||
| 447 | *count = 0; /* In case of early return */ | ||
| 448 | *names = NULL; | ||
| 449 | if (!clocks) | ||
| 450 | return NULL; | ||
| 451 | |||
| 452 | /* | ||
| 453 | * Count the number of names in the null-terminated array, | ||
| 454 | * and find out how many of those are actually clock names. | ||
| 455 | */ | ||
| 456 | for (clock = clocks; *clock; clock++) | ||
| 457 | if (*clock == BAD_CLK_NAME) | ||
| 458 | bad_count++; | ||
| 459 | orig_count = (u32)(clock - clocks); | ||
| 460 | parent_count = orig_count - bad_count; | ||
| 461 | |||
| 462 | /* If all clocks are unsupported, we treat it as no clock */ | ||
| 463 | if (!parent_count) | ||
| 464 | return NULL; | ||
| 465 | |||
| 466 | /* Avoid exceeding our parent clock limit */ | ||
| 467 | if (parent_count > PARENT_COUNT_MAX) { | ||
| 468 | pr_err("%s: too many parents (%u > %u)\n", __func__, | ||
| 469 | parent_count, PARENT_COUNT_MAX); | ||
| 470 | return ERR_PTR(-EINVAL); | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * There is one parent name for each defined parent clock. | ||
| 475 | * We also maintain an array containing the selector value | ||
| 476 | * for each defined clock. If there's only one clock, the | ||
| 477 | * selector is not required, but we allocate space for the | ||
| 478 | * array anyway to keep things simple. | ||
| 479 | */ | ||
| 480 | parent_names = kmalloc(parent_count * sizeof(parent_names), GFP_KERNEL); | ||
| 481 | if (!parent_names) { | ||
| 482 | pr_err("%s: error allocating %u parent names\n", __func__, | ||
| 483 | parent_count); | ||
| 484 | return ERR_PTR(-ENOMEM); | ||
| 485 | } | ||
| 486 | |||
| 487 | /* There is at least one parent, so allocate a selector array */ | ||
| 488 | |||
| 489 | parent_sel = kmalloc(parent_count * sizeof(*parent_sel), GFP_KERNEL); | ||
| 490 | if (!parent_sel) { | ||
| 491 | pr_err("%s: error allocating %u parent selectors\n", __func__, | ||
| 492 | parent_count); | ||
| 493 | kfree(parent_names); | ||
| 494 | |||
| 495 | return ERR_PTR(-ENOMEM); | ||
| 496 | } | ||
| 497 | |||
| 498 | /* Now fill in the parent names and selector arrays */ | ||
| 499 | for (i = 0, j = 0; i < orig_count; i++) { | ||
| 500 | if (clocks[i] != BAD_CLK_NAME) { | ||
| 501 | parent_names[j] = clocks[i]; | ||
| 502 | parent_sel[j] = i; | ||
| 503 | j++; | ||
| 504 | } | ||
| 505 | } | ||
| 506 | *names = parent_names; | ||
| 507 | *count = parent_count; | ||
| 508 | |||
| 509 | return parent_sel; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int | ||
| 513 | clk_sel_setup(const char **clocks, struct bcm_clk_sel *sel, | ||
| 514 | struct clk_init_data *init_data) | ||
| 515 | { | ||
| 516 | const char **parent_names = NULL; | ||
| 517 | u32 parent_count = 0; | ||
| 518 | u32 *parent_sel; | ||
| 519 | |||
| 520 | /* | ||
| 521 | * If a peripheral clock has multiple parents, the value | ||
| 522 | * used by the hardware to select that parent is represented | ||
| 523 | * by the parent clock's position in the "clocks" list. Some | ||
| 524 | * values don't have defined or supported clocks; these will | ||
| 525 | * have BAD_CLK_NAME entries in the parents[] array. The | ||
| 526 | * list is terminated by a NULL entry. | ||
| 527 | * | ||
| 528 | * We need to supply (only) the names of defined parent | ||
| 529 | * clocks when registering a clock though, so we use an | ||
| 530 | * array of parent selector values to map between the | ||
| 531 | * indexes the common clock code uses and the selector | ||
| 532 | * values we need. | ||
| 533 | */ | ||
| 534 | parent_sel = parent_process(clocks, &parent_count, &parent_names); | ||
| 535 | if (IS_ERR(parent_sel)) { | ||
| 536 | int ret = PTR_ERR(parent_sel); | ||
| 537 | |||
| 538 | pr_err("%s: error processing parent clocks for %s (%d)\n", | ||
| 539 | __func__, init_data->name, ret); | ||
| 540 | |||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | init_data->parent_names = parent_names; | ||
| 545 | init_data->num_parents = parent_count; | ||
| 546 | |||
| 547 | sel->parent_count = parent_count; | ||
| 548 | sel->parent_sel = parent_sel; | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static void clk_sel_teardown(struct bcm_clk_sel *sel, | ||
| 554 | struct clk_init_data *init_data) | ||
| 555 | { | ||
| 556 | kfree(sel->parent_sel); | ||
| 557 | sel->parent_sel = NULL; | ||
| 558 | sel->parent_count = 0; | ||
| 559 | |||
| 560 | init_data->num_parents = 0; | ||
| 561 | kfree(init_data->parent_names); | ||
| 562 | init_data->parent_names = NULL; | ||
| 563 | } | ||
| 564 | |||
| 565 | static void peri_clk_teardown(struct peri_clk_data *data, | ||
| 566 | struct clk_init_data *init_data) | ||
| 567 | { | ||
| 568 | clk_sel_teardown(&data->sel, init_data); | ||
| 569 | init_data->ops = NULL; | ||
| 570 | } | ||
| 571 | |||
| 572 | /* | ||
| 573 | * Caller is responsible for freeing the parent_names[] and | ||
| 574 | * parent_sel[] arrays in the peripheral clock's "data" structure | ||
| 575 | * that can be assigned if the clock has one or more parent clocks | ||
| 576 | * associated with it. | ||
| 577 | */ | ||
| 578 | static int peri_clk_setup(struct ccu_data *ccu, struct peri_clk_data *data, | ||
| 579 | struct clk_init_data *init_data) | ||
| 580 | { | ||
| 581 | init_data->ops = &kona_peri_clk_ops; | ||
| 582 | init_data->flags = CLK_IGNORE_UNUSED; | ||
| 583 | |||
| 584 | return clk_sel_setup(data->clocks, &data->sel, init_data); | ||
| 585 | } | ||
| 586 | |||
| 587 | static void bcm_clk_teardown(struct kona_clk *bcm_clk) | ||
| 588 | { | ||
| 589 | switch (bcm_clk->type) { | ||
| 590 | case bcm_clk_peri: | ||
| 591 | peri_clk_teardown(bcm_clk->data, &bcm_clk->init_data); | ||
| 592 | break; | ||
| 593 | default: | ||
| 594 | break; | ||
| 595 | } | ||
| 596 | bcm_clk->data = NULL; | ||
| 597 | bcm_clk->type = bcm_clk_none; | ||
| 598 | } | ||
| 599 | |||
| 600 | static void kona_clk_teardown(struct clk *clk) | ||
| 601 | { | ||
| 602 | struct clk_hw *hw; | ||
| 603 | struct kona_clk *bcm_clk; | ||
| 604 | |||
| 605 | if (!clk) | ||
| 606 | return; | ||
| 607 | |||
| 608 | hw = __clk_get_hw(clk); | ||
| 609 | if (!hw) { | ||
| 610 | pr_err("%s: clk %p has null hw pointer\n", __func__, clk); | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | clk_unregister(clk); | ||
| 614 | |||
| 615 | bcm_clk = to_kona_clk(hw); | ||
| 616 | bcm_clk_teardown(bcm_clk); | ||
| 617 | } | ||
| 618 | |||
| 619 | struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | ||
| 620 | enum bcm_clk_type type, void *data) | ||
| 621 | { | ||
| 622 | struct kona_clk *bcm_clk; | ||
| 623 | struct clk_init_data *init_data; | ||
| 624 | struct clk *clk = NULL; | ||
| 625 | |||
| 626 | bcm_clk = kzalloc(sizeof(*bcm_clk), GFP_KERNEL); | ||
| 627 | if (!bcm_clk) { | ||
| 628 | pr_err("%s: failed to allocate bcm_clk for %s\n", __func__, | ||
| 629 | name); | ||
| 630 | return NULL; | ||
| 631 | } | ||
| 632 | bcm_clk->ccu = ccu; | ||
| 633 | bcm_clk->name = name; | ||
| 634 | |||
| 635 | init_data = &bcm_clk->init_data; | ||
| 636 | init_data->name = name; | ||
| 637 | switch (type) { | ||
| 638 | case bcm_clk_peri: | ||
| 639 | if (peri_clk_setup(ccu, data, init_data)) | ||
| 640 | goto out_free; | ||
| 641 | break; | ||
| 642 | default: | ||
| 643 | data = NULL; | ||
| 644 | break; | ||
| 645 | } | ||
| 646 | bcm_clk->type = type; | ||
| 647 | bcm_clk->data = data; | ||
| 648 | |||
| 649 | /* Make sure everything makes sense before we set it up */ | ||
| 650 | if (!kona_clk_valid(bcm_clk)) { | ||
| 651 | pr_err("%s: clock data invalid for %s\n", __func__, name); | ||
| 652 | goto out_teardown; | ||
| 653 | } | ||
| 654 | |||
| 655 | bcm_clk->hw.init = init_data; | ||
| 656 | clk = clk_register(NULL, &bcm_clk->hw); | ||
| 657 | if (IS_ERR(clk)) { | ||
| 658 | pr_err("%s: error registering clock %s (%ld)\n", __func__, | ||
| 659 | name, PTR_ERR(clk)); | ||
| 660 | goto out_teardown; | ||
| 661 | } | ||
| 662 | BUG_ON(!clk); | ||
| 663 | |||
| 664 | return clk; | ||
| 665 | out_teardown: | ||
| 666 | bcm_clk_teardown(bcm_clk); | ||
| 667 | out_free: | ||
| 668 | kfree(bcm_clk); | ||
| 669 | |||
| 670 | return NULL; | ||
| 671 | } | ||
| 672 | |||
| 673 | static void ccu_clks_teardown(struct ccu_data *ccu) | ||
| 674 | { | ||
| 675 | u32 i; | ||
| 676 | |||
| 677 | for (i = 0; i < ccu->data.clk_num; i++) | ||
| 678 | kona_clk_teardown(ccu->data.clks[i]); | ||
| 679 | kfree(ccu->data.clks); | ||
| 680 | } | ||
| 681 | |||
| 682 | static void kona_ccu_teardown(struct ccu_data *ccu) | ||
| 683 | { | ||
| 684 | if (!ccu) | ||
| 685 | return; | ||
| 686 | |||
| 687 | if (!ccu->base) | ||
| 688 | goto done; | ||
| 689 | |||
| 690 | of_clk_del_provider(ccu->node); /* safe if never added */ | ||
| 691 | ccu_clks_teardown(ccu); | ||
| 692 | list_del(&ccu->links); | ||
| 693 | of_node_put(ccu->node); | ||
| 694 | iounmap(ccu->base); | ||
| 695 | done: | ||
| 696 | kfree(ccu->name); | ||
| 697 | kfree(ccu); | ||
| 698 | } | ||
| 699 | |||
| 700 | /* | ||
| 701 | * Set up a CCU. Call the provided ccu_clks_setup callback to | ||
| 702 | * initialize the array of clocks provided by the CCU. | ||
| 703 | */ | ||
| 704 | void __init kona_dt_ccu_setup(struct device_node *node, | ||
| 705 | int (*ccu_clks_setup)(struct ccu_data *)) | ||
| 706 | { | ||
| 707 | struct ccu_data *ccu; | ||
| 708 | struct resource res = { 0 }; | ||
| 709 | resource_size_t range; | ||
| 710 | int ret; | ||
| 711 | |||
| 712 | ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); | ||
| 713 | if (ccu) | ||
| 714 | ccu->name = kstrdup(node->name, GFP_KERNEL); | ||
| 715 | if (!ccu || !ccu->name) { | ||
| 716 | pr_err("%s: unable to allocate CCU struct for %s\n", | ||
| 717 | __func__, node->name); | ||
| 718 | kfree(ccu); | ||
| 719 | |||
| 720 | return; | ||
| 721 | } | ||
| 722 | |||
| 723 | ret = of_address_to_resource(node, 0, &res); | ||
| 724 | if (ret) { | ||
| 725 | pr_err("%s: no valid CCU registers found for %s\n", __func__, | ||
| 726 | node->name); | ||
| 727 | goto out_err; | ||
| 728 | } | ||
| 729 | |||
| 730 | range = resource_size(&res); | ||
| 731 | if (range > (resource_size_t)U32_MAX) { | ||
| 732 | pr_err("%s: address range too large for %s\n", __func__, | ||
| 733 | node->name); | ||
| 734 | goto out_err; | ||
| 735 | } | ||
| 736 | |||
| 737 | ccu->range = (u32)range; | ||
| 738 | ccu->base = ioremap(res.start, ccu->range); | ||
| 739 | if (!ccu->base) { | ||
| 740 | pr_err("%s: unable to map CCU registers for %s\n", __func__, | ||
| 741 | node->name); | ||
| 742 | goto out_err; | ||
| 743 | } | ||
| 744 | |||
| 745 | spin_lock_init(&ccu->lock); | ||
| 746 | INIT_LIST_HEAD(&ccu->links); | ||
| 747 | ccu->node = of_node_get(node); | ||
| 748 | |||
| 749 | list_add_tail(&ccu->links, &ccu_list); | ||
| 750 | |||
| 751 | /* Set up clocks array (in ccu->data) */ | ||
| 752 | if (ccu_clks_setup(ccu)) | ||
| 753 | goto out_err; | ||
| 754 | |||
| 755 | ret = of_clk_add_provider(node, of_clk_src_onecell_get, &ccu->data); | ||
| 756 | if (ret) { | ||
| 757 | pr_err("%s: error adding ccu %s as provider (%d)\n", __func__, | ||
| 758 | node->name, ret); | ||
| 759 | goto out_err; | ||
| 760 | } | ||
| 761 | |||
| 762 | if (!kona_ccu_init(ccu)) | ||
| 763 | pr_err("Broadcom %s initialization had errors\n", node->name); | ||
| 764 | |||
| 765 | return; | ||
| 766 | out_err: | ||
| 767 | kona_ccu_teardown(ccu); | ||
| 768 | pr_err("Broadcom %s setup aborted\n", node->name); | ||
| 769 | } | ||
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c new file mode 100644 index 000000000000..e3d339e08309 --- /dev/null +++ b/drivers/clk/bcm/clk-kona.c | |||
| @@ -0,0 +1,1033 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * Copyright 2013 Linaro Limited | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License as | ||
| 7 | * published by the Free Software Foundation version 2. | ||
| 8 | * | ||
| 9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 10 | * kind, whether express or implied; without even the implied warranty | ||
| 11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "clk-kona.h" | ||
| 16 | |||
| 17 | #include <linux/delay.h> | ||
| 18 | |||
| 19 | #define CCU_ACCESS_PASSWORD 0xA5A500 | ||
| 20 | #define CLK_GATE_DELAY_LOOP 2000 | ||
| 21 | |||
| 22 | /* Bitfield operations */ | ||
| 23 | |||
| 24 | /* Produces a mask of set bits covering a range of a 32-bit value */ | ||
| 25 | static inline u32 bitfield_mask(u32 shift, u32 width) | ||
| 26 | { | ||
| 27 | return ((1 << width) - 1) << shift; | ||
| 28 | } | ||
| 29 | |||
| 30 | /* Extract the value of a bitfield found within a given register value */ | ||
| 31 | static inline u32 bitfield_extract(u32 reg_val, u32 shift, u32 width) | ||
| 32 | { | ||
| 33 | return (reg_val & bitfield_mask(shift, width)) >> shift; | ||
| 34 | } | ||
| 35 | |||
| 36 | /* Replace the value of a bitfield found within a given register value */ | ||
| 37 | static inline u32 bitfield_replace(u32 reg_val, u32 shift, u32 width, u32 val) | ||
| 38 | { | ||
| 39 | u32 mask = bitfield_mask(shift, width); | ||
| 40 | |||
| 41 | return (reg_val & ~mask) | (val << shift); | ||
| 42 | } | ||
| 43 | |||
| 44 | /* Divider and scaling helpers */ | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Implement DIV_ROUND_CLOSEST() for 64-bit dividend and both values | ||
| 48 | * unsigned. Note that unlike do_div(), the remainder is discarded | ||
| 49 | * and the return value is the quotient (not the remainder). | ||
| 50 | */ | ||
| 51 | u64 do_div_round_closest(u64 dividend, unsigned long divisor) | ||
| 52 | { | ||
| 53 | u64 result; | ||
| 54 | |||
| 55 | result = dividend + ((u64)divisor >> 1); | ||
| 56 | (void)do_div(result, divisor); | ||
| 57 | |||
| 58 | return result; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* Convert a divider into the scaled divisor value it represents. */ | ||
| 62 | static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) | ||
| 63 | { | ||
| 64 | return (u64)reg_div + ((u64)1 << div->frac_width); | ||
| 65 | } | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Build a scaled divider value as close as possible to the | ||
| 69 | * given whole part (div_value) and fractional part (expressed | ||
| 70 | * in billionths). | ||
| 71 | */ | ||
| 72 | u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths) | ||
| 73 | { | ||
| 74 | u64 combined; | ||
| 75 | |||
| 76 | BUG_ON(!div_value); | ||
| 77 | BUG_ON(billionths >= BILLION); | ||
| 78 | |||
| 79 | combined = (u64)div_value * BILLION + billionths; | ||
| 80 | combined <<= div->frac_width; | ||
| 81 | |||
| 82 | return do_div_round_closest(combined, BILLION); | ||
| 83 | } | ||
| 84 | |||
| 85 | /* The scaled minimum divisor representable by a divider */ | ||
| 86 | static inline u64 | ||
| 87 | scaled_div_min(struct bcm_clk_div *div) | ||
| 88 | { | ||
| 89 | if (divider_is_fixed(div)) | ||
| 90 | return (u64)div->fixed; | ||
| 91 | |||
| 92 | return scaled_div_value(div, 0); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* The scaled maximum divisor representable by a divider */ | ||
| 96 | u64 scaled_div_max(struct bcm_clk_div *div) | ||
| 97 | { | ||
| 98 | u32 reg_div; | ||
| 99 | |||
| 100 | if (divider_is_fixed(div)) | ||
| 101 | return (u64)div->fixed; | ||
| 102 | |||
| 103 | reg_div = ((u32)1 << div->width) - 1; | ||
| 104 | |||
| 105 | return scaled_div_value(div, reg_div); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Convert a scaled divisor into its divider representation as | ||
| 110 | * stored in a divider register field. | ||
| 111 | */ | ||
| 112 | static inline u32 | ||
| 113 | divider(struct bcm_clk_div *div, u64 scaled_div) | ||
| 114 | { | ||
| 115 | BUG_ON(scaled_div < scaled_div_min(div)); | ||
| 116 | BUG_ON(scaled_div > scaled_div_max(div)); | ||
| 117 | |||
| 118 | return (u32)(scaled_div - ((u64)1 << div->frac_width)); | ||
| 119 | } | ||
| 120 | |||
| 121 | /* Return a rate scaled for use when dividing by a scaled divisor. */ | ||
| 122 | static inline u64 | ||
| 123 | scale_rate(struct bcm_clk_div *div, u32 rate) | ||
| 124 | { | ||
| 125 | if (divider_is_fixed(div)) | ||
| 126 | return (u64)rate; | ||
| 127 | |||
| 128 | return (u64)rate << div->frac_width; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* CCU access */ | ||
| 132 | |||
| 133 | /* Read a 32-bit register value from a CCU's address space. */ | ||
| 134 | static inline u32 __ccu_read(struct ccu_data *ccu, u32 reg_offset) | ||
| 135 | { | ||
| 136 | return readl(ccu->base + reg_offset); | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Write a 32-bit register value into a CCU's address space. */ | ||
| 140 | static inline void | ||
| 141 | __ccu_write(struct ccu_data *ccu, u32 reg_offset, u32 reg_val) | ||
| 142 | { | ||
| 143 | writel(reg_val, ccu->base + reg_offset); | ||
| 144 | } | ||
| 145 | |||
| 146 | static inline unsigned long ccu_lock(struct ccu_data *ccu) | ||
| 147 | { | ||
| 148 | unsigned long flags; | ||
| 149 | |||
| 150 | spin_lock_irqsave(&ccu->lock, flags); | ||
| 151 | |||
| 152 | return flags; | ||
| 153 | } | ||
| 154 | static inline void ccu_unlock(struct ccu_data *ccu, unsigned long flags) | ||
| 155 | { | ||
| 156 | spin_unlock_irqrestore(&ccu->lock, flags); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Enable/disable write access to CCU protected registers. The | ||
| 161 | * WR_ACCESS register for all CCUs is at offset 0. | ||
| 162 | */ | ||
| 163 | static inline void __ccu_write_enable(struct ccu_data *ccu) | ||
| 164 | { | ||
| 165 | if (ccu->write_enabled) { | ||
| 166 | pr_err("%s: access already enabled for %s\n", __func__, | ||
| 167 | ccu->name); | ||
| 168 | return; | ||
| 169 | } | ||
| 170 | ccu->write_enabled = true; | ||
| 171 | __ccu_write(ccu, 0, CCU_ACCESS_PASSWORD | 1); | ||
| 172 | } | ||
| 173 | |||
| 174 | static inline void __ccu_write_disable(struct ccu_data *ccu) | ||
| 175 | { | ||
| 176 | if (!ccu->write_enabled) { | ||
| 177 | pr_err("%s: access wasn't enabled for %s\n", __func__, | ||
| 178 | ccu->name); | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 182 | __ccu_write(ccu, 0, CCU_ACCESS_PASSWORD); | ||
| 183 | ccu->write_enabled = false; | ||
| 184 | } | ||
| 185 | |||
| 186 | /* | ||
| 187 | * Poll a register in a CCU's address space, returning when the | ||
| 188 | * specified bit in that register's value is set (or clear). Delay | ||
| 189 | * a microsecond after each read of the register. Returns true if | ||
| 190 | * successful, or false if we gave up trying. | ||
| 191 | * | ||
| 192 | * Caller must ensure the CCU lock is held. | ||
| 193 | */ | ||
| 194 | static inline bool | ||
| 195 | __ccu_wait_bit(struct ccu_data *ccu, u32 reg_offset, u32 bit, bool want) | ||
| 196 | { | ||
| 197 | unsigned int tries; | ||
| 198 | u32 bit_mask = 1 << bit; | ||
| 199 | |||
| 200 | for (tries = 0; tries < CLK_GATE_DELAY_LOOP; tries++) { | ||
| 201 | u32 val; | ||
| 202 | bool bit_val; | ||
| 203 | |||
| 204 | val = __ccu_read(ccu, reg_offset); | ||
| 205 | bit_val = (val & bit_mask) != 0; | ||
| 206 | if (bit_val == want) | ||
| 207 | return true; | ||
| 208 | udelay(1); | ||
| 209 | } | ||
| 210 | return false; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Gate operations */ | ||
| 214 | |||
| 215 | /* Determine whether a clock is gated. CCU lock must be held. */ | ||
| 216 | static bool | ||
| 217 | __is_clk_gate_enabled(struct ccu_data *ccu, struct bcm_clk_gate *gate) | ||
| 218 | { | ||
| 219 | u32 bit_mask; | ||
| 220 | u32 reg_val; | ||
| 221 | |||
| 222 | /* If there is no gate we can assume it's enabled. */ | ||
| 223 | if (!gate_exists(gate)) | ||
| 224 | return true; | ||
| 225 | |||
| 226 | bit_mask = 1 << gate->status_bit; | ||
| 227 | reg_val = __ccu_read(ccu, gate->offset); | ||
| 228 | |||
| 229 | return (reg_val & bit_mask) != 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Determine whether a clock is gated. */ | ||
| 233 | static bool | ||
| 234 | is_clk_gate_enabled(struct ccu_data *ccu, struct bcm_clk_gate *gate) | ||
| 235 | { | ||
| 236 | long flags; | ||
| 237 | bool ret; | ||
| 238 | |||
| 239 | /* Avoid taking the lock if we can */ | ||
| 240 | if (!gate_exists(gate)) | ||
| 241 | return true; | ||
| 242 | |||
| 243 | flags = ccu_lock(ccu); | ||
| 244 | ret = __is_clk_gate_enabled(ccu, gate); | ||
| 245 | ccu_unlock(ccu, flags); | ||
| 246 | |||
| 247 | return ret; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* | ||
| 251 | * Commit our desired gate state to the hardware. | ||
| 252 | * Returns true if successful, false otherwise. | ||
| 253 | */ | ||
| 254 | static bool | ||
| 255 | __gate_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate) | ||
| 256 | { | ||
| 257 | u32 reg_val; | ||
| 258 | u32 mask; | ||
| 259 | bool enabled = false; | ||
| 260 | |||
| 261 | BUG_ON(!gate_exists(gate)); | ||
| 262 | if (!gate_is_sw_controllable(gate)) | ||
| 263 | return true; /* Nothing we can change */ | ||
| 264 | |||
| 265 | reg_val = __ccu_read(ccu, gate->offset); | ||
| 266 | |||
| 267 | /* For a hardware/software gate, set which is in control */ | ||
| 268 | if (gate_is_hw_controllable(gate)) { | ||
| 269 | mask = (u32)1 << gate->hw_sw_sel_bit; | ||
| 270 | if (gate_is_sw_managed(gate)) | ||
| 271 | reg_val |= mask; | ||
| 272 | else | ||
| 273 | reg_val &= ~mask; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* | ||
| 277 | * If software is in control, enable or disable the gate. | ||
| 278 | * If hardware is, clear the enabled bit for good measure. | ||
| 279 | * If a software controlled gate can't be disabled, we're | ||
| 280 | * required to write a 0 into the enable bit (but the gate | ||
| 281 | * will be enabled). | ||
| 282 | */ | ||
| 283 | mask = (u32)1 << gate->en_bit; | ||
| 284 | if (gate_is_sw_managed(gate) && (enabled = gate_is_enabled(gate)) && | ||
| 285 | !gate_is_no_disable(gate)) | ||
| 286 | reg_val |= mask; | ||
| 287 | else | ||
| 288 | reg_val &= ~mask; | ||
| 289 | |||
| 290 | __ccu_write(ccu, gate->offset, reg_val); | ||
| 291 | |||
| 292 | /* For a hardware controlled gate, we're done */ | ||
| 293 | if (!gate_is_sw_managed(gate)) | ||
| 294 | return true; | ||
| 295 | |||
| 296 | /* Otherwise wait for the gate to be in desired state */ | ||
| 297 | return __ccu_wait_bit(ccu, gate->offset, gate->status_bit, enabled); | ||
| 298 | } | ||
| 299 | |||
| 300 | /* | ||
| 301 | * Initialize a gate. Our desired state (hardware/software select, | ||
| 302 | * and if software, its enable state) is committed to hardware | ||
| 303 | * without the usual checks to see if it's already set up that way. | ||
| 304 | * Returns true if successful, false otherwise. | ||
| 305 | */ | ||
| 306 | static bool gate_init(struct ccu_data *ccu, struct bcm_clk_gate *gate) | ||
| 307 | { | ||
| 308 | if (!gate_exists(gate)) | ||
| 309 | return true; | ||
| 310 | return __gate_commit(ccu, gate); | ||
| 311 | } | ||
| 312 | |||
| 313 | /* | ||
| 314 | * Set a gate to enabled or disabled state. Does nothing if the | ||
| 315 | * gate is not currently under software control, or if it is already | ||
| 316 | * in the requested state. Returns true if successful, false | ||
| 317 | * otherwise. CCU lock must be held. | ||
| 318 | */ | ||
| 319 | static bool | ||
| 320 | __clk_gate(struct ccu_data *ccu, struct bcm_clk_gate *gate, bool enable) | ||
| 321 | { | ||
| 322 | bool ret; | ||
| 323 | |||
| 324 | if (!gate_exists(gate) || !gate_is_sw_managed(gate)) | ||
| 325 | return true; /* Nothing to do */ | ||
| 326 | |||
| 327 | if (!enable && gate_is_no_disable(gate)) { | ||
| 328 | pr_warn("%s: invalid gate disable request (ignoring)\n", | ||
| 329 | __func__); | ||
| 330 | return true; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (enable == gate_is_enabled(gate)) | ||
| 334 | return true; /* No change */ | ||
| 335 | |||
| 336 | gate_flip_enabled(gate); | ||
| 337 | ret = __gate_commit(ccu, gate); | ||
| 338 | if (!ret) | ||
| 339 | gate_flip_enabled(gate); /* Revert the change */ | ||
| 340 | |||
| 341 | return ret; | ||
| 342 | } | ||
| 343 | |||
| 344 | /* Enable or disable a gate. Returns 0 if successful, -EIO otherwise */ | ||
| 345 | static int clk_gate(struct ccu_data *ccu, const char *name, | ||
| 346 | struct bcm_clk_gate *gate, bool enable) | ||
| 347 | { | ||
| 348 | unsigned long flags; | ||
| 349 | bool success; | ||
| 350 | |||
| 351 | /* | ||
| 352 | * Avoid taking the lock if we can. We quietly ignore | ||
| 353 | * requests to change state that don't make sense. | ||
| 354 | */ | ||
| 355 | if (!gate_exists(gate) || !gate_is_sw_managed(gate)) | ||
| 356 | return 0; | ||
| 357 | if (!enable && gate_is_no_disable(gate)) | ||
| 358 | return 0; | ||
| 359 | |||
| 360 | flags = ccu_lock(ccu); | ||
| 361 | __ccu_write_enable(ccu); | ||
| 362 | |||
| 363 | success = __clk_gate(ccu, gate, enable); | ||
| 364 | |||
| 365 | __ccu_write_disable(ccu); | ||
| 366 | ccu_unlock(ccu, flags); | ||
| 367 | |||
| 368 | if (success) | ||
| 369 | return 0; | ||
| 370 | |||
| 371 | pr_err("%s: failed to %s gate for %s\n", __func__, | ||
| 372 | enable ? "enable" : "disable", name); | ||
| 373 | |||
| 374 | return -EIO; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Trigger operations */ | ||
| 378 | |||
| 379 | /* | ||
| 380 | * Caller must ensure CCU lock is held and access is enabled. | ||
| 381 | * Returns true if successful, false otherwise. | ||
| 382 | */ | ||
| 383 | static bool __clk_trigger(struct ccu_data *ccu, struct bcm_clk_trig *trig) | ||
| 384 | { | ||
| 385 | /* Trigger the clock and wait for it to finish */ | ||
| 386 | __ccu_write(ccu, trig->offset, 1 << trig->bit); | ||
| 387 | |||
| 388 | return __ccu_wait_bit(ccu, trig->offset, trig->bit, false); | ||
| 389 | } | ||
| 390 | |||
| 391 | /* Divider operations */ | ||
| 392 | |||
| 393 | /* Read a divider value and return the scaled divisor it represents. */ | ||
| 394 | static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div) | ||
| 395 | { | ||
| 396 | unsigned long flags; | ||
| 397 | u32 reg_val; | ||
| 398 | u32 reg_div; | ||
| 399 | |||
| 400 | if (divider_is_fixed(div)) | ||
| 401 | return (u64)div->fixed; | ||
| 402 | |||
| 403 | flags = ccu_lock(ccu); | ||
| 404 | reg_val = __ccu_read(ccu, div->offset); | ||
| 405 | ccu_unlock(ccu, flags); | ||
| 406 | |||
| 407 | /* Extract the full divider field from the register value */ | ||
| 408 | reg_div = bitfield_extract(reg_val, div->shift, div->width); | ||
| 409 | |||
| 410 | /* Return the scaled divisor value it represents */ | ||
| 411 | return scaled_div_value(div, reg_div); | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Convert a divider's scaled divisor value into its recorded form | ||
| 416 | * and commit it into the hardware divider register. | ||
| 417 | * | ||
| 418 | * Returns 0 on success. Returns -EINVAL for invalid arguments. | ||
| 419 | * Returns -ENXIO if gating failed, and -EIO if a trigger failed. | ||
| 420 | */ | ||
| 421 | static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 422 | struct bcm_clk_div *div, struct bcm_clk_trig *trig) | ||
| 423 | { | ||
| 424 | bool enabled; | ||
| 425 | u32 reg_div; | ||
| 426 | u32 reg_val; | ||
| 427 | int ret = 0; | ||
| 428 | |||
| 429 | BUG_ON(divider_is_fixed(div)); | ||
| 430 | |||
| 431 | /* | ||
| 432 | * If we're just initializing the divider, and no initial | ||
| 433 | * state was defined in the device tree, we just find out | ||
| 434 | * what its current value is rather than updating it. | ||
| 435 | */ | ||
| 436 | if (div->scaled_div == BAD_SCALED_DIV_VALUE) { | ||
| 437 | reg_val = __ccu_read(ccu, div->offset); | ||
| 438 | reg_div = bitfield_extract(reg_val, div->shift, div->width); | ||
| 439 | div->scaled_div = scaled_div_value(div, reg_div); | ||
| 440 | |||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | /* Convert the scaled divisor to the value we need to record */ | ||
| 445 | reg_div = divider(div, div->scaled_div); | ||
| 446 | |||
| 447 | /* Clock needs to be enabled before changing the rate */ | ||
| 448 | enabled = __is_clk_gate_enabled(ccu, gate); | ||
| 449 | if (!enabled && !__clk_gate(ccu, gate, true)) { | ||
| 450 | ret = -ENXIO; | ||
| 451 | goto out; | ||
| 452 | } | ||
| 453 | |||
| 454 | /* Replace the divider value and record the result */ | ||
| 455 | reg_val = __ccu_read(ccu, div->offset); | ||
| 456 | reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div); | ||
| 457 | __ccu_write(ccu, div->offset, reg_val); | ||
| 458 | |||
| 459 | /* If the trigger fails we still want to disable the gate */ | ||
| 460 | if (!__clk_trigger(ccu, trig)) | ||
| 461 | ret = -EIO; | ||
| 462 | |||
| 463 | /* Disable the clock again if it was disabled to begin with */ | ||
| 464 | if (!enabled && !__clk_gate(ccu, gate, false)) | ||
| 465 | ret = ret ? ret : -ENXIO; /* return first error */ | ||
| 466 | out: | ||
| 467 | return ret; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* | ||
| 471 | * Initialize a divider by committing our desired state to hardware | ||
| 472 | * without the usual checks to see if it's already set up that way. | ||
| 473 | * Returns true if successful, false otherwise. | ||
| 474 | */ | ||
| 475 | static bool div_init(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 476 | struct bcm_clk_div *div, struct bcm_clk_trig *trig) | ||
| 477 | { | ||
| 478 | if (!divider_exists(div) || divider_is_fixed(div)) | ||
| 479 | return true; | ||
| 480 | return !__div_commit(ccu, gate, div, trig); | ||
| 481 | } | ||
| 482 | |||
| 483 | static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 484 | struct bcm_clk_div *div, struct bcm_clk_trig *trig, | ||
| 485 | u64 scaled_div) | ||
| 486 | { | ||
| 487 | unsigned long flags; | ||
| 488 | u64 previous; | ||
| 489 | int ret; | ||
| 490 | |||
| 491 | BUG_ON(divider_is_fixed(div)); | ||
| 492 | |||
| 493 | previous = div->scaled_div; | ||
| 494 | if (previous == scaled_div) | ||
| 495 | return 0; /* No change */ | ||
| 496 | |||
| 497 | div->scaled_div = scaled_div; | ||
| 498 | |||
| 499 | flags = ccu_lock(ccu); | ||
| 500 | __ccu_write_enable(ccu); | ||
| 501 | |||
| 502 | ret = __div_commit(ccu, gate, div, trig); | ||
| 503 | |||
| 504 | __ccu_write_disable(ccu); | ||
| 505 | ccu_unlock(ccu, flags); | ||
| 506 | |||
| 507 | if (ret) | ||
| 508 | div->scaled_div = previous; /* Revert the change */ | ||
| 509 | |||
| 510 | return ret; | ||
| 511 | |||
| 512 | } | ||
| 513 | |||
| 514 | /* Common clock rate helpers */ | ||
| 515 | |||
| 516 | /* | ||
| 517 | * Implement the common clock framework recalc_rate method, taking | ||
| 518 | * into account a divider and an optional pre-divider. The | ||
| 519 | * pre-divider register pointer may be NULL. | ||
| 520 | */ | ||
| 521 | static unsigned long clk_recalc_rate(struct ccu_data *ccu, | ||
| 522 | struct bcm_clk_div *div, struct bcm_clk_div *pre_div, | ||
| 523 | unsigned long parent_rate) | ||
| 524 | { | ||
| 525 | u64 scaled_parent_rate; | ||
| 526 | u64 scaled_div; | ||
| 527 | u64 result; | ||
| 528 | |||
| 529 | if (!divider_exists(div)) | ||
| 530 | return parent_rate; | ||
| 531 | |||
| 532 | if (parent_rate > (unsigned long)LONG_MAX) | ||
| 533 | return 0; /* actually this would be a caller bug */ | ||
| 534 | |||
| 535 | /* | ||
| 536 | * If there is a pre-divider, divide the scaled parent rate | ||
| 537 | * by the pre-divider value first. In this case--to improve | ||
| 538 | * accuracy--scale the parent rate by *both* the pre-divider | ||
| 539 | * value and the divider before actually computing the | ||
| 540 | * result of the pre-divider. | ||
| 541 | * | ||
| 542 | * If there's only one divider, just scale the parent rate. | ||
| 543 | */ | ||
| 544 | if (pre_div && divider_exists(pre_div)) { | ||
| 545 | u64 scaled_rate; | ||
| 546 | |||
| 547 | scaled_rate = scale_rate(pre_div, parent_rate); | ||
| 548 | scaled_rate = scale_rate(div, scaled_rate); | ||
| 549 | scaled_div = divider_read_scaled(ccu, pre_div); | ||
| 550 | scaled_parent_rate = do_div_round_closest(scaled_rate, | ||
| 551 | scaled_div); | ||
| 552 | } else { | ||
| 553 | scaled_parent_rate = scale_rate(div, parent_rate); | ||
| 554 | } | ||
| 555 | |||
| 556 | /* | ||
| 557 | * Get the scaled divisor value, and divide the scaled | ||
| 558 | * parent rate by that to determine this clock's resulting | ||
| 559 | * rate. | ||
| 560 | */ | ||
| 561 | scaled_div = divider_read_scaled(ccu, div); | ||
| 562 | result = do_div_round_closest(scaled_parent_rate, scaled_div); | ||
| 563 | |||
| 564 | return (unsigned long)result; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* | ||
| 568 | * Compute the output rate produced when a given parent rate is fed | ||
| 569 | * into two dividers. The pre-divider can be NULL, and even if it's | ||
| 570 | * non-null it may be nonexistent. It's also OK for the divider to | ||
| 571 | * be nonexistent, and in that case the pre-divider is also ignored. | ||
| 572 | * | ||
| 573 | * If scaled_div is non-null, it is used to return the scaled divisor | ||
| 574 | * value used by the (downstream) divider to produce that rate. | ||
| 575 | */ | ||
| 576 | static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, | ||
| 577 | struct bcm_clk_div *pre_div, | ||
| 578 | unsigned long rate, unsigned long parent_rate, | ||
| 579 | u64 *scaled_div) | ||
| 580 | { | ||
| 581 | u64 scaled_parent_rate; | ||
| 582 | u64 min_scaled_div; | ||
| 583 | u64 max_scaled_div; | ||
| 584 | u64 best_scaled_div; | ||
| 585 | u64 result; | ||
| 586 | |||
| 587 | BUG_ON(!divider_exists(div)); | ||
| 588 | BUG_ON(!rate); | ||
| 589 | BUG_ON(parent_rate > (u64)LONG_MAX); | ||
| 590 | |||
| 591 | /* | ||
| 592 | * If there is a pre-divider, divide the scaled parent rate | ||
| 593 | * by the pre-divider value first. In this case--to improve | ||
| 594 | * accuracy--scale the parent rate by *both* the pre-divider | ||
| 595 | * value and the divider before actually computing the | ||
| 596 | * result of the pre-divider. | ||
| 597 | * | ||
| 598 | * If there's only one divider, just scale the parent rate. | ||
| 599 | * | ||
| 600 | * For simplicity we treat the pre-divider as fixed (for now). | ||
| 601 | */ | ||
| 602 | if (divider_exists(pre_div)) { | ||
| 603 | u64 scaled_rate; | ||
| 604 | u64 scaled_pre_div; | ||
| 605 | |||
| 606 | scaled_rate = scale_rate(pre_div, parent_rate); | ||
| 607 | scaled_rate = scale_rate(div, scaled_rate); | ||
| 608 | scaled_pre_div = divider_read_scaled(ccu, pre_div); | ||
| 609 | scaled_parent_rate = do_div_round_closest(scaled_rate, | ||
| 610 | scaled_pre_div); | ||
| 611 | } else { | ||
| 612 | scaled_parent_rate = scale_rate(div, parent_rate); | ||
| 613 | } | ||
| 614 | |||
| 615 | /* | ||
| 616 | * Compute the best possible divider and ensure it is in | ||
| 617 | * range. A fixed divider can't be changed, so just report | ||
| 618 | * the best we can do. | ||
| 619 | */ | ||
| 620 | if (!divider_is_fixed(div)) { | ||
| 621 | best_scaled_div = do_div_round_closest(scaled_parent_rate, | ||
| 622 | rate); | ||
| 623 | min_scaled_div = scaled_div_min(div); | ||
| 624 | max_scaled_div = scaled_div_max(div); | ||
| 625 | if (best_scaled_div > max_scaled_div) | ||
| 626 | best_scaled_div = max_scaled_div; | ||
| 627 | else if (best_scaled_div < min_scaled_div) | ||
| 628 | best_scaled_div = min_scaled_div; | ||
| 629 | } else { | ||
| 630 | best_scaled_div = divider_read_scaled(ccu, div); | ||
| 631 | } | ||
| 632 | |||
| 633 | /* OK, figure out the resulting rate */ | ||
| 634 | result = do_div_round_closest(scaled_parent_rate, best_scaled_div); | ||
| 635 | |||
| 636 | if (scaled_div) | ||
| 637 | *scaled_div = best_scaled_div; | ||
| 638 | |||
| 639 | return (long)result; | ||
| 640 | } | ||
| 641 | |||
| 642 | /* Common clock parent helpers */ | ||
| 643 | |||
| 644 | /* | ||
| 645 | * For a given parent selector (register field) value, find the | ||
| 646 | * index into a selector's parent_sel array that contains it. | ||
| 647 | * Returns the index, or BAD_CLK_INDEX if it's not found. | ||
| 648 | */ | ||
| 649 | static u8 parent_index(struct bcm_clk_sel *sel, u8 parent_sel) | ||
| 650 | { | ||
| 651 | u8 i; | ||
| 652 | |||
| 653 | BUG_ON(sel->parent_count > (u32)U8_MAX); | ||
| 654 | for (i = 0; i < sel->parent_count; i++) | ||
| 655 | if (sel->parent_sel[i] == parent_sel) | ||
| 656 | return i; | ||
| 657 | return BAD_CLK_INDEX; | ||
| 658 | } | ||
| 659 | |||
| 660 | /* | ||
| 661 | * Fetch the current value of the selector, and translate that into | ||
| 662 | * its corresponding index in the parent array we registered with | ||
| 663 | * the clock framework. | ||
| 664 | * | ||
| 665 | * Returns parent array index that corresponds with the value found, | ||
| 666 | * or BAD_CLK_INDEX if the found value is out of range. | ||
| 667 | */ | ||
| 668 | static u8 selector_read_index(struct ccu_data *ccu, struct bcm_clk_sel *sel) | ||
| 669 | { | ||
| 670 | unsigned long flags; | ||
| 671 | u32 reg_val; | ||
| 672 | u32 parent_sel; | ||
| 673 | u8 index; | ||
| 674 | |||
| 675 | /* If there's no selector, there's only one parent */ | ||
| 676 | if (!selector_exists(sel)) | ||
| 677 | return 0; | ||
| 678 | |||
| 679 | /* Get the value in the selector register */ | ||
| 680 | flags = ccu_lock(ccu); | ||
| 681 | reg_val = __ccu_read(ccu, sel->offset); | ||
| 682 | ccu_unlock(ccu, flags); | ||
| 683 | |||
| 684 | parent_sel = bitfield_extract(reg_val, sel->shift, sel->width); | ||
| 685 | |||
| 686 | /* Look up that selector's parent array index and return it */ | ||
| 687 | index = parent_index(sel, parent_sel); | ||
| 688 | if (index == BAD_CLK_INDEX) | ||
| 689 | pr_err("%s: out-of-range parent selector %u (%s 0x%04x)\n", | ||
| 690 | __func__, parent_sel, ccu->name, sel->offset); | ||
| 691 | |||
| 692 | return index; | ||
| 693 | } | ||
| 694 | |||
| 695 | /* | ||
| 696 | * Commit our desired selector value to the hardware. | ||
| 697 | * | ||
| 698 | * Returns 0 on success. Returns -EINVAL for invalid arguments. | ||
| 699 | * Returns -ENXIO if gating failed, and -EIO if a trigger failed. | ||
| 700 | */ | ||
| 701 | static int | ||
| 702 | __sel_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 703 | struct bcm_clk_sel *sel, struct bcm_clk_trig *trig) | ||
| 704 | { | ||
| 705 | u32 parent_sel; | ||
| 706 | u32 reg_val; | ||
| 707 | bool enabled; | ||
| 708 | int ret = 0; | ||
| 709 | |||
| 710 | BUG_ON(!selector_exists(sel)); | ||
| 711 | |||
| 712 | /* | ||
| 713 | * If we're just initializing the selector, and no initial | ||
| 714 | * state was defined in the device tree, we just find out | ||
| 715 | * what its current value is rather than updating it. | ||
| 716 | */ | ||
| 717 | if (sel->clk_index == BAD_CLK_INDEX) { | ||
| 718 | u8 index; | ||
| 719 | |||
| 720 | reg_val = __ccu_read(ccu, sel->offset); | ||
| 721 | parent_sel = bitfield_extract(reg_val, sel->shift, sel->width); | ||
| 722 | index = parent_index(sel, parent_sel); | ||
| 723 | if (index == BAD_CLK_INDEX) | ||
| 724 | return -EINVAL; | ||
| 725 | sel->clk_index = index; | ||
| 726 | |||
| 727 | return 0; | ||
| 728 | } | ||
| 729 | |||
| 730 | BUG_ON((u32)sel->clk_index >= sel->parent_count); | ||
| 731 | parent_sel = sel->parent_sel[sel->clk_index]; | ||
| 732 | |||
| 733 | /* Clock needs to be enabled before changing the parent */ | ||
| 734 | enabled = __is_clk_gate_enabled(ccu, gate); | ||
| 735 | if (!enabled && !__clk_gate(ccu, gate, true)) | ||
| 736 | return -ENXIO; | ||
| 737 | |||
| 738 | /* Replace the selector value and record the result */ | ||
| 739 | reg_val = __ccu_read(ccu, sel->offset); | ||
| 740 | reg_val = bitfield_replace(reg_val, sel->shift, sel->width, parent_sel); | ||
| 741 | __ccu_write(ccu, sel->offset, reg_val); | ||
| 742 | |||
| 743 | /* If the trigger fails we still want to disable the gate */ | ||
| 744 | if (!__clk_trigger(ccu, trig)) | ||
| 745 | ret = -EIO; | ||
| 746 | |||
| 747 | /* Disable the clock again if it was disabled to begin with */ | ||
| 748 | if (!enabled && !__clk_gate(ccu, gate, false)) | ||
| 749 | ret = ret ? ret : -ENXIO; /* return first error */ | ||
| 750 | |||
| 751 | return ret; | ||
| 752 | } | ||
| 753 | |||
| 754 | /* | ||
| 755 | * Initialize a selector by committing our desired state to hardware | ||
| 756 | * without the usual checks to see if it's already set up that way. | ||
| 757 | * Returns true if successful, false otherwise. | ||
| 758 | */ | ||
| 759 | static bool sel_init(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 760 | struct bcm_clk_sel *sel, struct bcm_clk_trig *trig) | ||
| 761 | { | ||
| 762 | if (!selector_exists(sel)) | ||
| 763 | return true; | ||
| 764 | return !__sel_commit(ccu, gate, sel, trig); | ||
| 765 | } | ||
| 766 | |||
| 767 | /* | ||
| 768 | * Write a new value into a selector register to switch to a | ||
| 769 | * different parent clock. Returns 0 on success, or an error code | ||
| 770 | * (from __sel_commit()) otherwise. | ||
| 771 | */ | ||
| 772 | static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, | ||
| 773 | struct bcm_clk_sel *sel, struct bcm_clk_trig *trig, | ||
| 774 | u8 index) | ||
| 775 | { | ||
| 776 | unsigned long flags; | ||
| 777 | u8 previous; | ||
| 778 | int ret; | ||
| 779 | |||
| 780 | previous = sel->clk_index; | ||
| 781 | if (previous == index) | ||
| 782 | return 0; /* No change */ | ||
| 783 | |||
| 784 | sel->clk_index = index; | ||
| 785 | |||
| 786 | flags = ccu_lock(ccu); | ||
| 787 | __ccu_write_enable(ccu); | ||
| 788 | |||
| 789 | ret = __sel_commit(ccu, gate, sel, trig); | ||
| 790 | |||
| 791 | __ccu_write_disable(ccu); | ||
| 792 | ccu_unlock(ccu, flags); | ||
| 793 | |||
| 794 | if (ret) | ||
| 795 | sel->clk_index = previous; /* Revert the change */ | ||
| 796 | |||
| 797 | return ret; | ||
| 798 | } | ||
| 799 | |||
| 800 | /* Clock operations */ | ||
| 801 | |||
| 802 | static int kona_peri_clk_enable(struct clk_hw *hw) | ||
| 803 | { | ||
| 804 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 805 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | ||
| 806 | |||
| 807 | return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true); | ||
| 808 | } | ||
| 809 | |||
| 810 | static void kona_peri_clk_disable(struct clk_hw *hw) | ||
| 811 | { | ||
| 812 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 813 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | ||
| 814 | |||
| 815 | (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false); | ||
| 816 | } | ||
| 817 | |||
| 818 | static int kona_peri_clk_is_enabled(struct clk_hw *hw) | ||
| 819 | { | ||
| 820 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 821 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | ||
| 822 | |||
| 823 | return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0; | ||
| 824 | } | ||
| 825 | |||
| 826 | static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw, | ||
| 827 | unsigned long parent_rate) | ||
| 828 | { | ||
| 829 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 830 | struct peri_clk_data *data = bcm_clk->peri; | ||
| 831 | |||
| 832 | return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div, | ||
| 833 | parent_rate); | ||
| 834 | } | ||
| 835 | |||
| 836 | static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 837 | unsigned long *parent_rate) | ||
| 838 | { | ||
| 839 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 840 | struct bcm_clk_div *div = &bcm_clk->peri->div; | ||
| 841 | |||
| 842 | if (!divider_exists(div)) | ||
| 843 | return __clk_get_rate(hw->clk); | ||
| 844 | |||
| 845 | /* Quietly avoid a zero rate */ | ||
| 846 | return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div, | ||
| 847 | rate ? rate : 1, *parent_rate, NULL); | ||
| 848 | } | ||
| 849 | |||
| 850 | static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) | ||
| 851 | { | ||
| 852 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 853 | struct peri_clk_data *data = bcm_clk->peri; | ||
| 854 | struct bcm_clk_sel *sel = &data->sel; | ||
| 855 | struct bcm_clk_trig *trig; | ||
| 856 | int ret; | ||
| 857 | |||
| 858 | BUG_ON(index >= sel->parent_count); | ||
| 859 | |||
| 860 | /* If there's only one parent we don't require a selector */ | ||
| 861 | if (!selector_exists(sel)) | ||
| 862 | return 0; | ||
| 863 | |||
| 864 | /* | ||
| 865 | * The regular trigger is used by default, but if there's a | ||
| 866 | * pre-trigger we want to use that instead. | ||
| 867 | */ | ||
| 868 | trig = trigger_exists(&data->pre_trig) ? &data->pre_trig | ||
| 869 | : &data->trig; | ||
| 870 | |||
| 871 | ret = selector_write(bcm_clk->ccu, &data->gate, sel, trig, index); | ||
| 872 | if (ret == -ENXIO) { | ||
| 873 | pr_err("%s: gating failure for %s\n", __func__, bcm_clk->name); | ||
| 874 | ret = -EIO; /* Don't proliferate weird errors */ | ||
| 875 | } else if (ret == -EIO) { | ||
| 876 | pr_err("%s: %strigger failed for %s\n", __func__, | ||
| 877 | trig == &data->pre_trig ? "pre-" : "", | ||
| 878 | bcm_clk->name); | ||
| 879 | } | ||
| 880 | |||
| 881 | return ret; | ||
| 882 | } | ||
| 883 | |||
| 884 | static u8 kona_peri_clk_get_parent(struct clk_hw *hw) | ||
| 885 | { | ||
| 886 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 887 | struct peri_clk_data *data = bcm_clk->peri; | ||
| 888 | u8 index; | ||
| 889 | |||
| 890 | index = selector_read_index(bcm_clk->ccu, &data->sel); | ||
| 891 | |||
| 892 | /* Not all callers would handle an out-of-range value gracefully */ | ||
| 893 | return index == BAD_CLK_INDEX ? 0 : index; | ||
| 894 | } | ||
| 895 | |||
| 896 | static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 897 | unsigned long parent_rate) | ||
| 898 | { | ||
| 899 | struct kona_clk *bcm_clk = to_kona_clk(hw); | ||
| 900 | struct peri_clk_data *data = bcm_clk->peri; | ||
| 901 | struct bcm_clk_div *div = &data->div; | ||
| 902 | u64 scaled_div = 0; | ||
| 903 | int ret; | ||
| 904 | |||
| 905 | if (parent_rate > (unsigned long)LONG_MAX) | ||
| 906 | return -EINVAL; | ||
| 907 | |||
| 908 | if (rate == __clk_get_rate(hw->clk)) | ||
| 909 | return 0; | ||
| 910 | |||
| 911 | if (!divider_exists(div)) | ||
| 912 | return rate == parent_rate ? 0 : -EINVAL; | ||
| 913 | |||
| 914 | /* | ||
| 915 | * A fixed divider can't be changed. (Nor can a fixed | ||
| 916 | * pre-divider be, but for now we never actually try to | ||
| 917 | * change that.) Tolerate a request for a no-op change. | ||
| 918 | */ | ||
| 919 | if (divider_is_fixed(&data->div)) | ||
| 920 | return rate == parent_rate ? 0 : -EINVAL; | ||
| 921 | |||
| 922 | /* | ||
| 923 | * Get the scaled divisor value needed to achieve a clock | ||
| 924 | * rate as close as possible to what was requested, given | ||
| 925 | * the parent clock rate supplied. | ||
| 926 | */ | ||
| 927 | (void)round_rate(bcm_clk->ccu, div, &data->pre_div, | ||
| 928 | rate ? rate : 1, parent_rate, &scaled_div); | ||
| 929 | |||
| 930 | /* | ||
| 931 | * We aren't updating any pre-divider at this point, so | ||
| 932 | * we'll use the regular trigger. | ||
| 933 | */ | ||
| 934 | ret = divider_write(bcm_clk->ccu, &data->gate, &data->div, | ||
| 935 | &data->trig, scaled_div); | ||
| 936 | if (ret == -ENXIO) { | ||
| 937 | pr_err("%s: gating failure for %s\n", __func__, bcm_clk->name); | ||
| 938 | ret = -EIO; /* Don't proliferate weird errors */ | ||
| 939 | } else if (ret == -EIO) { | ||
| 940 | pr_err("%s: trigger failed for %s\n", __func__, bcm_clk->name); | ||
| 941 | } | ||
| 942 | |||
| 943 | return ret; | ||
| 944 | } | ||
| 945 | |||
| 946 | struct clk_ops kona_peri_clk_ops = { | ||
| 947 | .enable = kona_peri_clk_enable, | ||
| 948 | .disable = kona_peri_clk_disable, | ||
| 949 | .is_enabled = kona_peri_clk_is_enabled, | ||
| 950 | .recalc_rate = kona_peri_clk_recalc_rate, | ||
| 951 | .round_rate = kona_peri_clk_round_rate, | ||
| 952 | .set_parent = kona_peri_clk_set_parent, | ||
| 953 | .get_parent = kona_peri_clk_get_parent, | ||
| 954 | .set_rate = kona_peri_clk_set_rate, | ||
| 955 | }; | ||
| 956 | |||
| 957 | /* Put a peripheral clock into its initial state */ | ||
| 958 | static bool __peri_clk_init(struct kona_clk *bcm_clk) | ||
| 959 | { | ||
| 960 | struct ccu_data *ccu = bcm_clk->ccu; | ||
| 961 | struct peri_clk_data *peri = bcm_clk->peri; | ||
| 962 | const char *name = bcm_clk->name; | ||
| 963 | struct bcm_clk_trig *trig; | ||
| 964 | |||
| 965 | BUG_ON(bcm_clk->type != bcm_clk_peri); | ||
| 966 | |||
| 967 | if (!gate_init(ccu, &peri->gate)) { | ||
| 968 | pr_err("%s: error initializing gate for %s\n", __func__, name); | ||
| 969 | return false; | ||
| 970 | } | ||
| 971 | if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) { | ||
| 972 | pr_err("%s: error initializing divider for %s\n", __func__, | ||
| 973 | name); | ||
| 974 | return false; | ||
| 975 | } | ||
| 976 | |||
| 977 | /* | ||
| 978 | * For the pre-divider and selector, the pre-trigger is used | ||
| 979 | * if it's present, otherwise we just use the regular trigger. | ||
| 980 | */ | ||
| 981 | trig = trigger_exists(&peri->pre_trig) ? &peri->pre_trig | ||
| 982 | : &peri->trig; | ||
| 983 | |||
| 984 | if (!div_init(ccu, &peri->gate, &peri->pre_div, trig)) { | ||
| 985 | pr_err("%s: error initializing pre-divider for %s\n", __func__, | ||
| 986 | name); | ||
| 987 | return false; | ||
| 988 | } | ||
| 989 | |||
| 990 | if (!sel_init(ccu, &peri->gate, &peri->sel, trig)) { | ||
| 991 | pr_err("%s: error initializing selector for %s\n", __func__, | ||
| 992 | name); | ||
| 993 | return false; | ||
| 994 | } | ||
| 995 | |||
| 996 | return true; | ||
| 997 | } | ||
| 998 | |||
| 999 | static bool __kona_clk_init(struct kona_clk *bcm_clk) | ||
| 1000 | { | ||
| 1001 | switch (bcm_clk->type) { | ||
| 1002 | case bcm_clk_peri: | ||
| 1003 | return __peri_clk_init(bcm_clk); | ||
| 1004 | default: | ||
| 1005 | BUG(); | ||
| 1006 | } | ||
| 1007 | return -EINVAL; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | /* Set a CCU and all its clocks into their desired initial state */ | ||
| 1011 | bool __init kona_ccu_init(struct ccu_data *ccu) | ||
| 1012 | { | ||
| 1013 | unsigned long flags; | ||
| 1014 | unsigned int which; | ||
| 1015 | struct clk **clks = ccu->data.clks; | ||
| 1016 | bool success = true; | ||
| 1017 | |||
| 1018 | flags = ccu_lock(ccu); | ||
| 1019 | __ccu_write_enable(ccu); | ||
| 1020 | |||
| 1021 | for (which = 0; which < ccu->data.clk_num; which++) { | ||
| 1022 | struct kona_clk *bcm_clk; | ||
| 1023 | |||
| 1024 | if (!clks[which]) | ||
| 1025 | continue; | ||
| 1026 | bcm_clk = to_kona_clk(__clk_get_hw(clks[which])); | ||
| 1027 | success &= __kona_clk_init(bcm_clk); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | __ccu_write_disable(ccu); | ||
| 1031 | ccu_unlock(ccu, flags); | ||
| 1032 | return success; | ||
| 1033 | } | ||
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h new file mode 100644 index 000000000000..5e139adc3dc5 --- /dev/null +++ b/drivers/clk/bcm/clk-kona.h | |||
| @@ -0,0 +1,410 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * Copyright 2013 Linaro Limited | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License as | ||
| 7 | * published by the Free Software Foundation version 2. | ||
| 8 | * | ||
| 9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 10 | * kind, whether express or implied; without even the implied warranty | ||
| 11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef _CLK_KONA_H | ||
| 16 | #define _CLK_KONA_H | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/list.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/of.h> | ||
| 24 | #include <linux/clk-provider.h> | ||
| 25 | |||
| 26 | #define BILLION 1000000000 | ||
| 27 | |||
| 28 | /* The common clock framework uses u8 to represent a parent index */ | ||
| 29 | #define PARENT_COUNT_MAX ((u32)U8_MAX) | ||
| 30 | |||
| 31 | #define BAD_CLK_INDEX U8_MAX /* Can't ever be valid */ | ||
| 32 | #define BAD_CLK_NAME ((const char *)-1) | ||
| 33 | |||
| 34 | #define BAD_SCALED_DIV_VALUE U64_MAX | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Utility macros for object flag management. If possible, flags | ||
| 38 | * should be defined such that 0 is the desired default value. | ||
| 39 | */ | ||
| 40 | #define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag | ||
| 41 | #define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag)) | ||
| 42 | #define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag))) | ||
| 43 | #define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag)) | ||
| 44 | #define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag))) | ||
| 45 | |||
| 46 | /* Clock field state tests */ | ||
| 47 | |||
| 48 | #define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS) | ||
| 49 | #define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED) | ||
| 50 | #define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW) | ||
| 51 | #define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW) | ||
| 52 | #define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED) | ||
| 53 | #define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE) | ||
| 54 | |||
| 55 | #define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) | ||
| 56 | |||
| 57 | #define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) | ||
| 58 | #define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) | ||
| 59 | #define divider_has_fraction(div) (!divider_is_fixed(div) && \ | ||
| 60 | (div)->frac_width > 0) | ||
| 61 | |||
| 62 | #define selector_exists(sel) ((sel)->width != 0) | ||
| 63 | #define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) | ||
| 64 | |||
| 65 | /* Clock type, used to tell common block what it's part of */ | ||
| 66 | enum bcm_clk_type { | ||
| 67 | bcm_clk_none, /* undefined clock type */ | ||
| 68 | bcm_clk_bus, | ||
| 69 | bcm_clk_core, | ||
| 70 | bcm_clk_peri | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Each CCU defines a mapped area of memory containing registers | ||
| 75 | * used to manage clocks implemented by the CCU. Access to memory | ||
| 76 | * within the CCU's space is serialized by a spinlock. Before any | ||
| 77 | * (other) address can be written, a special access "password" value | ||
| 78 | * must be written to its WR_ACCESS register (located at the base | ||
| 79 | * address of the range). We keep track of the name of each CCU as | ||
| 80 | * it is set up, and maintain them in a list. | ||
| 81 | */ | ||
| 82 | struct ccu_data { | ||
| 83 | void __iomem *base; /* base of mapped address space */ | ||
| 84 | spinlock_t lock; /* serialization lock */ | ||
| 85 | bool write_enabled; /* write access is currently enabled */ | ||
| 86 | struct list_head links; /* for ccu_list */ | ||
| 87 | struct device_node *node; | ||
| 88 | struct clk_onecell_data data; | ||
| 89 | const char *name; | ||
| 90 | u32 range; /* byte range of address space */ | ||
| 91 | }; | ||
| 92 | |||
| 93 | /* | ||
| 94 | * Gating control and status is managed by a 32-bit gate register. | ||
| 95 | * | ||
| 96 | * There are several types of gating available: | ||
| 97 | * - (no gate) | ||
| 98 | * A clock with no gate is assumed to be always enabled. | ||
| 99 | * - hardware-only gating (auto-gating) | ||
| 100 | * Enabling or disabling clocks with this type of gate is | ||
| 101 | * managed automatically by the hardware. Such clocks can be | ||
| 102 | * considered by the software to be enabled. The current status | ||
| 103 | * of auto-gated clocks can be read from the gate status bit. | ||
| 104 | * - software-only gating | ||
| 105 | * Auto-gating is not available for this type of clock. | ||
| 106 | * Instead, software manages whether it's enabled by setting or | ||
| 107 | * clearing the enable bit. The current gate status of a gate | ||
| 108 | * under software control can be read from the gate status bit. | ||
| 109 | * To ensure a change to the gating status is complete, the | ||
| 110 | * status bit can be polled to verify that the gate has entered | ||
| 111 | * the desired state. | ||
| 112 | * - selectable hardware or software gating | ||
| 113 | * Gating for this type of clock can be configured to be either | ||
| 114 | * under software or hardware control. Which type is in use is | ||
| 115 | * determined by the hw_sw_sel bit of the gate register. | ||
| 116 | */ | ||
| 117 | struct bcm_clk_gate { | ||
| 118 | u32 offset; /* gate register offset */ | ||
| 119 | u32 status_bit; /* 0: gate is disabled; 0: gatge is enabled */ | ||
| 120 | u32 en_bit; /* 0: disable; 1: enable */ | ||
| 121 | u32 hw_sw_sel_bit; /* 0: hardware gating; 1: software gating */ | ||
| 122 | u32 flags; /* BCM_CLK_GATE_FLAGS_* below */ | ||
| 123 | }; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * Gate flags: | ||
| 127 | * HW means this gate can be auto-gated | ||
| 128 | * SW means the state of this gate can be software controlled | ||
| 129 | * NO_DISABLE means this gate is (only) enabled if under software control | ||
| 130 | * SW_MANAGED means the status of this gate is under software control | ||
| 131 | * ENABLED means this software-managed gate is *supposed* to be enabled | ||
| 132 | */ | ||
| 133 | #define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0) /* Gate is valid */ | ||
| 134 | #define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1) /* Can auto-gate */ | ||
| 135 | #define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2) /* Software control */ | ||
| 136 | #define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3) /* HW or enabled */ | ||
| 137 | #define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4) /* SW now in control */ | ||
| 138 | #define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5) /* If SW_MANAGED */ | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Gate initialization macros. | ||
| 142 | * | ||
| 143 | * Any gate initially under software control will be enabled. | ||
| 144 | */ | ||
| 145 | |||
| 146 | /* A hardware/software gate initially under software control */ | ||
| 147 | #define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ | ||
| 148 | { \ | ||
| 149 | .offset = (_offset), \ | ||
| 150 | .status_bit = (_status_bit), \ | ||
| 151 | .en_bit = (_en_bit), \ | ||
| 152 | .hw_sw_sel_bit = (_hw_sw_sel_bit), \ | ||
| 153 | .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ | ||
| 154 | FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \ | ||
| 155 | FLAG(GATE, EXISTS), \ | ||
| 156 | } | ||
| 157 | |||
| 158 | /* A hardware/software gate initially under hardware control */ | ||
| 159 | #define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ | ||
| 160 | { \ | ||
| 161 | .offset = (_offset), \ | ||
| 162 | .status_bit = (_status_bit), \ | ||
| 163 | .en_bit = (_en_bit), \ | ||
| 164 | .hw_sw_sel_bit = (_hw_sw_sel_bit), \ | ||
| 165 | .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ | ||
| 166 | FLAG(GATE, EXISTS), \ | ||
| 167 | } | ||
| 168 | |||
| 169 | /* A hardware-or-enabled gate (enabled if not under hardware control) */ | ||
| 170 | #define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ | ||
| 171 | { \ | ||
| 172 | .offset = (_offset), \ | ||
| 173 | .status_bit = (_status_bit), \ | ||
| 174 | .en_bit = (_en_bit), \ | ||
| 175 | .hw_sw_sel_bit = (_hw_sw_sel_bit), \ | ||
| 176 | .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ | ||
| 177 | FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \ | ||
| 178 | } | ||
| 179 | |||
| 180 | /* A software-only gate */ | ||
| 181 | #define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \ | ||
| 182 | { \ | ||
| 183 | .offset = (_offset), \ | ||
| 184 | .status_bit = (_status_bit), \ | ||
| 185 | .en_bit = (_en_bit), \ | ||
| 186 | .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \ | ||
| 187 | FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \ | ||
| 188 | } | ||
| 189 | |||
| 190 | /* A hardware-only gate */ | ||
| 191 | #define HW_ONLY_GATE(_offset, _status_bit) \ | ||
| 192 | { \ | ||
| 193 | .offset = (_offset), \ | ||
| 194 | .status_bit = (_status_bit), \ | ||
| 195 | .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Each clock can have zero, one, or two dividers which change the | ||
| 200 | * output rate of the clock. Each divider can be either fixed or | ||
| 201 | * variable. If there are two dividers, they are the "pre-divider" | ||
| 202 | * and the "regular" or "downstream" divider. If there is only one, | ||
| 203 | * there is no pre-divider. | ||
| 204 | * | ||
| 205 | * A fixed divider is any non-zero (positive) value, and it | ||
| 206 | * indicates how the input rate is affected by the divider. | ||
| 207 | * | ||
| 208 | * The value of a variable divider is maintained in a sub-field of a | ||
| 209 | * 32-bit divider register. The position of the field in the | ||
| 210 | * register is defined by its offset and width. The value recorded | ||
| 211 | * in this field is always 1 less than the value it represents. | ||
| 212 | * | ||
| 213 | * In addition, a variable divider can indicate that some subset | ||
| 214 | * of its bits represent a "fractional" part of the divider. Such | ||
| 215 | * bits comprise the low-order portion of the divider field, and can | ||
| 216 | * be viewed as representing the portion of the divider that lies to | ||
| 217 | * the right of the decimal point. Most variable dividers have zero | ||
| 218 | * fractional bits. Variable dividers with non-zero fraction width | ||
| 219 | * still record a value 1 less than the value they represent; the | ||
| 220 | * added 1 does *not* affect the low-order bit in this case, it | ||
| 221 | * affects the bits above the fractional part only. (Often in this | ||
| 222 | * code a divider field value is distinguished from the value it | ||
| 223 | * represents by referring to the latter as a "divisor".) | ||
| 224 | * | ||
| 225 | * In order to avoid dealing with fractions, divider arithmetic is | ||
| 226 | * performed using "scaled" values. A scaled value is one that's | ||
| 227 | * been left-shifted by the fractional width of a divider. Dividing | ||
| 228 | * a scaled value by a scaled divisor produces the desired quotient | ||
| 229 | * without loss of precision and without any other special handling | ||
| 230 | * for fractions. | ||
| 231 | * | ||
| 232 | * The recorded value of a variable divider can be modified. To | ||
| 233 | * modify either divider (or both), a clock must be enabled (i.e., | ||
| 234 | * using its gate). In addition, a trigger register (described | ||
| 235 | * below) must be used to commit the change, and polled to verify | ||
| 236 | * the change is complete. | ||
| 237 | */ | ||
| 238 | struct bcm_clk_div { | ||
| 239 | union { | ||
| 240 | struct { /* variable divider */ | ||
| 241 | u32 offset; /* divider register offset */ | ||
| 242 | u32 shift; /* field shift */ | ||
| 243 | u32 width; /* field width */ | ||
| 244 | u32 frac_width; /* field fraction width */ | ||
| 245 | |||
| 246 | u64 scaled_div; /* scaled divider value */ | ||
| 247 | }; | ||
| 248 | u32 fixed; /* non-zero fixed divider value */ | ||
| 249 | }; | ||
| 250 | u32 flags; /* BCM_CLK_DIV_FLAGS_* below */ | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Divider flags: | ||
| 255 | * EXISTS means this divider exists | ||
| 256 | * FIXED means it is a fixed-rate divider | ||
| 257 | */ | ||
| 258 | #define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0) /* Divider is valid */ | ||
| 259 | #define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1) /* Fixed-value */ | ||
| 260 | |||
| 261 | /* Divider initialization macros */ | ||
| 262 | |||
| 263 | /* A fixed (non-zero) divider */ | ||
| 264 | #define FIXED_DIVIDER(_value) \ | ||
| 265 | { \ | ||
| 266 | .fixed = (_value), \ | ||
| 267 | .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \ | ||
| 268 | } | ||
| 269 | |||
| 270 | /* A divider with an integral divisor */ | ||
| 271 | #define DIVIDER(_offset, _shift, _width) \ | ||
| 272 | { \ | ||
| 273 | .offset = (_offset), \ | ||
| 274 | .shift = (_shift), \ | ||
| 275 | .width = (_width), \ | ||
| 276 | .scaled_div = BAD_SCALED_DIV_VALUE, \ | ||
| 277 | .flags = FLAG(DIV, EXISTS), \ | ||
| 278 | } | ||
| 279 | |||
| 280 | /* A divider whose divisor has an integer and fractional part */ | ||
| 281 | #define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \ | ||
| 282 | { \ | ||
| 283 | .offset = (_offset), \ | ||
| 284 | .shift = (_shift), \ | ||
| 285 | .width = (_width), \ | ||
| 286 | .frac_width = (_frac_width), \ | ||
| 287 | .scaled_div = BAD_SCALED_DIV_VALUE, \ | ||
| 288 | .flags = FLAG(DIV, EXISTS), \ | ||
| 289 | } | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Clocks may have multiple "parent" clocks. If there is more than | ||
| 293 | * one, a selector must be specified to define which of the parent | ||
| 294 | * clocks is currently in use. The selected clock is indicated in a | ||
| 295 | * sub-field of a 32-bit selector register. The range of | ||
| 296 | * representable selector values typically exceeds the number of | ||
| 297 | * available parent clocks. Occasionally the reset value of a | ||
| 298 | * selector field is explicitly set to a (specific) value that does | ||
| 299 | * not correspond to a defined input clock. | ||
| 300 | * | ||
| 301 | * We register all known parent clocks with the common clock code | ||
| 302 | * using a packed array (i.e., no empty slots) of (parent) clock | ||
| 303 | * names, and refer to them later using indexes into that array. | ||
| 304 | * We maintain an array of selector values indexed by common clock | ||
| 305 | * index values in order to map between these common clock indexes | ||
| 306 | * and the selector values used by the hardware. | ||
| 307 | * | ||
| 308 | * Like dividers, a selector can be modified, but to do so a clock | ||
| 309 | * must be enabled, and a trigger must be used to commit the change. | ||
| 310 | */ | ||
| 311 | struct bcm_clk_sel { | ||
| 312 | u32 offset; /* selector register offset */ | ||
| 313 | u32 shift; /* field shift */ | ||
| 314 | u32 width; /* field width */ | ||
| 315 | |||
| 316 | u32 parent_count; /* number of entries in parent_sel[] */ | ||
| 317 | u32 *parent_sel; /* array of parent selector values */ | ||
| 318 | u8 clk_index; /* current selected index in parent_sel[] */ | ||
| 319 | }; | ||
| 320 | |||
| 321 | /* Selector initialization macro */ | ||
| 322 | #define SELECTOR(_offset, _shift, _width) \ | ||
| 323 | { \ | ||
| 324 | .offset = (_offset), \ | ||
| 325 | .shift = (_shift), \ | ||
| 326 | .width = (_width), \ | ||
| 327 | .clk_index = BAD_CLK_INDEX, \ | ||
| 328 | } | ||
| 329 | |||
| 330 | /* | ||
| 331 | * Making changes to a variable divider or a selector for a clock | ||
| 332 | * requires the use of a trigger. A trigger is defined by a single | ||
| 333 | * bit within a register. To signal a change, a 1 is written into | ||
| 334 | * that bit. To determine when the change has been completed, that | ||
| 335 | * trigger bit is polled; the read value will be 1 while the change | ||
| 336 | * is in progress, and 0 when it is complete. | ||
| 337 | * | ||
| 338 | * Occasionally a clock will have more than one trigger. In this | ||
| 339 | * case, the "pre-trigger" will be used when changing a clock's | ||
| 340 | * selector and/or its pre-divider. | ||
| 341 | */ | ||
| 342 | struct bcm_clk_trig { | ||
| 343 | u32 offset; /* trigger register offset */ | ||
| 344 | u32 bit; /* trigger bit */ | ||
| 345 | u32 flags; /* BCM_CLK_TRIG_FLAGS_* below */ | ||
| 346 | }; | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Trigger flags: | ||
| 350 | * EXISTS means this trigger exists | ||
| 351 | */ | ||
| 352 | #define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0) /* Trigger is valid */ | ||
| 353 | |||
| 354 | /* Trigger initialization macro */ | ||
| 355 | #define TRIGGER(_offset, _bit) \ | ||
| 356 | { \ | ||
| 357 | .offset = (_offset), \ | ||
| 358 | .bit = (_bit), \ | ||
| 359 | .flags = FLAG(TRIG, EXISTS), \ | ||
| 360 | } | ||
| 361 | |||
| 362 | struct peri_clk_data { | ||
| 363 | struct bcm_clk_gate gate; | ||
| 364 | struct bcm_clk_trig pre_trig; | ||
| 365 | struct bcm_clk_div pre_div; | ||
| 366 | struct bcm_clk_trig trig; | ||
| 367 | struct bcm_clk_div div; | ||
| 368 | struct bcm_clk_sel sel; | ||
| 369 | const char *clocks[]; /* must be last; use CLOCKS() to declare */ | ||
| 370 | }; | ||
| 371 | #define CLOCKS(...) { __VA_ARGS__, NULL, } | ||
| 372 | #define NO_CLOCKS { NULL, } /* Must use of no parent clocks */ | ||
| 373 | |||
| 374 | struct kona_clk { | ||
| 375 | struct clk_hw hw; | ||
| 376 | struct clk_init_data init_data; | ||
| 377 | const char *name; /* name of this clock */ | ||
| 378 | struct ccu_data *ccu; /* ccu this clock is associated with */ | ||
| 379 | enum bcm_clk_type type; | ||
| 380 | union { | ||
| 381 | void *data; | ||
| 382 | struct peri_clk_data *peri; | ||
| 383 | }; | ||
| 384 | }; | ||
| 385 | #define to_kona_clk(_hw) \ | ||
| 386 | container_of(_hw, struct kona_clk, hw) | ||
| 387 | |||
| 388 | /* Exported globals */ | ||
| 389 | |||
| 390 | extern struct clk_ops kona_peri_clk_ops; | ||
| 391 | |||
| 392 | /* Help functions */ | ||
| 393 | |||
| 394 | #define PERI_CLK_SETUP(clks, ccu, id, name) \ | ||
| 395 | clks[id] = kona_clk_setup(ccu, #name, bcm_clk_peri, &name ## _data) | ||
| 396 | |||
| 397 | /* Externally visible functions */ | ||
| 398 | |||
| 399 | extern u64 do_div_round_closest(u64 dividend, unsigned long divisor); | ||
| 400 | extern u64 scaled_div_max(struct bcm_clk_div *div); | ||
| 401 | extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, | ||
| 402 | u32 billionths); | ||
| 403 | |||
| 404 | extern struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | ||
| 405 | enum bcm_clk_type type, void *data); | ||
| 406 | extern void __init kona_dt_ccu_setup(struct device_node *node, | ||
| 407 | int (*ccu_clks_setup)(struct ccu_data *)); | ||
| 408 | extern bool __init kona_ccu_init(struct ccu_data *ccu); | ||
| 409 | |||
| 410 | #endif /* _CLK_KONA_H */ | ||
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 010f071af883..b4f967210175 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/clk-provider.h> | 16 | #include <linux/clk-provider.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 19 | #include <linux/syscore_ops.h> | ||
| 19 | 20 | ||
| 20 | #include "clk.h" | 21 | #include "clk.h" |
| 21 | 22 | ||
| @@ -130,6 +131,17 @@ enum exynos4_plls { | |||
| 130 | nr_plls /* number of PLLs */ | 131 | nr_plls /* number of PLLs */ |
| 131 | }; | 132 | }; |
| 132 | 133 | ||
| 134 | static void __iomem *reg_base; | ||
| 135 | static enum exynos4_soc exynos4_soc; | ||
| 136 | |||
| 137 | /* | ||
| 138 | * Support for CMU save/restore across system suspends | ||
| 139 | */ | ||
| 140 | #ifdef CONFIG_PM_SLEEP | ||
| 141 | static struct samsung_clk_reg_dump *exynos4_save_common; | ||
| 142 | static struct samsung_clk_reg_dump *exynos4_save_soc; | ||
| 143 | static struct samsung_clk_reg_dump *exynos4_save_pll; | ||
| 144 | |||
| 133 | /* | 145 | /* |
| 134 | * list of controller registers to be saved and restored during a | 146 | * list of controller registers to be saved and restored during a |
| 135 | * suspend/resume cycle. | 147 | * suspend/resume cycle. |
| @@ -154,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = { | |||
| 154 | E4X12_MPLL_CON0, | 166 | E4X12_MPLL_CON0, |
| 155 | }; | 167 | }; |
| 156 | 168 | ||
| 169 | static unsigned long exynos4_clk_pll_regs[] __initdata = { | ||
| 170 | EPLL_LOCK, | ||
| 171 | VPLL_LOCK, | ||
| 172 | EPLL_CON0, | ||
| 173 | EPLL_CON1, | ||
| 174 | EPLL_CON2, | ||
| 175 | VPLL_CON0, | ||
| 176 | VPLL_CON1, | ||
| 177 | VPLL_CON2, | ||
| 178 | }; | ||
| 179 | |||
| 157 | static unsigned long exynos4_clk_regs[] __initdata = { | 180 | static unsigned long exynos4_clk_regs[] __initdata = { |
| 158 | SRC_LEFTBUS, | 181 | SRC_LEFTBUS, |
| 159 | DIV_LEFTBUS, | 182 | DIV_LEFTBUS, |
| @@ -161,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = { | |||
| 161 | SRC_RIGHTBUS, | 184 | SRC_RIGHTBUS, |
| 162 | DIV_RIGHTBUS, | 185 | DIV_RIGHTBUS, |
| 163 | GATE_IP_RIGHTBUS, | 186 | GATE_IP_RIGHTBUS, |
| 164 | EPLL_CON0, | ||
| 165 | EPLL_CON1, | ||
| 166 | EPLL_CON2, | ||
| 167 | VPLL_CON0, | ||
| 168 | VPLL_CON1, | ||
| 169 | VPLL_CON2, | ||
| 170 | SRC_TOP0, | 187 | SRC_TOP0, |
| 171 | SRC_TOP1, | 188 | SRC_TOP1, |
| 172 | SRC_CAM, | 189 | SRC_CAM, |
| @@ -227,6 +244,124 @@ static unsigned long exynos4_clk_regs[] __initdata = { | |||
| 227 | GATE_IP_CPU, | 244 | GATE_IP_CPU, |
| 228 | }; | 245 | }; |
| 229 | 246 | ||
| 247 | static const struct samsung_clk_reg_dump src_mask_suspend[] = { | ||
| 248 | { .offset = SRC_MASK_TOP, .value = 0x00000001, }, | ||
| 249 | { .offset = SRC_MASK_CAM, .value = 0x11111111, }, | ||
| 250 | { .offset = SRC_MASK_TV, .value = 0x00000111, }, | ||
| 251 | { .offset = SRC_MASK_LCD0, .value = 0x00001111, }, | ||
| 252 | { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, }, | ||
| 253 | { .offset = SRC_MASK_FSYS, .value = 0x01011111, }, | ||
| 254 | { .offset = SRC_MASK_PERIL0, .value = 0x01111111, }, | ||
| 255 | { .offset = SRC_MASK_PERIL1, .value = 0x01110111, }, | ||
| 256 | { .offset = SRC_MASK_DMC, .value = 0x00010000, }, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = { | ||
| 260 | { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, }, | ||
| 261 | }; | ||
| 262 | |||
| 263 | #define PLL_ENABLED (1 << 31) | ||
| 264 | #define PLL_LOCKED (1 << 29) | ||
| 265 | |||
| 266 | static void exynos4_clk_wait_for_pll(u32 reg) | ||
| 267 | { | ||
| 268 | u32 pll_con; | ||
| 269 | |||
| 270 | pll_con = readl(reg_base + reg); | ||
| 271 | if (!(pll_con & PLL_ENABLED)) | ||
| 272 | return; | ||
| 273 | |||
| 274 | while (!(pll_con & PLL_LOCKED)) { | ||
| 275 | cpu_relax(); | ||
| 276 | pll_con = readl(reg_base + reg); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | static int exynos4_clk_suspend(void) | ||
| 281 | { | ||
| 282 | samsung_clk_save(reg_base, exynos4_save_common, | ||
| 283 | ARRAY_SIZE(exynos4_clk_regs)); | ||
| 284 | samsung_clk_save(reg_base, exynos4_save_pll, | ||
| 285 | ARRAY_SIZE(exynos4_clk_pll_regs)); | ||
| 286 | |||
| 287 | if (exynos4_soc == EXYNOS4210) { | ||
| 288 | samsung_clk_save(reg_base, exynos4_save_soc, | ||
| 289 | ARRAY_SIZE(exynos4210_clk_save)); | ||
| 290 | samsung_clk_restore(reg_base, src_mask_suspend_e4210, | ||
| 291 | ARRAY_SIZE(src_mask_suspend_e4210)); | ||
| 292 | } else { | ||
| 293 | samsung_clk_save(reg_base, exynos4_save_soc, | ||
| 294 | ARRAY_SIZE(exynos4x12_clk_save)); | ||
| 295 | } | ||
| 296 | |||
| 297 | samsung_clk_restore(reg_base, src_mask_suspend, | ||
| 298 | ARRAY_SIZE(src_mask_suspend)); | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static void exynos4_clk_resume(void) | ||
| 304 | { | ||
| 305 | samsung_clk_restore(reg_base, exynos4_save_pll, | ||
| 306 | ARRAY_SIZE(exynos4_clk_pll_regs)); | ||
| 307 | |||
| 308 | exynos4_clk_wait_for_pll(EPLL_CON0); | ||
| 309 | exynos4_clk_wait_for_pll(VPLL_CON0); | ||
| 310 | |||
| 311 | samsung_clk_restore(reg_base, exynos4_save_common, | ||
| 312 | ARRAY_SIZE(exynos4_clk_regs)); | ||
| 313 | |||
| 314 | if (exynos4_soc == EXYNOS4210) | ||
| 315 | samsung_clk_restore(reg_base, exynos4_save_soc, | ||
| 316 | ARRAY_SIZE(exynos4210_clk_save)); | ||
| 317 | else | ||
| 318 | samsung_clk_restore(reg_base, exynos4_save_soc, | ||
| 319 | ARRAY_SIZE(exynos4x12_clk_save)); | ||
| 320 | } | ||
| 321 | |||
| 322 | static struct syscore_ops exynos4_clk_syscore_ops = { | ||
| 323 | .suspend = exynos4_clk_suspend, | ||
| 324 | .resume = exynos4_clk_resume, | ||
| 325 | }; | ||
| 326 | |||
| 327 | static void exynos4_clk_sleep_init(void) | ||
| 328 | { | ||
| 329 | exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs, | ||
| 330 | ARRAY_SIZE(exynos4_clk_regs)); | ||
| 331 | if (!exynos4_save_common) | ||
| 332 | goto err_warn; | ||
| 333 | |||
| 334 | if (exynos4_soc == EXYNOS4210) | ||
| 335 | exynos4_save_soc = samsung_clk_alloc_reg_dump( | ||
| 336 | exynos4210_clk_save, | ||
| 337 | ARRAY_SIZE(exynos4210_clk_save)); | ||
| 338 | else | ||
| 339 | exynos4_save_soc = samsung_clk_alloc_reg_dump( | ||
| 340 | exynos4x12_clk_save, | ||
| 341 | ARRAY_SIZE(exynos4x12_clk_save)); | ||
| 342 | if (!exynos4_save_soc) | ||
| 343 | goto err_common; | ||
| 344 | |||
| 345 | exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs, | ||
| 346 | ARRAY_SIZE(exynos4_clk_pll_regs)); | ||
| 347 | if (!exynos4_save_pll) | ||
| 348 | goto err_soc; | ||
| 349 | |||
| 350 | register_syscore_ops(&exynos4_clk_syscore_ops); | ||
| 351 | return; | ||
| 352 | |||
| 353 | err_soc: | ||
| 354 | kfree(exynos4_save_soc); | ||
| 355 | err_common: | ||
| 356 | kfree(exynos4_save_common); | ||
| 357 | err_warn: | ||
| 358 | pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", | ||
| 359 | __func__); | ||
| 360 | } | ||
| 361 | #else | ||
| 362 | static void exynos4_clk_sleep_init(void) {} | ||
| 363 | #endif | ||
| 364 | |||
| 230 | /* list of all parent clock list */ | 365 | /* list of all parent clock list */ |
| 231 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; | 366 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; |
| 232 | PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; | 367 | PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; |
| @@ -908,12 +1043,13 @@ static unsigned long exynos4_get_xom(void) | |||
| 908 | return xom; | 1043 | return xom; |
| 909 | } | 1044 | } |
| 910 | 1045 | ||
| 911 | static void __init exynos4_clk_register_finpll(unsigned long xom) | 1046 | static void __init exynos4_clk_register_finpll(void) |
| 912 | { | 1047 | { |
| 913 | struct samsung_fixed_rate_clock fclk; | 1048 | struct samsung_fixed_rate_clock fclk; |
| 914 | struct clk *clk; | 1049 | struct clk *clk; |
| 915 | unsigned long finpll_f = 24000000; | 1050 | unsigned long finpll_f = 24000000; |
| 916 | char *parent_name; | 1051 | char *parent_name; |
| 1052 | unsigned int xom = exynos4_get_xom(); | ||
| 917 | 1053 | ||
| 918 | parent_name = xom & 1 ? "xusbxti" : "xxti"; | 1054 | parent_name = xom & 1 ? "xusbxti" : "xxti"; |
| 919 | clk = clk_get(NULL, parent_name); | 1055 | clk = clk_get(NULL, parent_name); |
| @@ -1038,27 +1174,21 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { | |||
| 1038 | 1174 | ||
| 1039 | /* register exynos4 clocks */ | 1175 | /* register exynos4 clocks */ |
| 1040 | static void __init exynos4_clk_init(struct device_node *np, | 1176 | static void __init exynos4_clk_init(struct device_node *np, |
| 1041 | enum exynos4_soc exynos4_soc, | 1177 | enum exynos4_soc soc) |
| 1042 | void __iomem *reg_base, unsigned long xom) | ||
| 1043 | { | 1178 | { |
| 1179 | exynos4_soc = soc; | ||
| 1180 | |||
| 1044 | reg_base = of_iomap(np, 0); | 1181 | reg_base = of_iomap(np, 0); |
| 1045 | if (!reg_base) | 1182 | if (!reg_base) |
| 1046 | panic("%s: failed to map registers\n", __func__); | 1183 | panic("%s: failed to map registers\n", __func__); |
| 1047 | 1184 | ||
| 1048 | if (exynos4_soc == EXYNOS4210) | 1185 | samsung_clk_init(np, reg_base, CLK_NR_CLKS); |
| 1049 | samsung_clk_init(np, reg_base, CLK_NR_CLKS, | ||
| 1050 | exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), | ||
| 1051 | exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save)); | ||
| 1052 | else | ||
| 1053 | samsung_clk_init(np, reg_base, CLK_NR_CLKS, | ||
| 1054 | exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), | ||
| 1055 | exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save)); | ||
| 1056 | 1186 | ||
| 1057 | samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, | 1187 | samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, |
| 1058 | ARRAY_SIZE(exynos4_fixed_rate_ext_clks), | 1188 | ARRAY_SIZE(exynos4_fixed_rate_ext_clks), |
| 1059 | ext_clk_match); | 1189 | ext_clk_match); |
| 1060 | 1190 | ||
| 1061 | exynos4_clk_register_finpll(xom); | 1191 | exynos4_clk_register_finpll(); |
| 1062 | 1192 | ||
| 1063 | if (exynos4_soc == EXYNOS4210) { | 1193 | if (exynos4_soc == EXYNOS4210) { |
| 1064 | samsung_clk_register_mux(exynos4210_mux_early, | 1194 | samsung_clk_register_mux(exynos4210_mux_early, |
| @@ -1125,6 +1255,8 @@ static void __init exynos4_clk_init(struct device_node *np, | |||
| 1125 | samsung_clk_register_alias(exynos4_aliases, | 1255 | samsung_clk_register_alias(exynos4_aliases, |
| 1126 | ARRAY_SIZE(exynos4_aliases)); | 1256 | ARRAY_SIZE(exynos4_aliases)); |
| 1127 | 1257 | ||
| 1258 | exynos4_clk_sleep_init(); | ||
| 1259 | |||
| 1128 | pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" | 1260 | pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" |
| 1129 | "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", | 1261 | "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", |
| 1130 | exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", | 1262 | exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", |
| @@ -1136,12 +1268,12 @@ static void __init exynos4_clk_init(struct device_node *np, | |||
| 1136 | 1268 | ||
| 1137 | static void __init exynos4210_clk_init(struct device_node *np) | 1269 | static void __init exynos4210_clk_init(struct device_node *np) |
| 1138 | { | 1270 | { |
| 1139 | exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom()); | 1271 | exynos4_clk_init(np, EXYNOS4210); |
| 1140 | } | 1272 | } |
| 1141 | CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init); | 1273 | CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init); |
| 1142 | 1274 | ||
| 1143 | static void __init exynos4412_clk_init(struct device_node *np) | 1275 | static void __init exynos4412_clk_init(struct device_node *np) |
| 1144 | { | 1276 | { |
| 1145 | exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom()); | 1277 | exynos4_clk_init(np, EXYNOS4X12); |
| 1146 | } | 1278 | } |
| 1147 | CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init); | 1279 | CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init); |
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index ff4beebe1f0b..e7ee4420da81 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/clk-provider.h> | 16 | #include <linux/clk-provider.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 19 | #include <linux/syscore_ops.h> | ||
| 19 | 20 | ||
| 20 | #include "clk.h" | 21 | #include "clk.h" |
| 21 | 22 | ||
| @@ -85,6 +86,11 @@ enum exynos5250_plls { | |||
| 85 | nr_plls /* number of PLLs */ | 86 | nr_plls /* number of PLLs */ |
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| 89 | static void __iomem *reg_base; | ||
| 90 | |||
| 91 | #ifdef CONFIG_PM_SLEEP | ||
| 92 | static struct samsung_clk_reg_dump *exynos5250_save; | ||
| 93 | |||
| 88 | /* | 94 | /* |
| 89 | * list of controller registers to be saved and restored during a | 95 | * list of controller registers to be saved and restored during a |
| 90 | * suspend/resume cycle. | 96 | * suspend/resume cycle. |
| @@ -137,6 +143,41 @@ static unsigned long exynos5250_clk_regs[] __initdata = { | |||
| 137 | GATE_IP_ACP, | 143 | GATE_IP_ACP, |
| 138 | }; | 144 | }; |
| 139 | 145 | ||
| 146 | static int exynos5250_clk_suspend(void) | ||
| 147 | { | ||
| 148 | samsung_clk_save(reg_base, exynos5250_save, | ||
| 149 | ARRAY_SIZE(exynos5250_clk_regs)); | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void exynos5250_clk_resume(void) | ||
| 155 | { | ||
| 156 | samsung_clk_restore(reg_base, exynos5250_save, | ||
| 157 | ARRAY_SIZE(exynos5250_clk_regs)); | ||
| 158 | } | ||
| 159 | |||
| 160 | static struct syscore_ops exynos5250_clk_syscore_ops = { | ||
| 161 | .suspend = exynos5250_clk_suspend, | ||
| 162 | .resume = exynos5250_clk_resume, | ||
| 163 | }; | ||
| 164 | |||
| 165 | static void exynos5250_clk_sleep_init(void) | ||
| 166 | { | ||
| 167 | exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs, | ||
| 168 | ARRAY_SIZE(exynos5250_clk_regs)); | ||
| 169 | if (!exynos5250_save) { | ||
| 170 | pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", | ||
| 171 | __func__); | ||
| 172 | return; | ||
| 173 | } | ||
| 174 | |||
| 175 | register_syscore_ops(&exynos5250_clk_syscore_ops); | ||
| 176 | } | ||
| 177 | #else | ||
| 178 | static void exynos5250_clk_sleep_init(void) {} | ||
| 179 | #endif | ||
| 180 | |||
| 140 | /* list of all parent clock list */ | 181 | /* list of all parent clock list */ |
| 141 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; | 182 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; |
| 142 | PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", }; | 183 | PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", }; |
| @@ -645,8 +686,6 @@ static struct of_device_id ext_clk_match[] __initdata = { | |||
| 645 | /* register exynox5250 clocks */ | 686 | /* register exynox5250 clocks */ |
| 646 | static void __init exynos5250_clk_init(struct device_node *np) | 687 | static void __init exynos5250_clk_init(struct device_node *np) |
| 647 | { | 688 | { |
| 648 | void __iomem *reg_base; | ||
| 649 | |||
| 650 | if (np) { | 689 | if (np) { |
| 651 | reg_base = of_iomap(np, 0); | 690 | reg_base = of_iomap(np, 0); |
| 652 | if (!reg_base) | 691 | if (!reg_base) |
| @@ -655,9 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np) | |||
| 655 | panic("%s: unable to determine soc\n", __func__); | 694 | panic("%s: unable to determine soc\n", __func__); |
| 656 | } | 695 | } |
| 657 | 696 | ||
| 658 | samsung_clk_init(np, reg_base, CLK_NR_CLKS, | 697 | samsung_clk_init(np, reg_base, CLK_NR_CLKS); |
| 659 | exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs), | ||
| 660 | NULL, 0); | ||
| 661 | samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, | 698 | samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, |
| 662 | ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), | 699 | ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), |
| 663 | ext_clk_match); | 700 | ext_clk_match); |
| @@ -685,6 +722,8 @@ static void __init exynos5250_clk_init(struct device_node *np) | |||
| 685 | samsung_clk_register_gate(exynos5250_gate_clks, | 722 | samsung_clk_register_gate(exynos5250_gate_clks, |
| 686 | ARRAY_SIZE(exynos5250_gate_clks)); | 723 | ARRAY_SIZE(exynos5250_gate_clks)); |
| 687 | 724 | ||
| 725 | exynos5250_clk_sleep_init(); | ||
| 726 | |||
| 688 | pr_info("Exynos5250: clock setup completed, armclk=%ld\n", | 727 | pr_info("Exynos5250: clock setup completed, armclk=%ld\n", |
| 689 | _get_rate("div_arm2")); | 728 | _get_rate("div_arm2")); |
| 690 | } | 729 | } |
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index ab4f2f7d88ef..60b26819bed5 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/clk-provider.h> | 16 | #include <linux/clk-provider.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
| 19 | #include <linux/syscore_ops.h> | ||
| 19 | 20 | ||
| 20 | #include "clk.h" | 21 | #include "clk.h" |
| 21 | 22 | ||
| @@ -108,6 +109,11 @@ enum exynos5420_plls { | |||
| 108 | nr_plls /* number of PLLs */ | 109 | nr_plls /* number of PLLs */ |
| 109 | }; | 110 | }; |
| 110 | 111 | ||
| 112 | static void __iomem *reg_base; | ||
| 113 | |||
| 114 | #ifdef CONFIG_PM_SLEEP | ||
| 115 | static struct samsung_clk_reg_dump *exynos5420_save; | ||
| 116 | |||
| 111 | /* | 117 | /* |
| 112 | * list of controller registers to be saved and restored during a | 118 | * list of controller registers to be saved and restored during a |
| 113 | * suspend/resume cycle. | 119 | * suspend/resume cycle. |
| @@ -174,6 +180,41 @@ static unsigned long exynos5420_clk_regs[] __initdata = { | |||
| 174 | DIV_KFC0, | 180 | DIV_KFC0, |
| 175 | }; | 181 | }; |
| 176 | 182 | ||
| 183 | static int exynos5420_clk_suspend(void) | ||
| 184 | { | ||
| 185 | samsung_clk_save(reg_base, exynos5420_save, | ||
| 186 | ARRAY_SIZE(exynos5420_clk_regs)); | ||
| 187 | |||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static void exynos5420_clk_resume(void) | ||
| 192 | { | ||
| 193 | samsung_clk_restore(reg_base, exynos5420_save, | ||
| 194 | ARRAY_SIZE(exynos5420_clk_regs)); | ||
| 195 | } | ||
| 196 | |||
| 197 | static struct syscore_ops exynos5420_clk_syscore_ops = { | ||
| 198 | .suspend = exynos5420_clk_suspend, | ||
| 199 | .resume = exynos5420_clk_resume, | ||
| 200 | }; | ||
| 201 | |||
| 202 | static void exynos5420_clk_sleep_init(void) | ||
| 203 | { | ||
| 204 | exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs, | ||
| 205 | ARRAY_SIZE(exynos5420_clk_regs)); | ||
| 206 | if (!exynos5420_save) { | ||
| 207 | pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", | ||
| 208 | __func__); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | |||
| 212 | register_syscore_ops(&exynos5420_clk_syscore_ops); | ||
| 213 | } | ||
| 214 | #else | ||
| 215 | static void exynos5420_clk_sleep_init(void) {} | ||
| 216 | #endif | ||
| 217 | |||
| 177 | /* list of all parent clocks */ | 218 | /* list of all parent clocks */ |
| 178 | PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", | 219 | PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", |
| 179 | "sclk_mpll", "sclk_spll" }; | 220 | "sclk_mpll", "sclk_spll" }; |
| @@ -737,8 +778,6 @@ static struct of_device_id ext_clk_match[] __initdata = { | |||
| 737 | /* register exynos5420 clocks */ | 778 | /* register exynos5420 clocks */ |
| 738 | static void __init exynos5420_clk_init(struct device_node *np) | 779 | static void __init exynos5420_clk_init(struct device_node *np) |
| 739 | { | 780 | { |
| 740 | void __iomem *reg_base; | ||
| 741 | |||
| 742 | if (np) { | 781 | if (np) { |
| 743 | reg_base = of_iomap(np, 0); | 782 | reg_base = of_iomap(np, 0); |
| 744 | if (!reg_base) | 783 | if (!reg_base) |
| @@ -747,9 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np) | |||
| 747 | panic("%s: unable to determine soc\n", __func__); | 786 | panic("%s: unable to determine soc\n", __func__); |
| 748 | } | 787 | } |
| 749 | 788 | ||
| 750 | samsung_clk_init(np, reg_base, CLK_NR_CLKS, | 789 | samsung_clk_init(np, reg_base, CLK_NR_CLKS); |
| 751 | exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs), | ||
| 752 | NULL, 0); | ||
| 753 | samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, | 790 | samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, |
| 754 | ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), | 791 | ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), |
| 755 | ext_clk_match); | 792 | ext_clk_match); |
| @@ -765,5 +802,7 @@ static void __init exynos5420_clk_init(struct device_node *np) | |||
| 765 | ARRAY_SIZE(exynos5420_div_clks)); | 802 | ARRAY_SIZE(exynos5420_div_clks)); |
| 766 | samsung_clk_register_gate(exynos5420_gate_clks, | 803 | samsung_clk_register_gate(exynos5420_gate_clks, |
| 767 | ARRAY_SIZE(exynos5420_gate_clks)); | 804 | ARRAY_SIZE(exynos5420_gate_clks)); |
| 805 | |||
| 806 | exynos5420_clk_sleep_init(); | ||
| 768 | } | 807 | } |
| 769 | CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); | 808 | CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); |
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index cbc15b56891d..2bfad5a993d0 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c | |||
| @@ -101,7 +101,7 @@ static void __init exynos5440_clk_init(struct device_node *np) | |||
| 101 | return; | 101 | return; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); | 104 | samsung_clk_init(np, reg_base, CLK_NR_CLKS); |
| 105 | samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, | 105 | samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, |
| 106 | ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); | 106 | ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); |
| 107 | 107 | ||
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 8e27aee6887e..8bda658137a8 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/clk-provider.h> | 13 | #include <linux/clk-provider.h> |
| 14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
| 15 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
| 16 | #include <linux/syscore_ops.h> | ||
| 16 | 17 | ||
| 17 | #include <dt-bindings/clock/samsung,s3c64xx-clock.h> | 18 | #include <dt-bindings/clock/samsung,s3c64xx-clock.h> |
| 18 | 19 | ||
| @@ -61,6 +62,13 @@ enum s3c64xx_plls { | |||
| 61 | apll, mpll, epll, | 62 | apll, mpll, epll, |
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 65 | static void __iomem *reg_base; | ||
| 66 | static bool is_s3c6400; | ||
| 67 | |||
| 68 | #ifdef CONFIG_PM_SLEEP | ||
| 69 | static struct samsung_clk_reg_dump *s3c64xx_save_common; | ||
| 70 | static struct samsung_clk_reg_dump *s3c64xx_save_soc; | ||
| 71 | |||
| 64 | /* | 72 | /* |
| 65 | * List of controller registers to be saved and restored during | 73 | * List of controller registers to be saved and restored during |
| 66 | * a suspend/resume cycle. | 74 | * a suspend/resume cycle. |
| @@ -87,6 +95,60 @@ static unsigned long s3c6410_clk_regs[] __initdata = { | |||
| 87 | MEM0_GATE, | 95 | MEM0_GATE, |
| 88 | }; | 96 | }; |
| 89 | 97 | ||
| 98 | static int s3c64xx_clk_suspend(void) | ||
| 99 | { | ||
| 100 | samsung_clk_save(reg_base, s3c64xx_save_common, | ||
| 101 | ARRAY_SIZE(s3c64xx_clk_regs)); | ||
| 102 | |||
| 103 | if (!is_s3c6400) | ||
| 104 | samsung_clk_save(reg_base, s3c64xx_save_soc, | ||
| 105 | ARRAY_SIZE(s3c6410_clk_regs)); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void s3c64xx_clk_resume(void) | ||
| 111 | { | ||
| 112 | samsung_clk_restore(reg_base, s3c64xx_save_common, | ||
| 113 | ARRAY_SIZE(s3c64xx_clk_regs)); | ||
| 114 | |||
| 115 | if (!is_s3c6400) | ||
| 116 | samsung_clk_restore(reg_base, s3c64xx_save_soc, | ||
| 117 | ARRAY_SIZE(s3c6410_clk_regs)); | ||
| 118 | } | ||
| 119 | |||
| 120 | static struct syscore_ops s3c64xx_clk_syscore_ops = { | ||
| 121 | .suspend = s3c64xx_clk_suspend, | ||
| 122 | .resume = s3c64xx_clk_resume, | ||
| 123 | }; | ||
| 124 | |||
| 125 | static void s3c64xx_clk_sleep_init(void) | ||
| 126 | { | ||
| 127 | s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs, | ||
| 128 | ARRAY_SIZE(s3c64xx_clk_regs)); | ||
| 129 | if (!s3c64xx_save_common) | ||
| 130 | goto err_warn; | ||
| 131 | |||
| 132 | if (!is_s3c6400) { | ||
| 133 | s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs, | ||
| 134 | ARRAY_SIZE(s3c6410_clk_regs)); | ||
| 135 | if (!s3c64xx_save_soc) | ||
| 136 | goto err_soc; | ||
| 137 | } | ||
| 138 | |||
| 139 | register_syscore_ops(&s3c64xx_clk_syscore_ops); | ||
| 140 | return; | ||
| 141 | |||
| 142 | err_soc: | ||
| 143 | kfree(s3c64xx_save_common); | ||
| 144 | err_warn: | ||
| 145 | pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", | ||
| 146 | __func__); | ||
| 147 | } | ||
| 148 | #else | ||
| 149 | static void s3c64xx_clk_sleep_init(void) {} | ||
| 150 | #endif | ||
| 151 | |||
| 90 | /* List of parent clocks common for all S3C64xx SoCs. */ | 152 | /* List of parent clocks common for all S3C64xx SoCs. */ |
| 91 | PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" }; | 153 | PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" }; |
| 92 | PNAME(uart_p) = { "mout_epll", "dout_mpll" }; | 154 | PNAME(uart_p) = { "mout_epll", "dout_mpll" }; |
| @@ -391,11 +453,11 @@ static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, | |||
| 391 | 453 | ||
| 392 | /* Register s3c64xx clocks. */ | 454 | /* Register s3c64xx clocks. */ |
| 393 | void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, | 455 | void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, |
| 394 | unsigned long xusbxti_f, bool is_s3c6400, | 456 | unsigned long xusbxti_f, bool s3c6400, |
| 395 | void __iomem *reg_base) | 457 | void __iomem *base) |
| 396 | { | 458 | { |
| 397 | unsigned long *soc_regs = NULL; | 459 | reg_base = base; |
| 398 | unsigned long nr_soc_regs = 0; | 460 | is_s3c6400 = s3c6400; |
| 399 | 461 | ||
| 400 | if (np) { | 462 | if (np) { |
| 401 | reg_base = of_iomap(np, 0); | 463 | reg_base = of_iomap(np, 0); |
| @@ -403,13 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, | |||
| 403 | panic("%s: failed to map registers\n", __func__); | 465 | panic("%s: failed to map registers\n", __func__); |
| 404 | } | 466 | } |
| 405 | 467 | ||
| 406 | if (!is_s3c6400) { | 468 | samsung_clk_init(np, reg_base, NR_CLKS); |
| 407 | soc_regs = s3c6410_clk_regs; | ||
| 408 | nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs); | ||
| 409 | } | ||
| 410 | |||
| 411 | samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs, | ||
| 412 | ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs); | ||
| 413 | 469 | ||
| 414 | /* Register external clocks. */ | 470 | /* Register external clocks. */ |
| 415 | if (!np) | 471 | if (!np) |
| @@ -452,6 +508,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, | |||
| 452 | 508 | ||
| 453 | samsung_clk_register_alias(s3c64xx_clock_aliases, | 509 | samsung_clk_register_alias(s3c64xx_clock_aliases, |
| 454 | ARRAY_SIZE(s3c64xx_clock_aliases)); | 510 | ARRAY_SIZE(s3c64xx_clock_aliases)); |
| 511 | s3c64xx_clk_sleep_init(); | ||
| 455 | 512 | ||
| 456 | pr_info("%s clocks: apll = %lu, mpll = %lu\n" | 513 | pr_info("%s clocks: apll = %lu, mpll = %lu\n" |
| 457 | "\tepll = %lu, arm_clk = %lu\n", | 514 | "\tepll = %lu, arm_clk = %lu\n", |
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index f503f32e2f80..91bec3ebdc8f 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c | |||
| @@ -21,64 +21,45 @@ static void __iomem *reg_base; | |||
| 21 | static struct clk_onecell_data clk_data; | 21 | static struct clk_onecell_data clk_data; |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
| 24 | #ifdef CONFIG_PM_SLEEP | 24 | void samsung_clk_save(void __iomem *base, |
| 25 | static struct samsung_clk_reg_dump *reg_dump; | 25 | struct samsung_clk_reg_dump *rd, |
| 26 | static unsigned long nr_reg_dump; | 26 | unsigned int num_regs) |
| 27 | |||
| 28 | static int samsung_clk_suspend(void) | ||
| 29 | { | 27 | { |
| 30 | struct samsung_clk_reg_dump *rd = reg_dump; | 28 | for (; num_regs > 0; --num_regs, ++rd) |
| 31 | unsigned long i; | 29 | rd->value = readl(base + rd->offset); |
| 32 | 30 | } | |
| 33 | for (i = 0; i < nr_reg_dump; i++, rd++) | ||
| 34 | rd->value = __raw_readl(reg_base + rd->offset); | ||
| 35 | 31 | ||
| 36 | return 0; | 32 | void samsung_clk_restore(void __iomem *base, |
| 33 | const struct samsung_clk_reg_dump *rd, | ||
| 34 | unsigned int num_regs) | ||
| 35 | { | ||
| 36 | for (; num_regs > 0; --num_regs, ++rd) | ||
| 37 | writel(rd->value, base + rd->offset); | ||
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | static void samsung_clk_resume(void) | 40 | struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( |
| 41 | const unsigned long *rdump, | ||
| 42 | unsigned long nr_rdump) | ||
| 40 | { | 43 | { |
| 41 | struct samsung_clk_reg_dump *rd = reg_dump; | 44 | struct samsung_clk_reg_dump *rd; |
| 42 | unsigned long i; | 45 | unsigned int i; |
| 43 | 46 | ||
| 44 | for (i = 0; i < nr_reg_dump; i++, rd++) | 47 | rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); |
| 45 | __raw_writel(rd->value, reg_base + rd->offset); | 48 | if (!rd) |
| 46 | } | 49 | return NULL; |
| 50 | |||
| 51 | for (i = 0; i < nr_rdump; ++i) | ||
| 52 | rd[i].offset = rdump[i]; | ||
| 47 | 53 | ||
| 48 | static struct syscore_ops samsung_clk_syscore_ops = { | 54 | return rd; |
| 49 | .suspend = samsung_clk_suspend, | 55 | } |
| 50 | .resume = samsung_clk_resume, | ||
| 51 | }; | ||
| 52 | #endif /* CONFIG_PM_SLEEP */ | ||
| 53 | 56 | ||
| 54 | /* setup the essentials required to support clock lookup using ccf */ | 57 | /* setup the essentials required to support clock lookup using ccf */ |
| 55 | void __init samsung_clk_init(struct device_node *np, void __iomem *base, | 58 | void __init samsung_clk_init(struct device_node *np, void __iomem *base, |
| 56 | unsigned long nr_clks, unsigned long *rdump, | 59 | unsigned long nr_clks) |
| 57 | unsigned long nr_rdump, unsigned long *soc_rdump, | ||
| 58 | unsigned long nr_soc_rdump) | ||
| 59 | { | 60 | { |
| 60 | reg_base = base; | 61 | reg_base = base; |
| 61 | 62 | ||
| 62 | #ifdef CONFIG_PM_SLEEP | ||
| 63 | if (rdump && nr_rdump) { | ||
| 64 | unsigned int idx; | ||
| 65 | reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump) | ||
| 66 | * (nr_rdump + nr_soc_rdump), GFP_KERNEL); | ||
| 67 | if (!reg_dump) { | ||
| 68 | pr_err("%s: memory alloc for register dump failed\n", | ||
| 69 | __func__); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | |||
| 73 | for (idx = 0; idx < nr_rdump; idx++) | ||
| 74 | reg_dump[idx].offset = rdump[idx]; | ||
| 75 | for (idx = 0; idx < nr_soc_rdump; idx++) | ||
| 76 | reg_dump[nr_rdump + idx].offset = soc_rdump[idx]; | ||
| 77 | nr_reg_dump = nr_rdump + nr_soc_rdump; | ||
| 78 | register_syscore_ops(&samsung_clk_syscore_ops); | ||
| 79 | } | ||
| 80 | #endif | ||
| 81 | |||
| 82 | clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); | 63 | clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); |
| 83 | if (!clk_table) | 64 | if (!clk_table) |
| 84 | panic("could not allocate clock lookup table\n"); | 65 | panic("could not allocate clock lookup table\n"); |
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 31b4174e7a5b..c7141ba826e0 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h | |||
| @@ -313,9 +313,7 @@ struct samsung_pll_clock { | |||
| 313 | _lock, _con, _rtable, _alias) | 313 | _lock, _con, _rtable, _alias) |
| 314 | 314 | ||
| 315 | extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, | 315 | extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, |
| 316 | unsigned long nr_clks, unsigned long *rdump, | 316 | unsigned long nr_clks); |
| 317 | unsigned long nr_rdump, unsigned long *soc_rdump, | ||
| 318 | unsigned long nr_soc_rdump); | ||
| 319 | extern void __init samsung_clk_of_register_fixed_ext( | 317 | extern void __init samsung_clk_of_register_fixed_ext( |
| 320 | struct samsung_fixed_rate_clock *fixed_rate_clk, | 318 | struct samsung_fixed_rate_clock *fixed_rate_clk, |
| 321 | unsigned int nr_fixed_rate_clk, | 319 | unsigned int nr_fixed_rate_clk, |
| @@ -340,4 +338,14 @@ extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, | |||
| 340 | 338 | ||
| 341 | extern unsigned long _get_rate(const char *clk_name); | 339 | extern unsigned long _get_rate(const char *clk_name); |
| 342 | 340 | ||
| 341 | extern void samsung_clk_save(void __iomem *base, | ||
| 342 | struct samsung_clk_reg_dump *rd, | ||
| 343 | unsigned int num_regs); | ||
| 344 | extern void samsung_clk_restore(void __iomem *base, | ||
| 345 | const struct samsung_clk_reg_dump *rd, | ||
| 346 | unsigned int num_regs); | ||
| 347 | extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( | ||
| 348 | const unsigned long *rdump, | ||
| 349 | unsigned long nr_rdump); | ||
| 350 | |||
| 343 | #endif /* __SAMSUNG_CLK_H */ | 351 | #endif /* __SAMSUNG_CLK_H */ |
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 8cbfcf88fae3..a820b0cfcf57 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c | |||
| @@ -33,7 +33,7 @@ struct clk_icst { | |||
| 33 | struct clk_hw hw; | 33 | struct clk_hw hw; |
| 34 | void __iomem *vcoreg; | 34 | void __iomem *vcoreg; |
| 35 | void __iomem *lockreg; | 35 | void __iomem *lockreg; |
| 36 | const struct icst_params *params; | 36 | struct icst_params *params; |
| 37 | unsigned long rate; | 37 | unsigned long rate; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| @@ -84,6 +84,8 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw, | |||
| 84 | struct clk_icst *icst = to_icst(hw); | 84 | struct clk_icst *icst = to_icst(hw); |
| 85 | struct icst_vco vco; | 85 | struct icst_vco vco; |
| 86 | 86 | ||
| 87 | if (parent_rate) | ||
| 88 | icst->params->ref = parent_rate; | ||
| 87 | vco = vco_get(icst->vcoreg); | 89 | vco = vco_get(icst->vcoreg); |
| 88 | icst->rate = icst_hz(icst->params, vco); | 90 | icst->rate = icst_hz(icst->params, vco); |
| 89 | return icst->rate; | 91 | return icst->rate; |
| @@ -105,6 +107,8 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 105 | struct clk_icst *icst = to_icst(hw); | 107 | struct clk_icst *icst = to_icst(hw); |
| 106 | struct icst_vco vco; | 108 | struct icst_vco vco; |
| 107 | 109 | ||
| 110 | if (parent_rate) | ||
| 111 | icst->params->ref = parent_rate; | ||
| 108 | vco = icst_hz_to_vco(icst->params, rate); | 112 | vco = icst_hz_to_vco(icst->params, rate); |
| 109 | icst->rate = icst_hz(icst->params, vco); | 113 | icst->rate = icst_hz(icst->params, vco); |
| 110 | vco_set(icst->lockreg, icst->vcoreg, vco); | 114 | vco_set(icst->lockreg, icst->vcoreg, vco); |
| @@ -120,24 +124,33 @@ static const struct clk_ops icst_ops = { | |||
| 120 | struct clk *icst_clk_register(struct device *dev, | 124 | struct clk *icst_clk_register(struct device *dev, |
| 121 | const struct clk_icst_desc *desc, | 125 | const struct clk_icst_desc *desc, |
| 122 | const char *name, | 126 | const char *name, |
| 127 | const char *parent_name, | ||
| 123 | void __iomem *base) | 128 | void __iomem *base) |
| 124 | { | 129 | { |
| 125 | struct clk *clk; | 130 | struct clk *clk; |
| 126 | struct clk_icst *icst; | 131 | struct clk_icst *icst; |
| 127 | struct clk_init_data init; | 132 | struct clk_init_data init; |
| 133 | struct icst_params *pclone; | ||
| 128 | 134 | ||
| 129 | icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); | 135 | icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); |
| 130 | if (!icst) { | 136 | if (!icst) { |
| 131 | pr_err("could not allocate ICST clock!\n"); | 137 | pr_err("could not allocate ICST clock!\n"); |
| 132 | return ERR_PTR(-ENOMEM); | 138 | return ERR_PTR(-ENOMEM); |
| 133 | } | 139 | } |
| 140 | |||
| 141 | pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL); | ||
| 142 | if (!pclone) { | ||
| 143 | pr_err("could not clone ICST params\n"); | ||
| 144 | return ERR_PTR(-ENOMEM); | ||
| 145 | } | ||
| 146 | |||
| 134 | init.name = name; | 147 | init.name = name; |
| 135 | init.ops = &icst_ops; | 148 | init.ops = &icst_ops; |
| 136 | init.flags = CLK_IS_ROOT; | 149 | init.flags = CLK_IS_ROOT; |
| 137 | init.parent_names = NULL; | 150 | init.parent_names = (parent_name ? &parent_name : NULL); |
| 138 | init.num_parents = 0; | 151 | init.num_parents = (parent_name ? 1 : 0); |
| 139 | icst->hw.init = &init; | 152 | icst->hw.init = &init; |
| 140 | icst->params = desc->params; | 153 | icst->params = pclone; |
| 141 | icst->vcoreg = base + desc->vco_offset; | 154 | icst->vcoreg = base + desc->vco_offset; |
| 142 | icst->lockreg = base + desc->lock_offset; | 155 | icst->lockreg = base + desc->lock_offset; |
| 143 | 156 | ||
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index be99dd0da785..04e6f0aef588 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h | |||
| @@ -16,4 +16,5 @@ struct clk_icst_desc { | |||
| 16 | struct clk *icst_clk_register(struct device *dev, | 16 | struct clk *icst_clk_register(struct device *dev, |
| 17 | const struct clk_icst_desc *desc, | 17 | const struct clk_icst_desc *desc, |
| 18 | const char *name, | 18 | const char *name, |
| 19 | const char *parent_name, | ||
| 19 | void __iomem *base); | 20 | void __iomem *base); |
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 844f8d711a12..6d8b8e1a080a 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c | |||
| @@ -93,13 +93,15 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id) | |||
| 93 | imc = &impd1_clks[id]; | 93 | imc = &impd1_clks[id]; |
| 94 | 94 | ||
| 95 | imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); | 95 | imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); |
| 96 | clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base); | 96 | clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL, |
| 97 | base); | ||
| 97 | imc->vco1clk = clk; | 98 | imc->vco1clk = clk; |
| 98 | imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); | 99 | imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); |
| 99 | 100 | ||
| 100 | /* VCO2 is also called "CLK2" */ | 101 | /* VCO2 is also called "CLK2" */ |
| 101 | imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); | 102 | imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); |
| 102 | clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base); | 103 | clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, NULL, |
| 104 | base); | ||
| 103 | imc->vco2clk = clk; | 105 | imc->vco2clk = clk; |
| 104 | 106 | ||
| 105 | /* MMCI uses CLK2 right off */ | 107 | /* MMCI uses CLK2 right off */ |
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c index bda8967e09c2..734c4b8fe6ab 100644 --- a/drivers/clk/versatile/clk-integrator.c +++ b/drivers/clk/versatile/clk-integrator.c | |||
| @@ -10,21 +10,17 @@ | |||
| 10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
| 11 | #include <linux/clkdev.h> | 11 | #include <linux/clkdev.h> |
| 12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/platform_data/clk-integrator.h> | 13 | #include <linux/of.h> |
| 14 | 14 | #include <linux/of_address.h> | |
| 15 | #include <mach/hardware.h> | ||
| 16 | #include <mach/platform.h> | ||
| 17 | 15 | ||
| 18 | #include "clk-icst.h" | 16 | #include "clk-icst.h" |
| 19 | 17 | ||
| 20 | /* | 18 | #define INTEGRATOR_HDR_LOCK_OFFSET 0x14 |
| 21 | * Implementation of the ARM Integrator/AP and Integrator/CP clock tree. | ||
| 22 | * Inspired by portions of: | ||
| 23 | * plat-versatile/clock.c and plat-versatile/include/plat/clock.h | ||
| 24 | */ | ||
| 25 | 19 | ||
| 26 | static const struct icst_params cp_auxvco_params = { | 20 | /* Base offset for the core module */ |
| 27 | .ref = 24000000, | 21 | static void __iomem *cm_base; |
| 22 | |||
| 23 | static const struct icst_params cp_auxosc_params = { | ||
| 28 | .vco_max = ICST525_VCO_MAX_5V, | 24 | .vco_max = ICST525_VCO_MAX_5V, |
| 29 | .vco_min = ICST525_VCO_MIN, | 25 | .vco_min = ICST525_VCO_MIN, |
| 30 | .vd_min = 8, | 26 | .vd_min = 8, |
| @@ -35,50 +31,39 @@ static const struct icst_params cp_auxvco_params = { | |||
| 35 | .idx2s = icst525_idx2s, | 31 | .idx2s = icst525_idx2s, |
| 36 | }; | 32 | }; |
| 37 | 33 | ||
| 38 | static const struct clk_icst_desc __initdata cp_icst_desc = { | 34 | static const struct clk_icst_desc __initdata cm_auxosc_desc = { |
| 39 | .params = &cp_auxvco_params, | 35 | .params = &cp_auxosc_params, |
| 40 | .vco_offset = 0x1c, | 36 | .vco_offset = 0x1c, |
| 41 | .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, | 37 | .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, |
| 42 | }; | 38 | }; |
| 43 | 39 | ||
| 44 | /* | 40 | static void __init of_integrator_cm_osc_setup(struct device_node *np) |
| 45 | * integrator_clk_init() - set up the integrator clock tree | ||
| 46 | * @is_cp: pass true if it's the Integrator/CP else AP is assumed | ||
| 47 | */ | ||
| 48 | void __init integrator_clk_init(bool is_cp) | ||
| 49 | { | 41 | { |
| 50 | struct clk *clk; | 42 | struct clk *clk = ERR_PTR(-EINVAL); |
| 51 | 43 | const char *clk_name = np->name; | |
| 52 | /* APB clock dummy */ | 44 | const struct clk_icst_desc *desc = &cm_auxosc_desc; |
| 53 | clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); | 45 | const char *parent_name; |
| 54 | clk_register_clkdev(clk, "apb_pclk", NULL); | ||
| 55 | |||
| 56 | /* UART reference clock */ | ||
| 57 | clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT, | ||
| 58 | 14745600); | ||
| 59 | clk_register_clkdev(clk, NULL, "uart0"); | ||
| 60 | clk_register_clkdev(clk, NULL, "uart1"); | ||
| 61 | if (is_cp) | ||
| 62 | clk_register_clkdev(clk, NULL, "mmci"); | ||
| 63 | |||
| 64 | /* 24 MHz clock */ | ||
| 65 | clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT, | ||
| 66 | 24000000); | ||
| 67 | clk_register_clkdev(clk, NULL, "kmi0"); | ||
| 68 | clk_register_clkdev(clk, NULL, "kmi1"); | ||
| 69 | if (!is_cp) | ||
| 70 | clk_register_clkdev(clk, NULL, "ap_timer"); | ||
| 71 | 46 | ||
| 72 | if (!is_cp) | 47 | if (!cm_base) { |
| 73 | return; | 48 | /* Remap the core module base if not done yet */ |
| 49 | struct device_node *parent; | ||
| 74 | 50 | ||
| 75 | /* 1 MHz clock */ | 51 | parent = of_get_parent(np); |
| 76 | clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT, | 52 | if (!np) { |
| 77 | 1000000); | 53 | pr_err("no parent on core module clock\n"); |
| 78 | clk_register_clkdev(clk, NULL, "sp804"); | 54 | return; |
| 55 | } | ||
| 56 | cm_base = of_iomap(parent, 0); | ||
| 57 | if (!cm_base) { | ||
| 58 | pr_err("could not remap core module base\n"); | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | } | ||
| 79 | 62 | ||
| 80 | /* ICST VCO clock used on the Integrator/CP CLCD */ | 63 | parent_name = of_clk_get_parent_name(np, 0); |
| 81 | clk = icst_clk_register(NULL, &cp_icst_desc, "icst", | 64 | clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base); |
| 82 | __io_address(INTEGRATOR_HDR_BASE)); | 65 | if (!IS_ERR(clk)) |
| 83 | clk_register_clkdev(clk, NULL, "clcd"); | 66 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
| 84 | } | 67 | } |
| 68 | CLK_OF_DECLARE(integrator_cm_auxosc_clk, | ||
| 69 | "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup); | ||
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index 747e7b31117c..c8b523117fb7 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c | |||
| @@ -85,10 +85,10 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) | |||
| 85 | /* ICST VCO clock */ | 85 | /* ICST VCO clock */ |
| 86 | if (is_pb1176) | 86 | if (is_pb1176) |
| 87 | clk = icst_clk_register(NULL, &realview_osc0_desc, | 87 | clk = icst_clk_register(NULL, &realview_osc0_desc, |
| 88 | "osc0", sysbase); | 88 | "osc0", NULL, sysbase); |
| 89 | else | 89 | else |
| 90 | clk = icst_clk_register(NULL, &realview_osc4_desc, | 90 | clk = icst_clk_register(NULL, &realview_osc4_desc, |
| 91 | "osc4", sysbase); | 91 | "osc4", NULL, sysbase); |
| 92 | 92 | ||
| 93 | clk_register_clkdev(clk, NULL, "dev:clcd"); | 93 | clk_register_clkdev(clk, NULL, "dev:clcd"); |
| 94 | clk_register_clkdev(clk, NULL, "issp:clcd"); | 94 | clk_register_clkdev(clk, NULL, "issp:clcd"); |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 9fb627046e17..1e2b9db563ec 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
| @@ -122,7 +122,7 @@ config ARM_INTEGRATOR | |||
| 122 | If in doubt, say Y. | 122 | If in doubt, say Y. |
| 123 | 123 | ||
| 124 | config ARM_KIRKWOOD_CPUFREQ | 124 | config ARM_KIRKWOOD_CPUFREQ |
| 125 | def_bool ARCH_KIRKWOOD && OF | 125 | def_bool MACH_KIRKWOOD |
| 126 | help | 126 | help |
| 127 | This adds the CPUFreq driver for Marvell Kirkwood | 127 | This adds the CPUFreq driver for Marvell Kirkwood |
| 128 | SoCs. | 128 | SoCs. |
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index d988948a89a0..97ccc31dbdd8 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm | |||
| @@ -22,7 +22,7 @@ config ARM_HIGHBANK_CPUIDLE | |||
| 22 | 22 | ||
| 23 | config ARM_KIRKWOOD_CPUIDLE | 23 | config ARM_KIRKWOOD_CPUIDLE |
| 24 | bool "CPU Idle Driver for Marvell Kirkwood SoCs" | 24 | bool "CPU Idle Driver for Marvell Kirkwood SoCs" |
| 25 | depends on ARCH_KIRKWOOD | 25 | depends on ARCH_KIRKWOOD || MACH_KIRKWOOD |
| 26 | help | 26 | help |
| 27 | This adds the CPU Idle driver for Marvell Kirkwood SoCs. | 27 | This adds the CPU Idle driver for Marvell Kirkwood SoCs. |
| 28 | 28 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 92d8e9a064b4..a86c49a605c6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -210,7 +210,7 @@ config GPIO_MSM_V1 | |||
| 210 | 210 | ||
| 211 | config GPIO_MSM_V2 | 211 | config GPIO_MSM_V2 |
| 212 | tristate "Qualcomm MSM GPIO v2" | 212 | tristate "Qualcomm MSM GPIO v2" |
| 213 | depends on GPIOLIB && OF && ARCH_MSM | 213 | depends on GPIOLIB && OF && ARCH_QCOM |
| 214 | help | 214 | help |
| 215 | Say yes here to support the GPIO interface on ARM v7 based | 215 | Say yes here to support the GPIO interface on ARM v7 based |
| 216 | Qualcomm MSM chips. Most of the pins on the MSM can be | 216 | Qualcomm MSM chips. Most of the pins on the MSM can be |
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index c69d1e07a3a6..b6984971ce0c 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig | |||
| @@ -3,7 +3,7 @@ config DRM_MSM | |||
| 3 | tristate "MSM DRM" | 3 | tristate "MSM DRM" |
| 4 | depends on DRM | 4 | depends on DRM |
| 5 | depends on MSM_IOMMU | 5 | depends on MSM_IOMMU |
| 6 | depends on (ARCH_MSM && ARCH_MSM8960) || (ARM && COMPILE_TEST) | 6 | depends on ARCH_MSM8960 || (ARM && COMPILE_TEST) |
| 7 | select DRM_KMS_HELPER | 7 | select DRM_KMS_HELPER |
| 8 | select SHMEM | 8 | select SHMEM |
| 9 | select TMPFS | 9 | select TMPFS |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index ec42d2decb2f..d770f7406631 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
| @@ -77,3 +77,11 @@ config VERSATILE_FPGA_IRQ_NR | |||
| 77 | config XTENSA_MX | 77 | config XTENSA_MX |
| 78 | bool | 78 | bool |
| 79 | select IRQ_DOMAIN | 79 | select IRQ_DOMAIN |
| 80 | |||
| 81 | config IRQ_CROSSBAR | ||
| 82 | bool | ||
| 83 | help | ||
| 84 | Support for a CROSSBAR ip that preceeds the main interrupt controller. | ||
| 85 | The primary irqchip invokes the crossbar's callback which inturn allocates | ||
| 86 | a free irq and configures the IP. Thus the peripheral interrupts are | ||
| 87 | routed to one of the free irqchip interrupt lines. | ||
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 6cee9efa26e7..f180f8d5fb7b 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
| @@ -28,3 +28,4 @@ obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o | |||
| 28 | obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o | 28 | obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o |
| 29 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o | 29 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o |
| 30 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o | 30 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o |
| 31 | obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o | ||
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c new file mode 100644 index 000000000000..fc817d28d1fe --- /dev/null +++ b/drivers/irqchip/irq-crossbar.c | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /* | ||
| 2 | * drivers/irqchip/irq-crossbar.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
| 5 | * Author: Sricharan R <r.sricharan@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/of_address.h> | ||
| 15 | #include <linux/of_irq.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | #include <linux/irqchip/arm-gic.h> | ||
| 18 | |||
| 19 | #define IRQ_FREE -1 | ||
| 20 | #define GIC_IRQ_START 32 | ||
| 21 | |||
| 22 | /* | ||
| 23 | * @int_max: maximum number of supported interrupts | ||
| 24 | * @irq_map: array of interrupts to crossbar number mapping | ||
| 25 | * @crossbar_base: crossbar base address | ||
| 26 | * @register_offsets: offsets for each irq number | ||
| 27 | */ | ||
| 28 | struct crossbar_device { | ||
| 29 | uint int_max; | ||
| 30 | uint *irq_map; | ||
| 31 | void __iomem *crossbar_base; | ||
| 32 | int *register_offsets; | ||
| 33 | void (*write) (int, int); | ||
| 34 | }; | ||
| 35 | |||
| 36 | static struct crossbar_device *cb; | ||
| 37 | |||
| 38 | static inline void crossbar_writel(int irq_no, int cb_no) | ||
| 39 | { | ||
| 40 | writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline void crossbar_writew(int irq_no, int cb_no) | ||
| 44 | { | ||
| 45 | writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline void crossbar_writeb(int irq_no, int cb_no) | ||
| 49 | { | ||
| 50 | writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline int allocate_free_irq(int cb_no) | ||
| 54 | { | ||
| 55 | int i; | ||
| 56 | |||
| 57 | for (i = 0; i < cb->int_max; i++) { | ||
| 58 | if (cb->irq_map[i] == IRQ_FREE) { | ||
| 59 | cb->irq_map[i] = cb_no; | ||
| 60 | return i; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | return -ENODEV; | ||
| 65 | } | ||
| 66 | |||
| 67 | static int crossbar_domain_map(struct irq_domain *d, unsigned int irq, | ||
| 68 | irq_hw_number_t hw) | ||
| 69 | { | ||
| 70 | cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]); | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq) | ||
| 75 | { | ||
| 76 | irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq; | ||
| 77 | |||
| 78 | if (hw > GIC_IRQ_START) | ||
| 79 | cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int crossbar_domain_xlate(struct irq_domain *d, | ||
| 83 | struct device_node *controller, | ||
| 84 | const u32 *intspec, unsigned int intsize, | ||
| 85 | unsigned long *out_hwirq, | ||
| 86 | unsigned int *out_type) | ||
| 87 | { | ||
| 88 | unsigned long ret; | ||
| 89 | |||
| 90 | ret = allocate_free_irq(intspec[1]); | ||
| 91 | |||
| 92 | if (IS_ERR_VALUE(ret)) | ||
| 93 | return ret; | ||
| 94 | |||
| 95 | *out_hwirq = ret + GIC_IRQ_START; | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | const struct irq_domain_ops routable_irq_domain_ops = { | ||
| 100 | .map = crossbar_domain_map, | ||
| 101 | .unmap = crossbar_domain_unmap, | ||
| 102 | .xlate = crossbar_domain_xlate | ||
| 103 | }; | ||
| 104 | |||
| 105 | static int __init crossbar_of_init(struct device_node *node) | ||
| 106 | { | ||
| 107 | int i, size, max, reserved = 0, entry; | ||
| 108 | const __be32 *irqsr; | ||
| 109 | |||
| 110 | cb = kzalloc(sizeof(struct cb_device *), GFP_KERNEL); | ||
| 111 | |||
| 112 | if (!cb) | ||
| 113 | return -ENOMEM; | ||
| 114 | |||
| 115 | cb->crossbar_base = of_iomap(node, 0); | ||
| 116 | if (!cb->crossbar_base) | ||
| 117 | goto err1; | ||
| 118 | |||
| 119 | of_property_read_u32(node, "ti,max-irqs", &max); | ||
| 120 | cb->irq_map = kzalloc(max * sizeof(int), GFP_KERNEL); | ||
| 121 | if (!cb->irq_map) | ||
| 122 | goto err2; | ||
| 123 | |||
| 124 | cb->int_max = max; | ||
| 125 | |||
| 126 | for (i = 0; i < max; i++) | ||
| 127 | cb->irq_map[i] = IRQ_FREE; | ||
| 128 | |||
| 129 | /* Get and mark reserved irqs */ | ||
| 130 | irqsr = of_get_property(node, "ti,irqs-reserved", &size); | ||
| 131 | if (irqsr) { | ||
| 132 | size /= sizeof(__be32); | ||
| 133 | |||
| 134 | for (i = 0; i < size; i++) { | ||
| 135 | of_property_read_u32_index(node, | ||
| 136 | "ti,irqs-reserved", | ||
| 137 | i, &entry); | ||
| 138 | if (entry > max) { | ||
| 139 | pr_err("Invalid reserved entry\n"); | ||
| 140 | goto err3; | ||
| 141 | } | ||
| 142 | cb->irq_map[entry] = 0; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | cb->register_offsets = kzalloc(max * sizeof(int), GFP_KERNEL); | ||
| 147 | if (!cb->register_offsets) | ||
| 148 | goto err3; | ||
| 149 | |||
| 150 | of_property_read_u32(node, "ti,reg-size", &size); | ||
| 151 | |||
| 152 | switch (size) { | ||
| 153 | case 1: | ||
| 154 | cb->write = crossbar_writeb; | ||
| 155 | break; | ||
| 156 | case 2: | ||
| 157 | cb->write = crossbar_writew; | ||
| 158 | break; | ||
| 159 | case 4: | ||
| 160 | cb->write = crossbar_writel; | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | pr_err("Invalid reg-size property\n"); | ||
| 164 | goto err4; | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Register offsets are not linear because of the | ||
| 170 | * reserved irqs. so find and store the offsets once. | ||
| 171 | */ | ||
| 172 | for (i = 0; i < max; i++) { | ||
| 173 | if (!cb->irq_map[i]) | ||
| 174 | continue; | ||
| 175 | |||
| 176 | cb->register_offsets[i] = reserved; | ||
| 177 | reserved += size; | ||
| 178 | } | ||
| 179 | |||
| 180 | register_routable_domain_ops(&routable_irq_domain_ops); | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | err4: | ||
| 184 | kfree(cb->register_offsets); | ||
| 185 | err3: | ||
| 186 | kfree(cb->irq_map); | ||
| 187 | err2: | ||
| 188 | iounmap(cb->crossbar_base); | ||
| 189 | err1: | ||
| 190 | kfree(cb); | ||
| 191 | return -ENOMEM; | ||
| 192 | } | ||
| 193 | |||
| 194 | static const struct of_device_id crossbar_match[] __initconst = { | ||
| 195 | { .compatible = "ti,irq-crossbar" }, | ||
| 196 | {} | ||
| 197 | }; | ||
| 198 | |||
| 199 | int __init irqcrossbar_init(void) | ||
| 200 | { | ||
| 201 | struct device_node *np; | ||
| 202 | np = of_find_matching_node(NULL, crossbar_match); | ||
| 203 | if (!np) | ||
| 204 | return -ENODEV; | ||
| 205 | |||
| 206 | crossbar_of_init(np); | ||
| 207 | return 0; | ||
| 208 | } | ||
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 63922b9ba6b7..4300b6606f5e 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
| @@ -824,16 +824,25 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | |||
| 824 | irq_set_chip_and_handler(irq, &gic_chip, | 824 | irq_set_chip_and_handler(irq, &gic_chip, |
| 825 | handle_fasteoi_irq); | 825 | handle_fasteoi_irq); |
| 826 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 826 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
| 827 | |||
| 828 | gic_routable_irq_domain_ops->map(d, irq, hw); | ||
| 827 | } | 829 | } |
| 828 | irq_set_chip_data(irq, d->host_data); | 830 | irq_set_chip_data(irq, d->host_data); |
| 829 | return 0; | 831 | return 0; |
| 830 | } | 832 | } |
| 831 | 833 | ||
| 834 | static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq) | ||
| 835 | { | ||
| 836 | gic_routable_irq_domain_ops->unmap(d, irq); | ||
| 837 | } | ||
| 838 | |||
| 832 | static int gic_irq_domain_xlate(struct irq_domain *d, | 839 | static int gic_irq_domain_xlate(struct irq_domain *d, |
| 833 | struct device_node *controller, | 840 | struct device_node *controller, |
| 834 | const u32 *intspec, unsigned int intsize, | 841 | const u32 *intspec, unsigned int intsize, |
| 835 | unsigned long *out_hwirq, unsigned int *out_type) | 842 | unsigned long *out_hwirq, unsigned int *out_type) |
| 836 | { | 843 | { |
| 844 | unsigned long ret = 0; | ||
| 845 | |||
| 837 | if (d->of_node != controller) | 846 | if (d->of_node != controller) |
| 838 | return -EINVAL; | 847 | return -EINVAL; |
| 839 | if (intsize < 3) | 848 | if (intsize < 3) |
| @@ -843,11 +852,20 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
| 843 | *out_hwirq = intspec[1] + 16; | 852 | *out_hwirq = intspec[1] + 16; |
| 844 | 853 | ||
| 845 | /* For SPIs, we need to add 16 more to get the GIC irq ID number */ | 854 | /* For SPIs, we need to add 16 more to get the GIC irq ID number */ |
| 846 | if (!intspec[0]) | 855 | if (!intspec[0]) { |
| 847 | *out_hwirq += 16; | 856 | ret = gic_routable_irq_domain_ops->xlate(d, controller, |
| 857 | intspec, | ||
| 858 | intsize, | ||
| 859 | out_hwirq, | ||
| 860 | out_type); | ||
| 861 | |||
| 862 | if (IS_ERR_VALUE(ret)) | ||
| 863 | return ret; | ||
| 864 | } | ||
| 848 | 865 | ||
| 849 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; | 866 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; |
| 850 | return 0; | 867 | |
| 868 | return ret; | ||
| 851 | } | 869 | } |
| 852 | 870 | ||
| 853 | #ifdef CONFIG_SMP | 871 | #ifdef CONFIG_SMP |
| @@ -871,9 +889,41 @@ static struct notifier_block gic_cpu_notifier = { | |||
| 871 | 889 | ||
| 872 | static const struct irq_domain_ops gic_irq_domain_ops = { | 890 | static const struct irq_domain_ops gic_irq_domain_ops = { |
| 873 | .map = gic_irq_domain_map, | 891 | .map = gic_irq_domain_map, |
| 892 | .unmap = gic_irq_domain_unmap, | ||
| 874 | .xlate = gic_irq_domain_xlate, | 893 | .xlate = gic_irq_domain_xlate, |
| 875 | }; | 894 | }; |
| 876 | 895 | ||
| 896 | /* Default functions for routable irq domain */ | ||
| 897 | static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq, | ||
| 898 | irq_hw_number_t hw) | ||
| 899 | { | ||
| 900 | return 0; | ||
| 901 | } | ||
| 902 | |||
| 903 | static void gic_routable_irq_domain_unmap(struct irq_domain *d, | ||
| 904 | unsigned int irq) | ||
| 905 | { | ||
| 906 | } | ||
| 907 | |||
| 908 | static int gic_routable_irq_domain_xlate(struct irq_domain *d, | ||
| 909 | struct device_node *controller, | ||
| 910 | const u32 *intspec, unsigned int intsize, | ||
| 911 | unsigned long *out_hwirq, | ||
| 912 | unsigned int *out_type) | ||
| 913 | { | ||
| 914 | *out_hwirq += 16; | ||
| 915 | return 0; | ||
| 916 | } | ||
| 917 | |||
| 918 | const struct irq_domain_ops gic_default_routable_irq_domain_ops = { | ||
| 919 | .map = gic_routable_irq_domain_map, | ||
| 920 | .unmap = gic_routable_irq_domain_unmap, | ||
| 921 | .xlate = gic_routable_irq_domain_xlate, | ||
| 922 | }; | ||
| 923 | |||
| 924 | const struct irq_domain_ops *gic_routable_irq_domain_ops = | ||
| 925 | &gic_default_routable_irq_domain_ops; | ||
| 926 | |||
| 877 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, | 927 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, |
| 878 | void __iomem *dist_base, void __iomem *cpu_base, | 928 | void __iomem *dist_base, void __iomem *cpu_base, |
| 879 | u32 percpu_offset, struct device_node *node) | 929 | u32 percpu_offset, struct device_node *node) |
| @@ -881,6 +931,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
| 881 | irq_hw_number_t hwirq_base; | 931 | irq_hw_number_t hwirq_base; |
| 882 | struct gic_chip_data *gic; | 932 | struct gic_chip_data *gic; |
| 883 | int gic_irqs, irq_base, i; | 933 | int gic_irqs, irq_base, i; |
| 934 | int nr_routable_irqs; | ||
| 884 | 935 | ||
| 885 | BUG_ON(gic_nr >= MAX_GIC_NR); | 936 | BUG_ON(gic_nr >= MAX_GIC_NR); |
| 886 | 937 | ||
| @@ -946,14 +997,25 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
| 946 | gic->gic_irqs = gic_irqs; | 997 | gic->gic_irqs = gic_irqs; |
| 947 | 998 | ||
| 948 | gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ | 999 | gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ |
| 949 | irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); | 1000 | |
| 950 | if (IS_ERR_VALUE(irq_base)) { | 1001 | if (of_property_read_u32(node, "arm,routable-irqs", |
| 951 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", | 1002 | &nr_routable_irqs)) { |
| 952 | irq_start); | 1003 | irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, |
| 953 | irq_base = irq_start; | 1004 | numa_node_id()); |
| 1005 | if (IS_ERR_VALUE(irq_base)) { | ||
| 1006 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", | ||
| 1007 | irq_start); | ||
| 1008 | irq_base = irq_start; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, | ||
| 1012 | hwirq_base, &gic_irq_domain_ops, gic); | ||
| 1013 | } else { | ||
| 1014 | gic->domain = irq_domain_add_linear(node, nr_routable_irqs, | ||
| 1015 | &gic_irq_domain_ops, | ||
| 1016 | gic); | ||
| 954 | } | 1017 | } |
| 955 | gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, | 1018 | |
| 956 | hwirq_base, &gic_irq_domain_ops, gic); | ||
| 957 | if (WARN_ON(!gic->domain)) | 1019 | if (WARN_ON(!gic->domain)) |
| 958 | return; | 1020 | return; |
| 959 | 1021 | ||
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 473f09a74d4d..37dab0b472cd 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | 57 | ||
| 58 | /** | 58 | /** |
| 59 | * struct vic_device - VIC PM device | 59 | * struct vic_device - VIC PM device |
| 60 | * @parent_irq: The parent IRQ number of the VIC if cascaded, or 0. | ||
| 60 | * @irq: The IRQ number for the base of the VIC. | 61 | * @irq: The IRQ number for the base of the VIC. |
| 61 | * @base: The register base for the VIC. | 62 | * @base: The register base for the VIC. |
| 62 | * @valid_sources: A bitmask of valid interrupts | 63 | * @valid_sources: A bitmask of valid interrupts |
| @@ -224,6 +225,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | |||
| 224 | return handled; | 225 | return handled; |
| 225 | } | 226 | } |
| 226 | 227 | ||
| 228 | static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc) | ||
| 229 | { | ||
| 230 | u32 stat, hwirq; | ||
| 231 | struct vic_device *vic = irq_desc_get_handler_data(desc); | ||
| 232 | |||
| 233 | while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { | ||
| 234 | hwirq = ffs(stat) - 1; | ||
| 235 | generic_handle_irq(irq_find_mapping(vic->domain, hwirq)); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 227 | /* | 239 | /* |
| 228 | * Keep iterating over all registered VIC's until there are no pending | 240 | * Keep iterating over all registered VIC's until there are no pending |
| 229 | * interrupts. | 241 | * interrupts. |
| @@ -246,6 +258,7 @@ static struct irq_domain_ops vic_irqdomain_ops = { | |||
| 246 | /** | 258 | /** |
| 247 | * vic_register() - Register a VIC. | 259 | * vic_register() - Register a VIC. |
| 248 | * @base: The base address of the VIC. | 260 | * @base: The base address of the VIC. |
| 261 | * @parent_irq: The parent IRQ if cascaded, else 0. | ||
| 249 | * @irq: The base IRQ for the VIC. | 262 | * @irq: The base IRQ for the VIC. |
| 250 | * @valid_sources: bitmask of valid interrupts | 263 | * @valid_sources: bitmask of valid interrupts |
| 251 | * @resume_sources: bitmask of interrupts allowed for resume sources. | 264 | * @resume_sources: bitmask of interrupts allowed for resume sources. |
| @@ -257,7 +270,8 @@ static struct irq_domain_ops vic_irqdomain_ops = { | |||
| 257 | * | 270 | * |
| 258 | * This also configures the IRQ domain for the VIC. | 271 | * This also configures the IRQ domain for the VIC. |
| 259 | */ | 272 | */ |
| 260 | static void __init vic_register(void __iomem *base, unsigned int irq, | 273 | static void __init vic_register(void __iomem *base, unsigned int parent_irq, |
| 274 | unsigned int irq, | ||
| 261 | u32 valid_sources, u32 resume_sources, | 275 | u32 valid_sources, u32 resume_sources, |
| 262 | struct device_node *node) | 276 | struct device_node *node) |
| 263 | { | 277 | { |
| @@ -273,15 +287,25 @@ static void __init vic_register(void __iomem *base, unsigned int irq, | |||
| 273 | v->base = base; | 287 | v->base = base; |
| 274 | v->valid_sources = valid_sources; | 288 | v->valid_sources = valid_sources; |
| 275 | v->resume_sources = resume_sources; | 289 | v->resume_sources = resume_sources; |
| 276 | v->irq = irq; | ||
| 277 | set_handle_irq(vic_handle_irq); | 290 | set_handle_irq(vic_handle_irq); |
| 278 | vic_id++; | 291 | vic_id++; |
| 292 | |||
| 293 | if (parent_irq) { | ||
| 294 | irq_set_handler_data(parent_irq, v); | ||
| 295 | irq_set_chained_handler(parent_irq, vic_handle_irq_cascaded); | ||
| 296 | } | ||
| 297 | |||
| 279 | v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, | 298 | v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, |
| 280 | &vic_irqdomain_ops, v); | 299 | &vic_irqdomain_ops, v); |
| 281 | /* create an IRQ mapping for each valid IRQ */ | 300 | /* create an IRQ mapping for each valid IRQ */ |
| 282 | for (i = 0; i < fls(valid_sources); i++) | 301 | for (i = 0; i < fls(valid_sources); i++) |
| 283 | if (valid_sources & (1 << i)) | 302 | if (valid_sources & (1 << i)) |
| 284 | irq_create_mapping(v->domain, i); | 303 | irq_create_mapping(v->domain, i); |
| 304 | /* If no base IRQ was passed, figure out our allocated base */ | ||
| 305 | if (irq) | ||
| 306 | v->irq = irq; | ||
| 307 | else | ||
| 308 | v->irq = irq_find_mapping(v->domain, 0); | ||
| 285 | } | 309 | } |
| 286 | 310 | ||
| 287 | static void vic_ack_irq(struct irq_data *d) | 311 | static void vic_ack_irq(struct irq_data *d) |
| @@ -409,10 +433,10 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, | |||
| 409 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); | 433 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); |
| 410 | } | 434 | } |
| 411 | 435 | ||
| 412 | vic_register(base, irq_start, vic_sources, 0, node); | 436 | vic_register(base, 0, irq_start, vic_sources, 0, node); |
| 413 | } | 437 | } |
| 414 | 438 | ||
| 415 | void __init __vic_init(void __iomem *base, int irq_start, | 439 | void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, |
| 416 | u32 vic_sources, u32 resume_sources, | 440 | u32 vic_sources, u32 resume_sources, |
| 417 | struct device_node *node) | 441 | struct device_node *node) |
| 418 | { | 442 | { |
| @@ -449,7 +473,7 @@ void __init __vic_init(void __iomem *base, int irq_start, | |||
| 449 | 473 | ||
| 450 | vic_init2(base); | 474 | vic_init2(base); |
| 451 | 475 | ||
| 452 | vic_register(base, irq_start, vic_sources, resume_sources, node); | 476 | vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node); |
| 453 | } | 477 | } |
| 454 | 478 | ||
| 455 | /** | 479 | /** |
| @@ -462,8 +486,30 @@ void __init __vic_init(void __iomem *base, int irq_start, | |||
| 462 | void __init vic_init(void __iomem *base, unsigned int irq_start, | 486 | void __init vic_init(void __iomem *base, unsigned int irq_start, |
| 463 | u32 vic_sources, u32 resume_sources) | 487 | u32 vic_sources, u32 resume_sources) |
| 464 | { | 488 | { |
| 465 | __vic_init(base, irq_start, vic_sources, resume_sources, NULL); | 489 | __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); |
| 490 | } | ||
| 491 | |||
| 492 | /** | ||
| 493 | * vic_init_cascaded() - initialise a cascaded vectored interrupt controller | ||
| 494 | * @base: iomem base address | ||
| 495 | * @parent_irq: the parent IRQ we're cascaded off | ||
| 496 | * @irq_start: starting interrupt number, must be muliple of 32 | ||
| 497 | * @vic_sources: bitmask of interrupt sources to allow | ||
| 498 | * @resume_sources: bitmask of interrupt sources to allow for resume | ||
| 499 | * | ||
| 500 | * This returns the base for the new interrupts or negative on error. | ||
| 501 | */ | ||
| 502 | int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq, | ||
| 503 | u32 vic_sources, u32 resume_sources) | ||
| 504 | { | ||
| 505 | struct vic_device *v; | ||
| 506 | |||
| 507 | v = &vic_devices[vic_id]; | ||
| 508 | __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL); | ||
| 509 | /* Return out acquired base */ | ||
| 510 | return v->irq; | ||
| 466 | } | 511 | } |
| 512 | EXPORT_SYMBOL_GPL(vic_init_cascaded); | ||
| 467 | 513 | ||
| 468 | #ifdef CONFIG_OF | 514 | #ifdef CONFIG_OF |
| 469 | int __init vic_of_init(struct device_node *node, struct device_node *parent) | 515 | int __init vic_of_init(struct device_node *node, struct device_node *parent) |
| @@ -485,7 +531,7 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) | |||
| 485 | /* | 531 | /* |
| 486 | * Passing 0 as first IRQ makes the simple domain allocate descriptors | 532 | * Passing 0 as first IRQ makes the simple domain allocate descriptors |
| 487 | */ | 533 | */ |
| 488 | __vic_init(regs, 0, interrupt_mask, wakeup_mask, node); | 534 | __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node); |
| 489 | 535 | ||
| 490 | return 0; | 536 | return 0; |
| 491 | } | 537 | } |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 72156c123033..44c358ecf5a1 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -421,7 +421,7 @@ config LEDS_MC13783 | |||
| 421 | config LEDS_NS2 | 421 | config LEDS_NS2 |
| 422 | tristate "LED support for Network Space v2 GPIO LEDs" | 422 | tristate "LED support for Network Space v2 GPIO LEDs" |
| 423 | depends on LEDS_CLASS | 423 | depends on LEDS_CLASS |
| 424 | depends on ARCH_KIRKWOOD | 424 | depends on ARCH_KIRKWOOD || MACH_KIRKWOOD |
| 425 | default y | 425 | default y |
| 426 | help | 426 | help |
| 427 | This option enable support for the dual-GPIO LED found on the | 427 | This option enable support for the dual-GPIO LED found on the |
| @@ -431,7 +431,7 @@ config LEDS_NS2 | |||
| 431 | config LEDS_NETXBIG | 431 | config LEDS_NETXBIG |
| 432 | tristate "LED support for Big Network series LEDs" | 432 | tristate "LED support for Big Network series LEDs" |
| 433 | depends on LEDS_CLASS | 433 | depends on LEDS_CLASS |
| 434 | depends on ARCH_KIRKWOOD | 434 | depends on ARCH_KIRKWOOD || MACH_KIRKWOOD |
| 435 | default y | 435 | default y |
| 436 | help | 436 | help |
| 437 | This option enable support for LEDs found on the LaCie 2Big | 437 | This option enable support for LEDs found on the LaCie 2Big |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index a4989ec6292e..8eb6a36f125a 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
| @@ -746,28 +746,6 @@ static int nand_davinci_probe(struct platform_device *pdev) | |||
| 746 | goto err_clk_enable; | 746 | goto err_clk_enable; |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | /* | ||
| 750 | * Setup Async configuration register in case we did not boot from | ||
| 751 | * NAND and so bootloader did not bother to set it up. | ||
| 752 | */ | ||
| 753 | val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4); | ||
| 754 | |||
| 755 | /* Extended Wait is not valid and Select Strobe mode is not used */ | ||
| 756 | val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK); | ||
| 757 | if (info->chip.options & NAND_BUSWIDTH_16) | ||
| 758 | val |= 0x1; | ||
| 759 | |||
| 760 | davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val); | ||
| 761 | |||
| 762 | ret = 0; | ||
| 763 | if (info->timing) | ||
| 764 | ret = davinci_aemif_setup_timing(info->timing, info->base, | ||
| 765 | info->core_chipsel); | ||
| 766 | if (ret < 0) { | ||
| 767 | dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); | ||
| 768 | goto err; | ||
| 769 | } | ||
| 770 | |||
| 771 | spin_lock_irq(&davinci_nand_lock); | 749 | spin_lock_irq(&davinci_nand_lock); |
| 772 | 750 | ||
| 773 | /* put CSxNAND into NAND mode */ | 751 | /* put CSxNAND into NAND mode */ |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 8d3c49cc500f..3bb05f17b9b4 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
| @@ -27,7 +27,7 @@ config PHY_EXYNOS_MIPI_VIDEO | |||
| 27 | 27 | ||
| 28 | config PHY_MVEBU_SATA | 28 | config PHY_MVEBU_SATA |
| 29 | def_bool y | 29 | def_bool y |
| 30 | depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE | 30 | depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD |
| 31 | depends on OF | 31 | depends on OF |
| 32 | select GENERIC_PHY | 32 | select GENERIC_PHY |
| 33 | 33 | ||
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 6d452a78b19c..fa0e4e057b99 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig | |||
| @@ -22,7 +22,7 @@ config POWER_RESET_GPIO | |||
| 22 | 22 | ||
| 23 | config POWER_RESET_MSM | 23 | config POWER_RESET_MSM |
| 24 | bool "Qualcomm MSM power-off driver" | 24 | bool "Qualcomm MSM power-off driver" |
| 25 | depends on POWER_RESET && ARCH_MSM | 25 | depends on POWER_RESET && ARCH_QCOM |
| 26 | help | 26 | help |
| 27 | Power off and restart support for Qualcomm boards. | 27 | Power off and restart support for Qualcomm boards. |
| 28 | 28 | ||
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c index 37f56f7ee926..a75db7f8a92f 100644 --- a/drivers/power/reset/qnap-poweroff.c +++ b/drivers/power/reset/qnap-poweroff.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * QNAP Turbo NAS Board power off | 2 | * QNAP Turbo NAS Board power off. Can also be used on Synology devices. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch> | 4 | * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch> |
| 5 | * | 5 | * |
| @@ -25,17 +25,43 @@ | |||
| 25 | 25 | ||
| 26 | #define UART1_REG(x) (base + ((UART_##x) << 2)) | 26 | #define UART1_REG(x) (base + ((UART_##x) << 2)) |
| 27 | 27 | ||
| 28 | struct power_off_cfg { | ||
| 29 | u32 baud; | ||
| 30 | char cmd; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static const struct power_off_cfg qnap_power_off_cfg = { | ||
| 34 | .baud = 19200, | ||
| 35 | .cmd = 'A', | ||
| 36 | }; | ||
| 37 | |||
| 38 | static const struct power_off_cfg synology_power_off_cfg = { | ||
| 39 | .baud = 9600, | ||
| 40 | .cmd = '1', | ||
| 41 | }; | ||
| 42 | |||
| 43 | static const struct of_device_id qnap_power_off_of_match_table[] = { | ||
| 44 | { .compatible = "qnap,power-off", | ||
| 45 | .data = &qnap_power_off_cfg, | ||
| 46 | }, | ||
| 47 | { .compatible = "synology,power-off", | ||
| 48 | .data = &synology_power_off_cfg, | ||
| 49 | }, | ||
| 50 | {} | ||
| 51 | }; | ||
| 52 | MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table); | ||
| 53 | |||
| 28 | static void __iomem *base; | 54 | static void __iomem *base; |
| 29 | static unsigned long tclk; | 55 | static unsigned long tclk; |
| 56 | static const struct power_off_cfg *cfg; | ||
| 30 | 57 | ||
| 31 | static void qnap_power_off(void) | 58 | static void qnap_power_off(void) |
| 32 | { | 59 | { |
| 33 | /* 19200 baud divisor */ | 60 | const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud)); |
| 34 | const unsigned divisor = ((tclk + (8 * 19200)) / (16 * 19200)); | ||
| 35 | 61 | ||
| 36 | pr_err("%s: triggering power-off...\n", __func__); | 62 | pr_err("%s: triggering power-off...\n", __func__); |
| 37 | 63 | ||
| 38 | /* hijack UART1 and reset into sane state (19200,8n1) */ | 64 | /* hijack UART1 and reset into sane state */ |
| 39 | writel(0x83, UART1_REG(LCR)); | 65 | writel(0x83, UART1_REG(LCR)); |
| 40 | writel(divisor & 0xff, UART1_REG(DLL)); | 66 | writel(divisor & 0xff, UART1_REG(DLL)); |
| 41 | writel((divisor >> 8) & 0xff, UART1_REG(DLM)); | 67 | writel((divisor >> 8) & 0xff, UART1_REG(DLM)); |
| @@ -44,16 +70,21 @@ static void qnap_power_off(void) | |||
| 44 | writel(0x00, UART1_REG(FCR)); | 70 | writel(0x00, UART1_REG(FCR)); |
| 45 | writel(0x00, UART1_REG(MCR)); | 71 | writel(0x00, UART1_REG(MCR)); |
| 46 | 72 | ||
| 47 | /* send the power-off command 'A' to PIC */ | 73 | /* send the power-off command to PIC */ |
| 48 | writel('A', UART1_REG(TX)); | 74 | writel(cfg->cmd, UART1_REG(TX)); |
| 49 | } | 75 | } |
| 50 | 76 | ||
| 51 | static int qnap_power_off_probe(struct platform_device *pdev) | 77 | static int qnap_power_off_probe(struct platform_device *pdev) |
| 52 | { | 78 | { |
| 79 | struct device_node *np = pdev->dev.of_node; | ||
| 53 | struct resource *res; | 80 | struct resource *res; |
| 54 | struct clk *clk; | 81 | struct clk *clk; |
| 55 | char symname[KSYM_NAME_LEN]; | 82 | char symname[KSYM_NAME_LEN]; |
| 56 | 83 | ||
| 84 | const struct of_device_id *match = | ||
| 85 | of_match_node(qnap_power_off_of_match_table, np); | ||
| 86 | cfg = match->data; | ||
| 87 | |||
| 57 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 88 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 58 | if (!res) { | 89 | if (!res) { |
| 59 | dev_err(&pdev->dev, "Missing resource"); | 90 | dev_err(&pdev->dev, "Missing resource"); |
| @@ -94,12 +125,6 @@ static int qnap_power_off_remove(struct platform_device *pdev) | |||
| 94 | return 0; | 125 | return 0; |
| 95 | } | 126 | } |
| 96 | 127 | ||
| 97 | static const struct of_device_id qnap_power_off_of_match_table[] = { | ||
| 98 | { .compatible = "qnap,power-off", }, | ||
| 99 | {} | ||
| 100 | }; | ||
| 101 | MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table); | ||
| 102 | |||
| 103 | static struct platform_driver qnap_power_off_driver = { | 128 | static struct platform_driver qnap_power_off_driver = { |
| 104 | .probe = qnap_power_off_probe, | 129 | .probe = qnap_power_off_probe, |
| 105 | .remove = qnap_power_off_remove, | 130 | .remove = qnap_power_off_remove, |
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c9d04f797862..0615f50a14cd 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig | |||
| @@ -11,3 +11,5 @@ menuconfig RESET_CONTROLLER | |||
| 11 | via GPIOs or SoC-internal reset controller modules. | 11 | via GPIOs or SoC-internal reset controller modules. |
| 12 | 12 | ||
| 13 | If unsure, say no. | 13 | If unsure, say no. |
| 14 | |||
| 15 | source "drivers/reset/sti/Kconfig" | ||
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index cc29832c9638..4f60caf750ce 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile | |||
| @@ -1,2 +1,3 @@ | |||
| 1 | obj-$(CONFIG_RESET_CONTROLLER) += core.o | 1 | obj-$(CONFIG_RESET_CONTROLLER) += core.o |
| 2 | obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o | 2 | obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o |
| 3 | obj-$(CONFIG_ARCH_STI) += sti/ | ||
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index d1b6089a0ef8..baeaf82d40d9 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c | |||
| @@ -43,7 +43,7 @@ struct reset_control { | |||
| 43 | * This simple translation function should be used for reset controllers | 43 | * This simple translation function should be used for reset controllers |
| 44 | * with 1:1 mapping, where reset lines can be indexed by number without gaps. | 44 | * with 1:1 mapping, where reset lines can be indexed by number without gaps. |
| 45 | */ | 45 | */ |
| 46 | int of_reset_simple_xlate(struct reset_controller_dev *rcdev, | 46 | static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, |
| 47 | const struct of_phandle_args *reset_spec) | 47 | const struct of_phandle_args *reset_spec) |
| 48 | { | 48 | { |
| 49 | if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) | 49 | if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) |
| @@ -54,7 +54,6 @@ int of_reset_simple_xlate(struct reset_controller_dev *rcdev, | |||
| 54 | 54 | ||
| 55 | return reset_spec->args[0]; | 55 | return reset_spec->args[0]; |
| 56 | } | 56 | } |
| 57 | EXPORT_SYMBOL_GPL(of_reset_simple_xlate); | ||
| 58 | 57 | ||
| 59 | /** | 58 | /** |
| 60 | * reset_controller_register - register a reset controller device | 59 | * reset_controller_register - register a reset controller device |
| @@ -127,15 +126,16 @@ int reset_control_deassert(struct reset_control *rstc) | |||
| 127 | EXPORT_SYMBOL_GPL(reset_control_deassert); | 126 | EXPORT_SYMBOL_GPL(reset_control_deassert); |
| 128 | 127 | ||
| 129 | /** | 128 | /** |
| 130 | * reset_control_get - Lookup and obtain a reference to a reset controller. | 129 | * of_reset_control_get - Lookup and obtain a reference to a reset controller. |
| 131 | * @dev: device to be reset by the controller | 130 | * @node: device to be reset by the controller |
| 132 | * @id: reset line name | 131 | * @id: reset line name |
| 133 | * | 132 | * |
| 134 | * Returns a struct reset_control or IS_ERR() condition containing errno. | 133 | * Returns a struct reset_control or IS_ERR() condition containing errno. |
| 135 | * | 134 | * |
| 136 | * Use of id names is optional. | 135 | * Use of id names is optional. |
| 137 | */ | 136 | */ |
| 138 | struct reset_control *reset_control_get(struct device *dev, const char *id) | 137 | struct reset_control *of_reset_control_get(struct device_node *node, |
| 138 | const char *id) | ||
| 139 | { | 139 | { |
| 140 | struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER); | 140 | struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER); |
| 141 | struct reset_controller_dev *r, *rcdev; | 141 | struct reset_controller_dev *r, *rcdev; |
| @@ -144,13 +144,10 @@ struct reset_control *reset_control_get(struct device *dev, const char *id) | |||
| 144 | int rstc_id; | 144 | int rstc_id; |
| 145 | int ret; | 145 | int ret; |
| 146 | 146 | ||
| 147 | if (!dev) | ||
| 148 | return ERR_PTR(-EINVAL); | ||
| 149 | |||
| 150 | if (id) | 147 | if (id) |
| 151 | index = of_property_match_string(dev->of_node, | 148 | index = of_property_match_string(node, |
| 152 | "reset-names", id); | 149 | "reset-names", id); |
| 153 | ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells", | 150 | ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", |
| 154 | index, &args); | 151 | index, &args); |
| 155 | if (ret) | 152 | if (ret) |
| 156 | return ERR_PTR(ret); | 153 | return ERR_PTR(ret); |
| @@ -167,7 +164,7 @@ struct reset_control *reset_control_get(struct device *dev, const char *id) | |||
| 167 | 164 | ||
| 168 | if (!rcdev) { | 165 | if (!rcdev) { |
| 169 | mutex_unlock(&reset_controller_list_mutex); | 166 | mutex_unlock(&reset_controller_list_mutex); |
| 170 | return ERR_PTR(-ENODEV); | 167 | return ERR_PTR(-EPROBE_DEFER); |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 173 | rstc_id = rcdev->of_xlate(rcdev, &args); | 170 | rstc_id = rcdev->of_xlate(rcdev, &args); |
| @@ -185,12 +182,35 @@ struct reset_control *reset_control_get(struct device *dev, const char *id) | |||
| 185 | return ERR_PTR(-ENOMEM); | 182 | return ERR_PTR(-ENOMEM); |
| 186 | } | 183 | } |
| 187 | 184 | ||
| 188 | rstc->dev = dev; | ||
| 189 | rstc->rcdev = rcdev; | 185 | rstc->rcdev = rcdev; |
| 190 | rstc->id = rstc_id; | 186 | rstc->id = rstc_id; |
| 191 | 187 | ||
| 192 | return rstc; | 188 | return rstc; |
| 193 | } | 189 | } |
| 190 | EXPORT_SYMBOL_GPL(of_reset_control_get); | ||
| 191 | |||
| 192 | /** | ||
| 193 | * reset_control_get - Lookup and obtain a reference to a reset controller. | ||
| 194 | * @dev: device to be reset by the controller | ||
| 195 | * @id: reset line name | ||
| 196 | * | ||
| 197 | * Returns a struct reset_control or IS_ERR() condition containing errno. | ||
| 198 | * | ||
| 199 | * Use of id names is optional. | ||
| 200 | */ | ||
| 201 | struct reset_control *reset_control_get(struct device *dev, const char *id) | ||
| 202 | { | ||
| 203 | struct reset_control *rstc; | ||
| 204 | |||
| 205 | if (!dev) | ||
| 206 | return ERR_PTR(-EINVAL); | ||
| 207 | |||
| 208 | rstc = of_reset_control_get(dev->of_node, id); | ||
| 209 | if (!IS_ERR(rstc)) | ||
| 210 | rstc->dev = dev; | ||
| 211 | |||
| 212 | return rstc; | ||
| 213 | } | ||
| 194 | EXPORT_SYMBOL_GPL(reset_control_get); | 214 | EXPORT_SYMBOL_GPL(reset_control_get); |
| 195 | 215 | ||
| 196 | /** | 216 | /** |
| @@ -243,33 +263,6 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id) | |||
| 243 | } | 263 | } |
| 244 | EXPORT_SYMBOL_GPL(devm_reset_control_get); | 264 | EXPORT_SYMBOL_GPL(devm_reset_control_get); |
| 245 | 265 | ||
| 246 | static int devm_reset_control_match(struct device *dev, void *res, void *data) | ||
| 247 | { | ||
| 248 | struct reset_control **rstc = res; | ||
| 249 | if (WARN_ON(!rstc || !*rstc)) | ||
| 250 | return 0; | ||
| 251 | return *rstc == data; | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * devm_reset_control_put - resource managed reset_control_put() | ||
| 256 | * @rstc: reset controller to free | ||
| 257 | * | ||
| 258 | * Deallocate a reset control allocated withd devm_reset_control_get(). | ||
| 259 | * This function will not need to be called normally, as devres will take | ||
| 260 | * care of freeing the resource. | ||
| 261 | */ | ||
| 262 | void devm_reset_control_put(struct reset_control *rstc) | ||
| 263 | { | ||
| 264 | int ret; | ||
| 265 | |||
| 266 | ret = devres_release(rstc->dev, devm_reset_control_release, | ||
| 267 | devm_reset_control_match, rstc); | ||
| 268 | if (ret) | ||
| 269 | WARN_ON(ret); | ||
| 270 | } | ||
| 271 | EXPORT_SYMBOL_GPL(devm_reset_control_put); | ||
| 272 | |||
| 273 | /** | 266 | /** |
| 274 | * device_reset - find reset controller associated with the device | 267 | * device_reset - find reset controller associated with the device |
| 275 | * and perform reset | 268 | * and perform reset |
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig new file mode 100644 index 000000000000..88d2d0316613 --- /dev/null +++ b/drivers/reset/sti/Kconfig | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | if ARCH_STI | ||
| 2 | |||
| 3 | config STI_RESET_SYSCFG | ||
| 4 | bool | ||
| 5 | select RESET_CONTROLLER | ||
| 6 | |||
| 7 | config STIH415_RESET | ||
| 8 | bool | ||
| 9 | select STI_RESET_SYSCFG | ||
| 10 | |||
| 11 | config STIH416_RESET | ||
| 12 | bool | ||
| 13 | select STI_RESET_SYSCFG | ||
| 14 | |||
| 15 | endif | ||
diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile new file mode 100644 index 000000000000..be1c97647871 --- /dev/null +++ b/drivers/reset/sti/Makefile | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o | ||
| 2 | |||
| 3 | obj-$(CONFIG_STIH415_RESET) += reset-stih415.o | ||
| 4 | obj-$(CONFIG_STIH416_RESET) += reset-stih416.o | ||
diff --git a/drivers/reset/sti/reset-stih415.c b/drivers/reset/sti/reset-stih415.c new file mode 100644 index 000000000000..e6f6c41abe12 --- /dev/null +++ b/drivers/reset/sti/reset-stih415.c | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 STMicroelectronics (R&D) Limited | ||
| 3 | * Author: Stephen Gallimore <stephen.gallimore@st.com> | ||
| 4 | * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com> | ||
| 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 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_platform.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | #include <dt-bindings/reset-controller/stih415-resets.h> | ||
| 17 | |||
| 18 | #include "reset-syscfg.h" | ||
| 19 | |||
| 20 | /* | ||
| 21 | * STiH415 Peripheral powerdown definitions. | ||
| 22 | */ | ||
| 23 | static const char stih415_front[] = "st,stih415-front-syscfg"; | ||
| 24 | static const char stih415_rear[] = "st,stih415-rear-syscfg"; | ||
| 25 | static const char stih415_sbc[] = "st,stih415-sbc-syscfg"; | ||
| 26 | static const char stih415_lpm[] = "st,stih415-lpm-syscfg"; | ||
| 27 | |||
| 28 | #define STIH415_PDN_FRONT(_bit) \ | ||
| 29 | _SYSCFG_RST_CH(stih415_front, SYSCFG_114, _bit, SYSSTAT_187, _bit) | ||
| 30 | |||
| 31 | #define STIH415_PDN_REAR(_cntl, _stat) \ | ||
| 32 | _SYSCFG_RST_CH(stih415_rear, SYSCFG_336, _cntl, SYSSTAT_384, _stat) | ||
| 33 | |||
| 34 | #define STIH415_SRST_REAR(_reg, _bit) \ | ||
| 35 | _SYSCFG_RST_CH_NO_ACK(stih415_rear, _reg, _bit) | ||
| 36 | |||
| 37 | #define STIH415_SRST_SBC(_reg, _bit) \ | ||
| 38 | _SYSCFG_RST_CH_NO_ACK(stih415_sbc, _reg, _bit) | ||
| 39 | |||
| 40 | #define STIH415_SRST_FRONT(_reg, _bit) \ | ||
| 41 | _SYSCFG_RST_CH_NO_ACK(stih415_front, _reg, _bit) | ||
| 42 | |||
| 43 | #define STIH415_SRST_LPM(_reg, _bit) \ | ||
| 44 | _SYSCFG_RST_CH_NO_ACK(stih415_lpm, _reg, _bit) | ||
| 45 | |||
| 46 | #define SYSCFG_114 0x38 /* Powerdown request EMI/NAND/Keyscan */ | ||
| 47 | #define SYSSTAT_187 0x15c /* Powerdown status EMI/NAND/Keyscan */ | ||
| 48 | |||
| 49 | #define SYSCFG_336 0x90 /* Powerdown request USB/SATA/PCIe */ | ||
| 50 | #define SYSSTAT_384 0x150 /* Powerdown status USB/SATA/PCIe */ | ||
| 51 | |||
| 52 | #define SYSCFG_376 0x130 /* Reset generator 0 control 0 */ | ||
| 53 | #define SYSCFG_166 0x108 /* Softreset Ethernet 0 */ | ||
| 54 | #define SYSCFG_31 0x7c /* Softreset Ethernet 1 */ | ||
| 55 | #define LPM_SYSCFG_1 0x4 /* Softreset IRB */ | ||
| 56 | |||
| 57 | static const struct syscfg_reset_channel_data stih415_powerdowns[] = { | ||
| 58 | [STIH415_EMISS_POWERDOWN] = STIH415_PDN_FRONT(0), | ||
| 59 | [STIH415_NAND_POWERDOWN] = STIH415_PDN_FRONT(1), | ||
| 60 | [STIH415_KEYSCAN_POWERDOWN] = STIH415_PDN_FRONT(2), | ||
| 61 | [STIH415_USB0_POWERDOWN] = STIH415_PDN_REAR(0, 0), | ||
| 62 | [STIH415_USB1_POWERDOWN] = STIH415_PDN_REAR(1, 1), | ||
| 63 | [STIH415_USB2_POWERDOWN] = STIH415_PDN_REAR(2, 2), | ||
| 64 | [STIH415_SATA0_POWERDOWN] = STIH415_PDN_REAR(3, 3), | ||
| 65 | [STIH415_SATA1_POWERDOWN] = STIH415_PDN_REAR(4, 4), | ||
| 66 | [STIH415_PCIE_POWERDOWN] = STIH415_PDN_REAR(5, 8), | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const struct syscfg_reset_channel_data stih415_softresets[] = { | ||
| 70 | [STIH415_ETH0_SOFTRESET] = STIH415_SRST_FRONT(SYSCFG_166, 0), | ||
| 71 | [STIH415_ETH1_SOFTRESET] = STIH415_SRST_SBC(SYSCFG_31, 0), | ||
| 72 | [STIH415_IRB_SOFTRESET] = STIH415_SRST_LPM(LPM_SYSCFG_1, 6), | ||
| 73 | [STIH415_USB0_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 9), | ||
| 74 | [STIH415_USB1_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 10), | ||
| 75 | [STIH415_USB2_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 11), | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct syscfg_reset_controller_data stih415_powerdown_controller = { | ||
| 79 | .wait_for_ack = true, | ||
| 80 | .nr_channels = ARRAY_SIZE(stih415_powerdowns), | ||
| 81 | .channels = stih415_powerdowns, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static struct syscfg_reset_controller_data stih415_softreset_controller = { | ||
| 85 | .wait_for_ack = false, | ||
| 86 | .active_low = true, | ||
| 87 | .nr_channels = ARRAY_SIZE(stih415_softresets), | ||
| 88 | .channels = stih415_softresets, | ||
| 89 | }; | ||
| 90 | |||
| 91 | static struct of_device_id stih415_reset_match[] = { | ||
| 92 | { .compatible = "st,stih415-powerdown", | ||
| 93 | .data = &stih415_powerdown_controller, }, | ||
| 94 | { .compatible = "st,stih415-softreset", | ||
| 95 | .data = &stih415_softreset_controller, }, | ||
| 96 | {}, | ||
| 97 | }; | ||
| 98 | |||
| 99 | static struct platform_driver stih415_reset_driver = { | ||
| 100 | .probe = syscfg_reset_probe, | ||
| 101 | .driver = { | ||
| 102 | .name = "reset-stih415", | ||
| 103 | .owner = THIS_MODULE, | ||
| 104 | .of_match_table = stih415_reset_match, | ||
| 105 | }, | ||
| 106 | }; | ||
| 107 | |||
| 108 | static int __init stih415_reset_init(void) | ||
| 109 | { | ||
| 110 | return platform_driver_register(&stih415_reset_driver); | ||
| 111 | } | ||
| 112 | arch_initcall(stih415_reset_init); | ||
diff --git a/drivers/reset/sti/reset-stih416.c b/drivers/reset/sti/reset-stih416.c new file mode 100644 index 000000000000..fe3bf02bdc8c --- /dev/null +++ b/drivers/reset/sti/reset-stih416.c | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 STMicroelectronics (R&D) Limited | ||
| 3 | * Author: Stephen Gallimore <stephen.gallimore@st.com> | ||
| 4 | * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com> | ||
| 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 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_platform.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | #include <dt-bindings/reset-controller/stih416-resets.h> | ||
| 17 | |||
| 18 | #include "reset-syscfg.h" | ||
| 19 | |||
| 20 | /* | ||
| 21 | * STiH416 Peripheral powerdown definitions. | ||
| 22 | */ | ||
| 23 | static const char stih416_front[] = "st,stih416-front-syscfg"; | ||
| 24 | static const char stih416_rear[] = "st,stih416-rear-syscfg"; | ||
| 25 | static const char stih416_sbc[] = "st,stih416-sbc-syscfg"; | ||
| 26 | static const char stih416_lpm[] = "st,stih416-lpm-syscfg"; | ||
| 27 | static const char stih416_cpu[] = "st,stih416-cpu-syscfg"; | ||
| 28 | |||
| 29 | #define STIH416_PDN_FRONT(_bit) \ | ||
| 30 | _SYSCFG_RST_CH(stih416_front, SYSCFG_1500, _bit, SYSSTAT_1578, _bit) | ||
| 31 | |||
| 32 | #define STIH416_PDN_REAR(_cntl, _stat) \ | ||
| 33 | _SYSCFG_RST_CH(stih416_rear, SYSCFG_2525, _cntl, SYSSTAT_2583, _stat) | ||
| 34 | |||
| 35 | #define SYSCFG_1500 0x7d0 /* Powerdown request EMI/NAND/Keyscan */ | ||
| 36 | #define SYSSTAT_1578 0x908 /* Powerdown status EMI/NAND/Keyscan */ | ||
| 37 | |||
| 38 | #define SYSCFG_2525 0x834 /* Powerdown request USB/SATA/PCIe */ | ||
| 39 | #define SYSSTAT_2583 0x91c /* Powerdown status USB/SATA/PCIe */ | ||
| 40 | |||
| 41 | #define SYSCFG_2552 0x8A0 /* Reset Generator control 0 */ | ||
| 42 | #define SYSCFG_1539 0x86c /* Softreset Ethernet 0 */ | ||
| 43 | #define SYSCFG_510 0x7f8 /* Softreset Ethernet 1 */ | ||
| 44 | #define LPM_SYSCFG_1 0x4 /* Softreset IRB */ | ||
| 45 | #define SYSCFG_2553 0x8a4 /* Softreset SATA0/1, PCIE0/1 */ | ||
| 46 | #define SYSCFG_7563 0x8cc /* MPE softresets 0 */ | ||
| 47 | #define SYSCFG_7564 0x8d0 /* MPE softresets 1 */ | ||
| 48 | |||
| 49 | #define STIH416_SRST_CPU(_reg, _bit) \ | ||
| 50 | _SYSCFG_RST_CH_NO_ACK(stih416_cpu, _reg, _bit) | ||
| 51 | |||
| 52 | #define STIH416_SRST_FRONT(_reg, _bit) \ | ||
| 53 | _SYSCFG_RST_CH_NO_ACK(stih416_front, _reg, _bit) | ||
| 54 | |||
| 55 | #define STIH416_SRST_REAR(_reg, _bit) \ | ||
| 56 | _SYSCFG_RST_CH_NO_ACK(stih416_rear, _reg, _bit) | ||
| 57 | |||
| 58 | #define STIH416_SRST_LPM(_reg, _bit) \ | ||
| 59 | _SYSCFG_RST_CH_NO_ACK(stih416_lpm, _reg, _bit) | ||
| 60 | |||
| 61 | #define STIH416_SRST_SBC(_reg, _bit) \ | ||
| 62 | _SYSCFG_RST_CH_NO_ACK(stih416_sbc, _reg, _bit) | ||
| 63 | |||
| 64 | static const struct syscfg_reset_channel_data stih416_powerdowns[] = { | ||
| 65 | [STIH416_EMISS_POWERDOWN] = STIH416_PDN_FRONT(0), | ||
| 66 | [STIH416_NAND_POWERDOWN] = STIH416_PDN_FRONT(1), | ||
| 67 | [STIH416_KEYSCAN_POWERDOWN] = STIH416_PDN_FRONT(2), | ||
| 68 | [STIH416_USB0_POWERDOWN] = STIH416_PDN_REAR(0, 0), | ||
| 69 | [STIH416_USB1_POWERDOWN] = STIH416_PDN_REAR(1, 1), | ||
| 70 | [STIH416_USB2_POWERDOWN] = STIH416_PDN_REAR(2, 2), | ||
| 71 | [STIH416_USB3_POWERDOWN] = STIH416_PDN_REAR(6, 5), | ||
| 72 | [STIH416_SATA0_POWERDOWN] = STIH416_PDN_REAR(3, 3), | ||
| 73 | [STIH416_SATA1_POWERDOWN] = STIH416_PDN_REAR(4, 4), | ||
| 74 | [STIH416_PCIE0_POWERDOWN] = STIH416_PDN_REAR(7, 9), | ||
| 75 | [STIH416_PCIE1_POWERDOWN] = STIH416_PDN_REAR(5, 8), | ||
| 76 | }; | ||
| 77 | |||
| 78 | static const struct syscfg_reset_channel_data stih416_softresets[] = { | ||
| 79 | [STIH416_ETH0_SOFTRESET] = STIH416_SRST_FRONT(SYSCFG_1539, 0), | ||
| 80 | [STIH416_ETH1_SOFTRESET] = STIH416_SRST_SBC(SYSCFG_510, 0), | ||
| 81 | [STIH416_IRB_SOFTRESET] = STIH416_SRST_LPM(LPM_SYSCFG_1, 6), | ||
| 82 | [STIH416_USB0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 9), | ||
| 83 | [STIH416_USB1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 10), | ||
| 84 | [STIH416_USB2_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 11), | ||
| 85 | [STIH416_USB3_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 28), | ||
| 86 | [STIH416_SATA0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 7), | ||
| 87 | [STIH416_SATA1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 3), | ||
| 88 | [STIH416_PCIE0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 15), | ||
| 89 | [STIH416_PCIE1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 2), | ||
| 90 | [STIH416_AUD_DAC_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 14), | ||
| 91 | [STIH416_HDTVOUT_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 5), | ||
| 92 | [STIH416_VTAC_M_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 25), | ||
| 93 | [STIH416_VTAC_A_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 26), | ||
| 94 | [STIH416_SYNC_HD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 5), | ||
| 95 | [STIH416_SYNC_SD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 6), | ||
| 96 | [STIH416_BLITTER_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 10), | ||
| 97 | [STIH416_GPU_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 11), | ||
| 98 | [STIH416_VTAC_M_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 18), | ||
| 99 | [STIH416_VTAC_A_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 19), | ||
| 100 | [STIH416_VTG_AUX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 21), | ||
| 101 | [STIH416_JPEG_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 23), | ||
| 102 | [STIH416_HVA_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 2), | ||
| 103 | [STIH416_COMPO_M_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 3), | ||
| 104 | [STIH416_COMPO_A_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 4), | ||
| 105 | [STIH416_VP8_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 10), | ||
| 106 | [STIH416_VTG_MAIN_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 16), | ||
| 107 | }; | ||
| 108 | |||
| 109 | static struct syscfg_reset_controller_data stih416_powerdown_controller = { | ||
| 110 | .wait_for_ack = true, | ||
| 111 | .nr_channels = ARRAY_SIZE(stih416_powerdowns), | ||
| 112 | .channels = stih416_powerdowns, | ||
| 113 | }; | ||
| 114 | |||
| 115 | static struct syscfg_reset_controller_data stih416_softreset_controller = { | ||
| 116 | .wait_for_ack = false, | ||
| 117 | .active_low = true, | ||
| 118 | .nr_channels = ARRAY_SIZE(stih416_softresets), | ||
| 119 | .channels = stih416_softresets, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static struct of_device_id stih416_reset_match[] = { | ||
| 123 | { .compatible = "st,stih416-powerdown", | ||
| 124 | .data = &stih416_powerdown_controller, }, | ||
| 125 | { .compatible = "st,stih416-softreset", | ||
| 126 | .data = &stih416_softreset_controller, }, | ||
| 127 | {}, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static struct platform_driver stih416_reset_driver = { | ||
| 131 | .probe = syscfg_reset_probe, | ||
| 132 | .driver = { | ||
| 133 | .name = "reset-stih416", | ||
| 134 | .owner = THIS_MODULE, | ||
| 135 | .of_match_table = stih416_reset_match, | ||
| 136 | }, | ||
| 137 | }; | ||
| 138 | |||
| 139 | static int __init stih416_reset_init(void) | ||
| 140 | { | ||
| 141 | return platform_driver_register(&stih416_reset_driver); | ||
| 142 | } | ||
| 143 | arch_initcall(stih416_reset_init); | ||
diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c new file mode 100644 index 000000000000..a145cc066d4a --- /dev/null +++ b/drivers/reset/sti/reset-syscfg.c | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 STMicroelectronics Limited | ||
| 3 | * Author: Stephen Gallimore <stephen.gallimore@st.com> | ||
| 4 | * | ||
| 5 | * Inspired by mach-imx/src.c | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 18 | #include <linux/regmap.h> | ||
| 19 | #include <linux/mfd/syscon.h> | ||
| 20 | |||
| 21 | #include "reset-syscfg.h" | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Reset channel regmap configuration | ||
| 25 | * | ||
| 26 | * @reset: regmap field for the channel's reset bit. | ||
| 27 | * @ack: regmap field for the channel's ack bit (optional). | ||
| 28 | */ | ||
| 29 | struct syscfg_reset_channel { | ||
| 30 | struct regmap_field *reset; | ||
| 31 | struct regmap_field *ack; | ||
| 32 | }; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * A reset controller which groups together a set of related reset bits, which | ||
| 36 | * may be located in different system configuration registers. | ||
| 37 | * | ||
| 38 | * @rst: base reset controller structure. | ||
| 39 | * @active_low: are the resets in this controller active low, i.e. clearing | ||
| 40 | * the reset bit puts the hardware into reset. | ||
| 41 | * @channels: An array of reset channels for this controller. | ||
| 42 | */ | ||
| 43 | struct syscfg_reset_controller { | ||
| 44 | struct reset_controller_dev rst; | ||
| 45 | bool active_low; | ||
| 46 | struct syscfg_reset_channel *channels; | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define to_syscfg_reset_controller(_rst) \ | ||
| 50 | container_of(_rst, struct syscfg_reset_controller, rst) | ||
| 51 | |||
| 52 | static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev, | ||
| 53 | unsigned long idx, int assert) | ||
| 54 | { | ||
| 55 | struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); | ||
| 56 | const struct syscfg_reset_channel *ch; | ||
| 57 | u32 ctrl_val = rst->active_low ? !assert : !!assert; | ||
| 58 | int err; | ||
| 59 | |||
| 60 | if (idx >= rcdev->nr_resets) | ||
| 61 | return -EINVAL; | ||
| 62 | |||
| 63 | ch = &rst->channels[idx]; | ||
| 64 | |||
| 65 | err = regmap_field_write(ch->reset, ctrl_val); | ||
| 66 | if (err) | ||
| 67 | return err; | ||
| 68 | |||
| 69 | if (ch->ack) { | ||
| 70 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
| 71 | u32 ack_val; | ||
| 72 | |||
| 73 | while (true) { | ||
| 74 | err = regmap_field_read(ch->ack, &ack_val); | ||
| 75 | if (err) | ||
| 76 | return err; | ||
| 77 | |||
| 78 | if (ack_val == ctrl_val) | ||
| 79 | break; | ||
| 80 | |||
| 81 | if (time_after(jiffies, timeout)) | ||
| 82 | return -ETIME; | ||
| 83 | |||
| 84 | cpu_relax(); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int syscfg_reset_assert(struct reset_controller_dev *rcdev, | ||
| 92 | unsigned long idx) | ||
| 93 | { | ||
| 94 | return syscfg_reset_program_hw(rcdev, idx, true); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int syscfg_reset_deassert(struct reset_controller_dev *rcdev, | ||
| 98 | unsigned long idx) | ||
| 99 | { | ||
| 100 | return syscfg_reset_program_hw(rcdev, idx, false); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int syscfg_reset_dev(struct reset_controller_dev *rcdev, | ||
| 104 | unsigned long idx) | ||
| 105 | { | ||
| 106 | int err = syscfg_reset_assert(rcdev, idx); | ||
| 107 | if (err) | ||
| 108 | return err; | ||
| 109 | |||
| 110 | return syscfg_reset_deassert(rcdev, idx); | ||
| 111 | } | ||
| 112 | |||
| 113 | static struct reset_control_ops syscfg_reset_ops = { | ||
| 114 | .reset = syscfg_reset_dev, | ||
| 115 | .assert = syscfg_reset_assert, | ||
| 116 | .deassert = syscfg_reset_deassert, | ||
| 117 | }; | ||
| 118 | |||
| 119 | static int syscfg_reset_controller_register(struct device *dev, | ||
| 120 | const struct syscfg_reset_controller_data *data) | ||
| 121 | { | ||
| 122 | struct syscfg_reset_controller *rc; | ||
| 123 | size_t size; | ||
| 124 | int i, err; | ||
| 125 | |||
| 126 | rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL); | ||
| 127 | if (!rc) | ||
| 128 | return -ENOMEM; | ||
| 129 | |||
| 130 | size = sizeof(struct syscfg_reset_channel) * data->nr_channels; | ||
| 131 | |||
| 132 | rc->channels = devm_kzalloc(dev, size, GFP_KERNEL); | ||
| 133 | if (!rc->channels) | ||
| 134 | return -ENOMEM; | ||
| 135 | |||
| 136 | rc->rst.ops = &syscfg_reset_ops, | ||
| 137 | rc->rst.of_node = dev->of_node; | ||
| 138 | rc->rst.nr_resets = data->nr_channels; | ||
| 139 | rc->active_low = data->active_low; | ||
| 140 | |||
| 141 | for (i = 0; i < data->nr_channels; i++) { | ||
| 142 | struct regmap *map; | ||
| 143 | struct regmap_field *f; | ||
| 144 | const char *compatible = data->channels[i].compatible; | ||
| 145 | |||
| 146 | map = syscon_regmap_lookup_by_compatible(compatible); | ||
| 147 | if (IS_ERR(map)) | ||
| 148 | return PTR_ERR(map); | ||
| 149 | |||
| 150 | f = devm_regmap_field_alloc(dev, map, data->channels[i].reset); | ||
| 151 | if (IS_ERR(f)) | ||
| 152 | return PTR_ERR(f); | ||
| 153 | |||
| 154 | rc->channels[i].reset = f; | ||
| 155 | |||
| 156 | if (!data->wait_for_ack) | ||
| 157 | continue; | ||
| 158 | |||
| 159 | f = devm_regmap_field_alloc(dev, map, data->channels[i].ack); | ||
| 160 | if (IS_ERR(f)) | ||
| 161 | return PTR_ERR(f); | ||
| 162 | |||
| 163 | rc->channels[i].ack = f; | ||
| 164 | } | ||
| 165 | |||
| 166 | err = reset_controller_register(&rc->rst); | ||
| 167 | if (!err) | ||
| 168 | dev_info(dev, "registered\n"); | ||
| 169 | |||
| 170 | return err; | ||
| 171 | } | ||
| 172 | |||
| 173 | int syscfg_reset_probe(struct platform_device *pdev) | ||
| 174 | { | ||
| 175 | struct device *dev = pdev ? &pdev->dev : NULL; | ||
| 176 | const struct of_device_id *match; | ||
| 177 | |||
| 178 | if (!dev || !dev->driver) | ||
| 179 | return -ENODEV; | ||
| 180 | |||
| 181 | match = of_match_device(dev->driver->of_match_table, dev); | ||
| 182 | if (!match || !match->data) | ||
| 183 | return -EINVAL; | ||
| 184 | |||
| 185 | return syscfg_reset_controller_register(dev, match->data); | ||
| 186 | } | ||
diff --git a/drivers/reset/sti/reset-syscfg.h b/drivers/reset/sti/reset-syscfg.h new file mode 100644 index 000000000000..2cc2283bac40 --- /dev/null +++ b/drivers/reset/sti/reset-syscfg.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 STMicroelectronics (R&D) Limited | ||
| 3 | * Author: Stephen Gallimore <stephen.gallimore@st.com> | ||
| 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; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | */ | ||
| 10 | #ifndef __STI_RESET_SYSCFG_H | ||
| 11 | #define __STI_RESET_SYSCFG_H | ||
| 12 | |||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/regmap.h> | ||
| 15 | #include <linux/reset-controller.h> | ||
| 16 | |||
| 17 | /** | ||
| 18 | * Reset channel description for a system configuration register based | ||
| 19 | * reset controller. | ||
| 20 | * | ||
| 21 | * @compatible: Compatible string of the syscon regmap containing this | ||
| 22 | * channel's control and ack (status) bits. | ||
| 23 | * @reset: Regmap field description of the channel's reset bit. | ||
| 24 | * @ack: Regmap field description of the channel's acknowledge bit. | ||
| 25 | */ | ||
| 26 | struct syscfg_reset_channel_data { | ||
| 27 | const char *compatible; | ||
| 28 | struct reg_field reset; | ||
| 29 | struct reg_field ack; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #define _SYSCFG_RST_CH(_c, _rr, _rb, _ar, _ab) \ | ||
| 33 | { .compatible = _c, \ | ||
| 34 | .reset = REG_FIELD(_rr, _rb, _rb), \ | ||
| 35 | .ack = REG_FIELD(_ar, _ab, _ab), } | ||
| 36 | |||
| 37 | #define _SYSCFG_RST_CH_NO_ACK(_c, _rr, _rb) \ | ||
| 38 | { .compatible = _c, \ | ||
| 39 | .reset = REG_FIELD(_rr, _rb, _rb), } | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Description of a system configuration register based reset controller. | ||
| 43 | * | ||
| 44 | * @wait_for_ack: The controller will wait for reset assert and de-assert to | ||
| 45 | * be "ack'd" in a channel's ack field. | ||
| 46 | * @active_low: Are the resets in this controller active low, i.e. clearing | ||
| 47 | * the reset bit puts the hardware into reset. | ||
| 48 | * @nr_channels: The number of reset channels in this controller. | ||
| 49 | * @channels: An array of reset channel descriptions. | ||
| 50 | */ | ||
| 51 | struct syscfg_reset_controller_data { | ||
| 52 | bool wait_for_ack; | ||
| 53 | bool active_low; | ||
| 54 | int nr_channels; | ||
| 55 | const struct syscfg_reset_channel_data *channels; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /** | ||
| 59 | * syscfg_reset_probe(): platform device probe function used by syscfg | ||
| 60 | * reset controller drivers. This registers a reset | ||
| 61 | * controller configured by the OF match data for | ||
| 62 | * the compatible device which should be of type | ||
| 63 | * "struct syscfg_reset_controller_data". | ||
| 64 | * | ||
| 65 | * @pdev: platform device | ||
| 66 | */ | ||
| 67 | int syscfg_reset_probe(struct platform_device *pdev); | ||
| 68 | |||
| 69 | #endif /* __STI_RESET_SYSCFG_H */ | ||
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c index 7e5ead936a04..41bd76aaff76 100644 --- a/drivers/rtc/rtc-isl12057.c +++ b/drivers/rtc/rtc-isl12057.c | |||
| @@ -274,10 +274,7 @@ static int isl12057_probe(struct i2c_client *client, | |||
| 274 | dev_set_drvdata(dev, data); | 274 | dev_set_drvdata(dev, data); |
| 275 | 275 | ||
| 276 | rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE); | 276 | rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE); |
| 277 | if (IS_ERR(rtc)) | 277 | return PTR_ERR_OR_ZERO(rtc); |
| 278 | return PTR_ERR(rtc); | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | } | 278 | } |
| 282 | 279 | ||
| 283 | #ifdef CONFIG_OF | 280 | #ifdef CONFIG_OF |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index d536c5962c99..d15a999363fc 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
| @@ -222,6 +222,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev) | |||
| 222 | struct resource *res; | 222 | struct resource *res; |
| 223 | struct rtc_plat_data *pdata; | 223 | struct rtc_plat_data *pdata; |
| 224 | u32 rtc_time; | 224 | u32 rtc_time; |
| 225 | u32 rtc_date; | ||
| 225 | int ret = 0; | 226 | int ret = 0; |
| 226 | 227 | ||
| 227 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 228 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| @@ -257,6 +258,17 @@ static int __init mv_rtc_probe(struct platform_device *pdev) | |||
| 257 | } | 258 | } |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 261 | /* | ||
| 262 | * A date after January 19th, 2038 does not fit on 32 bits and | ||
| 263 | * will confuse the kernel and userspace. Reset to a sane date | ||
| 264 | * (January 1st, 2013) if we're after 2038. | ||
| 265 | */ | ||
| 266 | rtc_date = readl(pdata->ioaddr + RTC_DATE_REG_OFFS); | ||
| 267 | if (bcd2bin((rtc_date >> RTC_YEAR_OFFS) & 0xff) >= 38) { | ||
| 268 | dev_info(&pdev->dev, "invalid RTC date, resetting to January 1st, 2013\n"); | ||
| 269 | writel(0x130101, pdata->ioaddr + RTC_DATE_REG_OFFS); | ||
| 270 | } | ||
| 271 | |||
| 260 | pdata->irq = platform_get_irq(pdev, 0); | 272 | pdata->irq = platform_get_irq(pdev, 0); |
| 261 | 273 | ||
| 262 | platform_set_drvdata(pdev, pdata); | 274 | platform_set_drvdata(pdev, pdata); |
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 1ebe67cd1833..7442bc130055 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
| @@ -36,9 +36,47 @@ static void sh_clk_write(int value, struct clk *clk) | |||
| 36 | iowrite32(value, clk->mapped_reg); | 36 | iowrite32(value, clk->mapped_reg); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static unsigned int r8(const void __iomem *addr) | ||
| 40 | { | ||
| 41 | return ioread8(addr); | ||
| 42 | } | ||
| 43 | |||
| 44 | static unsigned int r16(const void __iomem *addr) | ||
| 45 | { | ||
| 46 | return ioread16(addr); | ||
| 47 | } | ||
| 48 | |||
| 49 | static unsigned int r32(const void __iomem *addr) | ||
| 50 | { | ||
| 51 | return ioread32(addr); | ||
| 52 | } | ||
| 53 | |||
| 39 | static int sh_clk_mstp_enable(struct clk *clk) | 54 | static int sh_clk_mstp_enable(struct clk *clk) |
| 40 | { | 55 | { |
| 41 | sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); | 56 | sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); |
| 57 | if (clk->status_reg) { | ||
| 58 | unsigned int (*read)(const void __iomem *addr); | ||
| 59 | int i; | ||
| 60 | void __iomem *mapped_status = (phys_addr_t)clk->status_reg - | ||
| 61 | (phys_addr_t)clk->enable_reg + clk->mapped_reg; | ||
| 62 | |||
| 63 | if (clk->flags & CLK_ENABLE_REG_8BIT) | ||
| 64 | read = r8; | ||
| 65 | else if (clk->flags & CLK_ENABLE_REG_16BIT) | ||
| 66 | read = r16; | ||
| 67 | else | ||
| 68 | read = r32; | ||
| 69 | |||
| 70 | for (i = 1000; | ||
| 71 | (read(mapped_status) & (1 << clk->enable_bit)) && i; | ||
| 72 | i--) | ||
| 73 | cpu_relax(); | ||
| 74 | if (!i) { | ||
| 75 | pr_err("cpg: failed to enable %p[%d]\n", | ||
| 76 | clk->enable_reg, clk->enable_bit); | ||
| 77 | return -ETIMEDOUT; | ||
| 78 | } | ||
| 79 | } | ||
| 42 | return 0; | 80 | return 0; |
| 43 | } | 81 | } |
| 44 | 82 | ||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 5f88d767671e..2d51912a6e40 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
| @@ -143,7 +143,7 @@ config RCAR_THERMAL | |||
| 143 | 143 | ||
| 144 | config KIRKWOOD_THERMAL | 144 | config KIRKWOOD_THERMAL |
| 145 | tristate "Temperature sensor on Marvell Kirkwood SoCs" | 145 | tristate "Temperature sensor on Marvell Kirkwood SoCs" |
| 146 | depends on ARCH_KIRKWOOD | 146 | depends on ARCH_KIRKWOOD || MACH_KIRKWOOD |
| 147 | depends on OF | 147 | depends on OF |
| 148 | help | 148 | help |
| 149 | Support for the Kirkwood thermal sensor driver into the Linux thermal | 149 | Support for the Kirkwood thermal sensor driver into the Linux thermal |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2577d67bacb2..2e6d8ddc4425 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
| @@ -1024,7 +1024,7 @@ config SERIAL_SGI_IOC3 | |||
| 1024 | 1024 | ||
| 1025 | config SERIAL_MSM | 1025 | config SERIAL_MSM |
| 1026 | bool "MSM on-chip serial port support" | 1026 | bool "MSM on-chip serial port support" |
| 1027 | depends on ARCH_MSM | 1027 | depends on ARCH_MSM || ARCH_QCOM |
| 1028 | select SERIAL_CORE | 1028 | select SERIAL_CORE |
| 1029 | 1029 | ||
| 1030 | config SERIAL_MSM_CONSOLE | 1030 | config SERIAL_MSM_CONSOLE |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0c6048d5c9a3..74ec8fc5cc03 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -301,7 +301,7 @@ config DAVINCI_WATCHDOG | |||
| 301 | 301 | ||
| 302 | config ORION_WATCHDOG | 302 | config ORION_WATCHDOG |
| 303 | tristate "Orion watchdog" | 303 | tristate "Orion watchdog" |
| 304 | depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE | 304 | depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || ARCH_MVEBU |
| 305 | select WATCHDOG_CORE | 305 | select WATCHDOG_CORE |
| 306 | help | 306 | help |
| 307 | Say Y here if to include support for the watchdog timer | 307 | Say Y here if to include support for the watchdog timer |
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 498163497c1c..9b3c41d18703 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
| @@ -18,101 +18,204 @@ | |||
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/watchdog.h> | 20 | #include <linux/watchdog.h> |
| 21 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
| 26 | #include <mach/bridge-regs.h> | 26 | #include <linux/of_device.h> |
| 27 | |||
| 28 | /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */ | ||
| 29 | #define ORION_RSTOUT_MASK_OFFSET 0x20108 | ||
| 30 | |||
| 31 | /* Internal registers can be configured at any 1 MiB aligned address */ | ||
| 32 | #define INTERNAL_REGS_MASK ~(SZ_1M - 1) | ||
| 27 | 33 | ||
| 28 | /* | 34 | /* |
| 29 | * Watchdog timer block registers. | 35 | * Watchdog timer block registers. |
| 30 | */ | 36 | */ |
| 31 | #define TIMER_CTRL 0x0000 | 37 | #define TIMER_CTRL 0x0000 |
| 32 | #define WDT_EN 0x0010 | 38 | #define TIMER_A370_STATUS 0x04 |
| 33 | #define WDT_VAL 0x0024 | ||
| 34 | 39 | ||
| 35 | #define WDT_MAX_CYCLE_COUNT 0xffffffff | 40 | #define WDT_MAX_CYCLE_COUNT 0xffffffff |
| 36 | #define WDT_IN_USE 0 | ||
| 37 | #define WDT_OK_TO_CLOSE 1 | ||
| 38 | 41 | ||
| 39 | #define WDT_RESET_OUT_EN BIT(1) | 42 | #define WDT_A370_RATIO_MASK(v) ((v) << 16) |
| 40 | #define WDT_INT_REQ BIT(3) | 43 | #define WDT_A370_RATIO_SHIFT 5 |
| 44 | #define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT) | ||
| 45 | |||
| 46 | #define WDT_AXP_FIXED_ENABLE_BIT BIT(10) | ||
| 47 | #define WDT_A370_EXPIRED BIT(31) | ||
| 41 | 48 | ||
| 42 | static bool nowayout = WATCHDOG_NOWAYOUT; | 49 | static bool nowayout = WATCHDOG_NOWAYOUT; |
| 43 | static int heartbeat = -1; /* module parameter (seconds) */ | 50 | static int heartbeat = -1; /* module parameter (seconds) */ |
| 44 | static unsigned int wdt_max_duration; /* (seconds) */ | ||
| 45 | static struct clk *clk; | ||
| 46 | static unsigned int wdt_tclk; | ||
| 47 | static void __iomem *wdt_reg; | ||
| 48 | static DEFINE_SPINLOCK(wdt_lock); | ||
| 49 | 51 | ||
| 50 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) | 52 | struct orion_watchdog; |
| 53 | |||
| 54 | struct orion_watchdog_data { | ||
| 55 | int wdt_counter_offset; | ||
| 56 | int wdt_enable_bit; | ||
| 57 | int rstout_enable_bit; | ||
| 58 | int (*clock_init)(struct platform_device *, | ||
| 59 | struct orion_watchdog *); | ||
| 60 | int (*start)(struct watchdog_device *); | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct orion_watchdog { | ||
| 64 | struct watchdog_device wdt; | ||
| 65 | void __iomem *reg; | ||
| 66 | void __iomem *rstout; | ||
| 67 | unsigned long clk_rate; | ||
| 68 | struct clk *clk; | ||
| 69 | const struct orion_watchdog_data *data; | ||
| 70 | }; | ||
| 71 | |||
| 72 | static int orion_wdt_clock_init(struct platform_device *pdev, | ||
| 73 | struct orion_watchdog *dev) | ||
| 51 | { | 74 | { |
| 52 | spin_lock(&wdt_lock); | 75 | int ret; |
| 53 | 76 | ||
| 54 | /* Reload watchdog duration */ | 77 | dev->clk = clk_get(&pdev->dev, NULL); |
| 55 | writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); | 78 | if (IS_ERR(dev->clk)) |
| 79 | return PTR_ERR(dev->clk); | ||
| 80 | ret = clk_prepare_enable(dev->clk); | ||
| 81 | if (ret) { | ||
| 82 | clk_put(dev->clk); | ||
| 83 | return ret; | ||
| 84 | } | ||
| 56 | 85 | ||
| 57 | spin_unlock(&wdt_lock); | 86 | dev->clk_rate = clk_get_rate(dev->clk); |
| 58 | return 0; | 87 | return 0; |
| 59 | } | 88 | } |
| 60 | 89 | ||
| 61 | static int orion_wdt_start(struct watchdog_device *wdt_dev) | 90 | static int armada370_wdt_clock_init(struct platform_device *pdev, |
| 91 | struct orion_watchdog *dev) | ||
| 62 | { | 92 | { |
| 63 | u32 reg; | 93 | int ret; |
| 64 | 94 | ||
| 65 | spin_lock(&wdt_lock); | 95 | dev->clk = clk_get(&pdev->dev, NULL); |
| 96 | if (IS_ERR(dev->clk)) | ||
| 97 | return PTR_ERR(dev->clk); | ||
| 98 | ret = clk_prepare_enable(dev->clk); | ||
| 99 | if (ret) { | ||
| 100 | clk_put(dev->clk); | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* Setup watchdog input clock */ | ||
| 105 | atomic_io_modify(dev->reg + TIMER_CTRL, | ||
| 106 | WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT), | ||
| 107 | WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT)); | ||
| 108 | |||
| 109 | dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO; | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int armadaxp_wdt_clock_init(struct platform_device *pdev, | ||
| 114 | struct orion_watchdog *dev) | ||
| 115 | { | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed"); | ||
| 119 | if (IS_ERR(dev->clk)) | ||
| 120 | return PTR_ERR(dev->clk); | ||
| 121 | ret = clk_prepare_enable(dev->clk); | ||
| 122 | if (ret) { | ||
| 123 | clk_put(dev->clk); | ||
| 124 | return ret; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* Enable the fixed watchdog clock input */ | ||
| 128 | atomic_io_modify(dev->reg + TIMER_CTRL, | ||
| 129 | WDT_AXP_FIXED_ENABLE_BIT, | ||
| 130 | WDT_AXP_FIXED_ENABLE_BIT); | ||
| 131 | |||
| 132 | dev->clk_rate = clk_get_rate(dev->clk); | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) | ||
| 137 | { | ||
| 138 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | ||
| 139 | /* Reload watchdog duration */ | ||
| 140 | writel(dev->clk_rate * wdt_dev->timeout, | ||
| 141 | dev->reg + dev->data->wdt_counter_offset); | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int armada370_start(struct watchdog_device *wdt_dev) | ||
| 146 | { | ||
| 147 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | ||
| 66 | 148 | ||
| 67 | /* Set watchdog duration */ | 149 | /* Set watchdog duration */ |
| 68 | writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); | 150 | writel(dev->clk_rate * wdt_dev->timeout, |
| 151 | dev->reg + dev->data->wdt_counter_offset); | ||
| 69 | 152 | ||
| 70 | /* Clear watchdog timer interrupt */ | 153 | /* Clear the watchdog expiration bit */ |
| 71 | writel(~WDT_INT_REQ, BRIDGE_CAUSE); | 154 | atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0); |
| 72 | 155 | ||
| 73 | /* Enable watchdog timer */ | 156 | /* Enable watchdog timer */ |
| 74 | reg = readl(wdt_reg + TIMER_CTRL); | 157 | atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, |
| 75 | reg |= WDT_EN; | 158 | dev->data->wdt_enable_bit); |
| 76 | writel(reg, wdt_reg + TIMER_CTRL); | 159 | |
| 160 | atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, | ||
| 161 | dev->data->rstout_enable_bit); | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int orion_start(struct watchdog_device *wdt_dev) | ||
| 166 | { | ||
| 167 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | ||
| 168 | |||
| 169 | /* Set watchdog duration */ | ||
| 170 | writel(dev->clk_rate * wdt_dev->timeout, | ||
| 171 | dev->reg + dev->data->wdt_counter_offset); | ||
| 172 | |||
| 173 | /* Enable watchdog timer */ | ||
| 174 | atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, | ||
| 175 | dev->data->wdt_enable_bit); | ||
| 77 | 176 | ||
| 78 | /* Enable reset on watchdog */ | 177 | /* Enable reset on watchdog */ |
| 79 | reg = readl(RSTOUTn_MASK); | 178 | atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, |
| 80 | reg |= WDT_RESET_OUT_EN; | 179 | dev->data->rstout_enable_bit); |
| 81 | writel(reg, RSTOUTn_MASK); | ||
| 82 | 180 | ||
| 83 | spin_unlock(&wdt_lock); | ||
| 84 | return 0; | 181 | return 0; |
| 85 | } | 182 | } |
| 86 | 183 | ||
| 87 | static int orion_wdt_stop(struct watchdog_device *wdt_dev) | 184 | static int orion_wdt_start(struct watchdog_device *wdt_dev) |
| 88 | { | 185 | { |
| 89 | u32 reg; | 186 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); |
| 90 | 187 | ||
| 91 | spin_lock(&wdt_lock); | 188 | /* There are some per-SoC quirks to handle */ |
| 189 | return dev->data->start(wdt_dev); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int orion_wdt_stop(struct watchdog_device *wdt_dev) | ||
| 193 | { | ||
| 194 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | ||
| 92 | 195 | ||
| 93 | /* Disable reset on watchdog */ | 196 | /* Disable reset on watchdog */ |
| 94 | reg = readl(RSTOUTn_MASK); | 197 | atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0); |
| 95 | reg &= ~WDT_RESET_OUT_EN; | ||
| 96 | writel(reg, RSTOUTn_MASK); | ||
| 97 | 198 | ||
| 98 | /* Disable watchdog timer */ | 199 | /* Disable watchdog timer */ |
| 99 | reg = readl(wdt_reg + TIMER_CTRL); | 200 | atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0); |
| 100 | reg &= ~WDT_EN; | ||
| 101 | writel(reg, wdt_reg + TIMER_CTRL); | ||
| 102 | 201 | ||
| 103 | spin_unlock(&wdt_lock); | ||
| 104 | return 0; | 202 | return 0; |
| 105 | } | 203 | } |
| 106 | 204 | ||
| 107 | static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) | 205 | static int orion_wdt_enabled(struct orion_watchdog *dev) |
| 108 | { | 206 | { |
| 109 | unsigned int time_left; | 207 | bool enabled, running; |
| 208 | |||
| 209 | enabled = readl(dev->rstout) & dev->data->rstout_enable_bit; | ||
| 210 | running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit; | ||
| 110 | 211 | ||
| 111 | spin_lock(&wdt_lock); | 212 | return enabled && running; |
| 112 | time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk; | 213 | } |
| 113 | spin_unlock(&wdt_lock); | ||
| 114 | 214 | ||
| 115 | return time_left; | 215 | static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) |
| 216 | { | ||
| 217 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); | ||
| 218 | return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate; | ||
| 116 | } | 219 | } |
| 117 | 220 | ||
| 118 | static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, | 221 | static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, |
| @@ -136,68 +239,188 @@ static const struct watchdog_ops orion_wdt_ops = { | |||
| 136 | .get_timeleft = orion_wdt_get_timeleft, | 239 | .get_timeleft = orion_wdt_get_timeleft, |
| 137 | }; | 240 | }; |
| 138 | 241 | ||
| 139 | static struct watchdog_device orion_wdt = { | 242 | static irqreturn_t orion_wdt_irq(int irq, void *devid) |
| 140 | .info = &orion_wdt_info, | 243 | { |
| 141 | .ops = &orion_wdt_ops, | 244 | panic("Watchdog Timeout"); |
| 142 | .min_timeout = 1, | 245 | return IRQ_HANDLED; |
| 246 | } | ||
| 247 | |||
| 248 | /* | ||
| 249 | * The original devicetree binding for this driver specified only | ||
| 250 | * one memory resource, so in order to keep DT backwards compatibility | ||
| 251 | * we try to fallback to a hardcoded register address, if the resource | ||
| 252 | * is missing from the devicetree. | ||
| 253 | */ | ||
| 254 | static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev, | ||
| 255 | phys_addr_t internal_regs) | ||
| 256 | { | ||
| 257 | struct resource *res; | ||
| 258 | phys_addr_t rstout; | ||
| 259 | |||
| 260 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 261 | if (res) | ||
| 262 | return devm_ioremap(&pdev->dev, res->start, | ||
| 263 | resource_size(res)); | ||
| 264 | |||
| 265 | /* This workaround works only for "orion-wdt", DT-enabled */ | ||
| 266 | if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt")) | ||
| 267 | return NULL; | ||
| 268 | |||
| 269 | rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET; | ||
| 270 | |||
| 271 | WARN(1, FW_BUG "falling back to harcoded RSTOUT reg %pa\n", &rstout); | ||
| 272 | return devm_ioremap(&pdev->dev, rstout, 0x4); | ||
| 273 | } | ||
| 274 | |||
| 275 | static const struct orion_watchdog_data orion_data = { | ||
| 276 | .rstout_enable_bit = BIT(1), | ||
| 277 | .wdt_enable_bit = BIT(4), | ||
| 278 | .wdt_counter_offset = 0x24, | ||
| 279 | .clock_init = orion_wdt_clock_init, | ||
| 280 | .start = orion_start, | ||
| 281 | }; | ||
| 282 | |||
| 283 | static const struct orion_watchdog_data armada370_data = { | ||
| 284 | .rstout_enable_bit = BIT(8), | ||
| 285 | .wdt_enable_bit = BIT(8), | ||
| 286 | .wdt_counter_offset = 0x34, | ||
| 287 | .clock_init = armada370_wdt_clock_init, | ||
| 288 | .start = armada370_start, | ||
| 143 | }; | 289 | }; |
| 144 | 290 | ||
| 291 | static const struct orion_watchdog_data armadaxp_data = { | ||
| 292 | .rstout_enable_bit = BIT(8), | ||
| 293 | .wdt_enable_bit = BIT(8), | ||
| 294 | .wdt_counter_offset = 0x34, | ||
| 295 | .clock_init = armadaxp_wdt_clock_init, | ||
| 296 | .start = armada370_start, | ||
| 297 | }; | ||
| 298 | |||
| 299 | static const struct of_device_id orion_wdt_of_match_table[] = { | ||
| 300 | { | ||
| 301 | .compatible = "marvell,orion-wdt", | ||
| 302 | .data = &orion_data, | ||
| 303 | }, | ||
| 304 | { | ||
| 305 | .compatible = "marvell,armada-370-wdt", | ||
| 306 | .data = &armada370_data, | ||
| 307 | }, | ||
| 308 | { | ||
| 309 | .compatible = "marvell,armada-xp-wdt", | ||
| 310 | .data = &armadaxp_data, | ||
| 311 | }, | ||
| 312 | {}, | ||
| 313 | }; | ||
| 314 | MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); | ||
| 315 | |||
| 145 | static int orion_wdt_probe(struct platform_device *pdev) | 316 | static int orion_wdt_probe(struct platform_device *pdev) |
| 146 | { | 317 | { |
| 318 | struct orion_watchdog *dev; | ||
| 319 | const struct of_device_id *match; | ||
| 320 | unsigned int wdt_max_duration; /* (seconds) */ | ||
| 147 | struct resource *res; | 321 | struct resource *res; |
| 148 | int ret; | 322 | int ret, irq; |
| 149 | 323 | ||
| 150 | clk = devm_clk_get(&pdev->dev, NULL); | 324 | dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog), |
| 151 | if (IS_ERR(clk)) { | 325 | GFP_KERNEL); |
| 152 | dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); | 326 | if (!dev) |
| 153 | return -ENODEV; | 327 | return -ENOMEM; |
| 154 | } | 328 | |
| 155 | clk_prepare_enable(clk); | 329 | match = of_match_device(orion_wdt_of_match_table, &pdev->dev); |
| 156 | wdt_tclk = clk_get_rate(clk); | 330 | if (!match) |
| 331 | /* Default legacy match */ | ||
| 332 | match = &orion_wdt_of_match_table[0]; | ||
| 333 | |||
| 334 | dev->wdt.info = &orion_wdt_info; | ||
| 335 | dev->wdt.ops = &orion_wdt_ops; | ||
| 336 | dev->wdt.min_timeout = 1; | ||
| 337 | dev->data = match->data; | ||
| 157 | 338 | ||
| 158 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 339 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 159 | if (!res) | 340 | if (!res) |
| 160 | return -ENODEV; | 341 | return -ENODEV; |
| 161 | wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
| 162 | if (!wdt_reg) | ||
| 163 | return -ENOMEM; | ||
| 164 | 342 | ||
| 165 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; | 343 | dev->reg = devm_ioremap(&pdev->dev, res->start, |
| 344 | resource_size(res)); | ||
| 345 | if (!dev->reg) | ||
| 346 | return -ENOMEM; | ||
| 166 | 347 | ||
| 167 | orion_wdt.timeout = wdt_max_duration; | 348 | dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start & |
| 168 | orion_wdt.max_timeout = wdt_max_duration; | 349 | INTERNAL_REGS_MASK); |
| 169 | watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev); | 350 | if (!dev->rstout) |
| 351 | return -ENODEV; | ||
| 170 | 352 | ||
| 171 | watchdog_set_nowayout(&orion_wdt, nowayout); | 353 | ret = dev->data->clock_init(pdev, dev); |
| 172 | ret = watchdog_register_device(&orion_wdt); | ||
| 173 | if (ret) { | 354 | if (ret) { |
| 174 | clk_disable_unprepare(clk); | 355 | dev_err(&pdev->dev, "cannot initialize clock\n"); |
| 175 | return ret; | 356 | return ret; |
| 176 | } | 357 | } |
| 177 | 358 | ||
| 359 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate; | ||
| 360 | |||
| 361 | dev->wdt.timeout = wdt_max_duration; | ||
| 362 | dev->wdt.max_timeout = wdt_max_duration; | ||
| 363 | watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev); | ||
| 364 | |||
| 365 | platform_set_drvdata(pdev, &dev->wdt); | ||
| 366 | watchdog_set_drvdata(&dev->wdt, dev); | ||
| 367 | |||
| 368 | /* | ||
| 369 | * Let's make sure the watchdog is fully stopped, unless it's | ||
| 370 | * explicitly enabled. This may be the case if the module was | ||
| 371 | * removed and re-insterted, or if the bootloader explicitly | ||
| 372 | * set a running watchdog before booting the kernel. | ||
| 373 | */ | ||
| 374 | if (!orion_wdt_enabled(dev)) | ||
| 375 | orion_wdt_stop(&dev->wdt); | ||
| 376 | |||
| 377 | /* Request the IRQ only after the watchdog is disabled */ | ||
| 378 | irq = platform_get_irq(pdev, 0); | ||
| 379 | if (irq > 0) { | ||
| 380 | /* | ||
| 381 | * Not all supported platforms specify an interrupt for the | ||
| 382 | * watchdog, so let's make it optional. | ||
| 383 | */ | ||
| 384 | ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0, | ||
| 385 | pdev->name, dev); | ||
| 386 | if (ret < 0) { | ||
| 387 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 388 | goto disable_clk; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | watchdog_set_nowayout(&dev->wdt, nowayout); | ||
| 393 | ret = watchdog_register_device(&dev->wdt); | ||
| 394 | if (ret) | ||
| 395 | goto disable_clk; | ||
| 396 | |||
| 178 | pr_info("Initial timeout %d sec%s\n", | 397 | pr_info("Initial timeout %d sec%s\n", |
| 179 | orion_wdt.timeout, nowayout ? ", nowayout" : ""); | 398 | dev->wdt.timeout, nowayout ? ", nowayout" : ""); |
| 180 | return 0; | 399 | return 0; |
| 400 | |||
| 401 | disable_clk: | ||
| 402 | clk_disable_unprepare(dev->clk); | ||
| 403 | clk_put(dev->clk); | ||
| 404 | return ret; | ||
| 181 | } | 405 | } |
| 182 | 406 | ||
| 183 | static int orion_wdt_remove(struct platform_device *pdev) | 407 | static int orion_wdt_remove(struct platform_device *pdev) |
| 184 | { | 408 | { |
| 185 | watchdog_unregister_device(&orion_wdt); | 409 | struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); |
| 186 | clk_disable_unprepare(clk); | 410 | struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev); |
| 411 | |||
| 412 | watchdog_unregister_device(wdt_dev); | ||
| 413 | clk_disable_unprepare(dev->clk); | ||
| 414 | clk_put(dev->clk); | ||
| 187 | return 0; | 415 | return 0; |
| 188 | } | 416 | } |
| 189 | 417 | ||
| 190 | static void orion_wdt_shutdown(struct platform_device *pdev) | 418 | static void orion_wdt_shutdown(struct platform_device *pdev) |
| 191 | { | 419 | { |
| 192 | orion_wdt_stop(&orion_wdt); | 420 | struct watchdog_device *wdt_dev = platform_get_drvdata(pdev); |
| 421 | orion_wdt_stop(wdt_dev); | ||
| 193 | } | 422 | } |
| 194 | 423 | ||
| 195 | static const struct of_device_id orion_wdt_of_match_table[] = { | ||
| 196 | { .compatible = "marvell,orion-wdt", }, | ||
| 197 | {}, | ||
| 198 | }; | ||
| 199 | MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table); | ||
| 200 | |||
| 201 | static struct platform_driver orion_wdt_driver = { | 424 | static struct platform_driver orion_wdt_driver = { |
| 202 | .probe = orion_wdt_probe, | 425 | .probe = orion_wdt_probe, |
| 203 | .remove = orion_wdt_remove, | 426 | .remove = orion_wdt_remove, |
diff --git a/include/dt-bindings/clock/bcm281xx.h b/include/dt-bindings/clock/bcm281xx.h new file mode 100644 index 000000000000..e0096940886d --- /dev/null +++ b/include/dt-bindings/clock/bcm281xx.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * Copyright 2013 Linaro Limited | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of the GNU General Public License as | ||
| 7 | * published by the Free Software Foundation version 2. | ||
| 8 | * | ||
| 9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 10 | * kind, whether express or implied; without even the implied warranty | ||
| 11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef _CLOCK_BCM281XX_H | ||
| 16 | #define _CLOCK_BCM281XX_H | ||
| 17 | |||
| 18 | /* | ||
| 19 | * This file defines the values used to specify clocks provided by | ||
| 20 | * the clock control units (CCUs) on Broadcom BCM281XX family SoCs. | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* root CCU clock ids */ | ||
| 24 | |||
| 25 | #define BCM281XX_ROOT_CCU_FRAC_1M 0 | ||
| 26 | #define BCM281XX_ROOT_CCU_CLOCK_COUNT 1 | ||
| 27 | |||
| 28 | /* aon CCU clock ids */ | ||
| 29 | |||
| 30 | #define BCM281XX_AON_CCU_HUB_TIMER 0 | ||
| 31 | #define BCM281XX_AON_CCU_PMU_BSC 1 | ||
| 32 | #define BCM281XX_AON_CCU_PMU_BSC_VAR 2 | ||
| 33 | #define BCM281XX_AON_CCU_CLOCK_COUNT 3 | ||
| 34 | |||
| 35 | /* hub CCU clock ids */ | ||
| 36 | |||
| 37 | #define BCM281XX_HUB_CCU_TMON_1M 0 | ||
| 38 | #define BCM281XX_HUB_CCU_CLOCK_COUNT 1 | ||
| 39 | |||
| 40 | /* master CCU clock ids */ | ||
| 41 | |||
| 42 | #define BCM281XX_MASTER_CCU_SDIO1 0 | ||
| 43 | #define BCM281XX_MASTER_CCU_SDIO2 1 | ||
| 44 | #define BCM281XX_MASTER_CCU_SDIO3 2 | ||
| 45 | #define BCM281XX_MASTER_CCU_SDIO4 3 | ||
| 46 | #define BCM281XX_MASTER_CCU_USB_IC 4 | ||
| 47 | #define BCM281XX_MASTER_CCU_HSIC2_48M 5 | ||
| 48 | #define BCM281XX_MASTER_CCU_HSIC2_12M 6 | ||
| 49 | #define BCM281XX_MASTER_CCU_CLOCK_COUNT 7 | ||
| 50 | |||
| 51 | /* slave CCU clock ids */ | ||
| 52 | |||
| 53 | #define BCM281XX_SLAVE_CCU_UARTB 0 | ||
| 54 | #define BCM281XX_SLAVE_CCU_UARTB2 1 | ||
| 55 | #define BCM281XX_SLAVE_CCU_UARTB3 2 | ||
| 56 | #define BCM281XX_SLAVE_CCU_UARTB4 3 | ||
| 57 | #define BCM281XX_SLAVE_CCU_SSP0 4 | ||
| 58 | #define BCM281XX_SLAVE_CCU_SSP2 5 | ||
| 59 | #define BCM281XX_SLAVE_CCU_BSC1 6 | ||
| 60 | #define BCM281XX_SLAVE_CCU_BSC2 7 | ||
| 61 | #define BCM281XX_SLAVE_CCU_BSC3 8 | ||
| 62 | #define BCM281XX_SLAVE_CCU_PWM 9 | ||
| 63 | #define BCM281XX_SLAVE_CCU_CLOCK_COUNT 10 | ||
| 64 | |||
| 65 | #endif /* _CLOCK_BCM281XX_H */ | ||
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h index 859e9be511d9..6548a5fbcf4a 100644 --- a/include/dt-bindings/clock/r8a7790-clock.h +++ b/include/dt-bindings/clock/r8a7790-clock.h | |||
| @@ -46,8 +46,8 @@ | |||
| 46 | #define R8A7790_CLK_MSIOF1 8 | 46 | #define R8A7790_CLK_MSIOF1 8 |
| 47 | #define R8A7790_CLK_MSIOF3 15 | 47 | #define R8A7790_CLK_MSIOF3 15 |
| 48 | #define R8A7790_CLK_SCIFB2 16 | 48 | #define R8A7790_CLK_SCIFB2 16 |
| 49 | #define R8A7790_CLK_SYS_DMAC0 18 | 49 | #define R8A7790_CLK_SYS_DMAC1 18 |
| 50 | #define R8A7790_CLK_SYS_DMAC1 19 | 50 | #define R8A7790_CLK_SYS_DMAC0 19 |
| 51 | 51 | ||
| 52 | /* MSTP3 */ | 52 | /* MSTP3 */ |
| 53 | #define R8A7790_CLK_TPU0 4 | 53 | #define R8A7790_CLK_TPU0 4 |
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 0ceb389dba6c..7ed92d0560d5 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h | |||
| @@ -93,6 +93,11 @@ int gic_get_cpu_id(unsigned int cpu); | |||
| 93 | void gic_migrate_target(unsigned int new_cpu_id); | 93 | void gic_migrate_target(unsigned int new_cpu_id); |
| 94 | unsigned long gic_get_sgir_physaddr(void); | 94 | unsigned long gic_get_sgir_physaddr(void); |
| 95 | 95 | ||
| 96 | extern const struct irq_domain_ops *gic_routable_irq_domain_ops; | ||
| 97 | static inline void __init register_routable_domain_ops | ||
| 98 | (const struct irq_domain_ops *ops) | ||
| 99 | { | ||
| 100 | gic_routable_irq_domain_ops = ops; | ||
| 101 | } | ||
| 96 | #endif /* __ASSEMBLY */ | 102 | #endif /* __ASSEMBLY */ |
| 97 | |||
| 98 | #endif | 103 | #endif |
diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h index e3c82dc95756..ba46c794b4e5 100644 --- a/include/linux/irqchip/arm-vic.h +++ b/include/linux/irqchip/arm-vic.h | |||
| @@ -29,8 +29,10 @@ | |||
| 29 | struct device_node; | 29 | struct device_node; |
| 30 | struct pt_regs; | 30 | struct pt_regs; |
| 31 | 31 | ||
| 32 | void __vic_init(void __iomem *base, int irq_start, u32 vic_sources, | 32 | void __vic_init(void __iomem *base, int parent_irq, int irq_start, |
| 33 | u32 resume_sources, struct device_node *node); | 33 | u32 vic_sources, u32 resume_sources, struct device_node *node); |
| 34 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); | 34 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); |
| 35 | int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, | ||
| 36 | u32 vic_sources, u32 resume_sources); | ||
| 35 | 37 | ||
| 36 | #endif | 38 | #endif |
diff --git a/include/linux/irqchip/irq-crossbar.h b/include/linux/irqchip/irq-crossbar.h new file mode 100644 index 000000000000..e5537b81df8d --- /dev/null +++ b/include/linux/irqchip/irq-crossbar.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | /* | ||
| 2 | * drivers/irqchip/irq-crossbar.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
| 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 version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | int irqcrossbar_init(void); | ||
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h index 280edac9d0a5..addd48cac625 100644 --- a/include/linux/platform_data/clk-integrator.h +++ b/include/linux/platform_data/clk-integrator.h | |||
| @@ -1,3 +1,2 @@ | |||
| 1 | void integrator_clk_init(bool is_cp); | ||
| 2 | void integrator_impd1_clk_init(void __iomem *base, unsigned int id); | 1 | void integrator_impd1_clk_init(void __iomem *base, unsigned int id); |
| 3 | void integrator_impd1_clk_exit(unsigned int id); | 2 | void integrator_impd1_clk_exit(unsigned int id); |
diff --git a/include/linux/platform_data/mtd-davinci-aemif.h b/include/linux/platform_data/mtd-davinci-aemif.h index 05b293443097..97948ac2bb9b 100644 --- a/include/linux/platform_data/mtd-davinci-aemif.h +++ b/include/linux/platform_data/mtd-davinci-aemif.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #ifndef _MACH_DAVINCI_AEMIF_H | 10 | #ifndef _MACH_DAVINCI_AEMIF_H |
| 11 | #define _MACH_DAVINCI_AEMIF_H | 11 | #define _MACH_DAVINCI_AEMIF_H |
| 12 | 12 | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 13 | #define NRCSR_OFFSET 0x00 | 15 | #define NRCSR_OFFSET 0x00 |
| 14 | #define AWCCR_OFFSET 0x04 | 16 | #define AWCCR_OFFSET 0x04 |
| 15 | #define A1CR_OFFSET 0x10 | 17 | #define A1CR_OFFSET 0x10 |
| @@ -31,6 +33,5 @@ struct davinci_aemif_timing { | |||
| 31 | u8 ta; | 33 | u8 ta; |
| 32 | }; | 34 | }; |
| 33 | 35 | ||
| 34 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | 36 | int davinci_aemif_setup(struct platform_device *pdev); |
| 35 | void __iomem *base, unsigned cs); | ||
| 36 | #endif | 37 | #endif |
diff --git a/include/linux/reset.h b/include/linux/reset.h index 6082247feab1..c0eda5023d74 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | struct device; | 4 | struct device; |
| 5 | struct reset_control; | 5 | struct reset_control; |
| 6 | 6 | ||
| 7 | #ifdef CONFIG_RESET_CONTROLLER | ||
| 8 | |||
| 7 | int reset_control_reset(struct reset_control *rstc); | 9 | int reset_control_reset(struct reset_control *rstc); |
| 8 | int reset_control_assert(struct reset_control *rstc); | 10 | int reset_control_assert(struct reset_control *rstc); |
| 9 | int reset_control_deassert(struct reset_control *rstc); | 11 | int reset_control_deassert(struct reset_control *rstc); |
| @@ -12,6 +14,67 @@ struct reset_control *reset_control_get(struct device *dev, const char *id); | |||
| 12 | void reset_control_put(struct reset_control *rstc); | 14 | void reset_control_put(struct reset_control *rstc); |
| 13 | struct reset_control *devm_reset_control_get(struct device *dev, const char *id); | 15 | struct reset_control *devm_reset_control_get(struct device *dev, const char *id); |
| 14 | 16 | ||
| 15 | int device_reset(struct device *dev); | 17 | int __must_check device_reset(struct device *dev); |
| 18 | |||
| 19 | static inline int device_reset_optional(struct device *dev) | ||
| 20 | { | ||
| 21 | return device_reset(dev); | ||
| 22 | } | ||
| 23 | |||
| 24 | static inline struct reset_control *reset_control_get_optional( | ||
| 25 | struct device *dev, const char *id) | ||
| 26 | { | ||
| 27 | return reset_control_get(dev, id); | ||
| 28 | } | ||
| 29 | |||
| 30 | static inline struct reset_control *devm_reset_control_get_optional( | ||
| 31 | struct device *dev, const char *id) | ||
| 32 | { | ||
| 33 | return devm_reset_control_get(dev, id); | ||
| 34 | } | ||
| 35 | |||
| 36 | #else | ||
| 37 | |||
| 38 | static inline int reset_control_reset(struct reset_control *rstc) | ||
| 39 | { | ||
| 40 | WARN_ON(1); | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline int reset_control_assert(struct reset_control *rstc) | ||
| 45 | { | ||
| 46 | WARN_ON(1); | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline int reset_control_deassert(struct reset_control *rstc) | ||
| 51 | { | ||
| 52 | WARN_ON(1); | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline void reset_control_put(struct reset_control *rstc) | ||
| 57 | { | ||
| 58 | WARN_ON(1); | ||
| 59 | } | ||
| 60 | |||
| 61 | static inline int device_reset_optional(struct device *dev) | ||
| 62 | { | ||
| 63 | return -ENOSYS; | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline struct reset_control *reset_control_get_optional( | ||
| 67 | struct device *dev, const char *id) | ||
| 68 | { | ||
| 69 | return ERR_PTR(-ENOSYS); | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline struct reset_control *devm_reset_control_get_optional( | ||
| 73 | struct device *dev, const char *id) | ||
| 74 | { | ||
| 75 | return ERR_PTR(-ENOSYS); | ||
| 76 | } | ||
| 77 | |||
| 78 | #endif /* CONFIG_RESET_CONTROLLER */ | ||
| 16 | 79 | ||
| 17 | #endif | 80 | #endif |
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index 60c72395ec6b..1f208b2a1ed6 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h | |||
| @@ -52,6 +52,7 @@ struct clk { | |||
| 52 | unsigned long flags; | 52 | unsigned long flags; |
| 53 | 53 | ||
| 54 | void __iomem *enable_reg; | 54 | void __iomem *enable_reg; |
| 55 | void __iomem *status_reg; | ||
| 55 | unsigned int enable_bit; | 56 | unsigned int enable_bit; |
| 56 | void __iomem *mapped_reg; | 57 | void __iomem *mapped_reg; |
| 57 | 58 | ||
| @@ -116,22 +117,26 @@ long clk_round_parent(struct clk *clk, unsigned long target, | |||
| 116 | unsigned long *best_freq, unsigned long *parent_freq, | 117 | unsigned long *best_freq, unsigned long *parent_freq, |
| 117 | unsigned int div_min, unsigned int div_max); | 118 | unsigned int div_min, unsigned int div_max); |
| 118 | 119 | ||
| 119 | #define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags) \ | 120 | #define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _status_reg, _flags) \ |
| 120 | { \ | 121 | { \ |
| 121 | .parent = _parent, \ | 122 | .parent = _parent, \ |
| 122 | .enable_reg = (void __iomem *)_enable_reg, \ | 123 | .enable_reg = (void __iomem *)_enable_reg, \ |
| 123 | .enable_bit = _enable_bit, \ | 124 | .enable_bit = _enable_bit, \ |
| 125 | .status_reg = _status_reg, \ | ||
| 124 | .flags = _flags, \ | 126 | .flags = _flags, \ |
| 125 | } | 127 | } |
| 126 | 128 | ||
| 127 | #define SH_CLK_MSTP32(_p, _r, _b, _f) \ | 129 | #define SH_CLK_MSTP32(_p, _r, _b, _f) \ |
| 128 | SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT) | 130 | SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_32BIT) |
| 129 | 131 | ||
| 130 | #define SH_CLK_MSTP16(_p, _r, _b, _f) \ | 132 | #define SH_CLK_MSTP32_STS(_p, _r, _b, _s, _f) \ |
| 131 | SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT) | 133 | SH_CLK_MSTP(_p, _r, _b, _s, _f | CLK_ENABLE_REG_32BIT) |
| 132 | 134 | ||
| 133 | #define SH_CLK_MSTP8(_p, _r, _b, _f) \ | 135 | #define SH_CLK_MSTP16(_p, _r, _b, _f) \ |
| 134 | SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT) | 136 | SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_16BIT) |
| 137 | |||
| 138 | #define SH_CLK_MSTP8(_p, _r, _b, _f) \ | ||
| 139 | SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_8BIT) | ||
| 135 | 140 | ||
| 136 | int sh_clk_mstp_register(struct clk *clks, int nr); | 141 | int sh_clk_mstp_register(struct clk *clks, int nr); |
| 137 | 142 | ||
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 49f8437665de..06f4e8aa93ae 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config SND_KIRKWOOD_SOC | 1 | config SND_KIRKWOOD_SOC |
| 2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" | 2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" |
| 3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST | 3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST |
| 4 | help | 4 | help |
| 5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
| 6 | the Kirkwood I2S interface. You will also need to select the | 6 | the Kirkwood I2S interface. You will also need to select the |
