diff options
1054 files changed, 15041 insertions, 13290 deletions
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt index 728c38c..56fb62b 100644 --- a/Documentation/device-mapper/dm-raid.txt +++ b/Documentation/device-mapper/dm-raid.txt @@ -141,3 +141,4 @@ Version History 1.2.0 Handle creation of arrays that contain failed devices. 1.3.0 Added support for RAID 10 1.3.1 Allow device replacement/rebuild for RAID 10 +1.3.2 Fix/improve redundancy checking for RAID10 diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt index 1881e1c..c6ba6d3 100644 --- a/Documentation/devicetree/bindings/arm/sirf.txt +++ b/Documentation/devicetree/bindings/arm/sirf.txt @@ -1,3 +1,9 @@ -prima2 "cb" evaluation board +CSR SiRFprimaII and SiRFmarco device tree bindings. +======================================== + Required root node properties: - - compatible = "sirf,prima2-cb", "sirf,prima2"; + - compatible: + - "sirf,prima2-cb" : prima2 "cb" evaluation board + - "sirf,marco-cb" : marco "cb" evaluation board + - "sirf,prima2" : prima2 device based board + - "sirf,marco" : marco device based board diff --git a/Documentation/devicetree/bindings/arm/vt8500.txt b/Documentation/devicetree/bindings/arm/vt8500.txt index d657832..87dc1dd 100644 --- a/Documentation/devicetree/bindings/arm/vt8500.txt +++ b/Documentation/devicetree/bindings/arm/vt8500.txt @@ -12,3 +12,11 @@ compatible = "wm,wm8505"; Boards with the Wondermedia WM8650 SoC shall have the following properties: Required root node property: compatible = "wm,wm8650"; + +Boards with the Wondermedia WM8750 SoC shall have the following properties: +Required root node property: +compatible = "wm,wm8750"; + +Boards with the Wondermedia WM8850 SoC shall have the following properties: +Required root node property: +compatible = "wm,wm8850"; diff --git a/Documentation/devicetree/bindings/clock/imx31-clock.txt b/Documentation/devicetree/bindings/clock/imx31-clock.txt new file mode 100644 index 0000000..19df842c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imx31-clock.txt @@ -0,0 +1,91 @@ +* Clock bindings for Freescale i.MX31 + +Required properties: +- compatible: Should be "fsl,imx31-ccm" +- reg: Address and length of the register set +- interrupts: Should contain CCM interrupt +- #clock-cells: Should be <1> + +The clock consumer should specify the desired clock by having the clock +ID in its "clocks" phandle cell. The following is a full list of i.MX31 +clocks and IDs. + + Clock ID + ----------------------- + dummy 0 + ckih 1 + ckil 2 + mpll 3 + spll 4 + upll 5 + mcu_main 6 + hsp 7 + ahb 8 + nfc 9 + ipg 10 + per_div 11 + per 12 + csi_sel 13 + fir_sel 14 + csi_div 15 + usb_div_pre 16 + usb_div_post 17 + fir_div_pre 18 + fir_div_post 19 + sdhc1_gate 20 + sdhc2_gate 21 + gpt_gate 22 + epit1_gate 23 + epit2_gate 24 + iim_gate 25 + ata_gate 26 + sdma_gate 27 + cspi3_gate 28 + rng_gate 29 + uart1_gate 30 + uart2_gate 31 + ssi1_gate 32 + i2c1_gate 33 + i2c2_gate 34 + i2c3_gate 35 + hantro_gate 36 + mstick1_gate 37 + mstick2_gate 38 + csi_gate 39 + rtc_gate 40 + wdog_gate 41 + pwm_gate 42 + sim_gate 43 + ect_gate 44 + usb_gate 45 + kpp_gate 46 + ipu_gate 47 + uart3_gate 48 + uart4_gate 49 + uart5_gate 50 + owire_gate 51 + ssi2_gate 52 + cspi1_gate 53 + cspi2_gate 54 + gacc_gate 55 + emi_gate 56 + rtic_gate 57 + firi_gate 58 + +Examples: + +clks: ccm@53f80000{ + compatible = "fsl,imx31-ccm"; + reg = <0x53f80000 0x4000>; + interrupts = <0 31 0x04 0 53 0x04>; + #clock-cells = <1>; +}; + +uart1: serial@43f90000 { + compatible = "fsl,imx31-uart", "fsl,imx21-uart"; + reg = <0x43f90000 0x4000>; + interrupts = <45>; + clocks = <&clks 10>, <&clks 30>; + clock-names = "ipg", "per"; + status = "disabled"; +}; diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt new file mode 100644 index 0000000..0921fac --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt @@ -0,0 +1,205 @@ +NVIDIA Tegra20 Clock And Reset Controller + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +The CAR (Clock And Reset) Controller on Tegra is the HW module responsible +for muxing and gating Tegra's clocks, and setting their rates. + +Required properties : +- compatible : Should be "nvidia,tegra20-car" +- reg : Should contain CAR registers location and length +- clocks : Should contain phandle and clock specifiers for two clocks: + the 32 KHz "32k_in", and the board-specific oscillator "osc". +- #clock-cells : Should be 1. + In clock consumers, this cell represents the clock ID exposed by the CAR. + + The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + registers. These IDs often match those in the CAR's RST_DEVICES registers, + but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + this case, those clocks are assigned IDs above 95 in order to highlight + this issue. Implementations that interpret these clock IDs as bit values + within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + explicitly handle these special cases. + + The balance of the clocks controlled by the CAR are assigned IDs of 96 and + above. + + 0 cpu + 1 unassigned + 2 unassigned + 3 ac97 + 4 rtc + 5 tmr + 6 uart1 + 7 unassigned (register bit affects uart2 and vfir) + 8 gpio + 9 sdmmc2 + 10 unassigned (register bit affects spdif_in and spdif_out) + 11 i2s1 + 12 i2c1 + 13 ndflash + 14 sdmmc1 + 15 sdmmc4 + 16 twc + 17 pwm + 18 i2s2 + 19 epp + 20 unassigned (register bit affects vi and vi_sensor) + 21 2d + 22 usbd + 23 isp + 24 3d + 25 ide + 26 disp2 + 27 disp1 + 28 host1x + 29 vcp + 30 unassigned + 31 cache2 + + 32 mem + 33 ahbdma + 34 apbdma + 35 unassigned + 36 kbc + 37 stat_mon + 38 pmc + 39 fuse + 40 kfuse + 41 sbc1 + 42 snor + 43 spi1 + 44 sbc2 + 45 xio + 46 sbc3 + 47 dvc + 48 dsi + 49 unassigned (register bit affects tvo and cve) + 50 mipi + 51 hdmi + 52 csi + 53 tvdac + 54 i2c2 + 55 uart3 + 56 unassigned + 57 emc + 58 usb2 + 59 usb3 + 60 mpe + 61 vde + 62 bsea + 63 bsev + + 64 speedo + 65 uart4 + 66 uart5 + 67 i2c3 + 68 sbc4 + 69 sdmmc3 + 70 pcie + 71 owr + 72 afi + 73 csite + 74 unassigned + 75 avpucq + 76 la + 77 unassigned + 78 unassigned + 79 unassigned + 80 unassigned + 81 unassigned + 82 unassigned + 83 unassigned + 84 irama + 85 iramb + 86 iramc + 87 iramd + 88 cram2 + 89 audio_2x a/k/a audio_2x_sync_clk + 90 clk_d + 91 unassigned + 92 sus + 93 cdev1 + 94 cdev2 + 95 unassigned + + 96 uart2 + 97 vfir + 98 spdif_in + 99 spdif_out + 100 vi + 101 vi_sensor + 102 tvo + 103 cve + 104 osc + 105 clk_32k a/k/a clk_s + 106 clk_m + 107 sclk + 108 cclk + 109 hclk + 110 pclk + 111 blink + 112 pll_a + 113 pll_a_out0 + 114 pll_c + 115 pll_c_out1 + 116 pll_d + 117 pll_d_out0 + 118 pll_e + 119 pll_m + 120 pll_m_out1 + 121 pll_p + 122 pll_p_out1 + 123 pll_p_out2 + 124 pll_p_out3 + 125 pll_p_out4 + 126 pll_s + 127 pll_u + 128 pll_x + 129 cop a/k/a avp + 130 audio a/k/a audio_sync_clk + 131 pll_ref + 132 twd + +Example SoC include file: + +/ { + tegra_car: clock { + compatible = "nvidia,tegra20-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + usb@c5004000 { + clocks = <&tegra_car 58>; /* usb2 */ + }; +}; + +Example board file: + +/ { + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + osc: clock@0 { + compatible = "fixed-clock"; + reg = <0>; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + clk_32k: clock@1 { + compatible = "fixed-clock"; + reg = <1>; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + }; + + &tegra_car { + clocks = <&clk_32k> <&osc>; + }; +}; diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt new file mode 100644 index 0000000..f3da3be --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt @@ -0,0 +1,262 @@ +NVIDIA Tegra30 Clock And Reset Controller + +This binding uses the common clock binding: +Documentation/devicetree/bindings/clock/clock-bindings.txt + +The CAR (Clock And Reset) Controller on Tegra is the HW module responsible +for muxing and gating Tegra's clocks, and setting their rates. + +Required properties : +- compatible : Should be "nvidia,tegra30-car" +- reg : Should contain CAR registers location and length +- clocks : Should contain phandle and clock specifiers for two clocks: + the 32 KHz "32k_in", and the board-specific oscillator "osc". +- #clock-cells : Should be 1. + In clock consumers, this cell represents the clock ID exposed by the CAR. + + The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + registers. These IDs often match those in the CAR's RST_DEVICES registers, + but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + this case, those clocks are assigned IDs above 160 in order to highlight + this issue. Implementations that interpret these clock IDs as bit values + within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + explicitly handle these special cases. + + The balance of the clocks controlled by the CAR are assigned IDs of 160 and + above. + + 0 cpu + 1 unassigned + 2 unassigned + 3 unassigned + 4 rtc + 5 timer + 6 uarta + 7 unassigned (register bit affects uartb and vfir) + 8 gpio + 9 sdmmc2 + 10 unassigned (register bit affects spdif_in and spdif_out) + 11 i2s1 + 12 i2c1 + 13 ndflash + 14 sdmmc1 + 15 sdmmc4 + 16 unassigned + 17 pwm + 18 i2s2 + 19 epp + 20 unassigned (register bit affects vi and vi_sensor) + 21 2d + 22 usbd + 23 isp + 24 3d + 25 unassigned + 26 disp2 + 27 disp1 + 28 host1x + 29 vcp + 30 i2s0 + 31 cop_cache + + 32 mc + 33 ahbdma + 34 apbdma + 35 unassigned + 36 kbc + 37 statmon + 38 pmc + 39 unassigned (register bit affects fuse and fuse_burn) + 40 kfuse + 41 sbc1 + 42 nor + 43 unassigned + 44 sbc2 + 45 unassigned + 46 sbc3 + 47 i2c5 + 48 dsia + 49 unassigned (register bit affects cve and tvo) + 50 mipi + 51 hdmi + 52 csi + 53 tvdac + 54 i2c2 + 55 uartc + 56 unassigned + 57 emc + 58 usb2 + 59 usb3 + 60 mpe + 61 vde + 62 bsea + 63 bsev + + 64 speedo + 65 uartd + 66 uarte + 67 i2c3 + 68 sbc4 + 69 sdmmc3 + 70 pcie + 71 owr + 72 afi + 73 csite + 74 pciex + 75 avpucq + 76 la + 77 unassigned + 78 unassigned + 79 dtv + 80 ndspeed + 81 i2cslow + 82 dsib + 83 unassigned + 84 irama + 85 iramb + 86 iramc + 87 iramd + 88 cram2 + 89 unassigned + 90 audio_2x a/k/a audio_2x_sync_clk + 91 unassigned + 92 csus + 93 cdev2 + 94 cdev1 + 95 unassigned + + 96 cpu_g + 97 cpu_lp + 98 3d2 + 99 mselect + 100 tsensor + 101 i2s3 + 102 i2s4 + 103 i2c4 + 104 sbc5 + 105 sbc6 + 106 d_audio + 107 apbif + 108 dam0 + 109 dam1 + 110 dam2 + 111 hda2codec_2x + 112 atomics + 113 audio0_2x + 114 audio1_2x + 115 audio2_2x + 116 audio3_2x + 117 audio4_2x + 118 audio5_2x + 119 actmon + 120 extern1 + 121 extern2 + 122 extern3 + 123 sata_oob + 124 sata + 125 hda + 127 se + 128 hda2hdmi + 129 sata_cold + + 160 uartb + 161 vfir + 162 spdif_in + 163 spdif_out + 164 vi + 165 vi_sensor + 166 fuse + 167 fuse_burn + 168 cve + 169 tvo + + 170 clk_32k + 171 clk_m + 172 clk_m_div2 + 173 clk_m_div4 + 174 pll_ref + 175 pll_c + 176 pll_c_out1 + 177 pll_m + 178 pll_m_out1 + 179 pll_p + 180 pll_p_out1 + 181 pll_p_out2 + 182 pll_p_out3 + 183 pll_p_out4 + 184 pll_a + 185 pll_a_out0 + 186 pll_d + 187 pll_d_out0 + 188 pll_d2 + 189 pll_d2_out0 + 190 pll_u + 191 pll_x + 192 pll_x_out0 + 193 pll_e + 194 spdif_in_sync + 195 i2s0_sync + 196 i2s1_sync + 197 i2s2_sync + 198 i2s3_sync + 199 i2s4_sync + 200 vimclk + 201 audio0 + 202 audio1 + 203 audio2 + 204 audio3 + 205 audio4 + 206 audio5 + 207 clk_out_1 (extern1) + 208 clk_out_2 (extern2) + 209 clk_out_3 (extern3) + 210 sclk + 211 blink + 212 cclk_g + 213 cclk_lp + 214 twd + 215 cml0 + 216 cml1 + 217 hclk + 218 pclk + +Example SoC include file: + +/ { + tegra_car: clock { + compatible = "nvidia,tegra30-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + usb@c5004000 { + clocks = <&tegra_car 58>; /* usb2 */ + }; +}; + +Example board file: + +/ { + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + osc: clock@0 { + compatible = "fixed-clock"; + reg = <0>; + #clock-cells = <0>; + clock-frequency = <12000000>; + }; + + clk_32k: clock@1 { + compatible = "fixed-clock"; + reg = <1>; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + }; + + &tegra_car { + clocks = <&clk_32k> <&osc>; + }; +}; diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt index e9b005d..34c9528 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt @@ -11,6 +11,7 @@ Required properties : - phy_type : Should be one of "ulpi" or "utmi". - nvidia,vbus-gpio : If present, specifies a gpio that needs to be activated for the bus to be powered. + - nvidia,phy : phandle of the PHY instance, the controller is connected to. Required properties for phy_type == ulpi: - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. @@ -27,3 +28,5 @@ Optional properties: registers are accessed through the APB_MISC base address instead of the USB controller. Since this is a legacy issue it probably does not warrant a compatible string of its own. + - nvidia,needs-double-reset : boolean is to be set for some of the Tegra2 + USB ports, which need reset twice due to hardware issues. diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt new file mode 100644 index 0000000..6bdaba2 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt @@ -0,0 +1,17 @@ +Tegra SOC USB PHY + +The device node for Tegra SOC USB PHY: + +Required properties : + - compatible : Should be "nvidia,tegra20-usb-phy". + - reg : Address and length of the register set for the USB PHY interface. + - phy_type : Should be one of "ulpi" or "utmi". + +Required properties for phy_type == ulpi: + - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. + +Optional properties: + - nvidia,has-legacy-mode : boolean indicates whether this controller can + operate in legacy mode (as APX 2500 / 2600). In legacy mode some + registers are accessed through the APB_MISC base address instead of + the USB controller.
\ No newline at end of file diff --git a/Documentation/hid/hid-sensor.txt b/Documentation/hid/hid-sensor.txt index 948b098..948b098 100755..100644 --- a/Documentation/hid/hid-sensor.txt +++ b/Documentation/hid/hid-sensor.txt diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 406d82d..3edb4c2 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -57,6 +57,10 @@ Protocol 2.10: (Kernel 2.6.31) Added a protocol for relaxed alignment Protocol 2.11: (Kernel 3.6) Added a field for offset of EFI handover protocol entry point. +Protocol 2.12: (Kernel 3.9) Added the xloadflags field and extension fields + to struct boot_params for for loading bzImage and ramdisk + above 4G in 64bit. + **** MEMORY LAYOUT The traditional memory map for the kernel loader, used for Image or @@ -182,7 +186,7 @@ Offset Proto Name Meaning 0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel 0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not 0235/1 2.10+ min_alignment Minimum alignment, as a power of two -0236/2 N/A pad3 Unused +0236/2 2.12+ xloadflags Boot protocol option flags 0238/4 2.06+ cmdline_size Maximum size of the kernel command line 023C/4 2.07+ hardware_subarch Hardware subarchitecture 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data @@ -582,6 +586,27 @@ Protocol: 2.10+ misaligned kernel. Therefore, a loader should typically try each power-of-two alignment from kernel_alignment down to this alignment. +Field name: xloadflags +Type: read +Offset/size: 0x236/2 +Protocol: 2.12+ + + This field is a bitmask. + + Bit 0 (read): XLF_KERNEL_64 + - If 1, this kernel has the legacy 64-bit entry point at 0x200. + + Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G + - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G. + + Bit 2 (read): XLF_EFI_HANDOVER_32 + - If 1, the kernel supports the 32-bit EFI handoff entry point + given at handover_offset. + + Bit 3 (read): XLF_EFI_HANDOVER_64 + - If 1, the kernel supports the 64-bit EFI handoff entry point + given at handover_offset + 0x200. + Field name: cmdline_size Type: read Offset/size: 0x238/4 diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt index cf5437d..199f453 100644 --- a/Documentation/x86/zero-page.txt +++ b/Documentation/x86/zero-page.txt @@ -19,6 +19,9 @@ Offset Proto Name Meaning 090/010 ALL hd1_info hd1 disk parameter, OBSOLETE!! 0A0/010 ALL sys_desc_table System description table (struct sys_desc_table) 0B0/010 ALL olpc_ofw_header OLPC's OpenFirmware CIF and friends +0C0/004 ALL ext_ramdisk_image ramdisk_image high 32bits +0C4/004 ALL ext_ramdisk_size ramdisk_size high 32bits +0C8/004 ALL ext_cmd_line_ptr cmd_line_ptr high 32bits 140/080 ALL edid_info Video mode setup (struct edid_info) 1C0/020 ALL efi_info EFI 32 information (struct efi_info) 1E0/004 ALL alk_mem_k Alternative mem check, in KB @@ -27,6 +30,7 @@ Offset Proto Name Meaning 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer (below) +1EF/001 ALL sentinel Used to detect broken bootloaders 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures 2D0/A00 ALL e820_map E820 memory map table (array of struct e820entry) diff --git a/MAINTAINERS b/MAINTAINERS index 8ae709e..43dbae1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2966,7 +2966,7 @@ S: Maintained F: drivers/net/ethernet/i825xx/eexpress.* ETHERNET BRIDGE -M: Stephen Hemminger <shemminger@vyatta.com> +M: Stephen Hemminger <stephen@networkplumber.org> L: bridge@lists.linux-foundation.org L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net:Bridge @@ -4216,6 +4216,7 @@ M: Thomas Gleixner <tglx@linutronix.de> S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core F: kernel/irq/ +F: drivers/irqchip/ IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) M: Benjamin Herrenschmidt <benh@kernel.crashing.org> @@ -4905,7 +4906,7 @@ S: Maintained MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner <mlindner@marvell.com> -M: Stephen Hemminger <shemminger@vyatta.com> +M: Stephen Hemminger <stephen@networkplumber.org> L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/marvell/sk* @@ -5180,7 +5181,7 @@ S: Supported F: drivers/infiniband/hw/nes/ NETEM NETWORK EMULATOR -M: Stephen Hemminger <shemminger@vyatta.com> +M: Stephen Hemminger <stephen@networkplumber.org> L: netem@lists.linux-foundation.org S: Maintained F: net/sched/sch_netem.c @@ -7088,7 +7089,7 @@ F: include/uapi/sound/ F: sound/ SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) -M: Liam Girdwood <lrg@ti.com> +M: Liam Girdwood <lgirdwood@gmail.com> M: Mark Brown <broonie@opensource.wolfsonmicro.com> T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git L: alsa-devel@alsa-project.org (moderated for non-subscribers) @@ -1,8 +1,8 @@ VERSION = 3 PATCHLEVEL = 8 SUBLEVEL = 0 -EXTRAVERSION = -rc5 -NAME = Terrified Chipmunk +EXTRAVERSION = -rc6 +NAME = Unicycling Gorilla # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 67874b8..22bfac3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -393,6 +393,7 @@ config ARCH_GEMINI config ARCH_SIRF bool "CSR SiRF" select ARCH_REQUIRE_GPIOLIB + select AUTO_ZRELADDR select COMMON_CLK select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP @@ -642,6 +643,7 @@ config ARCH_TEGRA select ARCH_HAS_CPUFREQ select CLKDEV_LOOKUP select CLKSRC_MMIO + select CLKSRC_OF select COMMON_CLK select GENERIC_CLOCKEVENTS select GENERIC_GPIO @@ -949,22 +951,6 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1/2/3/4). -config ARCH_VT8500_SINGLE - bool "VIA/WonderMedia 85xx" - select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select CLKDEV_LOOKUP - select COMMON_CLK - select CPU_ARM926T - select GENERIC_CLOCKEVENTS - select GENERIC_GPIO - select HAVE_CLK - select MULTI_IRQ_HANDLER - select SPARSE_IRQ - select USE_OF - help - Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. - endchoice menu "Multiple platform selection" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 7fee63f..305ceb8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -393,6 +393,20 @@ choice Say Y here if you want kernel low-level debugging support on Tegra based platforms. + config DEBUG_SIRFPRIMA2_UART1 + bool "Kernel low-level debugging messages via SiRFprimaII UART1" + depends on ARCH_PRIMA2 + help + Say Y here if you want the debug print routines to direct + their output to the uart1 port on SiRFprimaII devices. + + config DEBUG_SIRFMARCO_UART1 + bool "Kernel low-level debugging messages via SiRFmarco UART1" + depends on ARCH_MARCO + help + Say Y here if you want the debug print routines to direct + their output to the uart1 port on SiRFmarco devices. + config DEBUG_VEXPRESS_UART0_DETECT bool "Autodetect UART0 on Versatile Express Cortex-A core tiles" depends on ARCH_VEXPRESS && CPU_CP15_MMU @@ -419,6 +433,13 @@ choice of the tiles using the RS1 memory map, including all new A-class core tiles, FPGA-based SMMs and software models. + config DEBUG_VT8500_UART0 + bool "Use UART0 on VIA/Wondermedia SoCs" + depends on ARCH_VT8500 + help + This option selects UART0 on VIA/Wondermedia System-on-a-chip + devices, including VT8500, WM8505, WM8650 and WM8850. + config DEBUG_LL_UART_NONE bool "No low-level debugging UART" depends on !ARCH_MULTIPLATFORM @@ -519,6 +540,7 @@ config DEBUG_LL_INCLUDE default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1 default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 + default "debug/vt8500.S" if DEBUG_VT8500_UART0 default "debug/tegra.S" if DEBUG_TEGRA_UART default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 default "mach/debug-macro.S" diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5ebb44f..2e7a7e2 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -73,6 +73,7 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \ kirkwood-ts219-6281.dtb \ kirkwood-ts219-6282.dtb \ kirkwood-openblocks_a6.dtb +dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \ msm8960-cdp.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \ @@ -143,7 +144,9 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-ventana.dtb \ tegra20-whistler.dtb \ tegra30-cardhu-a02.dtb \ - tegra30-cardhu-a04.dtb + tegra30-cardhu-a04.dtb \ + tegra114-dalmore.dtb \ + tegra114-pluto.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ @@ -151,7 +154,8 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ xenvm-4.2.dtb dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ wm8505-ref.dtb \ - wm8650-mid.dtb + wm8650-mid.dtb \ + wm8850-w70v2.dtb dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb targets += dtbs diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 42eac1f..740630f 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -93,6 +93,7 @@ reg = <0xd0400 0x20>; ngpios = <32>; interrupt-controller; + #interrupt-cells = <2>; interrupts = <12>, <13>, <14>, <60>; }; @@ -103,6 +104,7 @@ reg = <0xd0420 0x20>; ngpios = <32>; interrupt-controller; + #interrupt-cells = <2>; interrupts = <61>; }; diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi index eb504a6..c8a8c08 100644 --- a/arch/arm/boot/dts/emev2.dtsi +++ b/arch/arm/boot/dts/emev2.dtsi @@ -15,11 +15,18 @@ interrupt-parent = <&gic>; cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; compatible = "arm,cortex-a9"; + reg = <0>; }; cpu@1 { + device_type = "cpu"; compatible = "arm,cortex-a9"; + reg = <1>; }; }; diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi index eef7099..454c2d1 100644 --- a/arch/arm/boot/dts/imx31.dtsi +++ b/arch/arm/boot/dts/imx31.dtsi @@ -45,6 +45,8 @@ compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x43f90000 0x4000>; interrupts = <45>; + clocks = <&clks 10>, <&clks 30>; + clock-names = "ipg", "per"; status = "disabled"; }; @@ -52,12 +54,16 @@ compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x43f94000 0x4000>; interrupts = <32>; + clocks = <&clks 10>, <&clks 31>; + clock-names = "ipg", "per"; status = "disabled"; }; uart4: serial@43fb0000 { compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x43fb0000 0x4000>; + clocks = <&clks 10>, <&clks 49>; + clock-names = "ipg", "per"; interrupts = <46>; status = "disabled"; }; @@ -66,6 +72,8 @@ compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x43fb4000 0x4000>; interrupts = <47>; + clocks = <&clks 10>, <&clks 50>; + clock-names = "ipg", "per"; status = "disabled"; }; }; @@ -81,8 +89,17 @@ compatible = "fsl,imx31-uart", "fsl,imx21-uart"; reg = <0x5000c000 0x4000>; interrupts = <18>; + clocks = <&clks 10>, <&clks 48>; + clock-names = "ipg", "per"; status = "disabled"; }; + + clks: ccm@53f80000{ + compatible = "fsl,imx31-ccm"; + reg = <0x53f80000 0x4000>; + interrupts = <0 31 0x04 0 53 0x04>; + #clock-cells = <1>; + }; }; }; }; diff --git a/arch/arm/boot/dts/marco-evb.dts b/arch/arm/boot/dts/marco-evb.dts new file mode 100644 index 0000000..5130aea --- /dev/null +++ b/arch/arm/boot/dts/marco-evb.dts @@ -0,0 +1,54 @@ +/* + * DTS file for CSR SiRFmarco Evaluation Board + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +/dts-v1/; + +/include/ "marco.dtsi" + +/ { + model = "CSR SiRFmarco Evaluation Board"; + compatible = "sirf,marco-cb", "sirf,marco"; + + memory { + reg = <0x40000000 0x60000000>; + }; + + axi { + peri-iobg { + uart1: uart@cc060000 { + status = "okay"; + }; + uart2: uart@cc070000 { + status = "okay"; + }; + i2c0: i2c@cc0e0000 { + status = "okay"; + fpga-cpld@4d { + compatible = "sirf,fpga-cpld"; + reg = <0x4d>; + }; + }; + spi1: spi@cc170000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins_a>; + spi@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <1000000>; + }; + }; + pci-iobg { + sd0: sdhci@cd000000 { + bus-width = <8>; + status = "okay"; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/marco.dtsi b/arch/arm/boot/dts/marco.dtsi new file mode 100644 index 0000000..1579c34 --- /dev/null +++ b/arch/arm/boot/dts/marco.dtsi @@ -0,0 +1,756 @@ +/* + * DTS file for CSR SiRFmarco SoC + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +/include/ "skeleton.dtsi" +/ { + compatible = "sirf,marco"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + + axi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x40000000 0x40000000 0xa0000000>; + + l2-cache-controller@c0030000 { + compatible = "sirf,marco-pl310-cache", "arm,pl310-cache"; + reg = <0xc0030000 0x1000>; + interrupts = <0 59 0>; + arm,tag-latency = <1 1 1>; + arm,data-latency = <1 1 1>; + arm,filter-ranges = <0x40000000 0x80000000>; + }; + + gic: interrupt-controller@c0011000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0xc0011000 0x1000>, + <0xc0010100 0x0100>; + }; + + rstc-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc2000000 0xc2000000 0x1000000>; + + reset-controller@c2000000 { + compatible = "sirf,marco-rstc"; + reg = <0xc2000000 0x10000>; + }; + }; + + sys-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc3000000 0xc3000000 0x1000000>; + + clock-controller@c3000000 { + compatible = "sirf,marco-clkc"; + reg = <0xc3000000 0x1000>; + interrupts = <0 3 0>; + }; + + rsc-controller@c3010000 { + compatible = "sirf,marco-rsc"; + reg = <0xc3010000 0x1000>; + }; + }; + + mem-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc4000000 0xc4000000 0x1000000>; + + memory-controller@c4000000 { + compatible = "sirf,marco-memc"; + reg = <0xc4000000 0x10000>; + interrupts = <0 27 0>; + }; + }; + + disp-iobg0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc5000000 0xc5000000 0x1000000>; + + display0@c5000000 { + compatible = "sirf,marco-lcd"; + reg = <0xc5000000 0x10000>; + interrupts = <0 30 0>; + }; + + vpp0@c5010000 { + compatible = "sirf,marco-vpp"; + reg = <0xc5010000 0x10000>; + interrupts = <0 31 0>; + }; + }; + + disp-iobg1 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc6000000 0xc6000000 0x1000000>; + + display1@c6000000 { + compatible = "sirf,marco-lcd"; + reg = <0xc6000000 0x10000>; + interrupts = <0 62 0>; + }; + + vpp1@c6010000 { + compatible = "sirf,marco-vpp"; + reg = <0xc6010000 0x10000>; + interrupts = <0 63 0>; + }; + }; + + graphics-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc8000000 0xc8000000 0x1000000>; + + graphics@c8000000 { + compatible = "powervr,sgx540"; + reg = <0xc8000000 0x1000000>; + interrupts = <0 6 0>; + }; + }; + + multimedia-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xc9000000 0xc9000000 0x1000000>; + + multimedia@a0000000 { + compatible = "sirf,marco-video-codec"; + reg = <0xc9000000 0x1000000>; + interrupts = <0 5 0>; + }; + }; + + dsp-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xca000000 0xca000000 0x2000000>; + + dspif@ca000000 { + compatible = "sirf,marco-dspif"; + reg = <0xca000000 0x10000>; + interrupts = <0 9 0>; + }; + + gps@ca010000 { + compatible = "sirf,marco-gps"; + reg = <0xca010000 0x10000>; + interrupts = <0 7 0>; + }; + + dsp@cb000000 { + compatible = "sirf,marco-dsp"; + reg = <0xcb000000 0x1000000>; + interrupts = <0 8 0>; + }; + }; + + peri-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xcc000000 0xcc000000 0x2000000>; + + timer@cc020000 { + compatible = "sirf,marco-tick"; + reg = <0xcc020000 0x1000>; + interrupts = <0 0 0>, + <0 1 0>, + <0 2 0>, + <0 49 0>, + <0 50 0>, + <0 51 0>; + }; + + nand@cc030000 { + compatible = "sirf,marco-nand"; + reg = <0xcc030000 0x10000>; + interrupts = <0 41 0>; + }; + + audio@cc040000 { + compatible = "sirf,marco-audio"; + reg = <0xcc040000 0x10000>; + interrupts = <0 35 0>; + }; + + uart0: uart@cc050000 { + cell-index = <0>; + compatible = "sirf,marco-uart"; + reg = <0xcc050000 0x1000>; + interrupts = <0 17 0>; + fifosize = <128>; + status = "disabled"; + }; + + uart1: uart@cc060000 { + cell-index = <1>; + compatible = "sirf,marco-uart"; + reg = <0xcc060000 0x1000>; + interrupts = <0 18 0>; + fifosize = <32>; + status = "disabled"; + }; + + uart2: uart@cc070000 { + cell-index = <2>; + compatible = "sirf,marco-uart"; + reg = <0xcc070000 0x1000>; + interrupts = <0 19 0>; + fifosize = <128>; + status = "disabled"; + }; + + uart3: uart@cc190000 { + cell-index = <3>; + compatible = "sirf,marco-uart"; + reg = <0xcc190000 0x1000>; + interrupts = <0 66 0>; + fifosize = <128>; + status = "disabled"; + }; + + uart4: uart@cc1a0000 { + cell-index = <4>; + compatible = "sirf,marco-uart"; + reg = <0xcc1a0000 0x1000>; + interrupts = <0 69 0>; + fifosize = <128>; + status = "disabled"; + }; + + usp0: usp@cc080000 { + cell-index = <0>; + compatible = "sirf,marco-usp"; + reg = <0xcc080000 0x10000>; + interrupts = <0 20 0>; + status = "disabled"; + }; + + usp1: usp@cc090000 { + cell-index = <1>; + compatible = "sirf,marco-usp"; + reg = <0xcc090000 0x10000>; + interrupts = <0 21 0>; + status = "disabled"; + }; + + usp2: usp@cc0a0000 { + cell-index = <2>; + compatible = "sirf,marco-usp"; + reg = <0xcc0a0000 0x10000>; + interrupts = <0 22 0>; + status = "disabled"; + }; + + dmac0: dma-controller@cc0b0000 { + cell-index = <0>; + compatible = "sirf,marco-dmac"; + reg = <0xcc0b0000 0x10000>; + interrupts = <0 12 0>; + }; + + dmac1: dma-controller@cc160000 { + cell-index = <1>; + compatible = "sirf,marco-dmac"; + reg = <0xcc160000 0x10000>; + interrupts = <0 13 0>; + }; + + vip@cc0c0000 { + compatible = "sirf,marco-vip"; + reg = <0xcc0c0000 0x10000>; + }; + + spi0: spi@cc0d0000 { + cell-index = <0>; + compatible = "sirf,marco-spi"; + reg = <0xcc0d0000 0x10000>; + interrupts = <0 15 0>; + sirf,spi-num-chipselects = <1>; + cs-gpios = <&gpio 0 0>; + sirf,spi-dma-rx-channel = <25>; + sirf,spi-dma-tx-channel = <20>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@cc170000 { + cell-index = <1>; + compatible = "sirf,marco-spi"; + reg = <0xcc170000 0x10000>; + interrupts = <0 16 0>; + sirf,spi-num-chipselects = <1>; + cs-gpios = <&gpio 0 0>; + sirf,spi-dma-rx-channel = <12>; + sirf,spi-dma-tx-channel = <13>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c0: i2c@cc0e0000 { + cell-index = <0>; + compatible = "sirf,marco-i2c"; + reg = <0xcc0e0000 0x10000>; + interrupts = <0 24 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@cc0f0000 { + cell-index = <1>; + compatible = "sirf,marco-i2c"; + reg = <0xcc0f0000 0x10000>; + interrupts = <0 25 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + tsc@cc110000 { + compatible = "sirf,marco-tsc"; + reg = <0xcc110000 0x10000>; + interrupts = <0 33 0>; + }; + + gpio: pinctrl@cc120000 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "sirf,marco-pinctrl"; + reg = <0xcc120000 0x10000>; + interrupts = <0 43 0>, + <0 44 0>, + <0 45 0>, + <0 46 0>, + <0 47 0>; + gpio-controller; + interrupt-controller; + + lcd_16pins_a: lcd0_0 { + lcd { + sirf,pins = "lcd_16bitsgrp"; + sirf,function = "lcd_16bits"; + }; + }; + lcd_18pins_a: lcd0_1 { + lcd { + sirf,pins = "lcd_18bitsgrp"; + sirf,function = "lcd_18bits"; + }; + }; + lcd_24pins_a: lcd0_2 { + lcd { + sirf,pins = "lcd_24bitsgrp"; + sirf,function = "lcd_24bits"; + }; + }; + lcdrom_pins_a: lcdrom0_0 { + lcd { + sirf,pins = "lcdromgrp"; + sirf,function = "lcdrom"; + }; + }; + uart0_pins_a: uart0_0 { + uart { + sirf,pins = "uart0grp"; + sirf,function = "uart0"; + }; + }; + uart1_pins_a: uart1_0 { + uart { + sirf,pins = "uart1grp"; + sirf,function = "uart1"; + }; + }; + uart2_pins_a: uart2_0 { + uart { + sirf,pins = "uart2grp"; + sirf,function = "uart2"; + }; + }; + uart2_noflow_pins_a: uart2_1 { + uart { + sirf,pins = "uart2_nostreamctrlgrp"; + sirf,function = "uart2_nostreamctrl"; + }; + }; + spi0_pins_a: spi0_0 { + spi { + sirf,pins = "spi0grp"; + sirf,function = "spi0"; + }; + }; + spi1_pins_a: spi1_0 { + spi { + sirf,pins = "spi1grp"; + sirf,function = "spi1"; + }; + }; + i2c0_pins_a: i2c0_0 { + i2c { + sirf,pins = "i2c0grp"; + sirf,function = "i2c0"; + }; + }; + i2c1_pins_a: i2c1_0 { + i2c { + sirf,pins = "i2c1grp"; + sirf,function = "i2c1"; + }; + }; + pwm0_pins_a: pwm0_0 { + pwm { + sirf,pins = "pwm0grp"; + sirf,function = "pwm0"; + }; + }; + pwm1_pins_a: pwm1_0 { + pwm { + sirf,pins = "pwm1grp"; + sirf,function = "pwm1"; + }; + }; + pwm2_pins_a: pwm2_0 { + pwm { + sirf,pins = "pwm2grp"; + sirf,function = "pwm2"; + }; + }; + pwm3_pins_a: pwm3_0 { + pwm { + sirf,pins = "pwm3grp"; + sirf,function = "pwm3"; + }; + }; + gps_pins_a: gps_0 { + gps { + sirf,pins = "gpsgrp"; + sirf,function = "gps"; + }; + }; + vip_pins_a: vip_0 { + vip { + sirf,pins = "vipgrp"; + sirf,function = "vip"; + }; + }; + sdmmc0_pins_a: sdmmc0_0 { + sdmmc0 { + sirf,pins = "sdmmc0grp"; + sirf,function = "sdmmc0"; + }; + }; + sdmmc1_pins_a: sdmmc1_0 { + sdmmc1 { + sirf,pins = "sdmmc1grp"; + sirf,function = "sdmmc1"; + }; + }; + sdmmc2_pins_a: sdmmc2_0 { + sdmmc2 { + sirf,pins = "sdmmc2grp"; + sirf,function = "sdmmc2"; + }; + }; + sdmmc3_pins_a: sdmmc3_0 { + sdmmc3 { + sirf,pins = "sdmmc3grp"; + sirf,function = "sdmmc3"; + }; + }; + sdmmc4_pins_a: sdmmc4_0 { + sdmmc4 { + sirf,pins = "sdmmc4grp"; + sirf,function = "sdmmc4"; + }; + }; + sdmmc5_pins_a: sdmmc5_0 { + sdmmc5 { + sirf,pins = "sdmmc5grp"; + sirf,function = "sdmmc5"; + }; + }; + i2s_pins_a: i2s_0 { + i2s { + sirf,pins = "i2sgrp"; + sirf,function = "i2s"; + }; + }; + ac97_pins_a: ac97_0 { + ac97 { + sirf,pins = "ac97grp"; + sirf,function = "ac97"; + }; + }; + nand_pins_a: nand_0 { + nand { + sirf,pins = "nandgrp"; + sirf,function = "nand"; + }; + }; + usp0_pins_a: usp0_0 { + usp0 { + sirf,pins = "usp0grp"; + sirf,function = "usp0"; + }; + }; + usp1_pins_a: usp1_0 { + usp1 { + sirf,pins = "usp1grp"; + sirf,function = "usp1"; + }; + }; + usp2_pins_a: usp2_0 { + usp2 { + sirf,pins = "usp2grp"; + sirf,function = "usp2"; + }; + }; + usb0_utmi_drvbus_pins_a: usb0_utmi_drvbus_0 { + usb0_utmi_drvbus { + sirf,pins = "usb0_utmi_drvbusgrp"; + sirf,function = "usb0_utmi_drvbus"; + }; + }; + usb1_utmi_drvbus_pins_a: usb1_utmi_drvbus_0 { + usb1_utmi_drvbus { + sirf,pins = "usb1_utmi_drvbusgrp"; + sirf,function = "usb1_utmi_drvbus"; + }; + }; + warm_rst_pins_a: warm_rst_0 { + warm_rst { + sirf,pins = "warm_rstgrp"; + sirf,function = "warm_rst"; + }; + }; + pulse_count_pins_a: pulse_count_0 { + pulse_count { + sirf,pins = "pulse_countgrp"; + sirf,function = "pulse_count"; + }; + }; + cko0_rst_pins_a: cko0_rst_0 { + cko0_rst { + sirf,pins = "cko0_rstgrp"; + sirf,function = "cko0_rst"; + }; + }; + cko1_rst_pins_a: cko1_rst_0 { + cko1_rst { + sirf,pins = "cko1_rstgrp"; + sirf,function = "cko1_rst"; + }; + }; + }; + + pwm@cc130000 { + compatible = "sirf,marco-pwm"; + reg = <0xcc130000 0x10000>; + }; + + efusesys@cc140000 { + compatible = "sirf,marco-efuse"; + reg = <0xcc140000 0x10000>; + }; + + pulsec@cc150000 { + compatible = "sirf,marco-pulsec"; + reg = <0xcc150000 0x10000>; + interrupts = <0 48 0>; + }; + + pci-iobg { + compatible = "sirf,marco-pciiobg", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xcd000000 0xcd000000 0x1000000>; + + sd0: sdhci@cd000000 { + cell-index = <0>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd000000 0x100000>; + interrupts = <0 38 0>; + status = "disabled"; + }; + + sd1: sdhci@cd100000 { + cell-index = <1>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd100000 0x100000>; + interrupts = <0 38 0>; + status = "disabled"; + }; + + sd2: sdhci@cd200000 { + cell-index = <2>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd200000 0x100000>; + interrupts = <0 23 0>; + status = "disabled"; + }; + + sd3: sdhci@cd300000 { + cell-index = <3>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd300000 0x100000>; + interrupts = <0 23 0>; + status = "disabled"; + }; + + sd4: sdhci@cd400000 { + cell-index = <4>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd400000 0x100000>; + interrupts = <0 39 0>; + status = "disabled"; + }; + + sd5: sdhci@cd500000 { + cell-index = <5>; + compatible = "sirf,marco-sdhc"; + reg = <0xcd500000 0x100000>; + interrupts = <0 39 0>; + status = "disabled"; + }; + + pci-copy@cd900000 { + compatible = "sirf,marco-pcicp"; + reg = <0xcd900000 0x100000>; + interrupts = <0 40 0>; + }; + + rom-interface@cda00000 { + compatible = "sirf,marco-romif"; + reg = <0xcda00000 0x100000>; + }; + }; + }; + + rtc-iobg { + compatible = "sirf,marco-rtciobg", "sirf-marco-rtciobg-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xc1000000 0x10000>; + + gpsrtc@1000 { + compatible = "sirf,marco-gpsrtc"; + reg = <0x1000 0x1000>; + interrupts = <0 55 0>, + <0 56 0>, + <0 57 0>; + }; + + sysrtc@2000 { + compatible = "sirf,marco-sysrtc"; + reg = <0x2000 0x1000>; + interrupts = <0 52 0>, + <0 53 0>, + <0 54 0>; + }; + + pwrc@3000 { + compatible = "sirf,marco-pwrc"; + reg = <0x3000 0x1000>; + interrupts = <0 32 0>; + }; + }; + + uus-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xce000000 0xce000000 0x1000000>; + + usb0: usb@ce000000 { + compatible = "chipidea,ci13611a-marco"; + reg = <0xce000000 0x10000>; + interrupts = <0 10 0>; + }; + + usb1: usb@ce010000 { + compatible = "chipidea,ci13611a-marco"; + reg = <0xce010000 0x10000>; + interrupts = <0 11 0>; + }; + + security@ce020000 { + compatible = "sirf,marco-security"; + reg = <0xce020000 0x10000>; + interrupts = <0 42 0>; + }; + }; + + can-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xd0000000 0xd0000000 0x1000000>; + + can0: can@d0000000 { + compatible = "sirf,marco-can"; + reg = <0xd0000000 0x10000>; + }; + + can1: can@d0010000 { + compatible = "sirf,marco-can"; + reg = <0xd0010000 0x10000>; + }; + }; + + lvds-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0xd1000000 0xd1000000 0x1000000>; + + lvds@d1000000 { + compatible = "sirf,marco-lvds"; + reg = <0xd1000000 0x10000>; + interrupts = <0 64 0>; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/sh73a0-reference.dtsi b/arch/arm/boot/dts/sh73a0-reference.dtsi new file mode 100644 index 0000000..d4bb012 --- /dev/null +++ b/arch/arm/boot/dts/sh73a0-reference.dtsi @@ -0,0 +1,24 @@ +/* + * Device Tree Source for the SH73A0 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "sh73a0.dtsi" + +/ { + compatible = "renesas,sh73a0"; + + mmcif: mmcif@0x10010000 { + compatible = "renesas,sh-mmcif"; + reg = <0xe6bd0000 0x100>; + interrupt-parent = <&gic>; + interrupts = <0 140 0x4 + 0 141 0x4>; + reg-io-width = <4>; + }; +}; diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi new file mode 100644 index 0000000..8a59465 --- /dev/null +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -0,0 +1,100 @@ +/* + * Device Tree Source for the SH73A0 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,sh73a0"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + + gic: interrupt-controller@f0001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <1>; + interrupt-controller; + reg = <0xf0001000 0x1000>, + <0xf0000100 0x100>; + }; + + i2c0: i2c@0xe6820000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,rmobile-iic"; + reg = <0xe6820000 0x425>; + interrupt-parent = <&gic>; + interrupts = <0 167 0x4 + 0 168 0x4 + 0 169 0x4 + 0 170 0x4>; + }; + + i2c1: i2c@0xe6822000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,rmobile-iic"; + reg = <0xe6822000 0x425>; + interrupt-parent = <&gic>; + interrupts = <0 51 0x4 + 0 52 0x4 + 0 53 0x4 + 0 54 0x4>; + }; + + i2c2: i2c@0xe6824000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,rmobile-iic"; + reg = <0xe6824000 0x425>; + interrupt-parent = <&gic>; + interrupts = <0 171 0x4 + 0 172 0x4 + 0 173 0x4 + 0 174 0x4>; + }; + + i2c3: i2c@0xe6826000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,rmobile-iic"; + reg = <0xe6826000 0x425>; + interrupt-parent = <&gic>; + interrupts = <0 183 0x4 + 0 184 0x4 + 0 185 0x4 + 0 186 0x4>; + }; + + i2c4: i2c@0xe6828000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,rmobile-iic"; + reg = <0xe6828000 0x425>; + interrupt-parent = <&gic>; + interrupts = <0 187 0x4 + 0 188 0x4 + 0 189 0x4 + 0 190 0x4>; + }; +}; diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts new file mode 100644 index 0000000..a30aca6 --- /dev/null +++ b/arch/arm/boot/dts/tegra114-dalmore.dts @@ -0,0 +1,21 @@ +/dts-v1/; + +/include/ "tegra114.dtsi" + +/ { + model = "NVIDIA Tegra114 Dalmore evaluation board"; + compatible = "nvidia,dalmore", "nvidia,tegra114"; + + memory { + reg = <0x80000000 0x40000000>; + }; + + serial@70006300 { + status = "okay"; + clock-frequency = <408000000>; + }; + + pmc { + nvidia,invert-interrupt; + }; +}; diff --git a/arch/arm/boot/dts/tegra114-pluto.dts b/arch/arm/boot/dts/tegra114-pluto.dts new file mode 100644 index 0000000..9bea8f5 --- /dev/null +++ b/arch/arm/boot/dts/tegra114-pluto.dts @@ -0,0 +1,21 @@ +/dts-v1/; + +/include/ "tegra114.dtsi" + +/ { + model = "NVIDIA Tegra114 Pluto evaluation board"; + compatible = "nvidia,pluto", "nvidia,tegra114"; + + memory { + reg = <0x80000000 0x40000000>; + }; + + serial@70006300 { + status = "okay"; + clock-frequency = <408000000>; + }; + + pmc { + nvidia,invert-interrupt; + }; +}; diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi new file mode 100644 index 0000000..1dfaf28 --- /dev/null +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -0,0 +1,153 @@ +/include/ "skeleton.dtsi" + +/ { + compatible = "nvidia,tegra114"; + interrupt-parent = <&gic>; + + gic: interrupt-controller { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x50041000 0x1000>, + <0x50042000 0x1000>, + <0x50044000 0x2000>, + <0x50046000 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer@60005000 { + compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer"; + reg = <0x60005000 0x400>; + interrupts = <0 0 0x04 + 0 1 0x04 + 0 41 0x04 + 0 42 0x04 + 0 121 0x04 + 0 122 0x04>; + }; + + tegra_car: clock { + compatible = "nvidia,tegra114-car, nvidia,tegra30-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + ahb: ahb { + compatible = "nvidia,tegra114-ahb", "nvidia,tegra30-ahb"; + reg = <0x6000c004 0x14c>; + }; + + gpio: gpio { + compatible = "nvidia,tegra114-gpio", "nvidia,tegra30-gpio"; + reg = <0x6000d000 0x1000>; + interrupts = <0 32 0x04 + 0 33 0x04 + 0 34 0x04 + 0 35 0x04 + 0 55 0x04 + 0 87 0x04 + 0 89 0x04 + 0 125 0x04>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + pinmux: pinmux { + compatible = "nvidia,tegra114-pinmux"; + reg = <0x70000868 0x148 /* Pad control registers */ + 0x70003000 0x40c>; /* Mux registers */ + }; + + serial@70006000 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006000 0x40>; + reg-shift = <2>; + interrupts = <0 36 0x04>; + status = "disabled"; + }; + + serial@70006040 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006040 0x40>; + reg-shift = <2>; + interrupts = <0 37 0x04>; + status = "disabled"; + }; + + serial@70006200 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006200 0x100>; + reg-shift = <2>; + interrupts = <0 46 0x04>; + status = "disabled"; + }; + + serial@70006300 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006300 0x100>; + reg-shift = <2>; + interrupts = <0 90 0x04>; + status = "disabled"; + }; + + rtc { + compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc"; + reg = <0x7000e000 0x100>; + interrupts = <0 2 0x04>; + }; + + pmc { + compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc"; + reg = <0x7000e400 0x400>; + }; + + iommu { + compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu"; + reg = <0x7000f010 0x02c + 0x7000f1f0 0x010 + 0x7000f228 0x074>; + nvidia,#asids = <4>; + dma-window = <0 0x40000000>; + nvidia,swgroups = <0x18659fe>; + nvidia,ahb = <&ahb>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <3>; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; +}; diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index 43eb72a..2b41697 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -432,6 +432,10 @@ status = "okay"; }; + usb-phy@c5004400 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + sdhci@c8000200 { status = "okay"; cd-gpios = <&gpio 69 0>; /* gpio PI5 */ diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index 6a93d14..11b30db 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -266,6 +266,8 @@ clock-frequency = <80000>; request-gpios = <&gpio 170 0>; /* gpio PV2 */ slave-addr = <138>; + clocks = <&tegra_car 67>, <&tegra_car 124>; + clock-names = "div-clk", "fast-clk"; }; i2c@7000d000 { @@ -418,6 +420,10 @@ status = "okay"; }; + usb-phy@c5004400 { + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; + sdhci@c8000000 { status = "okay"; cd-gpios = <&gpio 173 0>; /* gpio PV5 */ diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index 4204598..607bf0c 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -561,6 +561,10 @@ status = "okay"; }; + usb-phy@c5004400 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + sdhci@c8000000 { status = "okay"; power-gpios = <&gpio 86 0>; /* gpio PK6 */ diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index b70b4cb..e47cf6a 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -310,6 +310,10 @@ status = "okay"; }; + usb-phy@c5004400 { + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; + sdhci@c8000000 { status = "okay"; bus-width = <4>; diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index adc4754..f6c61d1 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -497,6 +497,10 @@ status = "okay"; }; + usb-phy@c5004400 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; + sdhci@c8000000 { status = "okay"; power-gpios = <&gpio 86 0>; /* gpio PK6 */ diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index b8effa1..2e7c83c 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -9,6 +9,7 @@ reg = <0x50000000 0x00024000>; interrupts = <0 65 0x04 /* mpcore syncpt */ 0 67 0x04>; /* mpcore general */ + clocks = <&tegra_car 28>; #address-cells = <1>; #size-cells = <1>; @@ -19,41 +20,49 @@ compatible = "nvidia,tegra20-mpe"; reg = <0x54040000 0x00040000>; interrupts = <0 68 0x04>; + clocks = <&tegra_car 60>; }; vi { compatible = "nvidia,tegra20-vi"; reg = <0x54080000 0x00040000>; interrupts = <0 69 0x04>; + clocks = <&tegra_car 100>; }; epp { compatible = "nvidia,tegra20-epp"; reg = <0x540c0000 0x00040000>; interrupts = <0 70 0x04>; + clocks = <&tegra_car 19>; }; isp { compatible = "nvidia,tegra20-isp"; reg = <0x54100000 0x00040000>; interrupts = <0 71 0x04>; + clocks = <&tegra_car 23>; }; gr2d { compatible = "nvidia,tegra20-gr2d"; reg = <0x54140000 0x00040000>; interrupts = <0 72 0x04>; + clocks = <&tegra_car 21>; }; gr3d { compatible = "nvidia,tegra20-gr3d"; reg = <0x54180000 0x00040000>; + clocks = <&tegra_car 24>; }; dc@54200000 { compatible = "nvidia,tegra20-dc"; reg = <0x54200000 0x00040000>; interrupts = <0 73 0x04>; + clocks = <&tegra_car 27>, <&tegra_car 121>; + clock-names = "disp1", "parent"; rgb { status = "disabled"; @@ -64,6 +73,8 @@ compatible = "nvidia,tegra20-dc"; reg = <0x54240000 0x00040000>; interrupts = <0 74 0x04>; + clocks = <&tegra_car 26>, <&tegra_car 121>; + clock-names = "disp2", "parent"; rgb { status = "disabled"; @@ -74,6 +85,8 @@ compatible = "nvidia,tegra20-hdmi"; reg = <0x54280000 0x00040000>; interrupts = <0 75 0x04>; + clocks = <&tegra_car 51>, <&tegra_car 117>; + clock-names = "hdmi", "parent"; status = "disabled"; }; @@ -81,12 +94,14 @@ compatible = "nvidia,tegra20-tvo"; reg = <0x542c0000 0x00040000>; interrupts = <0 76 0x04>; + clocks = <&tegra_car 102>; status = "disabled"; }; dsi { compatible = "nvidia,tegra20-dsi"; reg = <0x54300000 0x00040000>; + clocks = <&tegra_car 48>; status = "disabled"; }; }; @@ -123,6 +138,12 @@ 0 42 0x04>; }; + tegra_car: clock { + compatible = "nvidia,tegra20-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + apbdma: dma { compatible = "nvidia,tegra20-apbdma"; reg = <0x6000a000 0x1200>; @@ -142,6 +163,7 @@ 0 117 0x04 0 118 0x04 0 119 0x04>; + clocks = <&tegra_car 34>; }; ahb { @@ -183,6 +205,7 @@ reg = <0x70002800 0x200>; interrupts = <0 13 0x04>; nvidia,dma-request-selector = <&apbdma 2>; + clocks = <&tegra_car 11>; status = "disabled"; }; @@ -191,6 +214,7 @@ reg = <0x70002a00 0x200>; interrupts = <0 3 0x04>; nvidia,dma-request-selector = <&apbdma 1>; + clocks = <&tegra_car 18>; status = "disabled"; }; @@ -199,6 +223,7 @@ reg = <0x70006000 0x40>; reg-shift = <2>; interrupts = <0 36 0x04>; + clocks = <&tegra_car 6>; status = "disabled"; }; @@ -207,6 +232,7 @@ reg = <0x70006040 0x40>; reg-shift = <2>; interrupts = <0 37 0x04>; + clocks = <&tegra_car 96>; status = "disabled"; }; @@ -215,6 +241,7 @@ reg = <0x70006200 0x100>; reg-shift = <2>; interrupts = <0 46 0x04>; + clocks = <&tegra_car 55>; status = "disabled"; }; @@ -223,6 +250,7 @@ reg = <0x70006300 0x100>; reg-shift = <2>; interrupts = <0 90 0x04>; + clocks = <&tegra_car 65>; status = "disabled"; }; @@ -231,6 +259,7 @@ reg = <0x70006400 0x100>; reg-shift = <2>; interrupts = <0 91 0x04>; + clocks = <&tegra_car 66>; status = "disabled"; }; @@ -238,6 +267,7 @@ compatible = "nvidia,tegra20-pwm"; reg = <0x7000a000 0x100>; #pwm-cells = <2>; + clocks = <&tegra_car 17>; }; rtc { @@ -252,6 +282,8 @@ interrupts = <0 38 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 12>, <&tegra_car 124>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -262,6 +294,7 @@ nvidia,dma-request-selector = <&apbdma 11>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 43>; status = "disabled"; }; @@ -271,6 +304,8 @@ interrupts = <0 84 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 54>, <&tegra_car 124>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -280,6 +315,8 @@ interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 67>, <&tegra_car 124>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -289,6 +326,8 @@ interrupts = <0 53 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 47>, <&tegra_car 124>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -299,6 +338,7 @@ nvidia,dma-request-selector = <&apbdma 15>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 41>; status = "disabled"; }; @@ -309,6 +349,7 @@ nvidia,dma-request-selector = <&apbdma 16>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 44>; status = "disabled"; }; @@ -319,6 +360,7 @@ nvidia,dma-request-selector = <&apbdma 17>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 46>; status = "disabled"; }; @@ -329,6 +371,7 @@ nvidia,dma-request-selector = <&apbdma 18>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 68>; status = "disabled"; }; @@ -357,12 +400,40 @@ #size-cells = <0>; }; + phy1: usb-phy@c5000400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5000400 0x3c00>; + phy_type = "utmi"; + nvidia,has-legacy-mode; + clocks = <&tegra_car 22>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + + phy2: usb-phy@c5004400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5004400 0x3c00>; + phy_type = "ulpi"; + clocks = <&tegra_car 94>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + + phy3: usb-phy@c5008400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5008400 0x3C00>; + phy_type = "utmi"; + clocks = <&tegra_car 22>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + usb@c5000000 { compatible = "nvidia,tegra20-ehci", "usb-ehci"; reg = <0xc5000000 0x4000>; interrupts = <0 20 0x04>; phy_type = "utmi"; nvidia,has-legacy-mode; + clocks = <&tegra_car 22>; + nvidia,needs-double-reset; + nvidia,phy = <&phy1>; status = "disabled"; }; @@ -371,6 +442,8 @@ reg = <0xc5004000 0x4000>; interrupts = <0 21 0x04>; phy_type = "ulpi"; + clocks = <&tegra_car 58>; + nvidia,phy = <&phy2>; status = "disabled"; }; @@ -379,6 +452,8 @@ reg = <0xc5008000 0x4000>; interrupts = <0 97 0x04>; phy_type = "utmi"; + clocks = <&tegra_car 59>; + nvidia,phy = <&phy3>; status = "disabled"; }; @@ -386,6 +461,7 @@ compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000000 0x200>; interrupts = <0 14 0x04>; + clocks = <&tegra_car 14>; status = "disabled"; }; @@ -393,6 +469,7 @@ compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000200 0x200>; interrupts = <0 15 0x04>; + clocks = <&tegra_car 9>; status = "disabled"; }; @@ -400,6 +477,7 @@ compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000400 0x200>; interrupts = <0 19 0x04>; + clocks = <&tegra_car 69>; status = "disabled"; }; @@ -407,9 +485,27 @@ compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000600 0x200>; interrupts = <0 31 0x04>; + clocks = <&tegra_car 15>; status = "disabled"; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + pmu { compatible = "arm,cortex-a9-pmu"; interrupts = <0 56 0x04 diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 529fdb8..2de8b91 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -9,6 +9,7 @@ reg = <0x50000000 0x00024000>; interrupts = <0 65 0x04 /* mpcore syncpt */ 0 67 0x04>; /* mpcore general */ + clocks = <&tegra_car 28>; #address-cells = <1>; #size-cells = <1>; @@ -19,41 +20,50 @@ compatible = "nvidia,tegra30-mpe"; reg = <0x54040000 0x00040000>; interrupts = <0 68 0x04>; + clocks = <&tegra_car 60>; }; vi { compatible = "nvidia,tegra30-vi"; reg = <0x54080000 0x00040000>; interrupts = <0 69 0x04>; + clocks = <&tegra_car 164>; }; epp { compatible = "nvidia,tegra30-epp"; reg = <0x540c0000 0x00040000>; interrupts = <0 70 0x04>; + clocks = <&tegra_car 19>; }; isp { compatible = "nvidia,tegra30-isp"; reg = <0x54100000 0x00040000>; interrupts = <0 71 0x04>; + clocks = <&tegra_car 23>; }; gr2d { compatible = "nvidia,tegra30-gr2d"; reg = <0x54140000 0x00040000>; interrupts = <0 72 0x04>; + clocks = <&tegra_car 21>; }; gr3d { compatible = "nvidia,tegra30-gr3d"; reg = <0x54180000 0x00040000>; + clocks = <&tegra_car 24 &tegra_car 98>; + clock-names = "3d", "3d2"; }; dc@54200000 { compatible = "nvidia,tegra30-dc"; reg = <0x54200000 0x00040000>; interrupts = <0 73 0x04>; + clocks = <&tegra_car 27>, <&tegra_car 179>; + clock-names = "disp1", "parent"; rgb { status = "disabled"; @@ -64,6 +74,8 @@ compatible = "nvidia,tegra30-dc"; reg = <0x54240000 0x00040000>; interrupts = <0 74 0x04>; + clocks = <&tegra_car 26>, <&tegra_car 179>; + clock-names = "disp2", "parent"; rgb { status = "disabled"; @@ -74,6 +86,8 @@ compatible = "nvidia,tegra30-hdmi"; reg = <0x54280000 0x00040000>; interrupts = <0 75 0x04>; + clocks = <&tegra_car 51>, <&tegra_car 189>; + clock-names = "hdmi", "parent"; status = "disabled"; }; @@ -81,12 +95,14 @@ compatible = "nvidia,tegra30-tvo"; reg = <0x542c0000 0x00040000>; interrupts = <0 76 0x04>; + clocks = <&tegra_car 169>; status = "disabled"; }; dsi { compatible = "nvidia,tegra30-dsi"; reg = <0x54300000 0x00040000>; + clocks = <&tegra_car 48>; status = "disabled"; }; }; @@ -125,6 +141,12 @@ 0 122 0x04>; }; + tegra_car: clock { + compatible = "nvidia,tegra30-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + apbdma: dma { compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma"; reg = <0x6000a000 0x1400>; @@ -160,6 +182,7 @@ 0 141 0x04 0 142 0x04 0 143 0x04>; + clocks = <&tegra_car 34>; }; ahb: ahb { @@ -195,6 +218,7 @@ reg = <0x70006000 0x40>; reg-shift = <2>; interrupts = <0 36 0x04>; + clocks = <&tegra_car 6>; status = "disabled"; }; @@ -203,6 +227,7 @@ reg = <0x70006040 0x40>; reg-shift = <2>; interrupts = <0 37 0x04>; + clocks = <&tegra_car 160>; status = "disabled"; }; @@ -211,6 +236,7 @@ reg = <0x70006200 0x100>; reg-shift = <2>; interrupts = <0 46 0x04>; + clocks = <&tegra_car 55>; status = "disabled"; }; @@ -219,6 +245,7 @@ reg = <0x70006300 0x100>; reg-shift = <2>; interrupts = <0 90 0x04>; + clocks = <&tegra_car 65>; status = "disabled"; }; @@ -227,6 +254,7 @@ reg = <0x70006400 0x100>; reg-shift = <2>; interrupts = <0 91 0x04>; + clocks = <&tegra_car 66>; status = "disabled"; }; @@ -234,6 +262,7 @@ compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm"; reg = <0x7000a000 0x100>; #pwm-cells = <2>; + clocks = <&tegra_car 17>; }; rtc { @@ -248,6 +277,8 @@ interrupts = <0 38 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 12>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -257,6 +288,8 @@ interrupts = <0 84 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 54>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -266,6 +299,8 @@ interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 67>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -275,6 +310,8 @@ interrupts = <0 120 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 103>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -284,6 +321,8 @@ interrupts = <0 53 0x04>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 47>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; status = "disabled"; }; @@ -294,6 +333,7 @@ nvidia,dma-request-selector = <&apbdma 15>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 41>; status = "disabled"; }; @@ -304,6 +344,7 @@ nvidia,dma-request-selector = <&apbdma 16>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 44>; status = "disabled"; }; @@ -314,6 +355,7 @@ nvidia,dma-request-selector = <&apbdma 17>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 46>; status = "disabled"; }; @@ -324,6 +366,7 @@ nvidia,dma-request-selector = <&apbdma 18>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 68>; status = "disabled"; }; @@ -334,6 +377,7 @@ nvidia,dma-request-selector = <&apbdma 27>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 104>; status = "disabled"; }; @@ -344,6 +388,7 @@ nvidia,dma-request-selector = <&apbdma 28>; #address-cells = <1>; #size-cells = <0>; + clocks = <&tegra_car 105>; status = "disabled"; }; @@ -377,7 +422,13 @@ 0x70080200 0x100>; interrupts = <0 103 0x04>; nvidia,dma-request-selector = <&apbdma 1>; - + clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>, + <&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>, + <&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>, + <&tegra_car 110>, <&tegra_car 162>; + clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2", + "i2s3", "i2s4", "dam0", "dam1", "dam2", + "spdif_in"; ranges; #address-cells = <1>; #size-cells = <1>; @@ -386,6 +437,7 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080300 0x100>; nvidia,ahub-cif-ids = <4 4>; + clocks = <&tegra_car 30>; status = "disabled"; }; @@ -393,6 +445,7 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080400 0x100>; nvidia,ahub-cif-ids = <5 5>; + clocks = <&tegra_car 11>; status = "disabled"; }; @@ -400,6 +453,7 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080500 0x100>; nvidia,ahub-cif-ids = <6 6>; + clocks = <&tegra_car 18>; status = "disabled"; }; @@ -407,6 +461,7 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080600 0x100>; nvidia,ahub-cif-ids = <7 7>; + clocks = <&tegra_car 101>; status = "disabled"; }; @@ -414,6 +469,7 @@ compatible = "nvidia,tegra30-i2s"; reg = <0x70080700 0x100>; nvidia,ahub-cif-ids = <8 8>; + clocks = <&tegra_car 102>; status = "disabled"; }; }; @@ -422,6 +478,7 @@ compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000000 0x200>; interrupts = <0 14 0x04>; + clocks = <&tegra_car 14>; status = "disabled"; }; @@ -429,6 +486,7 @@ compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000200 0x200>; interrupts = <0 15 0x04>; + clocks = <&tegra_car 9>; status = "disabled"; }; @@ -436,6 +494,7 @@ compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000400 0x200>; interrupts = <0 19 0x04>; + clocks = <&tegra_car 69>; status = "disabled"; }; @@ -443,9 +502,39 @@ compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci"; reg = <0x78000600 0x200>; interrupts = <0 31 0x04>; + clocks = <&tegra_car 15>; status = "disabled"; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <3>; + }; + }; + pmu { compatible = "arm,cortex-a9-pmu"; interrupts = <0 144 0x04 diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts new file mode 100644 index 0000000..fcc660c --- /dev/null +++ b/arch/arm/boot/dts/wm8850-w70v2.dts @@ -0,0 +1,47 @@ +/* + * wm8850-w70v2.dts + * - Device tree file for Wondermedia WM8850 Tablet + * - 'W70-V2' mainboard + * - HongLianYing 'HLY070ML268-21A' 7" LCD panel + * + * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> + * + * Licensed under GPLv2 or later + */ + +/dts-v1/; +/include/ "wm8850.dtsi" + +/ { + model = "Wondermedia WM8850-W70v2 Tablet"; + + /* + * Display node is based on Sascha Hauer's patch on dri-devel. + * Added a bpp property to calculate the size of the framebuffer + * until the binding is formalized. + */ + display: display@0 { + modes { + mode0: mode@0 { + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hfront-porch = <40>; + hsync-len = <0>; + vback-porch = <32>; + vfront-porch = <11>; + vsync-len = <1>; + clock = <0>; /* unused but required */ + bpp = <16>; /* non-standard but required */ + }; + }; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 50000 1>; /* duty inverted */ + + brightness-levels = <0 40 60 80 100 130 190 255>; + default-brightness-level = <5>; + }; +}; diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/wm8850.dtsi new file mode 100644 index 0000000..e8cbfdc --- /dev/null +++ b/arch/arm/boot/dts/wm8850.dtsi @@ -0,0 +1,224 @@ +/* + * wm8850.dtsi - Device tree file for Wondermedia WM8850 SoC + * + * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> + * + * Licensed under GPLv2 or later + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "wm,wm8850"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + interrupt-parent = <&intc0>; + + intc0: interrupt-controller@d8140000 { + compatible = "via,vt8500-intc"; + interrupt-controller; + reg = <0xd8140000 0x10000>; + #interrupt-cells = <1>; + }; + + /* Secondary IC cascaded to intc0 */ + intc1: interrupt-controller@d8150000 { + compatible = "via,vt8500-intc"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0xD8150000 0x10000>; + interrupts = <56 57 58 59 60 61 62 63>; + }; + + gpio: gpio-controller@d8110000 { + compatible = "wm,wm8650-gpio"; + gpio-controller; + reg = <0xd8110000 0x10000>; + #gpio-cells = <3>; + }; + + pmc@d8130000 { + compatible = "via,vt8500-pmc"; + reg = <0xd8130000 0x1000>; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + ref25: ref25M { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + ref24: ref24M { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + plla: plla { + #clock-cells = <0>; + compatible = "wm,wm8750-pll-clock"; + clocks = <&ref25>; + reg = <0x200>; + }; + + pllb: pllb { + #clock-cells = <0>; + compatible = "wm,wm8750-pll-clock"; + clocks = <&ref25>; + reg = <0x204>; + }; + + clkuart0: uart0 { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&ref24>; + enable-reg = <0x254>; + enable-bit = <24>; + }; + + clkuart1: uart1 { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&ref24>; + enable-reg = <0x254>; + enable-bit = <25>; + }; + + clkuart2: uart2 { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&ref24>; + enable-reg = <0x254>; + enable-bit = <26>; + }; + + clkuart3: uart3 { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&ref24>; + enable-reg = <0x254>; + enable-bit = <27>; + }; + + clkpwm: pwm { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x350>; + enable-reg = <0x250>; + enable-bit = <17>; + }; + + clksdhc: sdhc { + #clock-cells = <0>; + compatible = "via,vt8500-device-clock"; + clocks = <&pllb>; + divisor-reg = <0x330>; + divisor-mask = <0x3f>; + enable-reg = <0x250>; + enable-bit = <0>; + }; + }; + }; + + fb@d8051700 { + compatible = "wm,wm8505-fb"; + reg = <0xd8051700 0x200>; + display = <&display>; + default-mode = <&mode0>; + }; + + ge_rops@d8050400 { + compatible = "wm,prizm-ge-rops"; + reg = <0xd8050400 0x100>; + }; + + pwm: pwm@d8220000 { + #pwm-cells = <3>; + compatible = "via,vt8500-pwm"; + reg = <0xd8220000 0x100>; + clocks = <&clkpwm>; + }; + + timer@d8130100 { + compatible = "via,vt8500-timer"; + reg = <0xd8130100 0x28>; + interrupts = <36>; + }; + + ehci@d8007900 { + compatible = "via,vt8500-ehci"; + reg = <0xd8007900 0x200>; + interrupts = <26>; + }; + + uhci@d8007b00 { + compatible = "platform-uhci"; + reg = <0xd8007b00 0x200>; + interrupts = <26>; + }; + + uhci@d8008d00 { + compatible = "platform-uhci"; + reg = <0xd8008d00 0x200>; + interrupts = <26>; + }; + + uart0: uart@d8200000 { + compatible = "via,vt8500-uart"; + reg = <0xd8200000 0x1040>; + interrupts = <32>; + clocks = <&clkuart0>; + }; + + uart1: uart@d82b0000 { + compatible = "via,vt8500-uart"; + reg = <0xd82b0000 0x1040>; + interrupts = <33>; + clocks = <&clkuart1>; + }; + + uart2: uart@d8210000 { + compatible = "via,vt8500-uart"; + reg = <0xd8210000 0x1040>; + interrupts = <47>; + clocks = <&clkuart2>; + }; + + uart3: uart@d82c0000 { + compatible = "via,vt8500-uart"; + reg = <0xd82c0000 0x1040>; + interrupts = <50>; + clocks = <&clkuart3>; + }; + + rtc@d8100000 { + compatible = "via,vt8500-rtc"; + reg = <0xd8100000 0x10000>; + interrupts = <48>; + }; + + sdhc@d800a000 { + compatible = "wm,wm8505-sdhc"; + reg = <0xd800a000 0x1000>; + interrupts = <20 21>; + clocks = <&clksdhc>; + bus-width = <4>; + sdon-inverted; + }; + }; +}; diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 45ceeb0..9353184 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -1,26 +1,3 @@ -config ARM_GIC - bool - select IRQ_DOMAIN - select MULTI_IRQ_HANDLER - -config GIC_NON_BANKED - bool - -config ARM_VIC - bool - select IRQ_DOMAIN - select MULTI_IRQ_HANDLER - -config ARM_VIC_NR - int - default 4 if ARCH_S5PV210 - default 3 if ARCH_S5PC100 - default 2 - depends on ARM_VIC - help - The maximum number of VICs available in the system, for - power management. - config ICST bool diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index e8a4e58..dc8dd0d 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -2,8 +2,6 @@ # Makefile for the linux kernel. # -obj-$(CONFIG_ARM_GIC) += gic.o -obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 6039f0c..0a39667 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -19,6 +19,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_ARCH_MXC=y CONFIG_ARCH_MULTI_V6=y CONFIG_ARCH_MULTI_V7=y +CONFIG_MACH_IMX31_DT=y CONFIG_MACH_MX31LILLY=y CONFIG_MACH_MX31LITE=y CONFIG_MACH_PCM037=y diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index 93f3794..13482ea 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -56,6 +56,7 @@ CONFIG_AEABI=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_KIRKWOOD=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index b5bc96c..cbd91bc 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -33,6 +33,8 @@ CONFIG_MVNETA=y CONFIG_MARVELL_PHY=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_I2C=y +CONFIG_I2C_MV64XXX=y CONFIG_SERIAL_8250_DW=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig index 6a936c7..002a1ce 100644 --- a/arch/arm/configs/prima2_defconfig +++ b/arch/arm/configs/prima2_defconfig @@ -11,6 +11,9 @@ CONFIG_PARTITION_ADVANCED=y CONFIG_BSD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y CONFIG_ARCH_SIRF=y +# CONFIG_SWP_EMULATE is not set +CONFIG_SMP=y +CONFIG_SCHED_MC=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_KEXEC=y diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index a59dcb5..ad41ec2 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -64,6 +64,24 @@ extern unsigned int processor_id; #define read_cpuid_ext(reg) 0 #endif +#define ARM_CPU_IMP_ARM 0x41 +#define ARM_CPU_IMP_INTEL 0x69 + +#define ARM_CPU_PART_ARM1136 0xB360 +#define ARM_CPU_PART_ARM1156 0xB560 +#define ARM_CPU_PART_ARM1176 0xB760 +#define ARM_CPU_PART_ARM11MPCORE 0xB020 +#define ARM_CPU_PART_CORTEX_A8 0xC080 +#define ARM_CPU_PART_CORTEX_A9 0xC090 +#define ARM_CPU_PART_CORTEX_A5 0xC050 +#define ARM_CPU_PART_CORTEX_A15 0xC0F0 +#define ARM_CPU_PART_CORTEX_A7 0xC070 + +#define ARM_CPU_XSCALE_ARCH_MASK 0xe000 +#define ARM_CPU_XSCALE_ARCH_V1 0x2000 +#define ARM_CPU_XSCALE_ARCH_V2 0x4000 +#define ARM_CPU_XSCALE_ARCH_V3 0x6000 + /* * The CPU ID never changes at run time, so we might as well tell the * compiler that it's constant. Use this function to read the CPU ID @@ -74,6 +92,21 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void) return read_cpuid(CPUID_ID); } +static inline unsigned int __attribute_const__ read_cpuid_implementor(void) +{ + return (read_cpuid_id() & 0xFF000000) >> 24; +} + +static inline unsigned int __attribute_const__ read_cpuid_part_number(void) +{ + return read_cpuid_id() & 0xFFF0; +} + +static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void) +{ + return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK; +} + static inline unsigned int __attribute_const__ read_cpuid_cachetype(void) { return read_cpuid(CPUID_CACHETYPE); diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 917d4fc..308ad7d 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -12,7 +12,6 @@ struct tag; struct meminfo; -struct sys_timer; struct pt_regs; struct smp_operations; #ifdef CONFIG_SMP @@ -48,7 +47,7 @@ struct machine_desc { void (*map_io)(void);/* IO mapping function */ void (*init_early)(void); void (*init_irq)(void); - struct sys_timer *timer; /* system tick timer */ + void (*init_time)(void); void (*init_machine)(void); void (*init_late)(void); #ifdef CONFIG_MULTI_IRQ_HANDLER diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index 15cb035..18c8830 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h @@ -22,6 +22,7 @@ extern int show_fiq_list(struct seq_file *, int); #ifdef CONFIG_MULTI_IRQ_HANDLER extern void (*handle_arch_irq)(struct pt_regs *); +extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); #endif /* diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index 6ca945f..90c12e1 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h @@ -10,36 +10,6 @@ #ifndef __ASM_ARM_MACH_TIME_H #define __ASM_ARM_MACH_TIME_H -/* - * This is our kernel timer structure. - * - * - init - * Initialise the kernels jiffy timer source, claim interrupt - * using setup_irq. This is called early on during initialisation - * while interrupts are still disabled on the local CPU. - * - suspend - * Suspend the kernel jiffy timer source, if necessary. This - * is called with interrupts disabled, after all normal devices - * have been suspended. If no action is required, set this to - * NULL. - * - resume - * Resume the kernel jiffy timer source, if necessary. This - * is called with interrupts disabled before any normal devices - * are resumed. If no action is required, set this to NULL. - * - offset - * Return the timer offset in microseconds since the last timer - * interrupt. Note: this must take account of any unprocessed - * timer interrupt which may be pending. - */ -struct sys_timer { - void (*init)(void); - void (*suspend)(void); - void (*resume)(void); -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET - unsigned long (*offset)(void); -#endif -}; - extern void timer_tick(void); struct timespec; diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h index 4eb6d00..006f026 100644 --- a/arch/arm/include/asm/smp_scu.h +++ b/arch/arm/include/asm/smp_scu.h @@ -6,6 +6,23 @@ #define SCU_PM_POWEROFF 3 #ifndef __ASSEMBLER__ + +#include <asm/cputype.h> + +static inline bool scu_a9_has_base(void) +{ + return read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9; +} + +static inline unsigned long scu_a9_get_base(void) +{ + unsigned long pa; + + asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa)); + + return pa; +} + unsigned int scu_get_core_count(void __iomem *); void scu_enable(void __iomem *); int scu_power_mode(void __iomem *, unsigned int); diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/include/debug/vt8500.S index ca292f2..0e0ca08 100644 --- a/arch/arm/mach-vt8500/include/mach/debug-macro.S +++ b/arch/arm/include/debug/vt8500.S @@ -1,20 +1,24 @@ -/* - * arch/arm/mach-vt8500/include/mach/debug-macro.S +/* + * Debugging macro include header * * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * Debugging macro include header + * Moved from arch/arm/mach-vt8500/include/mach/debug-macro.S + * Minor changes for readability. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * -*/ + */ + +#define DEBUG_LL_PHYS_BASE 0xD8000000 +#define DEBUG_LL_VIRT_BASE 0xF8000000 +#define DEBUG_LL_UART_OFFSET 0x00200000 +#if defined(CONFIG_DEBUG_VT8500_UART0) .macro addruart, rp, rv, tmp - mov \rp, #0x00200000 - orr \rv, \rp, #0xf8000000 - orr \rp, \rp, #0xd8000000 + mov \rp, #DEBUG_LL_UART_OFFSET + orr \rv, \rp, #DEBUG_LL_VIRT_BASE + orr \rp, \rp, #DEBUG_LL_PHYS_BASE .endm .macro senduart,rd,rx @@ -29,3 +33,5 @@ .macro waituart,rd,rx .endm + +#endif diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 8961650..8e4ef4c 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -117,6 +117,16 @@ void __init init_IRQ(void) machine_desc->init_irq(); } +#ifdef CONFIG_MULTI_IRQ_HANDLER +void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) +{ + if (handle_arch_irq) + return; + + handle_arch_irq = handle_irq; +} +#endif + #ifdef CONFIG_SPARSE_IRQ int __init arch_probe_nr_irqs(void) { diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index f9e8657..31e0eb3 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -149,12 +149,6 @@ again: static void armpmu_read(struct perf_event *event) { - struct hw_perf_event *hwc = &event->hw; - - /* Don't read disabled counters! */ - if (hwc->idx < 0) - return; - armpmu_event_update(event); } @@ -207,8 +201,6 @@ armpmu_del(struct perf_event *event, int flags) struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx; - WARN_ON(idx < 0); - armpmu_stop(event, PERF_EF_UPDATE); hw_events->events[idx] = NULL; clear_bit(idx, hw_events->used_mask); @@ -358,7 +350,7 @@ __hw_perf_event_init(struct perf_event *event) { struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; - int mapping, err; + int mapping; mapping = armpmu->map_event(event); @@ -407,14 +399,12 @@ __hw_perf_event_init(struct perf_event *event) local64_set(&hwc->period_left, hwc->sample_period); } - err = 0; if (event->group_leader != event) { - err = validate_group(event); - if (err) + if (validate_group(event) != 0); return -EINVAL; } - return err; + return 0; } static int armpmu_event_init(struct perf_event *event) diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 5f66206..1f2740e 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -147,7 +147,7 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->free_irq = cpu_pmu_free_irq; /* Ensure the PMU has sane values out of reset. */ - if (cpu_pmu && cpu_pmu->reset) + if (cpu_pmu->reset) on_each_cpu(cpu_pmu->reset, cpu_pmu, 1); } @@ -201,48 +201,46 @@ static struct platform_device_id cpu_pmu_plat_device_ids[] = { static int probe_current_pmu(struct arm_pmu *pmu) { int cpu = get_cpu(); - unsigned long cpuid = read_cpuid_id(); - unsigned long implementor = (cpuid & 0xFF000000) >> 24; - unsigned long part_number = (cpuid & 0xFFF0); + unsigned long implementor = read_cpuid_implementor(); + unsigned long part_number = read_cpuid_part_number(); int ret = -ENODEV; pr_info("probing PMU on CPU %d\n", cpu); /* ARM Ltd CPUs. */ - if (0x41 == implementor) { + if (implementor == ARM_CPU_IMP_ARM) { switch (part_number) { - case 0xB360: /* ARM1136 */ - case 0xB560: /* ARM1156 */ - case 0xB760: /* ARM1176 */ + case ARM_CPU_PART_ARM1136: + case ARM_CPU_PART_ARM1156: + case ARM_CPU_PART_ARM1176: ret = armv6pmu_init(pmu); break; - case 0xB020: /* ARM11mpcore */ + case ARM_CPU_PART_ARM11MPCORE: ret = armv6mpcore_pmu_init(pmu); break; - case 0xC080: /* Cortex-A8 */ + case ARM_CPU_PART_CORTEX_A8: ret = armv7_a8_pmu_init(pmu); break; - case 0xC090: /* Cortex-A9 */ + case ARM_CPU_PART_CORTEX_A9: ret = armv7_a9_pmu_init(pmu); break; - case 0xC050: /* Cortex-A5 */ + case ARM_CPU_PART_CORTEX_A5: ret = armv7_a5_pmu_init(pmu); break; - case 0xC0F0: /* Cortex-A15 */ + case ARM_CPU_PART_CORTEX_A15: ret = armv7_a15_pmu_init(pmu); break; - case 0xC070: /* Cortex-A7 */ + case ARM_CPU_PART_CORTEX_A7: ret = armv7_a7_pmu_init(pmu); break; } /* Intel CPUs [xscale]. */ - } else if (0x69 == implementor) { - part_number = (cpuid >> 13) & 0x7; - switch (part_number) { - case 1: + } else if (implementor == ARM_CPU_IMP_INTEL) { + switch (xscale_cpu_arch_version()) { + case ARM_CPU_XSCALE_ARCH_V1: ret = xscale1pmu_init(pmu); break; - case 2: + case ARM_CPU_XSCALE_ARCH_V2: ret = xscale2pmu_init(pmu); break; } @@ -279,17 +277,22 @@ static int cpu_pmu_device_probe(struct platform_device *pdev) } if (ret) { - pr_info("failed to register PMU devices!"); - kfree(pmu); - return ret; + pr_info("failed to probe PMU!"); + goto out_free; } cpu_pmu = pmu; cpu_pmu->plat_device = pdev; cpu_pmu_init(cpu_pmu); - armpmu_register(cpu_pmu, PERF_TYPE_RAW); + ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW); - return 0; + if (!ret) + return 0; + +out_free: + pr_info("failed to register PMU devices!"); + kfree(pmu); + return ret; } static struct platform_driver cpu_pmu_driver = { diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 041d052..03664b0 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -106,7 +106,7 @@ static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] }, [C(OP_WRITE)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, @@ -259,7 +259,7 @@ static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] }, [C(OP_WRITE)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4fbc757..8c79a9e 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -157,8 +157,8 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, }, [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, @@ -282,7 +282,7 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] }, [C(OP_WRITE)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, @@ -399,8 +399,8 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, }, [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, /* * The prefetch counters don't differentiate between the I @@ -527,8 +527,8 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, }, [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, @@ -651,8 +651,8 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, }, [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 2b0fe30..63990c4 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c @@ -83,7 +83,7 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] }, [C(OP_WRITE)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, [C(OP_PREFETCH)] = { [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 84f4cbf..3fc96db 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -416,7 +416,8 @@ static void (*smp_cross_call)(const struct cpumask *, unsigned int); void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) { - smp_cross_call = fn; + if (!smp_cross_call) + smp_cross_call = fn; } void arch_send_call_function_ipi_mask(const struct cpumask *mask) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 49f335d..dc9bb014 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -24,7 +24,6 @@ #include <asm/smp_twd.h> #include <asm/localtimer.h> -#include <asm/hardware/gic.h> /* set up by the platform code */ static void __iomem *twd_base; diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 09be0c3..955d92d 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -21,7 +21,6 @@ #include <linux/timex.h> #include <linux/errno.h> #include <linux/profile.h> -#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h> @@ -31,11 +30,6 @@ #include <asm/mach/arch.h> #include <asm/mach/time.h> -/* - * Our system timer. - */ -static struct sys_timer *system_timer; - #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) /* this needs a better home */ @@ -69,16 +63,6 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); #endif -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -u32 arch_gettimeoffset(void) -{ - if (system_timer->offset != NULL) - return system_timer->offset() * 1000; - - return 0; -} -#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ - #ifndef CONFIG_GENERIC_CLOCKEVENTS /* * Kernel system timer support. @@ -129,43 +113,8 @@ int __init register_persistent_clock(clock_access_fn read_boot, return -EINVAL; } -#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) -static int timer_suspend(void) -{ - if (system_timer->suspend) - system_timer->suspend(); - - return 0; -} - -static void timer_resume(void) -{ - if (system_timer->resume) - system_timer->resume(); -} -#else -#define timer_suspend NULL -#define timer_resume NULL -#endif - -static struct syscore_ops timer_syscore_ops = { - .suspend = timer_suspend, - .resume = timer_resume, -}; - -static int __init timer_init_syscore_ops(void) -{ - register_syscore_ops(&timer_syscore_ops); - - return 0; -} - -device_initcall(timer_init_syscore_ops); - void __init time_init(void) { - system_timer = machine_desc->timer; - system_timer->init(); + machine_desc->init_time(); sched_clock_postinit(); } - diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index cafe988..2acdff4 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) static struct clock_event_device clkevt = { .name = "at91_tick", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 150, .set_next_event = clkevt32k_next_event, .set_mode = clkevt32k_mode, @@ -265,17 +264,10 @@ void __init at91rm9200_timer_init(void) at91_st_write(AT91_ST_RTMR, 1); /* Setup timer clockevent, with minimum of two ticks (important!!) */ - clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift); - clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt); - clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1; clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt); + clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, + 2, AT91_ST_ALMV); /* register clocksource */ clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); } - -struct sys_timer at91rm9200_timer = { - .init = at91rm9200_timer_init, -}; - diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 358412f..3a4bc2e 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -104,12 +104,38 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) } } +static void at91sam926x_pit_suspend(struct clock_event_device *cedev) +{ + /* Disable timer */ + pit_write(AT91_PIT_MR, 0); +} + +static void at91sam926x_pit_reset(void) +{ + /* Disable timer and irqs */ + pit_write(AT91_PIT_MR, 0); + + /* Clear any pending interrupts, wait for PIT to stop counting */ + while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0) + cpu_relax(); + + /* Start PIT but don't enable IRQ */ + pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); +} + +static void at91sam926x_pit_resume(struct clock_event_device *cedev) +{ + at91sam926x_pit_reset(); +} + static struct clock_event_device pit_clkevt = { .name = "pit", .features = CLOCK_EVT_FEAT_PERIODIC, .shift = 32, .rating = 100, .set_mode = pit_clkevt_mode, + .suspend = at91sam926x_pit_suspend, + .resume = at91sam926x_pit_resume, }; @@ -150,19 +176,6 @@ static struct irqaction at91sam926x_pit_irq = { .irq = NR_IRQS_LEGACY + AT91_ID_SYS, }; -static void at91sam926x_pit_reset(void) -{ - /* Disable timer and irqs */ - pit_write(AT91_PIT_MR, 0); - - /* Clear any pending interrupts, wait for PIT to stop counting */ - while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0) - cpu_relax(); - - /* Start PIT but don't enable IRQ */ - pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); -} - #ifdef CONFIG_OF static struct of_device_id pit_timer_ids[] = { { .compatible = "atmel,at91sam9260-pit" }, @@ -211,7 +224,7 @@ static int __init of_at91sam926x_pit_init(void) /* * Set up both clocksource and clockevent support. */ -static void __init at91sam926x_pit_init(void) +void __init at91sam926x_pit_init(void) { unsigned long pit_rate; unsigned bits; @@ -250,12 +263,6 @@ static void __init at91sam926x_pit_init(void) clockevents_register_device(&pit_clkevt); } -static void at91sam926x_pit_suspend(void) -{ - /* Disable timer */ - pit_write(AT91_PIT_MR, 0); -} - void __init at91sam926x_ioremap_pit(u32 addr) { #if defined(CONFIG_OF) @@ -272,9 +279,3 @@ void __init at91sam926x_ioremap_pit(u32 addr) if (!pit_base_addr) panic("Impossible to ioremap PIT\n"); } - -struct sys_timer at91sam926x_timer = { - .init = at91sam926x_pit_init, - .suspend = at91sam926x_pit_suspend, - .resume = at91sam926x_pit_reset, -}; diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c index 0e57e44..0c07a44 100644 --- a/arch/arm/mach-at91/at91x40_time.c +++ b/arch/arm/mach-at91/at91x40_time.c @@ -42,9 +42,10 @@ #define AT91_TC_CLK1BASE 0x40 #define AT91_TC_CLK2BASE 0x80 -static unsigned long at91x40_gettimeoffset(void) +static u32 at91x40_gettimeoffset(void) { - return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128)); + return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / + (AT91X40_MASTER_CLOCK / 128)) * 1000; } static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id) @@ -64,6 +65,8 @@ void __init at91x40_timer_init(void) { unsigned int v; + arch_gettimeoffset = at91x40_gettimeoffset; + at91_tc_write(AT91_TC_BCR, 0); v = at91_tc_read(AT91_TC_BMR); v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE; @@ -79,9 +82,3 @@ void __init at91x40_timer_init(void) at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN)); } - -struct sys_timer at91x40_timer = { - .init = at91x40_timer_init, - .offset = at91x40_gettimeoffset, -}; - diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c index b99b575..35ab632 100644 --- a/arch/arm/mach-at91/board-1arm.c +++ b/arch/arm/mach-at91/board-1arm.c @@ -90,7 +90,7 @@ static void __init onearm_board_init(void) MACHINE_START(ONEARM, "Ajeco 1ARM single board computer") /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = onearm_init_early, diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c index 854b979..f95e31c 100644 --- a/arch/arm/mach-at91/board-afeb-9260v1.c +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -210,7 +210,7 @@ static void __init afeb9260_board_init(void) MACHINE_START(AFEB9260, "Custom afeb9260 board") /* Maintainer: Sergey Lapin <slapin@ossfans.org> */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = afeb9260_init_early, diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index 28a18ce..ade948b 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -187,7 +187,7 @@ static void __init cam60_board_init(void) MACHINE_START(CAM60, "KwikByte CAM60") /* Maintainer: KwikByte */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = cam60_init_early, diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c index c17bb53..9298305 100644 --- a/arch/arm/mach-at91/board-carmeva.c +++ b/arch/arm/mach-at91/board-carmeva.c @@ -157,7 +157,7 @@ static void __init carmeva_board_init(void) MACHINE_START(CARMEVA, "Carmeva") /* Maintainer: Conitec Datasystems */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = carmeva_init_early, diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c index 8474324..008527e 100644 --- a/arch/arm/mach-at91/board-cpu9krea.c +++ b/arch/arm/mach-at91/board-cpu9krea.c @@ -374,7 +374,7 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260") MACHINE_START(CPUAT9G20, "Eukrea CPU9G20") #endif /* Maintainer: Eric Benard - EUKREA Electromatique */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = cpu9krea_init_early, diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c index 2a7af78..42f1353 100644 --- a/arch/arm/mach-at91/board-cpuat91.c +++ b/arch/arm/mach-at91/board-cpuat91.c @@ -178,7 +178,7 @@ static void __init cpuat91_board_init(void) MACHINE_START(CPUAT91, "Eukrea") /* Maintainer: Eric Benard - EUKREA Electromatique */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = cpuat91_init_early, diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index 48a531e..e5fde215 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -251,7 +251,7 @@ static void __init csb337_board_init(void) MACHINE_START(CSB337, "Cogent CSB337") /* Maintainer: Bill Gatliff */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = csb337_init_early, diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c index ec0f3ab..fdf1106 100644 --- a/arch/arm/mach-at91/board-csb637.c +++ b/arch/arm/mach-at91/board-csb637.c @@ -132,7 +132,7 @@ static void __init csb637_board_init(void) MACHINE_START(CSB637, "Cogent CSB637") /* Maintainer: Bill Gatliff */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = csb637_init_early, diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 881170c..8db3013 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c @@ -49,7 +49,7 @@ static const char *at91_dt_board_compat[] __initdata = { DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = at91_dt_initialize, diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c index b489388..becf0a6 100644 --- a/arch/arm/mach-at91/board-eb01.c +++ b/arch/arm/mach-at91/board-eb01.c @@ -44,7 +44,7 @@ static void __init at91eb01_init_early(void) MACHINE_START(AT91EB01, "Atmel AT91 EB01") /* Maintainer: Greg Ungerer <gerg@snapgear.com> */ - .timer = &at91x40_timer, + .init_time = at91x40_timer_init, .handle_irq = at91_aic_handle_irq, .init_early = at91eb01_init_early, .init_irq = at91eb01_init_irq, diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c index 9f5e71c..f9be816 100644 --- a/arch/arm/mach-at91/board-eb9200.c +++ b/arch/arm/mach-at91/board-eb9200.c @@ -116,7 +116,7 @@ static void __init eb9200_board_init(void) } MACHINE_START(ATEB9200, "Embest ATEB9200") - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = eb9200_init_early, diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c index ef69e0e..b2fcd71 100644 --- a/arch/arm/mach-at91/board-ecbat91.c +++ b/arch/arm/mach-at91/board-ecbat91.c @@ -181,7 +181,7 @@ static void __init ecb_at91board_init(void) MACHINE_START(ECBAT91, "emQbit's ECB_AT91") /* Maintainer: emQbit.com */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ecb_at91init_early, diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c index 50f3d37..77de410 100644 --- a/arch/arm/mach-at91/board-eco920.c +++ b/arch/arm/mach-at91/board-eco920.c @@ -149,7 +149,7 @@ static void __init eco920_board_init(void) MACHINE_START(ECO920, "eco920") /* Maintainer: Sascha Hauer */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = eco920_init_early, diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c index 5d44eba..737c085 100644 --- a/arch/arm/mach-at91/board-flexibity.c +++ b/arch/arm/mach-at91/board-flexibity.c @@ -159,7 +159,7 @@ static void __init flexibity_board_init(void) MACHINE_START(FLEXIBITY, "Flexibity Connect") /* Maintainer: Maxim Osipov */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = flexibity_init_early, diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c index 191d37c..2ea7059 100644 --- a/arch/arm/mach-at91/board-foxg20.c +++ b/arch/arm/mach-at91/board-foxg20.c @@ -261,7 +261,7 @@ static void __init foxg20_board_init(void) MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20") /* Maintainer: Sergio Tanzilli */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = foxg20_init_early, diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c index 23a2fa1..c1d61d2 100644 --- a/arch/arm/mach-at91/board-gsia18s.c +++ b/arch/arm/mach-at91/board-gsia18s.c @@ -574,7 +574,7 @@ static void __init gsia18s_board_init(void) } MACHINE_START(GSIA18S, "GS_IA18_S") - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = gsia18s_init_early, diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c index 9a43d1e..88e2f5d 100644 --- a/arch/arm/mach-at91/board-kafa.c +++ b/arch/arm/mach-at91/board-kafa.c @@ -103,7 +103,7 @@ static void __init kafa_board_init(void) MACHINE_START(KAFA, "Sperry-Sun KAFA") /* Maintainer: Sergei Sharonov */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = kafa_init_early, diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index f168bec..0c519d9 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -149,7 +149,7 @@ static void __init kb9202_board_init(void) MACHINE_START(KB9200, "KB920x") /* Maintainer: KwikByte, Inc. */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = kb9202_init_early, diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index bc7a1c4..5b4760f 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -378,7 +378,7 @@ static void __init neocore926_board_init(void) MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926") /* Maintainer: ADENEO */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = neocore926_init_early, diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index 0299554..65c0d6b 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c @@ -217,7 +217,7 @@ static void __init pcontrol_g20_board_init(void) MACHINE_START(PCONTROL_G20, "PControl G20") /* Maintainer: pgsellmann@portner-elektronik.at */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = pcontrol_g20_init_early, diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c index 4938f1c..ab2b2ec 100644 --- a/arch/arm/mach-at91/board-picotux200.c +++ b/arch/arm/mach-at91/board-picotux200.c @@ -119,7 +119,7 @@ static void __init picotux200_board_init(void) MACHINE_START(PICOTUX2XX, "picotux 200") /* Maintainer: Kleinhenz Elektronik GmbH */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = picotux200_init_early, diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index 33b1628..aa3bc9b 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -257,7 +257,7 @@ static void __init ek_board_init(void) MACHINE_START(QIL_A9260, "CALAO QIL_A9260") /* Maintainer: calao-systems */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c index 5f9ce3d..3fcb662 100644 --- a/arch/arm/mach-at91/board-rm9200-dt.c +++ b/arch/arm/mach-at91/board-rm9200-dt.c @@ -47,7 +47,7 @@ static const char *at91rm9200_dt_board_compat[] __initdata = { }; DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)") - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = at91rm9200_dt_initialize, diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c index 9e5061b..690541b 100644 --- a/arch/arm/mach-at91/board-rm9200dk.c +++ b/arch/arm/mach-at91/board-rm9200dk.c @@ -219,7 +219,7 @@ static void __init dk_board_init(void) MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK") /* Maintainer: SAN People/Atmel */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = dk_init_early, diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c index 58277db..8b17dad 100644 --- a/arch/arm/mach-at91/board-rm9200ek.c +++ b/arch/arm/mach-at91/board-rm9200ek.c @@ -186,7 +186,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK") /* Maintainer: SAN People/Atmel */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c index 2e8b833..f6d7f19 100644 --- a/arch/arm/mach-at91/board-rsi-ews.c +++ b/arch/arm/mach-at91/board-rsi-ews.c @@ -222,7 +222,7 @@ static void __init rsi_ews_board_init(void) MACHINE_START(RSI_EWS, "RSI EWS") /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = rsi_ews_init_early, diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index b75fbf6..43ee4dc 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -218,7 +218,7 @@ static void __init ek_board_init(void) MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260") /* Maintainer: Olimex */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index f0135cd..0b153c8 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -343,7 +343,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 13ebaa8..b446645 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -612,7 +612,7 @@ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK") #endif /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 89b9608..3284df0 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -443,7 +443,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 1b7dd9f..f9cd1f2 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -409,7 +409,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, @@ -419,7 +419,7 @@ MACHINE_END MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index e4cc375..2a94896 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -502,7 +502,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 377a109..aa265dc 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -320,7 +320,7 @@ static void __init ek_board_init(void) MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK") /* Maintainer: Atmel */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 9877150..3aaa978 100644 --- a/arch/arm/mach-at91/board-snapper9260.c +++ b/arch/arm/mach-at91/board-snapper9260.c @@ -177,7 +177,7 @@ static void __init snapper9260_board_init(void) } MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module") - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = snapper9260_init_early, diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 48a962b..a033b8d 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -272,7 +272,7 @@ static void __init stamp9g20evb_board_init(void) MACHINE_START(PORTUXG20, "taskit PortuxG20") /* Maintainer: taskit GmbH */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = stamp9g20_init_early, @@ -282,7 +282,7 @@ MACHINE_END MACHINE_START(STAMP9G20, "taskit Stamp9G20") /* Maintainer: taskit GmbH */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = stamp9g20_init_early, diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c index c1060f9..2487d94 100644 --- a/arch/arm/mach-at91/board-usb-a926x.c +++ b/arch/arm/mach-at91/board-usb-a926x.c @@ -355,7 +355,7 @@ static void __init ek_board_init(void) MACHINE_START(USB_A9263, "CALAO USB_A9263") /* Maintainer: calao-systems */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, @@ -365,7 +365,7 @@ MACHINE_END MACHINE_START(USB_A9260, "CALAO USB_A9260") /* Maintainer: calao-systems */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, @@ -375,7 +375,7 @@ MACHINE_END MACHINE_START(USB_A9G20, "CALAO USB_A92G0") /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */ - .timer = &at91sam926x_timer, + .init_time = at91sam926x_pit_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = ek_init_early, diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 8673aeb..be08377 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -587,7 +587,7 @@ static void __init yl9200_board_init(void) MACHINE_START(YL9200, "uCdragon YL-9200") /* Maintainer: S.Birtles */ - .timer = &at91rm9200_timer, + .init_time = at91rm9200_timer_init, .map_io = at91_map_io, .handle_irq = at91_aic_handle_irq, .init_early = yl9200_init_early, diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index fc593d6..78ab065 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -36,12 +36,11 @@ extern int __init at91_aic5_of_init(struct device_node *node, /* Timer */ -struct sys_timer; extern void at91rm9200_ioremap_st(u32 addr); -extern struct sys_timer at91rm9200_timer; +extern void at91rm9200_timer_init(void); extern void at91sam926x_ioremap_pit(u32 addr); -extern struct sys_timer at91sam926x_timer; -extern struct sys_timer at91x40_timer; +extern void at91sam926x_pit_init(void); +extern void at91x40_timer_init(void); /* Clocks */ #ifdef CONFIG_AT91_PMC_UNIT diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c index 3a62f1b..f0f9aba 100644 --- a/arch/arm/mach-bcm/board_bcm.c +++ b/arch/arm/mach-bcm/board_bcm.c @@ -11,34 +11,19 @@ * GNU General Public License for more details. */ -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> +#include <linux/irqchip.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> - #include <asm/mach/time.h> -static const struct of_device_id irq_match[] = { - {.compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - static void timer_init(void) { } -static struct sys_timer timer = { - .init = timer_init, -}; - -static void __init init_irq(void) -{ - of_irq_init(irq_match); -} static void __init board_init(void) { @@ -49,9 +34,8 @@ static void __init board_init(void) static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, }; DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor") - .init_irq = init_irq, - .timer = &timer, + .init_irq = irqchip_init, + .init_time = timer_init, .init_machine = board_init, .dt_compat = bcm11351_dt_compat, - .handle_irq = gic_handle_irq, MACHINE_END diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c index f0d739f..1a446a1 100644 --- a/arch/arm/mach-bcm2835/bcm2835.c +++ b/arch/arm/mach-bcm2835/bcm2835.c @@ -26,11 +26,13 @@ #include <mach/bcm2835_soc.h> #define PM_RSTC 0x1c +#define PM_RSTS 0x20 #define PM_WDOG 0x24 #define PM_PASSWORD 0x5a000000 #define PM_RSTC_WRCFG_MASK 0x00000030 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTS_HADWRH_SET 0x00000040 static void __iomem *wdt_regs; @@ -67,6 +69,29 @@ static void bcm2835_restart(char mode, const char *cmd) mdelay(1); } +/* + * We can't really power off, but if we do the normal reset scheme, and + * indicate to bootcode.bin not to reboot, then most of the chip will be + * powered off. + */ +static void bcm2835_power_off(void) +{ + u32 val; + + /* + * We set the watchdog hard reset bit here to distinguish this reset + * from the normal (full) reset. bootcode.bin will not reboot after a + * hard reset. + */ + val = readl_relaxed(wdt_regs + PM_RSTS); + val &= ~PM_RSTC_WRCFG_MASK; + val |= PM_PASSWORD | PM_RSTS_HADWRH_SET; + writel_relaxed(val, wdt_regs + PM_RSTS); + + /* Continue with normal reset mechanism */ + bcm2835_restart(0, ""); +} + static struct map_desc io_map __initdata = { .virtual = BCM2835_PERIPH_VIRT, .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), @@ -84,6 +109,9 @@ static void __init bcm2835_init(void) int ret; bcm2835_setup_restart(); + if (wdt_regs) + pm_power_off = bcm2835_power_off; + bcm2835_init_clocks(); ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, @@ -104,7 +132,7 @@ DT_MACHINE_START(BCM2835, "BCM2835") .init_irq = bcm2835_init_irq, .handle_irq = bcm2835_handle_irq, .init_machine = bcm2835_init, - .timer = &bcm2835_timer, + .init_time = bcm2835_timer_init, .restart = bcm2835_restart, .dt_compat = bcm2835_compat MACHINE_END diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c index 3fbf43f..f385847 100644 --- a/arch/arm/mach-clps711x/board-autcpu12.c +++ b/arch/arm/mach-clps711x/board-autcpu12.c @@ -170,7 +170,7 @@ MACHINE_START(AUTCPU12, "autronix autcpu12") .nr_irqs = CLPS711X_NR_IRQS, .map_io = clps711x_map_io, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .init_machine = autcpu12_init, .init_late = autcpu12_init_late, .handle_irq = clps711x_handle_irq, diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c index 60900dd..baab7da 100644 --- a/arch/arm/mach-clps711x/board-cdb89712.c +++ b/arch/arm/mach-clps711x/board-cdb89712.c @@ -140,7 +140,7 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712") .nr_irqs = CLPS711X_NR_IRQS, .map_io = clps711x_map_io, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .init_machine = cdb89712_init, .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c index 0b32a48..014aa3c 100644 --- a/arch/arm/mach-clps711x/board-clep7312.c +++ b/arch/arm/mach-clps711x/board-clep7312.c @@ -40,7 +40,7 @@ MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") .fixup = fixup_clep7312, .map_io = clps711x_map_io, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c index 71aa5cf..5f928e9 100644 --- a/arch/arm/mach-clps711x/board-edb7211.c +++ b/arch/arm/mach-clps711x/board-edb7211.c @@ -173,7 +173,7 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") .reserve = edb7211_reserve, .map_io = edb7211_map_io, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .init_machine = edb7211_init, .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, diff --git a/arch/arm/mach-clps711x/board-fortunet.c b/arch/arm/mach-clps711x/board-fortunet.c index 7d01255..c5675ef 100644 --- a/arch/arm/mach-clps711x/board-fortunet.c +++ b/arch/arm/mach-clps711x/board-fortunet.c @@ -78,7 +78,7 @@ MACHINE_START(FORTUNET, "ARM-FortuNet") .fixup = fortunet_fixup, .map_io = clps711x_map_io, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c index 1518fc8..8d3ee67 100644 --- a/arch/arm/mach-clps711x/board-p720t.c +++ b/arch/arm/mach-clps711x/board-p720t.c @@ -224,7 +224,7 @@ MACHINE_START(P720T, "ARM-Prospector720T") .map_io = p720t_map_io, .init_early = p720t_init_early, .init_irq = clps711x_init_irq, - .timer = &clps711x_timer, + .init_time = clps711x_timer_init, .init_machine = p720t_init, .init_late = p720t_init_late, .handle_irq = clps711x_handle_irq, diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index e046439..20ff50f 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -282,7 +282,7 @@ static void add_fixed_clk(struct clk *clk, const char *name, int rate) clk_register_clkdev(clk, name, NULL); } -static void __init clps711x_timer_init(void) +void __init clps711x_timer_init(void) { int osc, ext, pll, cpu, bus, timl, timh, uart, spi; u32 tmp; @@ -345,10 +345,6 @@ static void __init clps711x_timer_init(void) setup_irq(IRQ_TC2OI, &clps711x_timer_irq); } -struct sys_timer clps711x_timer = { - .init = clps711x_timer_init, -}; - void clps711x_restart(char mode, const char *cmd) { soft_restart(0); diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h index b7c0c75..f84a729 100644 --- a/arch/arm/mach-clps711x/common.h +++ b/arch/arm/mach-clps711x/common.h @@ -8,10 +8,8 @@ #define CLPS711X_NR_GPIO (4 * 8 + 3) #define CLPS711X_GPIO(prt, bit) ((prt) * 8 + (bit)) -struct sys_timer; - extern void clps711x_map_io(void); extern void clps711x_init_irq(void); +extern void clps711x_timer_init(void); extern void clps711x_handle_irq(struct pt_regs *regs); extern void clps711x_restart(char mode, const char *cmd); -extern struct sys_timer clps711x_timer; diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c index ae30539..a71867e 100644 --- a/arch/arm/mach-cns3xxx/cns3420vb.c +++ b/arch/arm/mach-cns3xxx/cns3420vb.c @@ -28,7 +28,6 @@ #include <linux/usb/ohci_pdriver.h> #include <asm/setup.h> #include <asm/mach-types.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -250,8 +249,7 @@ MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board") .atag_offset = 0x100, .map_io = cns3420_map_io, .init_irq = cns3xxx_init_irq, - .timer = &cns3xxx_timer, - .handle_irq = gic_handle_irq, + .init_time = cns3xxx_timer_init, .init_machine = cns3420_init, .restart = cns3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 031805b..e698f26 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -12,10 +12,10 @@ #include <linux/interrupt.h> #include <linux/clockchips.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/mach/irq.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <mach/cns3xxx.h> #include "core.h" @@ -134,7 +134,6 @@ static int cns3xxx_timer_set_next_event(unsigned long evt, static struct clock_event_device cns3xxx_tmr1_clockevent = { .name = "cns3xxx timer1", - .shift = 8, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = cns3xxx_timer_set_mode, .set_next_event = cns3xxx_timer_set_next_event, @@ -145,15 +144,9 @@ static struct clock_event_device cns3xxx_tmr1_clockevent = { static void __init cns3xxx_clockevents_init(unsigned int timer_irq) { cns3xxx_tmr1_clockevent.irq = timer_irq; - cns3xxx_tmr1_clockevent.mult = - div_sc((cns3xxx_cpu_clock() >> 3) * 1000000, NSEC_PER_SEC, - cns3xxx_tmr1_clockevent.shift); - cns3xxx_tmr1_clockevent.max_delta_ns = - clockevent_delta2ns(0xffffffff, &cns3xxx_tmr1_clockevent); - cns3xxx_tmr1_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &cns3xxx_tmr1_clockevent); - - clockevents_register_device(&cns3xxx_tmr1_clockevent); + clockevents_config_and_register(&cns3xxx_tmr1_clockevent, + (cns3xxx_cpu_clock() >> 3) * 1000000, + 0xf, 0xffffffff); } /* @@ -235,17 +228,13 @@ static void __init __cns3xxx_timer_init(unsigned int timer_irq) cns3xxx_clockevents_init(timer_irq); } -static void __init cns3xxx_timer_init(void) +void __init cns3xxx_timer_init(void) { cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT); __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0); } -struct sys_timer cns3xxx_timer = { - .init = cns3xxx_timer_init, -}; - #ifdef CONFIG_CACHE_L2X0 void __init cns3xxx_l2x0_init(void) diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h index 4894b8c..b23b17b 100644 --- a/arch/arm/mach-cns3xxx/core.h +++ b/arch/arm/mach-cns3xxx/core.h @@ -11,7 +11,7 @@ #ifndef __CNS3XXX_CORE_H #define __CNS3XXX_CORE_H -extern struct sys_timer cns3xxx_timer; +extern void cns3xxx_timer_init(void); #ifdef CONFIG_CACHE_L2X0 void __init cns3xxx_l2x0_init(void); diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 95b5e10..6da25ee 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -652,8 +652,13 @@ static __init void da830_evm_init(void) if (ret) pr_warning("da830_evm_init: rtc setup failed: %d\n", ret); - ret = da8xx_register_spi(0, da830evm_spi_info, - ARRAY_SIZE(da830evm_spi_info)); + ret = spi_register_board_info(da830evm_spi_info, + ARRAY_SIZE(da830evm_spi_info)); + if (ret) + pr_warn("%s: spi info registration failed: %d\n", __func__, + ret); + + ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info)); if (ret) pr_warning("da830_evm_init: spi 0 registration failed: %d\n", ret); @@ -679,7 +684,7 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM") .atag_offset = 0x100, .map_io = da830_evm_map_io, .init_irq = cp_intc_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = da830_evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 0299915..3a76a47 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -1565,8 +1565,13 @@ static __init void da850_evm_init(void) da850_vpif_init(); - ret = da8xx_register_spi(1, da850evm_spi_info, - ARRAY_SIZE(da850evm_spi_info)); + ret = spi_register_board_info(da850evm_spi_info, + ARRAY_SIZE(da850evm_spi_info)); + if (ret) + pr_warn("%s: spi info registration failed: %d\n", __func__, + ret); + + ret = da8xx_register_spi_bus(1, ARRAY_SIZE(da850evm_spi_info)); if (ret) pr_warning("da850_evm_init: spi 1 registration failed: %d\n", ret); @@ -1599,7 +1604,7 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM") .atag_offset = 0x100, .map_io = da850_evm_map_io, .init_irq = cp_intc_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = da850_evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index cdf8d07..147b8e1 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -355,7 +355,7 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM") .atag_offset = 0x100, .map_io = dm355_evm_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = dm355_evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index d419545..dff4ddc 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -274,7 +274,7 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard") .atag_offset = 0x100, .map_io = dm355_leopard_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = dm355_leopard_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 5d49c75..c2d4958 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -616,7 +616,7 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM") .atag_offset = 0x100, .map_io = dm365_evm_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = dm365_evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index f5e018d..e4a16f9 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -825,7 +825,7 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM") .atag_offset = 0x100, .map_io = davinci_evm_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = davinci_evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 6e2f163..de7adff 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -818,7 +818,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") .atag_offset = 0x100, .map_io = davinci_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, @@ -829,7 +829,7 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM") .atag_offset = 0x100, .map_io = davinci_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = evm_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 43e4a0d..9549d53 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -529,8 +529,13 @@ static void __init mityomapl138_init(void) mityomapl138_setup_nand(); - ret = da8xx_register_spi(1, mityomapl138_spi_flash_info, - ARRAY_SIZE(mityomapl138_spi_flash_info)); + ret = spi_register_board_info(mityomapl138_spi_flash_info, + ARRAY_SIZE(mityomapl138_spi_flash_info)); + if (ret) + pr_warn("spi info registration failed: %d\n", ret); + + ret = da8xx_register_spi_bus(1, + ARRAY_SIZE(mityomapl138_spi_flash_info)); if (ret) pr_warning("spi 1 registration failed: %d\n", ret); @@ -570,7 +575,7 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808") .atag_offset = 0x100, .map_io = mityomapl138_map_io, .init_irq = cp_intc_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = mityomapl138_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 3e3e3af..1c98107 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -237,7 +237,7 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2") .atag_offset = 0x100, .map_io = davinci_ntosd2_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = davinci_ntosd2_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index dc1208e..deb3922 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -341,7 +341,7 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") .atag_offset = 0x100, .map_io = omapl138_hawk_map_io, .init_irq = cp_intc_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = omapl138_hawk_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 6957787..739be7e 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -155,7 +155,7 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR") .atag_offset = 0x100, .map_io = davinci_sffsdr_map_io, .init_irq = davinci_irq_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = davinci_sffsdr_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index be30997..4f41602 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -280,7 +280,7 @@ MACHINE_START(TNETV107X, "TNETV107X EVM") .atag_offset = 0x100, .map_io = tnetv107x_init, .init_irq = cp_intc_init, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = tnetv107x_evm_board_init, .init_late = davinci_init_late, .dma_zone_size = SZ_128M, diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 34668ea..d458558 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -52,6 +52,40 @@ static void __clk_disable(struct clk *clk) __clk_disable(clk->parent); } +int davinci_clk_reset(struct clk *clk, bool reset) +{ + unsigned long flags; + + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + spin_lock_irqsave(&clockfw_lock, flags); + if (clk->flags & CLK_PSC) + davinci_psc_reset(clk->gpsc, clk->lpsc, reset); + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} +EXPORT_SYMBOL(davinci_clk_reset); + +int davinci_clk_reset_assert(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk) || !clk->reset) + return -EINVAL; + + return clk->reset(clk, true); +} +EXPORT_SYMBOL(davinci_clk_reset_assert); + +int davinci_clk_reset_deassert(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk) || !clk->reset) + return -EINVAL; + + return clk->reset(clk, false); +} +EXPORT_SYMBOL(davinci_clk_reset_deassert); + int clk_enable(struct clk *clk) { unsigned long flags; @@ -535,7 +569,7 @@ int davinci_set_refclk_rate(unsigned long rate) } int __init davinci_clk_init(struct clk_lookup *clocks) - { +{ struct clk_lookup *c; struct clk *clk; size_t num_clocks = 0; @@ -576,6 +610,9 @@ int __init davinci_clk_init(struct clk_lookup *clocks) if (clk->lpsc) clk->flags |= CLK_PSC; + if (clk->flags & PSC_LRST) + clk->reset = davinci_clk_reset; + clk_register(clk); num_clocks++; diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 46f0f1b..8694b39 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -103,6 +103,7 @@ struct clk { unsigned long (*recalc) (struct clk *); int (*set_rate) (struct clk *clk, unsigned long rate); int (*round_rate) (struct clk *clk, unsigned long rate); + int (*reset) (struct clk *clk, bool reset); }; /* Clock flags: SoC-specific flags start at BIT(16) */ @@ -112,6 +113,7 @@ struct clk { #define PRE_PLL BIT(4) /* source is before PLL mult/div */ #define PSC_SWRSTDISABLE BIT(5) /* Disable state is SwRstDisable */ #define PSC_FORCE BIT(6) /* Force module state transtition */ +#define PSC_LRST BIT(8) /* Use local reset on enable/disable */ #define CLK(dev, con, ck) \ { \ @@ -126,6 +128,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate); int davinci_set_refclk_rate(unsigned long rate); int davinci_simple_set_rate(struct clk *clk, unsigned long rate); +int davinci_clk_reset(struct clk *clk, bool reset); extern struct platform_device davinci_wdt_device; extern void davinci_watchdog_reset(struct platform_device *); diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 6b9154e..0c4a26d 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -76,6 +76,13 @@ static struct clk pll0_aux_clk = { .flags = CLK_PLL | PRE_PLL, }; +static struct clk pll0_sysclk1 = { + .name = "pll0_sysclk1", + .parent = &pll0_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV1, +}; + static struct clk pll0_sysclk2 = { .name = "pll0_sysclk2", .parent = &pll0_clk, @@ -368,10 +375,19 @@ static struct clk sata_clk = { .flags = PSC_FORCE, }; +static struct clk dsp_clk = { + .name = "dsp", + .parent = &pll0_sysclk1, + .domain = DAVINCI_GPSC_DSPDOMAIN, + .lpsc = DA8XX_LPSC0_GEM, + .flags = PSC_LRST | PSC_FORCE, +}; + static struct clk_lookup da850_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "pll0", &pll0_clk), CLK(NULL, "pll0_aux", &pll0_aux_clk), + CLK(NULL, "pll0_sysclk1", &pll0_sysclk1), CLK(NULL, "pll0_sysclk2", &pll0_sysclk2), CLK(NULL, "pll0_sysclk3", &pll0_sysclk3), CLK(NULL, "pll0_sysclk4", &pll0_sysclk4), @@ -413,6 +429,7 @@ static struct clk_lookup da850_clks[] = { CLK("spi_davinci.1", NULL, &spi1_clk), CLK("vpif", NULL, &vpif_clk), CLK("ahci", NULL, &sata_clk), + CLK("davinci-rproc.0", NULL, &dsp_clk), CLK(NULL, NULL, NULL), }; diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index 37c27af..9a7c76e 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -56,7 +56,7 @@ static const char *da850_boards_compat[] __initdata = { DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x") .map_io = da850_init, .init_irq = da8xx_init_irq, - .timer = &davinci_timer, + .init_time = davinci_timer_init, .init_machine = da850_init_machine, .dt_compat = da850_boards_compat, .init_late = davinci_init_late, diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 2d5502d..aa402bc 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -751,7 +751,7 @@ void __iomem * __init da8xx_get_mem_ctlr(void) da8xx_ddr2_ctlr_base = ioremap(DA8XX_DDR2_CTL_BASE, SZ_32K); if (!da8xx_ddr2_ctlr_base) - pr_warning("%s: Unable to map DDR2 controller", __func__); + pr_warn("%s: Unable to map DDR2 controller", __func__); return da8xx_ddr2_ctlr_base; } @@ -832,7 +832,7 @@ static struct resource da8xx_spi1_resources[] = { }, }; -struct davinci_spi_platform_data da8xx_spi_pdata[] = { +static struct davinci_spi_platform_data da8xx_spi_pdata[] = { [0] = { .version = SPI_VERSION_2, .intr_line = 1, @@ -866,20 +866,12 @@ static struct platform_device da8xx_spi_device[] = { }, }; -int __init da8xx_register_spi(int instance, const struct spi_board_info *info, - unsigned len) +int __init da8xx_register_spi_bus(int instance, unsigned num_chipselect) { - int ret; - if (instance < 0 || instance > 1) return -EINVAL; - ret = spi_register_board_info(info, len); - if (ret) - pr_warning("%s: failed to register board info for spi %d :" - " %d\n", __func__, instance, ret); - - da8xx_spi_pdata[instance].num_chipselect = len; + da8xx_spi_pdata[instance].num_chipselect = num_chipselect; if (instance == 1 && cpu_is_davinci_da850()) { da8xx_spi1_resources[0].start = DA850_SPI1_BASE; diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h index a3b0402..3e8af6a 100644 --- a/arch/arm/mach-davinci/include/mach/clock.h +++ b/arch/arm/mach-davinci/include/mach/clock.h @@ -18,4 +18,7 @@ struct clk; extern int clk_register(struct clk *clk); extern void clk_unregister(struct clk *clk); +int davinci_clk_reset_assert(struct clk *c); +int davinci_clk_reset_deassert(struct clk *c); + #endif diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 046c723..b124b77 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -15,9 +15,7 @@ #include <linux/compiler.h> #include <linux/types.h> -struct sys_timer; - -extern struct sys_timer davinci_timer; +extern void davinci_timer_init(void); extern void davinci_irq_init(void); extern void __iomem *davinci_intc_base; diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 700d311..1b14aea 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -82,8 +82,7 @@ void __init da850_init(void); int da830_register_edma(struct edma_rsv_info *rsv); int da850_register_edma(struct edma_rsv_info *rsv[2]); int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata); -int da8xx_register_spi(int instance, - const struct spi_board_info *info, unsigned len); +int da8xx_register_spi_bus(int instance, unsigned num_chipselect); int da8xx_register_watchdog(void); int da8xx_register_usb20(unsigned mA, unsigned potpgt); int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); @@ -110,7 +109,6 @@ extern struct platform_device da8xx_serial_device; extern struct emac_platform_data da8xx_emac_pdata; extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata; extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata; -extern struct davinci_spi_platform_data da8xx_spi_pdata[]; extern struct platform_device da8xx_wdt_device; diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 40a0027..0a22710 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -246,6 +246,7 @@ #define MDSTAT_STATE_MASK 0x3f #define PDSTAT_STATE_MASK 0x1f +#define MDCTL_LRST BIT(8) #define MDCTL_FORCE BIT(31) #define PDCTL_NEXT BIT(0) #define PDCTL_EPCGOOD BIT(8) @@ -253,6 +254,8 @@ #ifndef __ASSEMBLER__ extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id); +extern void davinci_psc_reset(unsigned int ctlr, unsigned int id, + bool reset); extern void davinci_psc_config(unsigned int domain, unsigned int ctlr, unsigned int id, bool enable, u32 flags); diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index d7e210f..82fdc69 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -35,7 +35,7 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) struct davinci_soc_info *soc_info = &davinci_soc_info; if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { - pr_warning("PSC: Bad psc data: 0x%x[%d]\n", + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", (int)soc_info->psc_bases, ctlr); return 0; } @@ -48,6 +48,31 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) return mdstat & BIT(12); } +/* Control "reset" line associated with PSC domain */ +void davinci_psc_reset(unsigned int ctlr, unsigned int id, bool reset) +{ + u32 mdctl; + void __iomem *psc_base; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", + (int)soc_info->psc_bases, ctlr); + return; + } + + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); + + mdctl = readl(psc_base + MDCTL + 4 * id); + if (reset) + mdctl &= ~MDCTL_LRST; + else + mdctl |= MDCTL_LRST; + writel(mdctl, psc_base + MDCTL + 4 * id); + + iounmap(psc_base); +} + /* Enable or disable a PSC domain */ void davinci_psc_config(unsigned int domain, unsigned int ctlr, unsigned int id, bool enable, u32 flags) @@ -58,7 +83,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, u32 next_state = PSC_STATE_ENABLE; if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { - pr_warning("PSC: Bad psc data: 0x%x[%d]\n", + pr_warn("PSC: Bad psc data: 0x%x[%d]\n", (int)soc_info->psc_bases, ctlr); return; } diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 9847938..bad361e 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -337,7 +337,7 @@ static struct clock_event_device clockevent_davinci = { }; -static void __init davinci_timer_init(void) +void __init davinci_timer_init(void) { struct clk *timer_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; @@ -410,11 +410,6 @@ static void __init davinci_timer_init(void) timer32_config(&timers[i]); } -struct sys_timer davinci_timer = { - .init = davinci_timer_init, -}; - - /* reset board using watchdog timer */ void davinci_watchdog_reset(struct platform_device *pdev) { diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c index 792b4e2..0dc39cf 100644 --- a/arch/arm/mach-dove/cm-a510.c +++ b/arch/arm/mach-dove/cm-a510.c @@ -92,6 +92,6 @@ MACHINE_START(CM_A510, "Compulab CM-A510 Board") .map_io = dove_map_io, .init_early = dove_init_early, .init_irq = dove_init_irq, - .timer = &dove_timer, + .init_time = dove_timer_init, .restart = dove_restart, MACHINE_END diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 89f4f99..0c7911b 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -242,17 +242,13 @@ static int __init dove_find_tclk(void) return 166666667; } -static void __init dove_timer_init(void) +void __init dove_timer_init(void) { dove_tclk = dove_find_tclk(); orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR, IRQ_DOVE_BRIDGE, dove_tclk); } -struct sys_timer dove_timer = { - .init = dove_timer_init, -}; - /***************************************************************************** * Cryptographic Engines and Security Accelerator (CESA) ****************************************************************************/ @@ -454,7 +450,7 @@ DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)") .map_io = dove_map_io, .init_early = dove_init_early, .init_irq = orion_dt_init_irq, - .timer = &dove_timer, + .init_time = dove_timer_init, .init_machine = dove_dt_init, .restart = dove_restart, .dt_compat = dove_dt_board_compat, diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h index 1a23340..ee59fba 100644 --- a/arch/arm/mach-dove/common.h +++ b/arch/arm/mach-dove/common.h @@ -14,7 +14,7 @@ struct mv643xx_eth_platform_data; struct mv_sata_platform_data; -extern struct sys_timer dove_timer; +extern void dove_timer_init(void); /* * Basic Dove init functions used early by machine-setup. diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c index bc2867f..76e26f9 100644 --- a/arch/arm/mach-dove/dove-db-setup.c +++ b/arch/arm/mach-dove/dove-db-setup.c @@ -98,6 +98,6 @@ MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board") .map_io = dove_map_io, .init_early = dove_init_early, .init_irq = dove_init_irq, - .timer = &dove_timer, + .init_time = dove_timer_init, .restart = dove_restart, MACHINE_END diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index f0fe6b5..b13cc74 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -158,7 +158,7 @@ static void __init ebsa110_init_early(void) * interrupt, then the PIT counter will roll over (ie, be negative). * This actually works out to be convenient. */ -static unsigned long ebsa110_gettimeoffset(void) +static u32 ebsa110_gettimeoffset(void) { unsigned long offset, count; @@ -181,7 +181,7 @@ static unsigned long ebsa110_gettimeoffset(void) */ offset = offset * (1000000 / HZ) / COUNT; - return offset; + return offset * 1000; } static irqreturn_t @@ -213,8 +213,10 @@ static struct irqaction ebsa110_timer_irq = { /* * Set up timer interrupt. */ -static void __init ebsa110_timer_init(void) +void __init ebsa110_timer_init(void) { + arch_gettimeoffset = ebsa110_gettimeoffset; + /* * Timer 1, mode 2, LSB/MSB */ @@ -225,11 +227,6 @@ static void __init ebsa110_timer_init(void) setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq); } -static struct sys_timer ebsa110_timer = { - .init = ebsa110_timer_init, - .offset = ebsa110_gettimeoffset, -}; - static struct plat_serial8250_port serial_platform_data[] = { { .iobase = 0x3f8, @@ -328,6 +325,6 @@ MACHINE_START(EBSA110, "EBSA110") .map_io = ebsa110_map_io, .init_early = ebsa110_init_early, .init_irq = ebsa110_init_irq, - .timer = &ebsa110_timer, + .init_time = ebsa110_timer_init, .restart = ebsa110_restart, MACHINE_END diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index 41383bf..bda6c3a 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -17,7 +17,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,8 +38,7 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = adssphere_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index e85bf17..c49ed3d 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -34,6 +34,7 @@ #include <linux/i2c-gpio.h> #include <linux/spi/spi.h> #include <linux/export.h> +#include <linux/irqchip/arm-vic.h> #include <mach/hardware.h> #include <linux/platform_data/video-ep93xx.h> @@ -44,8 +45,6 @@ #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/vic.h> - #include "soc.h" /************************************************************************* @@ -140,11 +139,29 @@ static struct irqaction ep93xx_timer_irq = { .handler = ep93xx_timer_interrupt, }; -static void __init ep93xx_timer_init(void) +static u32 ep93xx_gettimeoffset(void) +{ + int offset; + + offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; + + /* + * Timer 4 is based on a 983.04 kHz reference clock, + * so dividing by 983040 gives the fraction of a second, + * so dividing by 0.983040 converts to uS. + * Refactor the calculation to avoid overflow. + * Finally, multiply by 1000 to give nS. + */ + return (offset + (53 * offset / 3072)) * 1000; +} + +void __init ep93xx_timer_init(void) { u32 tmode = EP93XX_TIMER123_CONTROL_MODE | EP93XX_TIMER123_CONTROL_CLKSEL; + arch_gettimeoffset = ep93xx_gettimeoffset; + /* Enable periodic HZ timer. */ __raw_writel(tmode, EP93XX_TIMER1_CONTROL); __raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD); @@ -158,21 +175,6 @@ static void __init ep93xx_timer_init(void) setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq); } -static unsigned long ep93xx_gettimeoffset(void) -{ - int offset; - - offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; - - /* Calculate (1000000 / 983040) * offset. */ - return offset + (53 * offset / 3072); -} - -struct sys_timer ep93xx_timer = { - .init = ep93xx_timer_init, - .offset = ep93xx_gettimeoffset, -}; - /************************************************************************* * EP93xx IRQ handling diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index b8f53d5..27b14ae 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -39,7 +39,6 @@ #include <linux/platform_data/spi-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -276,8 +275,7 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -290,8 +288,7 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -304,8 +301,7 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -318,8 +314,7 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -332,8 +327,7 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -346,8 +340,7 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -360,8 +353,7 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -374,8 +366,7 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = edb93xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index 7fd705b..0cca5b1 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -17,7 +17,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,8 +38,7 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = gesbc9312_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 33a5122..a14e1b3 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -53,7 +53,7 @@ int ep93xx_ide_acquire_gpio(struct platform_device *pdev); void ep93xx_ide_release_gpio(struct platform_device *pdev); void ep93xx_init_devices(void); -extern struct sys_timer ep93xx_timer; +extern void ep93xx_timer_init(void); void ep93xx_restart(char, const char *); void ep93xx_init_late(void); diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index 3d7cdab..373583c 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -18,7 +18,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -82,8 +81,7 @@ MACHINE_START(MICRO9, "Contec Micro9-High") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -96,8 +94,7 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -110,8 +107,7 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, @@ -124,8 +120,7 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = micro9_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 0eb3f17..36f22c1 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -25,7 +25,6 @@ #include <linux/platform_data/video-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -83,8 +82,7 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = simone_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 50043ee..aa86f86 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -31,7 +31,6 @@ #include <linux/platform_data/video-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -176,8 +175,7 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15") .atag_offset = 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = snappercl15_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 3c4c233..61f4b5d 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -22,7 +22,6 @@ #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> @@ -246,8 +245,7 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") .atag_offset = 0x100, .map_io = ts72xx_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = ts72xx_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c index ba92e25..605956f 100644 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ b/arch/arm/mach-ep93xx/vision_ep9307.c @@ -34,7 +34,6 @@ #include <linux/platform_data/spi-ep93xx.h> #include <mach/gpio-ep93xx.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> @@ -364,8 +363,7 @@ MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307") .atag_offset = 0x100, .map_io = vision_map_io, .init_irq = ep93xx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &ep93xx_timer, + .init_time = ep93xx_timer_init, .init_machine = vision_init_machine, .init_late = ep93xx_init_late, .restart = ep93xx_restart, diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 1a89824..4ea80bc 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -22,12 +22,13 @@ #include <linux/of_irq.h> #include <linux/export.h> #include <linux/irqdomain.h> +#include <linux/irqchip.h> #include <linux/of_address.h> +#include <linux/irqchip/arm-gic.h> #include <asm/proc-fns.h> #include <asm/exception.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> #include <asm/cacheflush.h> @@ -644,8 +645,6 @@ static int __init combiner_of_init(struct device_node *np, } static const struct of_device_id exynos_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, { .compatible = "samsung,exynos4210-combiner", .data = combiner_of_init, }, {}, @@ -661,8 +660,10 @@ void __init exynos4_init_irq(void) if (!of_have_populated_dt()) gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL); #ifdef CONFIG_OF - else + else { + irqchip_init(); of_irq_init(exynos_dt_irq_match); + } #endif if (!of_have_populated_dt()) @@ -679,6 +680,7 @@ void __init exynos4_init_irq(void) void __init exynos5_init_irq(void) { #ifdef CONFIG_OF + irqchip_init(); of_irq_init(exynos_dt_irq_match); #endif /* diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 04744f9..12f2f11 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -12,7 +12,7 @@ #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H #define __ARCH_ARM_MACH_EXYNOS_COMMON_H -extern struct sys_timer exynos4_timer; +extern void exynos4_timer_init(void); struct map_desc; void exynos_init_io(struct map_desc *mach_desc, int size); diff --git a/arch/arm/mach-exynos/include/mach/regs-irq.h b/arch/arm/mach-exynos/include/mach/regs-irq.h index 9c7b4bf..f2b5050 100644 --- a/arch/arm/mach-exynos/include/mach/regs-irq.h +++ b/arch/arm/mach-exynos/include/mach/regs-irq.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c index b938f9f..685f291 100644 --- a/arch/arm/mach-exynos/mach-armlex4210.c +++ b/arch/arm/mach-exynos/mach-armlex4210.c @@ -16,7 +16,6 @@ #include <linux/smsc911x.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <plat/cpu.h> @@ -201,9 +200,8 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = armlex4210_map_io, - .handle_irq = gic_handle_irq, .init_machine = armlex4210_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index 92757ff..112d10e 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -15,7 +15,6 @@ #include <linux/serial_core.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/map.h> #include <plat/cpu.h> @@ -107,10 +106,9 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = exynos4_dt_map_io, - .handle_irq = gic_handle_irq, .init_machine = exynos4_dt_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .dt_compat = exynos4_dt_compat, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index e99d3d8..0deeecf 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -16,7 +16,6 @@ #include <linux/io.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/map.h> #include <mach/regs-pmu.h> @@ -179,10 +178,9 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") .init_irq = exynos5_init_irq, .smp = smp_ops(exynos_smp_ops), .map_io = exynos5_dt_map_io, - .handle_irq = gic_handle_irq, .init_machine = exynos5_dt_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .dt_compat = exynos5_dt_compat, .restart = exynos5_restart, .reserve = exynos5_reserve, diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index 27d4ed8..b8b3fbf 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -39,7 +39,6 @@ #include <media/v4l2-mediabus.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <plat/adc.h> @@ -1379,10 +1378,9 @@ MACHINE_START(NURI, "NURI") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = nuri_map_io, - .handle_irq = gic_handle_irq, .init_machine = nuri_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .reserve = &nuri_reserve, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 5e34b9c..579d2d1 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -29,7 +29,6 @@ #include <linux/platform_data/usb-exynos.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/platform_lcd.h> @@ -814,10 +813,9 @@ MACHINE_START(ORIGEN, "ORIGEN") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = origen_map_io, - .handle_irq = gic_handle_irq, .init_machine = origen_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .reserve = &origen_reserve, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c index ae6da40..fe61496 100644 --- a/arch/arm/mach-exynos/mach-smdk4x12.c +++ b/arch/arm/mach-exynos/mach-smdk4x12.c @@ -25,7 +25,6 @@ #include <linux/platform_data/s3c-hsotg.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/samsung_fimd.h> @@ -376,9 +375,8 @@ MACHINE_START(SMDK4212, "SMDK4212") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdk4x12_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdk4x12_machine_init, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .restart = exynos4_restart, .reserve = &smdk4x12_reserve, MACHINE_END @@ -390,10 +388,9 @@ MACHINE_START(SMDK4412, "SMDK4412") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdk4x12_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdk4x12_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .restart = exynos4_restart, .reserve = &smdk4x12_reserve, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 35548e3..d716729 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -26,7 +26,6 @@ #include <linux/platform_data/usb-exynos.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/platform_lcd.h> @@ -423,9 +422,8 @@ MACHINE_START(SMDKV310, "SMDKV310") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdkv310_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdkv310_machine_init, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .reserve = &smdkv310_reserve, .restart = exynos4_restart, MACHINE_END @@ -436,10 +434,9 @@ MACHINE_START(SMDKC210, "SMDKC210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = smdkv310_map_io, - .handle_irq = gic_handle_irq, .init_machine = smdkv310_machine_init, .init_late = exynos_init_late, - .timer = &exynos4_timer, + .init_time = exynos4_timer_init, .reserve = &smdkv310_reserve, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 9e3340f..c9d33a4 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -29,7 +29,6 @@ #include <drm/exynos_drm.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <video/samsung_fimd.h> @@ -1151,10 +1150,9 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = universal_map_io, - .handle_irq = gic_handle_irq, .init_machine = universal_machine_init, .init_late = exynos_init_late, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .reserve = &universal_reserve, .restart = exynos4_restart, MACHINE_END diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 57668eb..c9d6650 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -22,7 +22,6 @@ #include <linux/of.h> #include <asm/arch_timer.h> -#include <asm/hardware/gic.h> #include <asm/localtimer.h> #include <plat/cpu.h> @@ -255,13 +254,9 @@ static struct irqaction mct_comp_event_irq = { static void exynos4_clockevent_init(void) { - clockevents_calc_mult_shift(&mct_comp_device, clk_rate, 5); - mct_comp_device.max_delta_ns = - clockevent_delta2ns(0xffffffff, &mct_comp_device); - mct_comp_device.min_delta_ns = - clockevent_delta2ns(0xf, &mct_comp_device); mct_comp_device.cpumask = cpumask_of(0); - clockevents_register_device(&mct_comp_device); + clockevents_config_and_register(&mct_comp_device, clk_rate, + 0xf, 0xffffffff); if (soc_is_exynos5250()) setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq); @@ -404,14 +399,8 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) evt->set_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450; - - clockevents_calc_mult_shift(evt, clk_rate / (TICK_BASE_CNT + 1), 5); - evt->max_delta_ns = - clockevent_delta2ns(0x7fffffff, evt); - evt->min_delta_ns = - clockevent_delta2ns(0xf, evt); - - clockevents_register_device(evt); + clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), + 0xf, 0x7fffffff); exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); @@ -478,7 +467,7 @@ static void __init exynos4_timer_resources(void) #endif /* CONFIG_LOCAL_TIMERS */ } -static void __init exynos_timer_init(void) +void __init exynos4_timer_init(void) { if (soc_is_exynos5440()) { arch_timer_of_register(); @@ -494,7 +483,3 @@ static void __init exynos_timer_init(void) exynos4_clocksource_init(); exynos4_clockevent_init(); } - -struct sys_timer exynos4_timer = { - .init = exynos_timer_init, -}; diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index c5c840e..60f7c5b 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -20,9 +20,9 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> @@ -149,7 +149,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct __raw_writel(virt_to_phys(exynos4_secondary_startup), cpu_boot_reg(phys_cpu)); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); if (pen_release == -1) break; @@ -190,8 +190,6 @@ static void __init exynos_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 25b4536..6987a09 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -90,6 +90,6 @@ MACHINE_START(CATS, "Chalice-CATS") .fixup = fixup_cats, .map_io = footbridge_map_io, .init_irq = footbridge_init_irq, - .timer = &isa_timer, + .init_time = isa_timer_init, .restart = footbridge_restart, MACHINE_END diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h index c9767b8..a846e50 100644 --- a/arch/arm/mach-footbridge/common.h +++ b/arch/arm/mach-footbridge/common.h @@ -1,6 +1,6 @@ -extern struct sys_timer footbridge_timer; -extern struct sys_timer isa_timer; +extern void footbridge_timer_init(void); +extern void isa_timer_init(void); extern void isa_rtc_init(void); diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 3b54196..9ee78f7 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -93,7 +93,7 @@ static struct irqaction footbridge_timer_irq = { /* * Set up timer interrupt. */ -static void __init footbridge_timer_init(void) +void __init footbridge_timer_init(void) { struct clock_event_device *ce = &ckevt_dc21285; @@ -101,14 +101,6 @@ static void __init footbridge_timer_init(void) setup_irq(ce->irq, &footbridge_timer_irq); - clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); - ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); - ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); ce->cpumask = cpumask_of(smp_processor_id()); - - clockevents_register_device(ce); + clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff); } - -struct sys_timer footbridge_timer = { - .init = footbridge_timer_init, -}; diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index b09551e..b082435 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -101,7 +101,7 @@ MACHINE_START(EBSA285, "EBSA285") .video_end = 0x000bffff, .map_io = footbridge_map_io, .init_irq = footbridge_init_irq, - .timer = &footbridge_timer, + .init_time = footbridge_timer_init, .restart = footbridge_restart, MACHINE_END diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index c40bb41..d9301dd 100644 --- a/arch/arm/mach-footbridge/isa-timer.c +++ b/arch/arm/mach-footbridge/isa-timer.c @@ -31,14 +31,10 @@ static struct irqaction pit_timer_irq = { .dev_id = &i8253_clockevent, }; -static void __init isa_timer_init(void) +void __init isa_timer_init(void) { clocksource_i8253_init(); setup_irq(i8253_clockevent.irq, &pit_timer_irq); clockevent_i8253_init(false); } - -struct sys_timer isa_timer = { - .init = isa_timer_init, -}; diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index d2d1433..90ea23f 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -766,6 +766,6 @@ MACHINE_START(NETWINDER, "Rebel-NetWinder") .fixup = fixup_netwinder, .map_io = footbridge_map_io, .init_irq = footbridge_init_irq, - .timer = &isa_timer, + .init_time = isa_timer_init, .restart = netwinder_restart, MACHINE_END diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c index e1e9990..7bdeabd 100644 --- a/arch/arm/mach-footbridge/personal.c +++ b/arch/arm/mach-footbridge/personal.c @@ -18,7 +18,7 @@ MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer") .atag_offset = 0x100, .map_io = footbridge_map_io, .init_irq = footbridge_init_irq, - .timer = &footbridge_timer, + .init_time = footbridge_timer_init, .restart = footbridge_restart, MACHINE_END diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c index 5927d3c..08bd650 100644 --- a/arch/arm/mach-gemini/board-nas4220b.c +++ b/arch/arm/mach-gemini/board-nas4220b.c @@ -31,10 +31,6 @@ #include "common.h" -static struct sys_timer ib4220b_timer = { - .init = gemini_timer_init, -}; - static struct gpio_led ib4220b_leds[] = { { .name = "nas4220b:orange:hdd", @@ -105,6 +101,6 @@ MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B") .atag_offset = 0x100, .map_io = gemini_map_io, .init_irq = gemini_init_irq, - .timer = &ib4220b_timer, + .init_time = gemini_timer_init, .init_machine = ib4220b_init, MACHINE_END diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c index cd7437a..fa0a363 100644 --- a/arch/arm/mach-gemini/board-rut1xx.c +++ b/arch/arm/mach-gemini/board-rut1xx.c @@ -71,10 +71,6 @@ static struct platform_device rut1xx_leds = { }, }; -static struct sys_timer rut1xx_timer = { - .init = gemini_timer_init, -}; - static void __init rut1xx_init(void) { gemini_gpio_init(); @@ -89,6 +85,6 @@ MACHINE_START(RUT100, "Teltonika RUT100") .atag_offset = 0x100, .map_io = gemini_map_io, .init_irq = gemini_init_irq, - .timer = &rut1xx_timer, + .init_time = gemini_timer_init, .init_machine = rut1xx_init, MACHINE_END diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c index a367880..3321cd6 100644 --- a/arch/arm/mach-gemini/board-wbd111.c +++ b/arch/arm/mach-gemini/board-wbd111.c @@ -80,10 +80,6 @@ static struct platform_device wbd111_leds_device = { }, }; -static struct sys_timer wbd111_timer = { - .init = gemini_timer_init, -}; - static struct mtd_partition wbd111_partitions[] = { { .name = "RedBoot", @@ -132,6 +128,6 @@ MACHINE_START(WBD111, "Wiliboard WBD-111") .atag_offset = 0x100, .map_io = gemini_map_io, .init_irq = gemini_init_irq, - .timer = &wbd111_timer, + .init_time = gemini_timer_init, .init_machine = wbd111_init, MACHINE_END diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c index f382811..fe33c82 100644 --- a/arch/arm/mach-gemini/board-wbd222.c +++ b/arch/arm/mach-gemini/board-wbd222.c @@ -80,10 +80,6 @@ static struct platform_device wbd222_leds_device = { }, }; -static struct sys_timer wbd222_timer = { - .init = gemini_timer_init, -}; - static struct mtd_partition wbd222_partitions[] = { { .name = "RedBoot", @@ -132,6 +128,6 @@ MACHINE_START(WBD222, "Wiliboard WBD-222") .atag_offset = 0x100, .map_io = gemini_map_io, .init_irq = gemini_init_irq, - .timer = &wbd222_timer, + .init_time = gemini_timer_init, .init_machine = wbd222_init, MACHINE_END diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c index aa1331e..17ef91f 100644 --- a/arch/arm/mach-h720x/common.c +++ b/arch/arm/mach-h720x/common.c @@ -42,12 +42,12 @@ void __init arch_dma_init(dma_t *dma) } /* - * Return usecs since last timer reload + * Return nsecs since last timer reload * (timercount * (usecs perjiffie)) / (ticks per jiffie) */ -unsigned long h720x_gettimeoffset(void) +u32 h720x_gettimeoffset(void) { - return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH; + return ((CPU_REG(TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH) * 1000; } /* diff --git a/arch/arm/mach-h720x/common.h b/arch/arm/mach-h720x/common.h index 2489537..7e73841 100644 --- a/arch/arm/mach-h720x/common.h +++ b/arch/arm/mach-h720x/common.h @@ -13,18 +13,18 @@ * */ -extern unsigned long h720x_gettimeoffset(void); +extern u32 h720x_gettimeoffset(void); extern void __init h720x_init_irq(void); extern void __init h720x_map_io(void); extern void h720x_restart(char, const char *); #ifdef CONFIG_ARCH_H7202 -extern struct sys_timer h7202_timer; +extern void h7202_timer_init(void); extern void __init init_hw_h7202(void); extern void __init h7202_init_irq(void); extern void __init h7202_init_time(void); #endif #ifdef CONFIG_ARCH_H7201 -extern struct sys_timer h7201_timer; +extern void h7201_timer_init(void); #endif diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c index 24df2a3..13c7412 100644 --- a/arch/arm/mach-h720x/cpu-h7201.c +++ b/arch/arm/mach-h720x/cpu-h7201.c @@ -44,8 +44,10 @@ static struct irqaction h7201_timer_irq = { /* * Setup TIMER0 as system timer */ -void __init h7201_init_time(void) +void __init h7201_timer_init(void) { + arch_gettimeoffset = h720x_gettimeoffset; + CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START; @@ -53,8 +55,3 @@ void __init h7201_init_time(void) setup_irq(IRQ_TIMER0, &h7201_timer_irq); } - -struct sys_timer h7201_timer = { - .init = h7201_init_time, - .offset = h720x_gettimeoffset, -}; diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index c37d570..e2ae7e8 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c @@ -178,8 +178,10 @@ static struct irqaction h7202_timer_irq = { /* * Setup TIMER0 as system timer */ -void __init h7202_init_time(void) +void __init h7202_timer_init(void) { + arch_gettimeoffset = h720x_gettimeoffset; + CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START; @@ -188,11 +190,6 @@ void __init h7202_init_time(void) setup_irq(IRQ_TIMER0, &h7202_timer_irq); } -struct sys_timer h7202_timer = { - .init = h7202_init_time, - .offset = h720x_gettimeoffset, -}; - void __init h7202_init_irq (void) { int irq; diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c index 5fdb20c..4fdeb68 100644 --- a/arch/arm/mach-h720x/h7201-eval.c +++ b/arch/arm/mach-h720x/h7201-eval.c @@ -32,7 +32,7 @@ MACHINE_START(H7201, "Hynix GMS30C7201") .atag_offset = 0x1000, .map_io = h720x_map_io, .init_irq = h720x_init_irq, - .timer = &h7201_timer, + .init_time = h7201_timer_init, .dma_zone_size = SZ_256M, .restart = h720x_restart, MACHINE_END diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c index 1696730..f68e967 100644 --- a/arch/arm/mach-h720x/h7202-eval.c +++ b/arch/arm/mach-h720x/h7202-eval.c @@ -74,7 +74,7 @@ MACHINE_START(H7202, "Hynix HMS30C7202") .atag_offset = 0x100, .map_io = h720x_map_io, .init_irq = h7202_init_irq, - .timer = &h7202_timer, + .init_time = h7202_timer_init, .init_machine = init_eval_h7202, .dma_zone_size = SZ_256M, .restart = h720x_restart, diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 981dc1e..fd630bc 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -18,6 +18,7 @@ #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/of_irq.h> @@ -32,7 +33,6 @@ #include <asm/smp_twd.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/timer-sp.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -66,12 +66,6 @@ void highbank_set_cpu_jump(int cpu, void *jump_addr) HB_JUMP_TABLE_PHYS(cpu) + 15); } -const static struct of_device_id irq_match[] = { - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - #ifdef CONFIG_CACHE_L2X0 static void highbank_l2x0_disable(void) { @@ -82,7 +76,7 @@ static void highbank_l2x0_disable(void) static void __init highbank_init_irq(void) { - of_irq_init(irq_match); + irqchip_init(); if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) highbank_scu_map_io(); @@ -129,10 +123,6 @@ static void __init highbank_timer_init(void) arch_timer_sched_clock_init(); } -static struct sys_timer highbank_timer = { - .init = highbank_timer_init, -}; - static void highbank_power_off(void) { highbank_set_pwr_shutdown(); @@ -209,8 +199,7 @@ DT_MACHINE_START(HIGHBANK, "Highbank") .smp = smp_ops(highbank_smp_ops), .map_io = debug_ll_io_init, .init_irq = highbank_init_irq, - .timer = &highbank_timer, - .handle_irq = gic_handle_irq, + .init_time = highbank_timer_init, .init_machine = highbank_init, .dt_compat = highbank_match, .restart = highbank_restart, diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c index 4ecc864..8797a70 100644 --- a/arch/arm/mach-highbank/platsmp.c +++ b/arch/arm/mach-highbank/platsmp.c @@ -17,9 +17,9 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include "core.h" @@ -33,7 +33,7 @@ static void __cpuinit highbank_secondary_init(unsigned int cpu) static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle) { highbank_set_cpu_jump(cpu, secondary_startup); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; } @@ -56,8 +56,6 @@ static void __init highbank_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init highbank_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 240e029..c4ce090 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -28,7 +28,11 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o + +ifeq ($(CONFIG_CPU_IDLE),y) +obj-y += cpuidle.o +obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o +endif ifdef CONFIG_SND_IMX_SOC obj-y += ssi-fiq.o diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 1ffe3b534..d24b0d6 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -62,7 +62,7 @@ static const char *clko_sel_clks[] = { "32k", "usb_div", "dptc", }; -static const char *ssi_sel_clks[] = { "spll", "mpll", }; +static const char *ssi_sel_clks[] = { "spll_gate", "mpll", }; enum mx27_clks { dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div, @@ -82,7 +82,7 @@ enum mx27_clks { csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate, uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate, uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel, - mpll_sel, clk_max + mpll_sel, spll_gate, clk_max }; static struct clk *clk[clk_max]; @@ -104,6 +104,7 @@ int __init mx27_clocks_init(unsigned long fref) ARRAY_SIZE(mpll_sel_clks)); clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0); clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0); + clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3); if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { @@ -121,7 +122,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6); clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6); - clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3); + clk[usb_div] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3); clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); if (mx27_revision() >= IMX_CHIP_REVISION_2_0) diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index 16ccbd4..b5b65f3 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -34,8 +34,8 @@ static const char *csi_sel[] = { "upll", "spll", }; static const char *fir_sel[] = { "mcu_main", "upll", "spll" }; enum mx31_clks { - ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, per_div, - per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre, + dummy, ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, + per_div, per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre, fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate, iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate, uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate, @@ -46,12 +46,15 @@ enum mx31_clks { }; static struct clk *clk[clk_max]; +static struct clk_onecell_data clk_data; int __init mx31_clocks_init(unsigned long fref) { void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR); int i; + struct device_node *np; + clk[dummy] = imx_clk_fixed("dummy", 0); clk[ckih] = imx_clk_fixed("ckih", fref); clk[ckil] = imx_clk_fixed("ckil", 32768); clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL); @@ -116,6 +119,14 @@ int __init mx31_clocks_init(unsigned long fref) pr_err("imx31 clk %d: register failed with %ld\n", i, PTR_ERR(clk[i])); + np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm"); + + if (np) { + clk_data.clks = clk; + clk_data.clk_num = ARRAY_SIZE(clk); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + } + clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0"); diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index f0727e8..74e3a34 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -67,13 +67,13 @@ enum mx35_clks { static struct clk *clk[clk_max]; -int __init mx35_clocks_init() +int __init mx35_clocks_init(void) { void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR); u32 pdr0, consumer_sel, hsp_sel; struct arm_ahb_div *aad; unsigned char *hsp_div; - int i; + u32 i; pdr0 = __raw_readl(base + MXC_CCM_PDR0); consumer_sel = (pdr0 >> 16) & 0xf; diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 19644f6..540138c 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -54,8 +54,19 @@ #define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) #define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) +#define CGPR 0x64 +#define BM_CGPR_CHICKEN_BIT (0x1 << 17) + static void __iomem *ccm_base; +void imx6q_set_chicken_bit(void) +{ + u32 val = readl_relaxed(ccm_base + CGPR); + + val |= BM_CGPR_CHICKEN_BIT; + writel_relaxed(val, ccm_base + CGPR); +} + int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) { u32 val = readl_relaxed(ccm_base + CLPCR); @@ -66,6 +77,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) break; case WAIT_UNCLOCKED: val |= 0x1 << BP_CLPCR_LPM; + val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; break; case STOP_POWER_ON: val |= 0x2 << BP_CLPCR_LPM; diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 1ef0a26..5a800bf 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -107,7 +107,6 @@ void tzic_handle_irq(struct pt_regs *); #define imx35_handle_irq avic_handle_irq #define imx51_handle_irq tzic_handle_irq #define imx53_handle_irq tzic_handle_irq -#define imx6q_handle_irq gic_handle_irq extern void imx_enable_cpu(int cpu, bool enable); extern void imx_set_cpu_jump(int cpu, void *jump_addr); @@ -117,9 +116,11 @@ extern u32 *pl310_get_save_ptr(void); extern void v7_secondary_startup(void); extern void imx_scu_map_io(void); extern void imx_smp_prepare(void); +extern void imx_scu_standby_enable(void); #else static inline void imx_scu_map_io(void) {} static inline void imx_smp_prepare(void) {} +static inline void imx_scu_standby_enable(void) {} #endif extern void imx_enable_cpu(int cpu, bool enable); extern void imx_set_cpu_jump(int cpu, void *jump_addr); @@ -129,6 +130,7 @@ extern void imx_gpc_init(void); extern void imx_gpc_pre_suspend(void); extern void imx_gpc_post_resume(void); extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); +extern void imx6q_set_chicken_bit(void); extern void imx_cpu_die(unsigned int cpu); extern int imx_cpu_kill(unsigned int cpu); diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c new file mode 100644 index 0000000..d533e26 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6q.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clockchips.h> +#include <linux/cpuidle.h> +#include <linux/module.h> +#include <asm/cpuidle.h> +#include <asm/proc-fns.h> + +#include "common.h" +#include "cpuidle.h" + +static atomic_t master = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(master_lock); + +static int imx6q_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + int cpu = dev->cpu; + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); + + if (atomic_inc_return(&master) == num_online_cpus()) { + /* + * With this lock, we prevent other cpu to exit and enter + * this function again and become the master. + */ + if (!spin_trylock(&master_lock)) + goto idle; + imx6q_set_lpm(WAIT_UNCLOCKED); + cpu_do_idle(); + imx6q_set_lpm(WAIT_CLOCKED); + spin_unlock(&master_lock); + goto done; + } + +idle: + cpu_do_idle(); +done: + atomic_dec(&master); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); + + return index; +} + +/* + * For each cpu, setup the broadcast timer because local timer + * stops for the states other than WFI. + */ +static void imx6q_setup_broadcast_timer(void *arg) +{ + int cpu = smp_processor_id(); + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); +} + +static struct cpuidle_driver imx6q_cpuidle_driver = { + .name = "imx6q_cpuidle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = imx6q_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + +int __init imx6q_cpuidle_init(void) +{ + /* Need to enable SCU standby for entering WAIT modes */ + imx_scu_standby_enable(); + + /* Set chicken bit to get a reliable WAIT mode support */ + imx6q_set_chicken_bit(); + + /* Configure the broadcast timer on each cpu */ + on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1); + + return imx_cpuidle_init(&imx6q_cpuidle_driver); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index bc932d1..e092d13 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -14,9 +14,14 @@ #ifdef CONFIG_CPU_IDLE extern int imx_cpuidle_init(struct cpuidle_driver *drv); +extern int imx6q_cpuidle_init(void); #else static inline int imx_cpuidle_init(struct cpuidle_driver *drv) { return -ENODEV; } +static inline int imx6q_cpuidle_init(void) +{ + return -ENODEV; +} #endif diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c index 04a5961..e02de18 100644 --- a/arch/arm/mach-imx/epit.c +++ b/arch/arm/mach-imx/epit.c @@ -178,7 +178,6 @@ static struct irqaction epit_timer_irq = { static struct clock_event_device clockevent_epit = { .name = "epit", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = epit_set_mode, .set_next_event = epit_set_next_event, .rating = 200, @@ -186,18 +185,10 @@ static struct clock_event_device clockevent_epit = { static int __init epit_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - - clockevent_epit.mult = div_sc(c, NSEC_PER_SEC, - clockevent_epit.shift); - clockevent_epit.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_epit); - clockevent_epit.min_delta_ns = - clockevent_delta2ns(0x800, &clockevent_epit); - clockevent_epit.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_epit); + clockevents_config_and_register(&clockevent_epit, + clk_get_rate(timer_clk), + 0x800, 0xfffffffe); return 0; } diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index e1537f9..a96ccc7 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -15,7 +15,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #define GPC_IMR1 0x008 #define GPC_PGC_CPU_PDN 0x2a0 @@ -101,11 +101,16 @@ static void imx_gpc_irq_mask(struct irq_data *d) void __init imx_gpc_init(void) { struct device_node *np; + int i; np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); gpc_base = of_iomap(np, 0); WARN_ON(!gpc_base); + /* Initially mask all interrupts */ + for (i = 0; i < IMR_NUM; i++) + writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4); + /* Register GPC as the secondary interrupt controller behind GIC */ gic_arch_extn.irq_mask = imx_gpc_irq_mask; gic_arch_extn.irq_unmask = imx_gpc_irq_unmask; diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c index e17dfbc..03b65e5 100644 --- a/arch/arm/mach-imx/imx25-dt.c +++ b/arch/arm/mach-imx/imx25-dt.c @@ -22,15 +22,6 @@ static void __init imx25_dt_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init imx25_timer_init(void) -{ - mx25_clocks_init_dt(); -} - -static struct sys_timer imx25_timer = { - .init = imx25_timer_init, -}; - static const char * const imx25_dt_board_compat[] __initconst = { "fsl,imx25", NULL @@ -41,7 +32,7 @@ DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)") .init_early = imx25_init_early, .init_irq = mx25_init_irq, .handle_irq = imx25_handle_irq, - .timer = &imx25_timer, + .init_time = imx25_timer_init, .init_machine = imx25_dt_init, .dt_compat = imx25_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index ebfae96..c915a49 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -39,26 +39,22 @@ static void __init imx27_dt_init(void) imx27_auxdata_lookup, NULL); } -static void __init imx27_timer_init(void) -{ - mx27_clocks_init_dt(); -} - -static struct sys_timer imx27_timer = { - .init = imx27_timer_init, -}; - static const char * const imx27_dt_board_compat[] __initconst = { "fsl,imx27", NULL }; +static void __init imx27_timer_init(void) +{ + mx27_clocks_init_dt(); +} + DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &imx27_timer, + .init_time = imx27_timer_init, .init_machine = imx27_dt_init, .dt_compat = imx27_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index af476de..00737eb 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -18,35 +18,11 @@ #include "common.h" #include "mx31.h" -static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR, - "imx21-uart.0", NULL), - OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART2_BASE_ADDR, - "imx21-uart.1", NULL), - OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART3_BASE_ADDR, - "imx21-uart.2", NULL), - OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART4_BASE_ADDR, - "imx21-uart.3", NULL), - OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART5_BASE_ADDR, - "imx21-uart.4", NULL), - { /* sentinel */ } -}; - static void __init imx31_dt_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, - imx31_auxdata_lookup, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init imx31_timer_init(void) -{ - mx31_clocks_init_dt(); -} - -static struct sys_timer imx31_timer = { - .init = imx31_timer_init, -}; - static const char *imx31_dt_board_compat[] __initdata = { "fsl,imx31", NULL @@ -57,7 +33,7 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &imx31_timer, + .init_time = mx31_clocks_init_dt, .init_machine = imx31_dt_init, .dt_compat = imx31_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index 5ffa40c..e2926a8 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -24,26 +24,22 @@ static void __init imx51_dt_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init imx51_timer_init(void) -{ - mx51_clocks_init_dt(); -} - -static struct sys_timer imx51_timer = { - .init = imx51_timer_init, -}; - static const char *imx51_dt_board_compat[] __initdata = { "fsl,imx51", NULL }; +static void __init imx51_timer_init(void) +{ + mx51_clocks_init_dt(); +} + DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)") .map_io = mx51_map_io, .init_early = imx51_init_early, .init_irq = mx51_init_irq, .handle_irq = imx51_handle_irq, - .timer = &imx51_timer, + .init_time = imx51_timer_init, .init_machine = imx51_dt_init, .init_late = imx51_init_late, .dt_compat = imx51_dt_board_compat, diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index 5c9bd2c..067580b 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -137,17 +137,13 @@ static void __init apf9328_timer_init(void) mx1_clocks_init(32768); } -static struct sys_timer apf9328_timer = { - .init = apf9328_timer_init, -}; - MACHINE_START(APF9328, "Armadeus APF9328") /* Maintainer: Gwenhael Goavec-Merou, ARMadeus Systems */ .map_io = mx1_map_io, .init_early = imx1_init_early, .init_irq = mx1_init_irq, .handle_irq = imx1_handle_irq, - .timer = &apf9328_timer, + .init_time = apf9328_timer_init, .init_machine = apf9328_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index 59bd6b0..368a6e3 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -557,10 +557,6 @@ static void __init armadillo5x0_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer armadillo5x0_timer = { - .init = armadillo5x0_timer_init, -}; - MACHINE_START(ARMADILLO5X0, "Armadillo-500") /* Maintainer: Alberto Panizzo */ .atag_offset = 0x100, @@ -568,7 +564,7 @@ MACHINE_START(ARMADILLO5X0, "Armadillo-500") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &armadillo5x0_timer, + .init_time = armadillo5x0_timer_init, .init_machine = armadillo5x0_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c index 3a39d5a..2d00476 100644 --- a/arch/arm/mach-imx/mach-bug.c +++ b/arch/arm/mach-imx/mach-bug.c @@ -53,16 +53,12 @@ static void __init bug_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer bug_timer = { - .init = bug_timer_init, -}; - MACHINE_START(BUG, "BugLabs BUGBase") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &bug_timer, + .init_time = bug_timer_init, .init_machine = bug_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index 12a3706..1465593 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -309,17 +309,13 @@ static void __init eukrea_cpuimx27_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer eukrea_cpuimx27_timer = { - .init = eukrea_cpuimx27_timer_init, -}; - MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27") .atag_offset = 0x100, .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &eukrea_cpuimx27_timer, + .init_time = eukrea_cpuimx27_timer_init, .init_machine = eukrea_cpuimx27_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 5a31bf8..771362d 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -193,10 +193,6 @@ static void __init eukrea_cpuimx35_timer_init(void) mx35_clocks_init(); } -static struct sys_timer eukrea_cpuimx35_timer = { - .init = eukrea_cpuimx35_timer_init, -}; - MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35") /* Maintainer: Eukrea Electromatique */ .atag_offset = 0x100, @@ -204,7 +200,7 @@ MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35") .init_early = imx35_init_early, .init_irq = mx35_init_irq, .handle_irq = imx35_handle_irq, - .timer = &eukrea_cpuimx35_timer, + .init_time = eukrea_cpuimx35_timer_init, .init_machine = eukrea_cpuimx35_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c index b727de0..9b73932 100644 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -355,10 +355,6 @@ static void __init eukrea_cpuimx51sd_timer_init(void) mx51_clocks_init(32768, 24000000, 22579200, 0); } -static struct sys_timer mxc_timer = { - .init = eukrea_cpuimx51sd_timer_init, -}; - MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD") /* Maintainer: Eric Bénard <eric@eukrea.com> */ .atag_offset = 0x100, @@ -366,7 +362,7 @@ MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD") .init_early = imx51_init_early, .init_irq = mx51_init_irq, .handle_irq = imx51_handle_irq, - .timer = &mxc_timer, + .init_time = eukrea_cpuimx51sd_timer_init, .init_machine = eukrea_cpuimx51sd_init, .init_late = imx51_init_late, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index 75027a5..4bf4544 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -159,10 +159,6 @@ static void __init eukrea_cpuimx25_timer_init(void) mx25_clocks_init(); } -static struct sys_timer eukrea_cpuimx25_timer = { - .init = eukrea_cpuimx25_timer_init, -}; - MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25") /* Maintainer: Eukrea Electromatique */ .atag_offset = 0x100, @@ -170,7 +166,7 @@ MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25") .init_early = imx25_init_early, .init_irq = mx25_init_irq, .handle_irq = imx25_handle_irq, - .timer = &eukrea_cpuimx25_timer, + .init_time = eukrea_cpuimx25_timer_init, .init_machine = eukrea_cpuimx25_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index 318bd8d..29ac8ee6 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -598,10 +598,6 @@ static void __init visstrim_m10_timer_init(void) mx27_clocks_init((unsigned long)25000000); } -static struct sys_timer visstrim_m10_timer = { - .init = visstrim_m10_timer_init, -}; - MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10") .atag_offset = 0x100, .reserve = visstrim_reserve, @@ -609,7 +605,7 @@ MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10") .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &visstrim_m10_timer, + .init_time = visstrim_m10_timer_init, .init_machine = visstrim_m10_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c index 53a8601..1a851ae 100644 --- a/arch/arm/mach-imx/mach-imx27ipcam.c +++ b/arch/arm/mach-imx/mach-imx27ipcam.c @@ -65,10 +65,6 @@ static void __init mx27ipcam_timer_init(void) mx27_clocks_init(25000000); } -static struct sys_timer mx27ipcam_timer = { - .init = mx27ipcam_timer_init, -}; - MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM") /* maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -76,7 +72,7 @@ MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM") .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &mx27ipcam_timer, + .init_time = mx27ipcam_timer_init, .init_machine = mx27ipcam_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c index fc8dce9..3da2e3e 100644 --- a/arch/arm/mach-imx/mach-imx27lite.c +++ b/arch/arm/mach-imx/mach-imx27lite.c @@ -72,17 +72,13 @@ static void __init mx27lite_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer mx27lite_timer = { - .init = mx27lite_timer_init, -}; - MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE") .atag_offset = 0x100, .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &mx27lite_timer, + .init_time = mx27lite_timer_init, .init_machine = mx27lite_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c index 860284d..f579c61 100644 --- a/arch/arm/mach-imx/mach-imx53.c +++ b/arch/arm/mach-imx/mach-imx53.c @@ -44,26 +44,22 @@ static void __init imx53_dt_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init imx53_timer_init(void) -{ - mx53_clocks_init_dt(); -} - -static struct sys_timer imx53_timer = { - .init = imx53_timer_init, -}; - static const char *imx53_dt_board_compat[] __initdata = { "fsl,imx53", NULL }; +static void __init imx53_timer_init(void) +{ + mx53_clocks_init_dt(); +} + DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") .map_io = mx53_map_io, .init_early = imx53_init_early, .init_irq = mx53_init_irq, .handle_irq = imx53_handle_irq, - .timer = &imx53_timer, + .init_time = imx53_timer_init, .init_machine = imx53_dt_init, .init_late = imx53_init_late, .dt_compat = imx53_dt_board_compat, diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index ce7476d..1786b2d 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -12,12 +12,12 @@ #include <linux/clk.h> #include <linux/clkdev.h> -#include <linux/cpuidle.h> #include <linux/delay.h> #include <linux/export.h> #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -26,10 +26,8 @@ #include <linux/regmap.h> #include <linux/micrel_phy.h> #include <linux/mfd/syscon.h> -#include <asm/cpuidle.h> #include <asm/smp_twd.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -202,17 +200,14 @@ static void __init imx6q_init_machine(void) imx6q_1588_init(); } -static struct cpuidle_driver imx6q_cpuidle_driver = { - .name = "imx6q_cpuidle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .state_count = 1, -}; - static void __init imx6q_init_late(void) { - imx_cpuidle_init(&imx6q_cpuidle_driver); + /* + * WAIT mode is broken on TO 1.0 and 1.1, so there is no point + * to run cpuidle on them. + */ + if (imx6q_revision() > IMX_CHIP_REVISION_1_1) + imx6q_cpuidle_init(); } static void __init imx6q_map_io(void) @@ -221,17 +216,12 @@ static void __init imx6q_map_io(void) imx_scu_map_io(); } -static const struct of_device_id imx6q_irq_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { /* sentinel */ } -}; - static void __init imx6q_init_irq(void) { l2x0_of_init(0, ~0UL); imx_src_init(); imx_gpc_init(); - of_irq_init(imx6q_irq_match); + irqchip_init(); } static void __init imx6q_timer_init(void) @@ -241,10 +231,6 @@ static void __init imx6q_timer_init(void) imx_print_silicon_rev("i.MX6Q", imx6q_revision()); } -static struct sys_timer imx6q_timer = { - .init = imx6q_timer_init, -}; - static const char *imx6q_dt_compat[] __initdata = { "fsl,imx6q", NULL, @@ -254,8 +240,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") .smp = smp_ops(imx_smp_ops), .map_io = imx6q_map_io, .init_irq = imx6q_init_irq, - .handle_irq = imx6q_handle_irq, - .timer = &imx6q_timer, + .init_time = imx6q_timer_init, .init_machine = imx6q_init_machine, .init_late = imx6q_init_late, .dt_compat = imx6q_dt_compat, diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index 2e536ea5..c7bc41d 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -284,17 +284,13 @@ static void __init kzm_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer kzm_timer = { - .init = kzm_timer_init, -}; - MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01") .atag_offset = 0x100, .map_io = kzm_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &kzm_timer, + .init_time = kzm_timer_init, .init_machine = kzm_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c index 06b4837..9f883e4 100644 --- a/arch/arm/mach-imx/mach-mx1ads.c +++ b/arch/arm/mach-imx/mach-mx1ads.c @@ -132,10 +132,6 @@ static void __init mx1ads_timer_init(void) mx1_clocks_init(32000); } -static struct sys_timer mx1ads_timer = { - .init = mx1ads_timer_init, -}; - MACHINE_START(MX1ADS, "Freescale MX1ADS") /* Maintainer: Sascha Hauer, Pengutronix */ .atag_offset = 0x100, @@ -143,7 +139,7 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS") .init_early = imx1_init_early, .init_irq = mx1_init_irq, .handle_irq = imx1_handle_irq, - .timer = &mx1ads_timer, + .init_time = mx1ads_timer_init, .init_machine = mx1ads_init, .restart = mxc_restart, MACHINE_END @@ -154,7 +150,7 @@ MACHINE_START(MXLADS, "Freescale MXLADS") .init_early = imx1_init_early, .init_irq = mx1_init_irq, .handle_irq = imx1_handle_irq, - .timer = &mx1ads_timer, + .init_time = mx1ads_timer_init, .init_machine = mx1ads_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index 6adb313..a06aa4d 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -318,10 +318,6 @@ static void __init mx21ads_timer_init(void) mx21_clocks_init(32768, 26000000); } -static struct sys_timer mx21ads_timer = { - .init = mx21ads_timer_init, -}; - MACHINE_START(MX21ADS, "Freescale i.MX21ADS") /* maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -329,7 +325,7 @@ MACHINE_START(MX21ADS, "Freescale i.MX21ADS") .init_early = imx21_init_early, .init_irq = mx21_init_irq, .handle_irq = imx21_handle_irq, - .timer = &mx21ads_timer, + .init_time = mx21ads_timer_init, .init_machine = mx21ads_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index b1b03aa..8bcda68 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -257,10 +257,6 @@ static void __init mx25pdk_timer_init(void) mx25_clocks_init(); } -static struct sys_timer mx25pdk_timer = { - .init = mx25pdk_timer_init, -}; - MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)") /* Maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -268,7 +264,7 @@ MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)") .init_early = imx25_init_early, .init_irq = mx25_init_irq, .handle_irq = imx25_handle_irq, - .timer = &mx25pdk_timer, + .init_time = mx25pdk_timer_init, .init_machine = mx25pdk_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index d0e547f..25b3e4c 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -538,10 +538,6 @@ static void __init mx27pdk_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer mx27pdk_timer = { - .init = mx27pdk_timer_init, -}; - MACHINE_START(MX27_3DS, "Freescale MX27PDK") /* maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -549,7 +545,7 @@ MACHINE_START(MX27_3DS, "Freescale MX27PDK") .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &mx27pdk_timer, + .init_time = mx27pdk_timer_init, .init_machine = mx27pdk_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c index 3d036f5..9821b824 100644 --- a/arch/arm/mach-imx/mach-mx27ads.c +++ b/arch/arm/mach-imx/mach-mx27ads.c @@ -323,10 +323,6 @@ static void __init mx27ads_timer_init(void) mx27_clocks_init(fref); } -static struct sys_timer mx27ads_timer = { - .init = mx27ads_timer_init, -}; - static struct map_desc mx27ads_io_desc[] __initdata = { { .virtual = PBC_BASE_ADDRESS, @@ -349,7 +345,7 @@ MACHINE_START(MX27ADS, "Freescale i.MX27ADS") .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &mx27ads_timer, + .init_time = mx27ads_timer_init, .init_machine = mx27ads_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index bc301be..1ed9161 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -762,10 +762,6 @@ static void __init mx31_3ds_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer mx31_3ds_timer = { - .init = mx31_3ds_timer_init, -}; - static void __init mx31_3ds_reserve(void) { /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */ @@ -780,7 +776,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &mx31_3ds_timer, + .init_time = mx31_3ds_timer_init, .init_machine = mx31_3ds_init, .reserve = mx31_3ds_reserve, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index 8b56f88..daf8889 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -576,10 +576,6 @@ static void __init mx31ads_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer mx31ads_timer = { - .init = mx31ads_timer_init, -}; - MACHINE_START(MX31ADS, "Freescale MX31ADS") /* Maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -587,7 +583,7 @@ MACHINE_START(MX31ADS, "Freescale MX31ADS") .init_early = imx31_init_early, .init_irq = mx31ads_init_irq, .handle_irq = imx31_handle_irq, - .timer = &mx31ads_timer, + .init_time = mx31ads_timer_init, .init_machine = mx31ads_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 08b9965..832b1e2 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -303,17 +303,13 @@ static void __init mx31lilly_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer mx31lilly_timer = { - .init = mx31lilly_timer_init, -}; - MACHINE_START(LILLY1131, "INCO startec LILLY-1131") .atag_offset = 0x100, .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &mx31lilly_timer, + .init_time = mx31lilly_timer_init, .init_machine = mx31lilly_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index bdcd92e..bea0729 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -285,10 +285,6 @@ static void __init mx31lite_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer mx31lite_timer = { - .init = mx31lite_timer_init, -}; - MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM") /* Maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, @@ -296,7 +292,7 @@ MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &mx31lite_timer, + .init_time = mx31lite_timer_init, .init_machine = mx31lite_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index 2517cfa..dae4cd7 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -596,10 +596,6 @@ static void __init mx31moboard_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer mx31moboard_timer = { - .init = mx31moboard_timer_init, -}; - static void __init mx31moboard_reserve(void) { /* reserve 4 MiB for mx3-camera */ @@ -615,7 +611,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &mx31moboard_timer, + .init_time = mx31moboard_timer_init, .init_machine = mx31moboard_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 5277da4..a42f4f0 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -602,10 +602,6 @@ static void __init mx35pdk_timer_init(void) mx35_clocks_init(); } -static struct sys_timer mx35pdk_timer = { - .init = mx35pdk_timer_init, -}; - static void __init mx35_3ds_reserve(void) { /* reserve MX35_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */ @@ -620,7 +616,7 @@ MACHINE_START(MX35_3DS, "Freescale MX35PDK") .init_early = imx35_init_early, .init_irq = mx35_init_irq, .handle_irq = imx35_handle_irq, - .timer = &mx35pdk_timer, + .init_time = mx35pdk_timer_init, .init_machine = mx35_3ds_init, .reserve = mx35_3ds_reserve, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c index d9a84ca..6c4d7fe 100644 --- a/arch/arm/mach-imx/mach-mx51_babbage.c +++ b/arch/arm/mach-imx/mach-mx51_babbage.c @@ -418,10 +418,6 @@ static void __init mx51_babbage_timer_init(void) mx51_clocks_init(32768, 24000000, 22579200, 0); } -static struct sys_timer mx51_babbage_timer = { - .init = mx51_babbage_timer_init, -}; - MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */ .atag_offset = 0x100, @@ -429,7 +425,7 @@ MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") .init_early = imx51_init_early, .init_irq = mx51_init_irq, .handle_irq = imx51_handle_irq, - .timer = &mx51_babbage_timer, + .init_time = mx51_babbage_timer_init, .init_machine = mx51_babbage_init, .init_late = imx51_init_late, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c index f4a8c7e..a27faab 100644 --- a/arch/arm/mach-imx/mach-mxt_td60.c +++ b/arch/arm/mach-imx/mach-mxt_td60.c @@ -261,10 +261,6 @@ static void __init mxt_td60_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer mxt_td60_timer = { - .init = mxt_td60_timer_init, -}; - MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60") /* maintainer: Maxtrack Industrial */ .atag_offset = 0x100, @@ -272,7 +268,7 @@ MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60") .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &mxt_td60_timer, + .init_time = mxt_td60_timer_init, .init_machine = mxt_td60_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index eee369f..b8b15bb 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -416,10 +416,6 @@ static void __init pca100_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer pca100_timer = { - .init = pca100_timer_init, -}; - MACHINE_START(PCA100, "phyCARD-i.MX27") .atag_offset = 0x100, .map_io = mx27_map_io, @@ -427,6 +423,6 @@ MACHINE_START(PCA100, "phyCARD-i.MX27") .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, .init_machine = pca100_init, - .timer = &pca100_timer, + .init_time = pca100_timer_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 547fef1..bc0261e 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -685,10 +685,6 @@ static void __init pcm037_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer pcm037_timer = { - .init = pcm037_timer_init, -}; - static void __init pcm037_reserve(void) { /* reserve 4 MiB for mx3-camera */ @@ -709,7 +705,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &pcm037_timer, + .init_time = pcm037_timer_init, .init_machine = pcm037_init, .init_late = pcm037_init_late, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 4aa0d07..e805ac2 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c @@ -346,17 +346,13 @@ static void __init pcm038_timer_init(void) mx27_clocks_init(26000000); } -static struct sys_timer pcm038_timer = { - .init = pcm038_timer_init, -}; - MACHINE_START(PCM038, "phyCORE-i.MX27") .atag_offset = 0x100, .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, .handle_irq = imx27_handle_irq, - .timer = &pcm038_timer, + .init_time = pcm038_timer_init, .init_machine = pcm038_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 9244544..8ed533f 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -394,10 +394,6 @@ static void __init pcm043_timer_init(void) mx35_clocks_init(); } -static struct sys_timer pcm043_timer = { - .init = pcm043_timer_init, -}; - MACHINE_START(PCM043, "Phytec Phycore pcm043") /* Maintainer: Pengutronix */ .atag_offset = 0x100, @@ -405,7 +401,7 @@ MACHINE_START(PCM043, "Phytec Phycore pcm043") .init_early = imx35_init_early, .init_irq = mx35_init_irq, .handle_irq = imx35_handle_irq, - .timer = &pcm043_timer, + .init_time = pcm043_timer_init, .init_machine = pcm043_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index 96d9a91..22af27e 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -260,10 +260,6 @@ static void __init qong_timer_init(void) mx31_clocks_init(26000000); } -static struct sys_timer qong_timer = { - .init = qong_timer_init, -}; - MACHINE_START(QONG, "Dave/DENX QongEVB-LITE") /* Maintainer: DENX Software Engineering GmbH */ .atag_offset = 0x100, @@ -271,7 +267,7 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .handle_irq = imx31_handle_irq, - .timer = &qong_timer, + .init_time = qong_timer_init, .init_machine = qong_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c index fc97040..b0fa10d 100644 --- a/arch/arm/mach-imx/mach-scb9328.c +++ b/arch/arm/mach-imx/mach-scb9328.c @@ -131,10 +131,6 @@ static void __init scb9328_timer_init(void) mx1_clocks_init(32000); } -static struct sys_timer scb9328_timer = { - .init = scb9328_timer_init, -}; - MACHINE_START(SCB9328, "Synertronixx scb9328") /* Sascha Hauer */ .atag_offset = 100, @@ -142,7 +138,7 @@ MACHINE_START(SCB9328, "Synertronixx scb9328") .init_early = imx1_init_early, .init_irq = mx1_init_irq, .handle_irq = imx1_handle_irq, - .timer = &scb9328_timer, + .init_time = scb9328_timer_init, .init_machine = scb9328_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index 3aecf91..0910761e 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -305,17 +305,13 @@ static void __init vpr200_timer_init(void) mx35_clocks_init(); } -static struct sys_timer vpr200_timer = { - .init = vpr200_timer_init, -}; - MACHINE_START(VPR200, "VPR200") /* Maintainer: Creative Product Design */ .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = mx35_init_irq, .handle_irq = imx35_handle_irq, - .timer = &vpr200_timer, + .init_time = vpr200_timer_init, .init_machine = vpr200_board_init, .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 66fae88..7c0b03f 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -12,14 +12,16 @@ #include <linux/init.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/page.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include "common.h" #include "hardware.h" +#define SCU_STANDBY_ENABLE (1 << 5) + static void __iomem *scu_base; static struct map_desc scu_io_desc __initdata = { @@ -42,6 +44,14 @@ void __init imx_scu_map_io(void) scu_base = IMX_IO_ADDRESS(base); } +void imx_scu_standby_enable(void) +{ + u32 val = readl_relaxed(scu_base); + + val |= SCU_STANDBY_ENABLE; + writel_relaxed(val, scu_base); +} + static void __cpuinit imx_secondary_init(unsigned int cpu) { /* @@ -71,8 +81,6 @@ static void __init imx_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } void imx_smp_prepare(void) diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index f017302..fea9131 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -152,7 +152,8 @@ static int v2_set_next_event(unsigned long evt, __raw_writel(tcmp, timer_base + V2_TCMP); - return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ? + return evt < 0x7fffffff && + (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ? -ETIME : 0; } @@ -256,7 +257,6 @@ static struct irqaction mxc_timer_irq = { static struct clock_event_device clockevent_mxc = { .name = "mxc_timer1", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = mxc_set_mode, .set_next_event = mx1_2_set_next_event, .rating = 200, @@ -264,21 +264,13 @@ static struct clock_event_device clockevent_mxc = { static int __init mxc_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - if (timer_is_v2()) clockevent_mxc.set_next_event = v2_set_next_event; - clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC, - clockevent_mxc.shift); - clockevent_mxc.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_mxc); - clockevent_mxc.min_delta_ns = - clockevent_delta2ns(0xff, &clockevent_mxc); - clockevent_mxc.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_mxc); + clockevents_config_and_register(&clockevent_mxc, + clk_get_rate(timer_clk), + 0xff, 0xfffffffe); return 0; } diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 11e2a41..78f1b38 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -425,7 +425,7 @@ void __init ap_init_early(void) #ifdef CONFIG_OF -static void __init ap_init_timer_of(void) +static void __init ap_of_timer_init(void) { struct device_node *node; const char *path; @@ -464,10 +464,6 @@ static void __init ap_init_timer_of(void) integrator_clockevent_init(rate, base, irq); } -static struct sys_timer ap_of_timer = { - .init = ap_init_timer_of, -}; - static const struct of_device_id fpga_irq_of_match[] __initconst = { { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, { /* Sentinel */ } @@ -586,7 +582,7 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)") .init_early = ap_init_early, .init_irq = ap_init_irq_of, .handle_irq = fpga_handle_irq, - .timer = &ap_of_timer, + .init_time = ap_of_timer_init, .init_machine = ap_init_of, .restart = integrator_restart, .dt_compat = ap_dt_board_compat, @@ -638,7 +634,7 @@ static struct platform_device cfi_flash_device = { .resource = &cfi_flash_resource, }; -static void __init ap_init_timer(void) +static void __init ap_timer_init(void) { struct clk *clk; unsigned long rate; @@ -657,10 +653,6 @@ static void __init ap_init_timer(void) IRQ_TIMERINT1); } -static struct sys_timer ap_timer = { - .init = ap_init_timer, -}; - #define INTEGRATOR_SC_VALID_INT 0x003fffff static void __init ap_init_irq(void) @@ -716,7 +708,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator") .init_early = ap_init_early, .init_irq = ap_init_irq, .handle_irq = fpga_handle_irq, - .timer = &ap_timer, + .init_time = ap_timer_init, .init_machine = ap_init, .restart = integrator_restart, MACHINE_END diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 7322838..4cef9a0 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -251,7 +251,7 @@ static void __init intcp_init_early(void) #ifdef CONFIG_OF -static void __init intcp_timer_init_of(void) +static void __init cp_of_timer_init(void) { struct device_node *node; const char *path; @@ -283,10 +283,6 @@ static void __init intcp_timer_init_of(void) sp804_clockevents_init(base, irq, node->name); } -static struct sys_timer cp_of_timer = { - .init = intcp_timer_init_of, -}; - static const struct of_device_id fpga_irq_of_match[] __initconst = { { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, { /* Sentinel */ } @@ -390,7 +386,7 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)") .init_early = intcp_init_early, .init_irq = intcp_init_irq_of, .handle_irq = fpga_handle_irq, - .timer = &cp_of_timer, + .init_time = cp_of_timer_init, .init_machine = intcp_init_of, .restart = integrator_restart, .dt_compat = intcp_dt_board_compat, @@ -512,7 +508,7 @@ static void __init intcp_init_irq(void) #define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE) #define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE) -static void __init intcp_timer_init(void) +static void __init cp_timer_init(void) { writel(0, TIMER0_VA_BASE + TIMER_CTRL); writel(0, TIMER1_VA_BASE + TIMER_CTRL); @@ -522,10 +518,6 @@ static void __init intcp_timer_init(void) sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1"); } -static struct sys_timer cp_timer = { - .init = intcp_timer_init, -}; - #define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 } #define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT } @@ -565,7 +557,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") .init_early = intcp_init_early, .init_irq = intcp_init_irq, .handle_irq = fpga_handle_irq, - .timer = &cp_timer, + .init_time = cp_timer_init, .init_machine = intcp_init, .restart = integrator_restart, MACHINE_END diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c index e3f3e7d..02a8228 100644 --- a/arch/arm/mach-iop13xx/iq81340mc.c +++ b/arch/arm/mach-iop13xx/iq81340mc.c @@ -84,17 +84,13 @@ static void __init iq81340mc_timer_init(void) iop_init_time(bus_freq); } -static struct sys_timer iq81340mc_timer = { - .init = iq81340mc_timer_init, -}; - MACHINE_START(IQ81340MC, "Intel IQ81340MC") /* Maintainer: Dan Williams <dan.j.williams@intel.com> */ .atag_offset = 0x100, .init_early = iop13xx_init_early, .map_io = iop13xx_map_io, .init_irq = iop13xx_init_irq, - .timer = &iq81340mc_timer, + .init_time = iq81340mc_timer_init, .init_machine = iq81340mc_init, .restart = iop13xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c index e947441..1b80f10 100644 --- a/arch/arm/mach-iop13xx/iq81340sc.c +++ b/arch/arm/mach-iop13xx/iq81340sc.c @@ -86,17 +86,13 @@ static void __init iq81340sc_timer_init(void) iop_init_time(bus_freq); } -static struct sys_timer iq81340sc_timer = { - .init = iq81340sc_timer_init, -}; - MACHINE_START(IQ81340SC, "Intel IQ81340SC") /* Maintainer: Dan Williams <dan.j.williams@intel.com> */ .atag_offset = 0x100, .init_early = iop13xx_init_early, .map_io = iop13xx_map_io, .init_irq = iop13xx_init_irq, - .timer = &iq81340sc_timer, + .init_time = iq81340sc_timer_init, .init_machine = iq81340sc_init, .restart = iop13xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c index 9f369f0..31fbb6c 100644 --- a/arch/arm/mach-iop32x/em7210.c +++ b/arch/arm/mach-iop32x/em7210.c @@ -40,10 +40,6 @@ static void __init em7210_timer_init(void) iop_init_time(200000000); } -static struct sys_timer em7210_timer = { - .init = em7210_timer_init, -}; - /* * EM7210 RTC */ @@ -205,7 +201,7 @@ MACHINE_START(EM7210, "Lanner EM7210") .atag_offset = 0x100, .map_io = em7210_map_io, .init_irq = iop32x_init_irq, - .timer = &em7210_timer, + .init_time = em7210_timer_init, .init_machine = em7210_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c index 02e20c3..ac30470 100644 --- a/arch/arm/mach-iop32x/glantank.c +++ b/arch/arm/mach-iop32x/glantank.c @@ -44,10 +44,6 @@ static void __init glantank_timer_init(void) iop_init_time(200000000); } -static struct sys_timer glantank_timer = { - .init = glantank_timer_init, -}; - /* * GLAN Tank I/O. @@ -209,7 +205,7 @@ MACHINE_START(GLANTANK, "GLAN Tank") .atag_offset = 0x100, .map_io = glantank_map_io, .init_irq = iop32x_init_irq, - .timer = &glantank_timer, + .init_time = glantank_timer_init, .init_machine = glantank_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c index ddd1c7e..f2cd296 100644 --- a/arch/arm/mach-iop32x/iq31244.c +++ b/arch/arm/mach-iop32x/iq31244.c @@ -75,10 +75,6 @@ static void __init iq31244_timer_init(void) } } -static struct sys_timer iq31244_timer = { - .init = iq31244_timer_init, -}; - /* * IQ31244 I/O. @@ -314,7 +310,7 @@ MACHINE_START(IQ31244, "Intel IQ31244") .atag_offset = 0x100, .map_io = iq31244_map_io, .init_irq = iop32x_init_irq, - .timer = &iq31244_timer, + .init_time = iq31244_timer_init, .init_machine = iq31244_init_machine, .restart = iop3xx_restart, MACHINE_END @@ -329,7 +325,7 @@ MACHINE_START(EP80219, "Intel EP80219") .atag_offset = 0x100, .map_io = iq31244_map_io, .init_irq = iop32x_init_irq, - .timer = &iq31244_timer, + .init_time = iq31244_timer_init, .init_machine = iq31244_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c index bf155e6..015435d 100644 --- a/arch/arm/mach-iop32x/iq80321.c +++ b/arch/arm/mach-iop32x/iq80321.c @@ -43,10 +43,6 @@ static void __init iq80321_timer_init(void) iop_init_time(200000000); } -static struct sys_timer iq80321_timer = { - .init = iq80321_timer_init, -}; - /* * IQ80321 I/O. @@ -188,7 +184,7 @@ MACHINE_START(IQ80321, "Intel IQ80321") .atag_offset = 0x100, .map_io = iq80321_map_io, .init_irq = iop32x_init_irq, - .timer = &iq80321_timer, + .init_time = iq80321_timer_init, .init_machine = iq80321_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index 5a7ae91..ea0984a 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c @@ -50,10 +50,6 @@ static void __init n2100_timer_init(void) iop_init_time(198000000); } -static struct sys_timer n2100_timer = { - .init = n2100_timer_init, -}; - /* * N2100 I/O. @@ -337,7 +333,7 @@ MACHINE_START(N2100, "Thecus N2100") .atag_offset = 0x100, .map_io = n2100_map_io, .init_irq = iop32x_init_irq, - .timer = &n2100_timer, + .init_time = n2100_timer_init, .init_machine = n2100_init_machine, .restart = n2100_restart, MACHINE_END diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c index e74a7de..c43304a 100644 --- a/arch/arm/mach-iop33x/iq80331.c +++ b/arch/arm/mach-iop33x/iq80331.c @@ -45,10 +45,6 @@ static void __init iq80331_timer_init(void) iop_init_time(266000000); } -static struct sys_timer iq80331_timer = { - .init = iq80331_timer_init, -}; - /* * IQ80331 PCI. @@ -143,7 +139,7 @@ MACHINE_START(IQ80331, "Intel IQ80331") .atag_offset = 0x100, .map_io = iop3xx_map_io, .init_irq = iop33x_init_irq, - .timer = &iq80331_timer, + .init_time = iq80331_timer_init, .init_machine = iq80331_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c index e2f5bee..8192987 100644 --- a/arch/arm/mach-iop33x/iq80332.c +++ b/arch/arm/mach-iop33x/iq80332.c @@ -45,10 +45,6 @@ static void __init iq80332_timer_init(void) iop_init_time(266000000); } -static struct sys_timer iq80332_timer = { - .init = iq80332_timer_init, -}; - /* * IQ80332 PCI. @@ -143,7 +139,7 @@ MACHINE_START(IQ80332, "Intel IQ80332") .atag_offset = 0x100, .map_io = iop3xx_map_io, .init_irq = iop33x_init_irq, - .timer = &iq80332_timer, + .init_time = iq80332_timer_init, .init_machine = iq80332_init_machine, .restart = iop3xx_restart, MACHINE_END diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c index 90e42e9..6beec15 100644 --- a/arch/arm/mach-ixp4xx/avila-setup.c +++ b/arch/arm/mach-ixp4xx/avila-setup.c @@ -167,7 +167,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = avila_init, #if defined(CONFIG_PCI) @@ -187,7 +187,7 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = avila_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 8c0c0e2..1dbeb7c 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -307,10 +307,6 @@ void __init ixp4xx_timer_init(void) ixp4xx_clockevent_init(); } -struct sys_timer ixp4xx_timer = { - .init = ixp4xx_timer_init, -}; - static struct pxa2xx_udc_mach_info ixp4xx_udc_info; void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) @@ -523,22 +519,15 @@ static struct clock_event_device clockevent_ixp4xx = { .name = "ixp4xx timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 200, - .shift = 24, .set_mode = ixp4xx_set_mode, .set_next_event = ixp4xx_set_next_event, }; static void __init ixp4xx_clockevent_init(void) { - clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC, - clockevent_ixp4xx.shift); - clockevent_ixp4xx.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); - clockevent_ixp4xx.min_delta_ns = - clockevent_delta2ns(0xf, &clockevent_ixp4xx); clockevent_ixp4xx.cpumask = cpumask_of(0); - - clockevents_register_device(&clockevent_ixp4xx); + clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ, + 0xf, 0xfffffffe); } void ixp4xx_restart(char mode, const char *cmd) diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 1b83110..820cae8 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -112,7 +112,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = coyote_init, #if defined(CONFIG_PCI) @@ -132,7 +132,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = coyote_init, .restart = ixp4xx_restart, diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index 97a0af8..5d413f8 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -226,10 +226,6 @@ static void __init dsmg600_timer_init(void) ixp4xx_timer_init(); } -static struct sys_timer dsmg600_timer = { - .init = dsmg600_timer_init, -}; - static void __init dsmg600_init(void) { ixp4xx_sys_init(); @@ -282,7 +278,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &dsmg600_timer, + .init_time = dsmg600_timer_init, .init_machine = dsmg600_init, #if defined(CONFIG_PCI) .dma_zone_size = SZ_64M, diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c index 9175a25..429966b7 100644 --- a/arch/arm/mach-ixp4xx/fsg-setup.c +++ b/arch/arm/mach-ixp4xx/fsg-setup.c @@ -272,7 +272,7 @@ MACHINE_START(FSG, "Freecom FSG-3") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = fsg_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c index 033c717..3d24b3f 100644 --- a/arch/arm/mach-ixp4xx/gateway7001-setup.c +++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c @@ -99,7 +99,7 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = gateway7001_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c index 53b8348..e54ff49 100644 --- a/arch/arm/mach-ixp4xx/goramo_mlr.c +++ b/arch/arm/mach-ixp4xx/goramo_mlr.c @@ -498,7 +498,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = gmlr_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 18ebc6b..16a1299 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -167,7 +167,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = gtwx5715_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/include/mach/platform.h b/arch/arm/mach-ixp4xx/include/mach/platform.h index 5bce94a..db5afb6 100644 --- a/arch/arm/mach-ixp4xx/include/mach/platform.h +++ b/arch/arm/mach-ixp4xx/include/mach/platform.h @@ -89,8 +89,6 @@ struct ixp4xx_pata_data { void __iomem *cs1; }; -struct sys_timer; - #define IXP4XX_ETH_NPEA 0x00 #define IXP4XX_ETH_NPEB 0x10 #define IXP4XX_ETH_NPEC 0x20 @@ -125,7 +123,6 @@ extern void ixp4xx_init_early(void); extern void ixp4xx_init_irq(void); extern void ixp4xx_sys_init(void); extern void ixp4xx_timer_init(void); -extern struct sys_timer ixp4xx_timer; extern void ixp4xx_restart(char, const char *); extern void ixp4xx_pci_preinit(void); struct pci_sys_data; diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 108a9d3..22d688b 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -252,7 +252,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = ixdp425_init, #if defined(CONFIG_PCI) @@ -268,7 +268,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = ixdp425_init, #if defined(CONFIG_PCI) @@ -283,7 +283,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = ixdp425_init, #if defined(CONFIG_PCI) @@ -298,7 +298,7 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = ixdp425_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 33cb095..ed667ce 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -317,7 +317,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .init_machine = nas100d_init, #if defined(CONFIG_PCI) .dma_zone_size = SZ_64M, diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index e2903fa..7e55236 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -232,10 +232,6 @@ static void __init nslu2_timer_init(void) ixp4xx_timer_init(); } -static struct sys_timer nslu2_timer = { - .init = nslu2_timer_init, -}; - static void __init nslu2_init(void) { uint8_t __iomem *f; @@ -303,7 +299,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &nslu2_timer, + .init_time = nslu2_timer_init, .init_machine = nslu2_init, #if defined(CONFIG_PCI) .dma_zone_size = SZ_64M, diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c index 158ddb7..46a89f5 100644 --- a/arch/arm/mach-ixp4xx/omixp-setup.c +++ b/arch/arm/mach-ixp4xx/omixp-setup.c @@ -245,7 +245,7 @@ MACHINE_START(DEVIXP, "Omicron DEVIXP") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .init_machine = omixp_init, .restart = ixp4xx_restart, MACHINE_END @@ -257,7 +257,7 @@ MACHINE_START(MICCPT, "Omicron MICCPT") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .init_machine = omixp_init, #if defined(CONFIG_PCI) .dma_zone_size = SZ_64M, @@ -272,7 +272,7 @@ MACHINE_START(MIC256, "Omicron MIC256") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .init_machine = omixp_init, .restart = ixp4xx_restart, MACHINE_END diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c index 2798f43..d42730a 100644 --- a/arch/arm/mach-ixp4xx/vulcan-setup.c +++ b/arch/arm/mach-ixp4xx/vulcan-setup.c @@ -239,7 +239,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = vulcan_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c index a785175..8f9ea2f 100644 --- a/arch/arm/mach-ixp4xx/wg302v2-setup.c +++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c @@ -100,7 +100,7 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2") .map_io = ixp4xx_map_io, .init_early = ixp4xx_init_early, .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, + .init_time = ixp4xx_timer_init, .atag_offset = 0x100, .init_machine = wg302v2_init, #if defined(CONFIG_PCI) diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 8d2e5a9..d665309 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_T5325) += t5325-setup.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o obj-$(CONFIG_MACH_DREAMPLUG_DT) += board-dreamplug.o obj-$(CONFIG_MACH_ICONNECT_DT) += board-iconnect.o diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index de4fd2b..95cc04d 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -98,6 +98,8 @@ static void __init kirkwood_dt_init(void) /* Setup root of clk tree */ kirkwood_of_clk_init(); + kirkwood_cpuidle_init(); + #ifdef CONFIG_KEXEC kexec_reinit = kirkwood_enable_pcie; #endif @@ -183,7 +185,7 @@ DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = orion_dt_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .init_machine = kirkwood_dt_init, .restart = kirkwood_restart, .dt_compat = kirkwood_dt_board_compat, diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index bac21a5..49792a0 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -499,6 +499,28 @@ void __init kirkwood_wdt_init(void) orion_wdt_init(); } +/***************************************************************************** + * CPU idle + ****************************************************************************/ +static struct resource kirkwood_cpuidle_resource[] = { + { + .flags = IORESOURCE_MEM, + .start = DDR_OPERATION_BASE, + .end = DDR_OPERATION_BASE + 3, + }, +}; + +static struct platform_device kirkwood_cpuidle = { + .name = "kirkwood_cpuidle", + .id = -1, + .resource = kirkwood_cpuidle_resource, + .num_resources = 1, +}; + +void __init kirkwood_cpuidle_init(void) +{ + platform_device_register(&kirkwood_cpuidle); +} /***************************************************************************** * Time handling @@ -530,7 +552,7 @@ static int __init kirkwood_find_tclk(void) return 166666667; } -static void __init kirkwood_timer_init(void) +void __init kirkwood_timer_init(void) { kirkwood_tclk = kirkwood_find_tclk(); @@ -538,10 +560,6 @@ static void __init kirkwood_timer_init(void) IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); } -struct sys_timer kirkwood_timer = { - .init = kirkwood_timer_init, -}; - /***************************************************************************** * Audio ****************************************************************************/ @@ -671,6 +689,7 @@ void __init kirkwood_init(void) kirkwood_xor1_init(); kirkwood_crypto_init(); + kirkwood_cpuidle_init(); #ifdef CONFIG_KEXEC kexec_reinit = kirkwood_enable_pcie; #endif diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 5ffa57f..e956d02 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -50,6 +50,7 @@ void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay); void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *)); void kirkwood_audio_init(void); +void kirkwood_cpuidle_init(void); void kirkwood_restart(char, const char *); void kirkwood_clk_init(void); @@ -156,7 +157,7 @@ void kirkwood_xor1_init(void); void kirkwood_crypto_init(void); extern int kirkwood_tclk; -extern struct sys_timer kirkwood_timer; +extern void kirkwood_timer_init(void); #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c index 2c1a453..4534180 100644 --- a/arch/arm/mach-kirkwood/d2net_v2-setup.c +++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c @@ -226,6 +226,6 @@ MACHINE_START(D2NET_V2, "LaCie d2 Network v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c index c49b177..5a369fe 100644 --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c @@ -103,6 +103,6 @@ MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c index 791a98f..77f98f2 100644 --- a/arch/arm/mach-kirkwood/dockstar-setup.c +++ b/arch/arm/mach-kirkwood/dockstar-setup.c @@ -107,6 +107,6 @@ MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c index 7cb55f9..1c6e736 100644 --- a/arch/arm/mach-kirkwood/guruplug-setup.c +++ b/arch/arm/mach-kirkwood/guruplug-setup.c @@ -126,6 +126,6 @@ MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index 041653a..a05563a 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -60,8 +60,9 @@ * Register Map */ #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x00000) +#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000) #define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE + 0x1500) -#define DDR_OPERATION_BASE (DDR_VIRT_BASE + 0x1418) +#define DDR_OPERATION_BASE (DDR_PHYS_BASE + 0x1418) #define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x10000) #define DEV_BUS_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x10000) diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c index 6d8364a..ba384b9 100644 --- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c +++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c @@ -167,6 +167,6 @@ MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c index 728e86d..3b70661 100644 --- a/arch/arm/mach-kirkwood/netspace_v2-setup.c +++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c @@ -263,7 +263,7 @@ MACHINE_START(NETSPACE_V2, "LaCie Network Space v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -275,7 +275,7 @@ MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -287,7 +287,7 @@ MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c index a3b0914..913d032 100644 --- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c +++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c @@ -404,7 +404,7 @@ MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -416,7 +416,7 @@ MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c index 7e81e9b..8ddd69f 100644 --- a/arch/arm/mach-kirkwood/openrd-setup.c +++ b/arch/arm/mach-kirkwood/openrd-setup.c @@ -221,7 +221,7 @@ MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -234,7 +234,7 @@ MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -247,7 +247,7 @@ MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index a1c3ab6..d96ad4c 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -247,13 +247,9 @@ static struct hw_pci kirkwood_pci __initdata = { static void __init add_pcie_port(int index, void __iomem *base) { - pr_info("Kirkwood PCIe port %d: ", index); - - if (orion_pcie_link_up(base)) { - pr_info("link up\n"); - pcie_port_map[num_pcie_ports++] = index; - } else - pr_info("link down, ignoring\n"); + pcie_port_map[num_pcie_ports++] = index; + pr_info("Kirkwood PCIe port %d: link %s\n", index, + orion_pcie_link_up(base) ? "up" : "down"); } void __init kirkwood_pcie_init(unsigned int portmask) diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c index 19072c8..e4fd312 100644 --- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c @@ -84,6 +84,6 @@ MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c index 9717101..c7d93b4 100644 --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c @@ -120,6 +120,6 @@ MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c index 8a17594..55b68fa 100644 --- a/arch/arm/mach-kirkwood/sheevaplug-setup.c +++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c @@ -143,7 +143,7 @@ MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif @@ -155,7 +155,7 @@ MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c index f2daf71..8736f8c 100644 --- a/arch/arm/mach-kirkwood/t5325-setup.c +++ b/arch/arm/mach-kirkwood/t5325-setup.c @@ -211,6 +211,6 @@ MACHINE_START(T5325, "HP t5325 Thin Client") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c index 73e2b6c..283abff 100644 --- a/arch/arm/mach-kirkwood/ts219-setup.c +++ b/arch/arm/mach-kirkwood/ts219-setup.c @@ -137,6 +137,6 @@ MACHINE_START(TS219, "QNAP TS-119/TS-219") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c index e4c6127..81d5858 100644 --- a/arch/arm/mach-kirkwood/ts41x-setup.c +++ b/arch/arm/mach-kirkwood/ts41x-setup.c @@ -181,6 +181,6 @@ MACHINE_START(TS41X, "QNAP TS-41x") .map_io = kirkwood_map_io, .init_early = kirkwood_init_early, .init_irq = kirkwood_init_irq, - .timer = &kirkwood_timer, + .init_time = kirkwood_timer_init, .restart = kirkwood_restart, MACHINE_END diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c index b0c306c..456d638 100644 --- a/arch/arm/mach-ks8695/board-acs5k.c +++ b/arch/arm/mach-ks8695/board-acs5k.c @@ -227,6 +227,6 @@ MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = acs5k_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c index e0d36ce..d37c218 100644 --- a/arch/arm/mach-ks8695/board-dsm320.c +++ b/arch/arm/mach-ks8695/board-dsm320.c @@ -125,6 +125,6 @@ MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = dsm320_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c index a827072..3acbdfd 100644 --- a/arch/arm/mach-ks8695/board-micrel.c +++ b/arch/arm/mach-ks8695/board-micrel.c @@ -57,6 +57,6 @@ MACHINE_START(KS8695, "KS8695 Centaur Development Board") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = micrel_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END diff --git a/arch/arm/mach-ks8695/board-og.c b/arch/arm/mach-ks8695/board-og.c index 1623ba4..002bc61 100644 --- a/arch/arm/mach-ks8695/board-og.c +++ b/arch/arm/mach-ks8695/board-og.c @@ -145,7 +145,7 @@ MACHINE_START(CM4002, "OpenGear/CM4002") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = og_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -157,7 +157,7 @@ MACHINE_START(CM4008, "OpenGear/CM4008") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = og_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -169,7 +169,7 @@ MACHINE_START(CM41XX, "OpenGear/CM41xx") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = og_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -181,7 +181,7 @@ MACHINE_START(IM4004, "OpenGear/IM4004") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = og_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -193,7 +193,7 @@ MACHINE_START(IM42XX, "OpenGear/IM42xx") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = og_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif diff --git a/arch/arm/mach-ks8695/board-sg.c b/arch/arm/mach-ks8695/board-sg.c index f35b98b..fdf2352 100644 --- a/arch/arm/mach-ks8695/board-sg.c +++ b/arch/arm/mach-ks8695/board-sg.c @@ -91,7 +91,7 @@ MACHINE_START(LITE300, "SecureComputing/SG300") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = sg_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -103,7 +103,7 @@ MACHINE_START(SG310, "McAfee/SG310") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = sg_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif @@ -115,7 +115,7 @@ MACHINE_START(SE4200, "SecureComputing/SE4200") .map_io = ks8695_map_io, .init_irq = ks8695_init_irq, .init_machine = sg_init, - .timer = &ks8695_timer, + .init_time = ks8695_timer_init, .restart = ks8695_restart, MACHINE_END #endif diff --git a/arch/arm/mach-ks8695/generic.h b/arch/arm/mach-ks8695/generic.h index f8bdb11..6e97ce4 100644 --- a/arch/arm/mach-ks8695/generic.h +++ b/arch/arm/mach-ks8695/generic.h @@ -13,4 +13,4 @@ extern __init void ks8695_map_io(void); extern __init void ks8695_init_irq(void); extern void ks8695_restart(char, const char *); -extern struct sys_timer ks8695_timer; +extern void ks8695_timer_init(void); diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c index 46c84bc..c272a386 100644 --- a/arch/arm/mach-ks8695/time.c +++ b/arch/arm/mach-ks8695/time.c @@ -146,7 +146,7 @@ static void ks8695_timer_setup(void) 0xFFFFFFFFU); } -static void __init ks8695_timer_init (void) +void __init ks8695_timer_init(void) { ks8695_timer_setup(); @@ -154,10 +154,6 @@ static void __init ks8695_timer_init (void) setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq); } -struct sys_timer ks8695_timer = { - .init = ks8695_timer_init, -}; - void ks8695_restart(char mode, const char *cmd) { unsigned int reg; diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h index afeac3b..e0b2606 100644 --- a/arch/arm/mach-lpc32xx/common.h +++ b/arch/arm/mach-lpc32xx/common.h @@ -25,7 +25,7 @@ /* * Other arch specific structures and functions */ -extern struct sys_timer lpc32xx_timer; +extern void lpc32xx_timer_init(void); extern void __init lpc32xx_init_irq(void); extern void __init lpc32xx_map_io(void); extern void __init lpc32xx_serial_init(void); diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index e8ff4c3..c1cd5a9 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -263,7 +263,7 @@ DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)") .atag_offset = 0x100, .map_io = lpc32xx_map_io, .init_irq = lpc32xx_init_irq, - .timer = &lpc32xx_timer, + .init_time = lpc32xx_timer_init, .init_machine = lpc3250_machine_init, .dt_compat = lpc32xx_dt_compat, .restart = lpc23xx_restart, diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index c40667c..20eab63 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -70,7 +70,6 @@ static void lpc32xx_clkevt_mode(enum clock_event_mode mode, static struct clock_event_device lpc32xx_clkevt = { .name = "lpc32xx_clkevt", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 300, .set_next_event = lpc32xx_clkevt_next_event, .set_mode = lpc32xx_clkevt_mode, @@ -100,7 +99,7 @@ static struct irqaction lpc32xx_timer_irq = { * clocks need to be enabled here manually and then tagged as used in * the clock driver initialization */ -static void __init lpc32xx_timer_init(void) +void __init lpc32xx_timer_init(void) { u32 clkrate, pllreg; @@ -141,14 +140,8 @@ static void __init lpc32xx_timer_init(void) setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq); /* Setup the clockevent structure. */ - lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC, - lpc32xx_clkevt.shift); - lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1, - &lpc32xx_clkevt); - lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1, - &lpc32xx_clkevt) + 1; lpc32xx_clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&lpc32xx_clkevt); + clockevents_config_and_register(&lpc32xx_clkevt, clkrate, 1, -1); /* Use timer1 as clock source. */ __raw_writel(LPC32XX_TIMER_CNTR_TCR_RESET, @@ -161,8 +154,3 @@ static void __init lpc32xx_timer_init(void) clocksource_mmio_init(LPC32XX_TIMER_TC(LPC32XX_TIMER1_BASE), "lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up); } - -struct sys_timer lpc32xx_timer = { - .init = &lpc32xx_timer_init, -}; - diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index e5dba9c..9f64d56 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -262,7 +262,7 @@ MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa168_init_irq, - .timer = &pxa168_timer, + .init_time = pxa168_timer_init, .init_machine = common_init, .restart = pxa168_restart, MACHINE_END @@ -271,7 +271,7 @@ MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa168_init_irq, - .timer = &pxa168_timer, + .init_time = pxa168_timer_init, .init_machine = common_init, .restart = pxa168_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c index 603542a..1f94957 100644 --- a/arch/arm/mach-mmp/avengers_lite.c +++ b/arch/arm/mach-mmp/avengers_lite.c @@ -45,7 +45,7 @@ MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa168_init_irq, - .timer = &pxa168_timer, + .init_time = pxa168_timer_init, .init_machine = avengers_lite_init, .restart = pxa168_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index 5cb769c..2358011 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -218,7 +218,7 @@ MACHINE_START(BROWNSTONE, "Brownstone Development Platform") .map_io = mmp_map_io, .nr_irqs = BROWNSTONE_NR_IRQS, .init_irq = mmp2_init_irq, - .timer = &mmp2_timer, + .init_time = mmp2_timer_init, .init_machine = brownstone_init, .restart = mmp_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h index bd45327..0bdc50b 100644 --- a/arch/arm/mach-mmp/common.h +++ b/arch/arm/mach-mmp/common.h @@ -1,7 +1,5 @@ #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) -struct sys_timer; - extern void timer_init(int irq); extern void __init icu_init_irq(void); diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c index 8059cc0..754c352 100644 --- a/arch/arm/mach-mmp/flint.c +++ b/arch/arm/mach-mmp/flint.c @@ -121,7 +121,7 @@ MACHINE_START(FLINT, "Flint Development Platform") .map_io = mmp_map_io, .nr_irqs = FLINT_NR_IRQS, .init_irq = mmp2_init_irq, - .timer = &mmp2_timer, + .init_time = mmp2_timer_init, .init_machine = flint_init, .restart = mmp_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 5c3d61e..d1e2d59 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -194,7 +194,7 @@ MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa168_init_irq, - .timer = &pxa168_timer, + .init_time = pxa168_timer_init, .init_machine = gplugd_init, .restart = pxa168_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h index c4ca4d1..0764f4e 100644 --- a/arch/arm/mach-mmp/include/mach/mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mmp2.h @@ -3,9 +3,7 @@ #include <linux/platform_data/pxa_sdhci.h> -struct sys_timer; - -extern struct sys_timer mmp2_timer; +extern void mmp2_timer_init(void); extern void __init mmp2_init_icu(void); extern void __init mmp2_init_irq(void); extern void mmp2_clear_pmic_int(void); diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 37632d9..7ed1df2 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -1,9 +1,7 @@ #ifndef __ASM_MACH_PXA168_H #define __ASM_MACH_PXA168_H -struct sys_timer; - -extern struct sys_timer pxa168_timer; +extern void pxa168_timer_init(void); extern void __init pxa168_init_irq(void); extern void pxa168_restart(char, const char *); extern void pxa168_clear_keypad_wakeup(void); diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h index 3b58a3b..eff31ab6 100644 --- a/arch/arm/mach-mmp/include/mach/pxa910.h +++ b/arch/arm/mach-mmp/include/mach/pxa910.h @@ -1,9 +1,7 @@ #ifndef __ASM_MACH_PXA910_H #define __ASM_MACH_PXA910_H -struct sys_timer; - -extern struct sys_timer pxa910_timer; +extern void pxa910_timer_init(void); extern void __init pxa910_init_irq(void); #include <linux/i2c.h> diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c index ff73249..66634fd 100644 --- a/arch/arm/mach-mmp/jasper.c +++ b/arch/arm/mach-mmp/jasper.c @@ -174,7 +174,7 @@ MACHINE_START(MARVELL_JASPER, "Jasper Development Platform") .map_io = mmp_map_io, .nr_irqs = JASPER_NR_IRQS, .init_irq = mmp2_init_irq, - .timer = &mmp2_timer, + .init_time = mmp2_timer_init, .init_machine = jasper_init, .restart = mmp_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/mmp-dt.c b/arch/arm/mach-mmp/mmp-dt.c index 033cc31..d063efa 100644 --- a/arch/arm/mach-mmp/mmp-dt.c +++ b/arch/arm/mach-mmp/mmp-dt.c @@ -22,10 +22,6 @@ extern void __init mmp_dt_irq_init(void); extern void __init mmp_dt_init_timer(void); -static struct sys_timer mmp_dt_timer = { - .init = mmp_dt_init_timer, -}; - static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL), OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL), @@ -69,7 +65,7 @@ static const char *mmp_dt_board_compat[] __initdata = { DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)") .map_io = mmp_map_io, .init_irq = mmp_dt_irq_init, - .timer = &mmp_dt_timer, + .init_time = mmp_dt_init_timer, .init_machine = pxa168_dt_init, .dt_compat = mmp_dt_board_compat, MACHINE_END @@ -77,7 +73,7 @@ MACHINE_END DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)") .map_io = mmp_map_io, .init_irq = mmp_dt_irq_init, - .timer = &mmp_dt_timer, + .init_time = mmp_dt_init_timer, .init_machine = pxa910_dt_init, .dt_compat = mmp_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c index 535a5ed..fad431a 100644 --- a/arch/arm/mach-mmp/mmp2-dt.c +++ b/arch/arm/mach-mmp/mmp2-dt.c @@ -24,10 +24,6 @@ extern void __init mmp_dt_irq_init(void); extern void __init mmp_dt_init_timer(void); -static struct sys_timer mmp_dt_timer = { - .init = mmp_dt_init_timer, -}; - static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL), OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL), @@ -54,7 +50,7 @@ static const char *mmp2_dt_board_compat[] __initdata = { DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)") .map_io = mmp_map_io, .init_irq = mmp_dt_irq_init, - .timer = &mmp_dt_timer, + .init_time = mmp_dt_init_timer, .init_machine = mmp2_dt_init, .dt_compat = mmp2_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 3a3768c..d94d114 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -114,7 +114,7 @@ postcore_initcall(mmp2_init); #define APBC_TIMERS APBC_REG(0x024) -static void __init mmp2_timer_init(void) +void __init mmp2_timer_init(void) { unsigned long clk_rst; @@ -130,10 +130,6 @@ static void __init mmp2_timer_init(void) timer_init(IRQ_MMP2_TIMER1); } -struct sys_timer mmp2_timer = { - .init = mmp2_timer_init, -}; - /* on-chip devices */ MMP2_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4030000, 0x30, 4, 5); MMP2_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4017000, 0x30, 20, 21); diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index b7f074f..9bc7b86 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -67,7 +67,7 @@ postcore_initcall(pxa168_init); #define TIMER_CLK_RST (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3)) #define APBC_TIMERS APBC_REG(0x34) -static void __init pxa168_timer_init(void) +void __init pxa168_timer_init(void) { /* this is early, we have to initialize the CCU registers by * ourselves instead of using clk_* API. Clock rate is defined @@ -81,10 +81,6 @@ static void __init pxa168_timer_init(void) timer_init(IRQ_PXA168_TIMER1); } -struct sys_timer pxa168_timer = { - .init = pxa168_timer_init, -}; - void pxa168_clear_keypad_wakeup(void) { uint32_t val; diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index 8b1e16f..c6a89f1 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -101,7 +101,7 @@ postcore_initcall(pxa910_init); #define TIMER_CLK_RST (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3)) #define APBC_TIMERS APBC_REG(0x34) -static void __init pxa910_timer_init(void) +void __init pxa910_timer_init(void) { /* reset and configure */ __raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS); @@ -110,10 +110,6 @@ static void __init pxa910_timer_init(void) timer_init(IRQ_PXA910_AP1_TIMER1); } -struct sys_timer pxa910_timer = { - .init = pxa910_timer_init, -}; - /* on-chip devices */ /* NOTE: there are totally 3 UARTs on PXA910: diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c index b28f908..4c127d2 100644 --- a/arch/arm/mach-mmp/tavorevb.c +++ b/arch/arm/mach-mmp/tavorevb.c @@ -103,7 +103,7 @@ MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa910_init_irq, - .timer = &pxa910_timer, + .init_time = pxa910_timer_init, .init_machine = tavorevb_init, .restart = mmp_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index dd30ea7..8609967 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c @@ -86,7 +86,7 @@ MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform") .map_io = mmp_map_io, .nr_irqs = MMP_NR_IRQS, .init_irq = pxa168_init_irq, - .timer = &pxa168_timer, + .init_time = pxa168_timer_init, .init_machine = teton_bga_init, .restart = pxa168_restart, MACHINE_END diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 936447c..86a18b3 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -141,7 +141,6 @@ static void timer_set_mode(enum clock_event_mode mode, static struct clock_event_device ckevt = { .name = "clockevent", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 200, .set_next_event = timer_set_next_event, .set_mode = timer_set_mode, @@ -198,15 +197,13 @@ void __init timer_init(int irq) setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE); - ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); - ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); - ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt); ckevt.cpumask = cpumask_of(0); setup_irq(irq, &timer_irq); clocksource_register_hz(&cksrc, CLOCK_TICK_RATE); - clockevents_register_device(&ckevt); + clockevents_config_and_register(&ckevt, CLOCK_TICK_RATE, + MIN_DELTA, MAX_DELTA); } #ifdef CONFIG_OF diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index ce55fd8..6e47490 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -218,7 +218,7 @@ MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform") .map_io = mmp_map_io, .nr_irqs = TTCDKB_NR_IRQS, .init_irq = pxa910_init_irq, - .timer = &pxa910_timer, + .init_time = pxa910_timer_init, .init_machine = ttc_dkb_init, .restart = mmp_restart, MACHINE_END diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c index b5b4de2..7dcfc53 100644 --- a/arch/arm/mach-msm/board-dt-8660.c +++ b/arch/arm/mach-msm/board-dt-8660.c @@ -11,26 +11,15 @@ */ #include <linux/init.h> +#include <linux/irqchip.h> #include <linux/of.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/board.h> #include "common.h" -static const struct of_device_id msm_dt_gic_match[] __initconst = { - { .compatible = "qcom,msm-8660-qgic", .data = gic_of_init }, - {} -}; - -static void __init msm8x60_init_irq(void) -{ - of_irq_init(msm_dt_gic_match); -} - static void __init msm8x60_init_late(void) { smd_debugfs_init(); @@ -55,10 +44,9 @@ static const char *msm8x60_fluid_match[] __initdata = { DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") .smp = smp_ops(msm_smp_ops), .map_io = msm_map_msm8x60_io, - .init_irq = msm8x60_init_irq, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = msm8x60_dt_init, .init_late = msm8x60_init_late, - .timer = &msm_dt_timer, + .init_time = msm_dt_timer_init, .dt_compat = msm8x60_fluid_match, MACHINE_END diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt-8960.c index 4490edb..7301936 100644 --- a/arch/arm/mach-msm/board-dt-8960.c +++ b/arch/arm/mach-msm/board-dt-8960.c @@ -11,24 +11,13 @@ */ #include <linux/init.h> -#include <linux/of_irq.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include "common.h" -static const struct of_device_id msm_dt_gic_match[] __initconst = { - { .compatible = "qcom,msm-qgic2", .data = gic_of_init }, - { } -}; - -static void __init msm_dt_init_irq(void) -{ - of_irq_init(msm_dt_gic_match); -} - static void __init msm_dt_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); @@ -42,9 +31,8 @@ static const char * const msm8960_dt_match[] __initconst = { DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)") .smp = smp_ops(msm_smp_ops), .map_io = msm_map_msm8960_io, - .init_irq = msm_dt_init_irq, - .timer = &msm_dt_timer, + .init_irq = irqchip_init, + .init_time = msm_dt_timer_init, .init_machine = msm_dt_init, .dt_compat = msm8960_dt_match, - .handle_irq = gic_handle_irq, MACHINE_END diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index 6ce542e..84d720a 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -106,5 +106,5 @@ MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)") .init_irq = halibut_init_irq, .init_machine = halibut_init, .init_late = halibut_init_late, - .timer = &msm7x01_timer, + .init_time = msm7x01_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c index df00bc0..30c3496 100644 --- a/arch/arm/mach-msm/board-mahimahi.c +++ b/arch/arm/mach-msm/board-mahimahi.c @@ -75,7 +75,7 @@ static void __init mahimahi_init_late(void) smd_debugfs_init(); } -extern struct sys_timer msm_timer; +void msm_timer_init(void); MACHINE_START(MAHIMAHI, "mahimahi") .atag_offset = 0x100, @@ -84,5 +84,5 @@ MACHINE_START(MAHIMAHI, "mahimahi") .init_irq = msm_init_irq, .init_machine = mahimahi_init, .init_late = mahimahi_init_late, - .timer = &msm_timer, + .init_time = msm_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index effa6f4..7bc3f82 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -131,7 +131,7 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF") .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, .init_late = msm7x30_init_late, - .timer = &msm7x30_timer, + .init_time = msm7x30_timer_init, MACHINE_END MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") @@ -142,7 +142,7 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, .init_late = msm7x30_init_late, - .timer = &msm7x30_timer, + .init_time = msm7x30_timer_init, MACHINE_END MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") @@ -153,5 +153,5 @@ MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, .init_late = msm7x30_init_late, - .timer = &msm7x30_timer, + .init_time = msm7x30_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 2448fcf..686e794 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -200,7 +200,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF") .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, .init_late = qsd8x50_init_late, - .timer = &qsd8x50_timer, + .init_time = qsd8x50_timer_init, MACHINE_END MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5") @@ -209,5 +209,5 @@ MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5") .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, .init_late = qsd8x50_init_late, - .timer = &qsd8x50_timer, + .init_time = qsd8x50_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c index b7b0fc7..7073011 100644 --- a/arch/arm/mach-msm/board-sapphire.c +++ b/arch/arm/mach-msm/board-sapphire.c @@ -53,7 +53,7 @@ static struct platform_device *devices[] __initdata = { &msm_device_uart3, }; -extern struct sys_timer msm_timer; +void msm_timer_init(void); static void __init sapphire_init_irq(void) { @@ -113,5 +113,5 @@ MACHINE_START(SAPPHIRE, "sapphire") .init_irq = sapphire_init_irq, .init_machine = sapphire_init, .init_late = sapphire_init_late, - .timer = &msm_timer, + .init_time = msm_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index 4ba0800..919bfa3 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -110,5 +110,5 @@ MACHINE_START(TROUT, "HTC Dream") .init_irq = trout_init_irq, .init_machine = trout_init, .init_late = trout_init_late, - .timer = &msm7x01_timer, + .init_time = msm7x01_timer_init, MACHINE_END diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h index 633a7159..ce8215a 100644 --- a/arch/arm/mach-msm/common.h +++ b/arch/arm/mach-msm/common.h @@ -12,10 +12,10 @@ #ifndef __MACH_COMMON_H #define __MACH_COMMON_H -extern struct sys_timer msm7x01_timer; -extern struct sys_timer msm7x30_timer; -extern struct sys_timer msm_dt_timer; -extern struct sys_timer qsd8x50_timer; +extern void msm7x01_timer_init(void); +extern void msm7x30_timer_init(void); +extern void msm_dt_timer_init(void); +extern void qsd8x50_timer_init(void); extern void msm_map_common_io(void); extern void msm_map_msm7x30_io(void); diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 7ed69b69..42932865 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -15,8 +15,8 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> -#include <asm/hardware/gic.h> #include <asm/cacheflush.h> #include <asm/cputype.h> #include <asm/mach-types.h> @@ -115,7 +115,7 @@ static int __cpuinit msm_boot_secondary(unsigned int cpu, struct task_struct *id * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -153,8 +153,6 @@ static void __init msm_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init msm_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 476549a..2969027 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -25,7 +25,6 @@ #include <linux/of_irq.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> #include <asm/localtimer.h> #include <asm/sched_clock.h> @@ -144,13 +143,9 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) evt->rating = msm_clockevent.rating; evt->set_mode = msm_timer_set_mode; evt->set_next_event = msm_timer_set_next_event; - evt->shift = msm_clockevent.shift; - evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); - evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); - evt->min_delta_ns = clockevent_delta2ns(4, evt); *__this_cpu_ptr(msm_evt.percpu_evt) = evt; - clockevents_register_device(evt); + clockevents_config_and_register(evt, GPT_HZ, 4, 0xf0000000); enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); return 0; } @@ -229,7 +224,7 @@ static const struct of_device_id msm_gpt_match[] __initconst = { { }, }; -static void __init msm_dt_timer_init(void) +void __init msm_dt_timer_init(void) { struct device_node *np; u32 freq; @@ -296,10 +291,6 @@ static void __init msm_dt_timer_init(void) msm_timer_init(freq, 32, irq, !!percpu_offset); } - -struct sys_timer msm_dt_timer = { - .init = msm_dt_timer_init -}; #endif static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) @@ -317,7 +308,7 @@ static int __init msm_timer_map(phys_addr_t event, phys_addr_t source) return 0; } -static void __init msm7x01_timer_init(void) +void __init msm7x01_timer_init(void) { struct clocksource *cs = &msm_clocksource; @@ -330,28 +321,16 @@ static void __init msm7x01_timer_init(void) false); } -struct sys_timer msm7x01_timer = { - .init = msm7x01_timer_init -}; - -static void __init msm7x30_timer_init(void) +void __init msm7x30_timer_init(void) { if (msm_timer_map(0xc0100004, 0xc0100024)) return; msm_timer_init(24576000 / 4, 32, 1, false); } -struct sys_timer msm7x30_timer = { - .init = msm7x30_timer_init -}; - -static void __init qsd8x50_timer_init(void) +void __init qsd8x50_timer_init(void) { if (msm_timer_map(0xAC100000, 0xAC100010)) return; msm_timer_init(19200000 / 4, 32, 7, false); } - -struct sys_timer qsd8x50_timer = { - .init = qsd8x50_timer_init -}; diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c index ee74ec9..1f2ef98 100644 --- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c +++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c @@ -150,6 +150,6 @@ MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL") .map_io = mv78xx0_map_io, .init_early = mv78xx0_init_early, .init_irq = mv78xx0_init_irq, - .timer = &mv78xx0_timer, + .init_time = mv78xx0_timer_init, .restart = mv78xx0_restart, MACHINE_END diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index d0cb485..0efa1449 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -336,16 +336,12 @@ void __init mv78xx0_init_early(void) orion_time_set_base(TIMER_VIRT_BASE); } -static void __init_refok mv78xx0_timer_init(void) +void __init_refok mv78xx0_timer_init(void) { orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR, IRQ_MV78XX0_TIMER_1, get_tclk()); } -struct sys_timer mv78xx0_timer = { - .init = mv78xx0_timer_init, -}; - /***************************************************************************** * General diff --git a/arch/arm/mach-mv78xx0/common.h b/arch/arm/mach-mv78xx0/common.h index 507c767..5e9485b 100644 --- a/arch/arm/mach-mv78xx0/common.h +++ b/arch/arm/mach-mv78xx0/common.h @@ -47,7 +47,7 @@ void mv78xx0_uart3_init(void); void mv78xx0_i2c_init(void); void mv78xx0_restart(char, const char *); -extern struct sys_timer mv78xx0_timer; +extern void mv78xx0_timer_init(void); #endif diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c index 4d6d48b..4e0f22b 100644 --- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c +++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c @@ -98,6 +98,6 @@ MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board") .map_io = mv78xx0_map_io, .init_early = mv78xx0_init_early, .init_irq = mv78xx0_init_irq, - .timer = &mv78xx0_timer, + .init_time = mv78xx0_timer_init, .restart = mv78xx0_restart, MACHINE_END diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c index 9a88270..d2d06f3 100644 --- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c +++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c @@ -83,6 +83,6 @@ MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board") .map_io = mv78xx0_map_io, .init_early = mv78xx0_init_early, .init_irq = mv78xx0_init_irq, - .timer = &mv78xx0_timer, + .init_time = mv78xx0_timer_init, .restart = mv78xx0_restart, MACHINE_END diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c index 7434b5e..a5ea616d 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@ -56,10 +56,6 @@ void __init armada_370_xp_init_early(void) init_dma_coherent_pool_size(SZ_1M); } -struct sys_timer armada_370_xp_timer = { - .init = armada_370_xp_timer_and_clk_init, -}; - static void __init armada_370_xp_dt_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); @@ -78,7 +74,7 @@ DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)") .init_early = armada_370_xp_init_early, .init_irq = armada_370_xp_init_irq, .handle_irq = armada_370_xp_handle_irq, - .timer = &armada_370_xp_timer, + .init_time = armada_370_xp_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_370_xp_dt_compat, MACHINE_END diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index c66129b..5fad7ce 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -163,19 +163,11 @@ static void __init imx23_timer_init(void) mx23_clocks_init(); } -static struct sys_timer imx23_timer = { - .init = imx23_timer_init, -}; - static void __init imx28_timer_init(void) { mx28_clocks_init(); } -static struct sys_timer imx28_timer = { - .init = imx28_timer_init, -}; - enum mac_oui { OUI_FSL, OUI_DENX, @@ -446,7 +438,7 @@ DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") .map_io = mx23_map_io, .init_irq = icoll_init_irq, .handle_irq = icoll_handle_irq, - .timer = &imx23_timer, + .init_time = imx23_timer_init, .init_machine = mxs_machine_init, .dt_compat = imx23_dt_compat, .restart = mxs_restart, @@ -456,7 +448,7 @@ DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") .map_io = mx28_map_io, .init_irq = icoll_init_irq, .handle_irq = icoll_handle_irq, - .timer = &imx28_timer, + .init_time = imx28_timer_init, .init_machine = mxs_machine_init, .dt_compat = imx28_dt_compat, .restart = mxs_restart, diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c index 856f4c7..27451b1 100644 --- a/arch/arm/mach-mxs/timer.c +++ b/arch/arm/mach-mxs/timer.c @@ -195,7 +195,6 @@ static void mxs_set_mode(enum clock_event_mode mode, static struct clock_event_device mxs_clockevent_device = { .name = "mxs_timrot", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_mode = mxs_set_mode, .set_next_event = timrotv2_set_next_event, .rating = 200, @@ -203,25 +202,12 @@ static struct clock_event_device mxs_clockevent_device = { static int __init mxs_clockevent_init(struct clk *timer_clk) { - unsigned int c = clk_get_rate(timer_clk); - - mxs_clockevent_device.mult = - div_sc(c, NSEC_PER_SEC, mxs_clockevent_device.shift); - mxs_clockevent_device.cpumask = cpumask_of(0); - if (timrot_is_v1()) { + if (timrot_is_v1()) mxs_clockevent_device.set_next_event = timrotv1_set_next_event; - mxs_clockevent_device.max_delta_ns = - clockevent_delta2ns(0xfffe, &mxs_clockevent_device); - mxs_clockevent_device.min_delta_ns = - clockevent_delta2ns(0xf, &mxs_clockevent_device); - } else { - mxs_clockevent_device.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &mxs_clockevent_device); - mxs_clockevent_device.min_delta_ns = - clockevent_delta2ns(0xf, &mxs_clockevent_device); - } - - clockevents_register_device(&mxs_clockevent_device); + mxs_clockevent_device.cpumask = cpumask_of(0); + clockevents_config_and_register(&mxs_clockevent_device, + clk_get_rate(timer_clk), 0xf, + timrot_is_v1() ? 0xfffe : 0xfffffffe); return 0; } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index aa62746..27c2cb7 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -23,9 +23,9 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/irqchip/arm-vic.h> #include <mach/hardware.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <asm/mach/irq.h> diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h index 9b91511..768b26b 100644 --- a/arch/arm/mach-netx/generic.h +++ b/arch/arm/mach-netx/generic.h @@ -21,5 +21,4 @@ extern void __init netx_map_io(void); extern void __init netx_init_irq(void); extern void netx_restart(char, const char *); -struct sys_timer; -extern struct sys_timer netx_timer; +extern void netx_timer_init(void); diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c index 8b781ff..9b558eb 100644 --- a/arch/arm/mach-netx/nxdb500.c +++ b/arch/arm/mach-netx/nxdb500.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -204,8 +203,7 @@ MACHINE_START(NXDB500, "Hilscher nxdb500") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &netx_timer, + .init_time = netx_timer_init, .init_machine = nxdb500_init, .restart = netx_restart, MACHINE_END diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c index b26dbce..a5e86cd 100644 --- a/arch/arm/mach-netx/nxdkn.c +++ b/arch/arm/mach-netx/nxdkn.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -97,8 +96,7 @@ MACHINE_START(NXDKN, "Hilscher nxdkn") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &netx_timer, + .init_time = netx_timer_init, .init_machine = nxdkn_init, .restart = netx_restart, MACHINE_END diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c index 257382e..ad17885 100644 --- a/arch/arm/mach-netx/nxeb500hmi.c +++ b/arch/arm/mach-netx/nxeb500hmi.c @@ -28,7 +28,6 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <linux/platform_data/eth-netx.h> @@ -181,8 +180,7 @@ MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") .atag_offset = 0x100, .map_io = netx_map_io, .init_irq = netx_init_irq, - .handle_irq = vic_handle_irq, - .timer = &netx_timer, + .init_time = netx_timer_init, .init_machine = nxeb500hmi_init, .restart = netx_restart, MACHINE_END diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index e24c141..6df42e6 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -76,7 +76,6 @@ static int netx_set_next_event(unsigned long evt, static struct clock_event_device netx_clockevent = { .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), - .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = netx_set_next_event, .set_mode = netx_set_mode, @@ -107,7 +106,7 @@ static struct irqaction netx_timer_irq = { /* * Set up timer interrupt */ -static void __init netx_timer_init(void) +void __init netx_timer_init(void) { /* disable timer initially */ writel(0, NETX_GPIO_COUNTER_CTRL(0)); @@ -140,18 +139,9 @@ static void __init netx_timer_init(void) clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE), "netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); - netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, - netx_clockevent.shift); - netx_clockevent.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &netx_clockevent); /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine. * Adding some safety ... */ - netx_clockevent.min_delta_ns = - clockevent_delta2ns(0xa00, &netx_clockevent); netx_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&netx_clockevent); + clockevents_config_and_register(&netx_clockevent, CLOCK_TICK_RATE, + 0xa00, 0xfffffffe); } - -struct sys_timer netx_timer = { - .init = netx_timer_init, -}; diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 9f19069..aaed48d 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -27,7 +27,6 @@ #include <linux/pinctrl/machine.h> #include <linux/platform_data/pinctrl-nomadik.h> #include <linux/platform_data/clocksource-nomadik-mtu.h> -#include <asm/hardware/vic.h> #include <asm/sizes.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -267,10 +266,6 @@ static void __init nomadik_timer_init(void) nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0); } -static struct sys_timer nomadik_timer = { - .init = nomadik_timer_init, -}; - static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = { { I2C_BOARD_INFO("stw4811", 0x2d), @@ -352,8 +347,7 @@ MACHINE_START(NOMADIK, "NHK8815") .atag_offset = 0x100, .map_io = cpu8815_map_io, .init_irq = cpu8815_init_irq, - .handle_irq = vic_handle_irq, - .timer = &nomadik_timer, + .init_time = nomadik_timer_init, .init_machine = nhk8815_platform_init, .restart = cpu8815_restart, MACHINE_END diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 1273931..3514046 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -25,13 +25,13 @@ #include <linux/slab.h> #include <linux/irq.h> #include <linux/dma-mapping.h> +#include <linux/irqchip/arm-vic.h> #include <linux/platform_data/clk-nomadik.h> #include <linux/platform_data/pinctrl-nomadik.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 2e98a3a..2aab761 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -628,6 +628,6 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)") .init_irq = omap1_init_irq, .init_machine = ams_delta_init, .init_late = ams_delta_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index 560a7dc..702d580 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -364,6 +364,6 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample") .init_irq = omap1_init_irq, .init_machine = omap_fsample_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index 608e7d2..e1d9171 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -84,6 +84,6 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") .init_irq = omap1_init_irq, .init_machine = omap_generic_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 2274bd6..0dac3d2 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -461,6 +461,6 @@ MACHINE_START(OMAP_H2, "TI-H2") .init_irq = omap1_init_irq, .init_machine = h2_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 1051935..816ecd1 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -454,6 +454,6 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") .init_irq = omap1_init_irq, .init_machine = h3_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index 356f816..35a2379 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -603,6 +603,6 @@ MACHINE_START(HERALD, "HTC Herald") .init_irq = omap1_init_irq, .init_machine = htcherald_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index f8033fa..bd5f02e 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -458,6 +458,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") .init_irq = omap1_init_irq, .init_machine = innovator_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 24d2f2d..4695ca7 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -242,6 +242,6 @@ MACHINE_START(NOKIA770, "Nokia 770") .init_irq = omap1_init_irq, .init_machine = omap_nokia770_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 872ea47..a7ce692 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -609,6 +609,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK") .init_irq = omap1_init_irq, .init_machine = osk_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index c33dceb..845a1a7 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -268,6 +268,6 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") .init_irq = omap1_init_irq, .init_machine = omap_palmte_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 2948b0e..65a4a3e 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -314,6 +314,6 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T") .init_irq = omap1_init_irq, .init_machine = omap_palmtt_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index 7a05895..01c9700 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -330,6 +330,6 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71") .init_irq = omap1_init_irq, .init_machine = omap_palmz71_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 27f8d12..8b2f712 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -326,6 +326,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") .init_irq = omap1_init_irq, .init_machine = omap_perseus2_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 20ed52a..9732a98 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -407,6 +407,6 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1") .init_irq = omap1_init_irq, .init_machine = omap_sx1_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = omap1_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index abf705f..6c116e1 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -289,6 +289,6 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") .init_irq = omap1_init_irq, .init_machine = voiceblue_init, .init_late = omap1_init_late, - .timer = &omap1_timer, + .init_time = omap1_timer_init, .restart = voiceblue_restart, MACHINE_END diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h index b53e085..fb18831 100644 --- a/arch/arm/mach-omap1/common.h +++ b/arch/arm/mach-omap1/common.h @@ -75,7 +75,7 @@ extern void __init omap_check_revision(void); extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl); -extern struct sys_timer omap1_timer; +extern void omap1_timer_init(void); #ifdef CONFIG_OMAP_32K_TIMER extern int omap_32k_timer_init(void); #else diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 4d4816f..726ec23 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -145,7 +145,6 @@ static void omap_mpu_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_mpu_timer1 = { .name = "mpu_timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_next_event = omap_mpu_set_next_event, .set_mode = omap_mpu_set_mode, }; @@ -170,15 +169,9 @@ static __init void omap_init_mpu_timer(unsigned long rate) setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); omap_mpu_timer_start(0, (rate / HZ) - 1, 1); - clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC, - clockevent_mpu_timer1.shift); - clockevent_mpu_timer1.max_delta_ns = - clockevent_delta2ns(-1, &clockevent_mpu_timer1); - clockevent_mpu_timer1.min_delta_ns = - clockevent_delta2ns(1, &clockevent_mpu_timer1); - clockevent_mpu_timer1.cpumask = cpumask_of(0); - clockevents_register_device(&clockevent_mpu_timer1); + clockevents_config_and_register(&clockevent_mpu_timer1, rate, + 1, -1); } @@ -236,12 +229,8 @@ static inline void omap_mpu_timer_init(void) * Timer initialization * --------------------------------------------------------------------------- */ -static void __init omap1_timer_init(void) +void __init omap1_timer_init(void) { if (omap_32k_timer_init() != 0) omap_mpu_timer_init(); } - -struct sys_timer omap1_timer = { - .init = omap1_timer_init, -}; diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 41152fa..0b74246 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -140,7 +140,6 @@ static void omap_32k_timer_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_32k_timer = { .name = "32k-timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .set_next_event = omap_32k_timer_set_next_event, .set_mode = omap_32k_timer_set_mode, }; @@ -165,16 +164,9 @@ static __init void omap_init_32k_timer(void) { setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); - clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC, - NSEC_PER_SEC, - clockevent_32k_timer.shift); - clockevent_32k_timer.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer); - clockevent_32k_timer.min_delta_ns = - clockevent_delta2ns(1, &clockevent_32k_timer); - clockevent_32k_timer.cpumask = cpumask_of(0); - clockevents_register_device(&clockevent_32k_timer); + clockevents_config_and_register(&clockevent_32k_timer, + OMAP_32K_TICKS_PER_SEC, 1, 0xfffffffe); } /* diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index af11dcd..a00d391 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -63,7 +63,7 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, struct platform_device *pdev; pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len, - NULL, 0, false); + false); if (IS_ERR(pdev)) { WARN(1, "Can't build omap_device for %s:%s.\n", oh->class->name, oh->name); diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 4815ea6..5f41396 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -284,6 +284,6 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board") .handle_irq = omap2_intc_handle_irq, .init_machine = omap_2430sdp_init, .init_late = omap2430_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index bb73afc..8e2513f6 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -597,6 +597,6 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap_3430sdp_init, .init_late = omap3430_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 050aaa7..3384627 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -211,6 +211,6 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap_sdp_init, .init_late = omap3630_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 1cc6696..f8eeef4 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -26,10 +26,10 @@ #include <linux/regulator/fixed.h> #include <linux/leds.h> #include <linux/leds_pwm.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/omap4-keypad.h> #include <linux/usb/musb.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -722,9 +722,8 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, .init_machine = omap_4430sdp_init, .init_late = omap4430_init_late, - .timer = &omap4_timer, + .init_time = omap4_local_timer_init, .restart = omap44xx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c index 51b96a1..07f0be2 100644 --- a/arch/arm/mach-omap2/board-am3517crane.c +++ b/arch/arm/mach-omap2/board-am3517crane.c @@ -92,6 +92,6 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD") .handle_irq = omap3_intc_handle_irq, .init_machine = am3517_crane_init, .init_late = am35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index f81a303..6f5b2a0 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -393,6 +393,6 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM") .handle_irq = omap3_intc_handle_irq, .init_machine = am3517_evm_init, .init_late = am35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 5d0a61f..3a6ca74 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -337,6 +337,6 @@ MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon") .handle_irq = omap2_intc_handle_irq, .init_machine = omap_apollon_init, .init_late = omap2420_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index b3102c2..68647c3 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -751,7 +751,7 @@ MACHINE_START(CM_T35, "Compulab CM-T35") .handle_irq = omap3_intc_handle_irq, .init_machine = cm_t35_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END @@ -764,6 +764,6 @@ MACHINE_START(CM_T3730, "Compulab CM-T3730") .handle_irq = omap3_intc_handle_irq, .init_machine = cm_t3730_init, .init_late = omap3630_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index ebbc2ad..6a9529a 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -297,6 +297,6 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517") .handle_irq = omap3_intc_handle_irq, .init_machine = cm_t3517_init, .init_late = am35xx_init_late, - .timer = &omap3_gp_timer, + .init_time = omap3_gp_gptimer_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 12865af..0b1d8f7 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -643,6 +643,6 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000") .handle_irq = omap3_intc_handle_irq, .init_machine = devkit8000_init, .init_late = omap35xx_init_late, - .timer = &omap3_secure_timer, + .init_time = omap3_secure_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 53cb380b..2590463 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -16,7 +16,6 @@ #include <linux/of_platform.h> #include <linux/irqdomain.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include "common.h" @@ -65,7 +64,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)") .init_irq = omap_intc_of_init, .handle_irq = omap2_intc_handle_irq, .init_machine = omap_generic_init, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .dt_compat = omap242x_boards_compat, .restart = omap2xxx_restart, MACHINE_END @@ -84,7 +83,7 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)") .init_irq = omap_intc_of_init, .handle_irq = omap2_intc_handle_irq, .init_machine = omap_generic_init, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .dt_compat = omap243x_boards_compat, .restart = omap2xxx_restart, MACHINE_END @@ -103,7 +102,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)") .init_irq = omap_intc_of_init, .handle_irq = omap3_intc_handle_irq, .init_machine = omap_generic_init, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .dt_compat = omap3_boards_compat, .restart = omap3xxx_restart, MACHINE_END @@ -120,7 +119,7 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)") .init_irq = omap_intc_of_init, .handle_irq = omap3_intc_handle_irq, .init_machine = omap_generic_init, - .timer = &omap3_secure_timer, + .init_time = omap3_secure_sync32k_timer_init, .dt_compat = omap3_gp_boards_compat, .restart = omap3xxx_restart, MACHINE_END @@ -139,7 +138,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)") .init_irq = omap_intc_of_init, .handle_irq = omap3_intc_handle_irq, .init_machine = omap_generic_init, - .timer = &omap3_am33xx_timer, + .init_time = omap3_am33xx_gptimer_timer_init, .dt_compat = am33xx_boards_compat, MACHINE_END #endif @@ -156,10 +155,9 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = omap_gic_of_init, - .handle_irq = gic_handle_irq, .init_machine = omap_generic_init, .init_late = omap4430_init_late, - .timer = &omap4_timer, + .init_time = omap4_local_timer_init, .dt_compat = omap4_boards_compat, .restart = omap44xx_restart, MACHINE_END @@ -177,9 +175,8 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)") .map_io = omap5_map_io, .init_early = omap5_init_early, .init_irq = omap_gic_of_init, - .handle_irq = gic_handle_irq, .init_machine = omap_generic_init, - .timer = &omap5_timer, + .init_time = omap5_realtime_timer_init, .dt_compat = omap5_boards_compat, .restart = omap44xx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 3be1311..812c829 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -342,6 +342,6 @@ MACHINE_START(OMAP_H4, "OMAP2420 H4 board") .handle_irq = omap2_intc_handle_irq, .init_machine = omap_h4_init, .init_late = omap2420_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 0f24cb8..5b44764 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -655,7 +655,7 @@ MACHINE_START(IGEP0020, "IGEP v2 board") .handle_irq = omap3_intc_handle_irq, .init_machine = igep_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END @@ -668,6 +668,6 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module") .handle_irq = omap3_intc_handle_irq, .init_machine = igep_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 0869f4f..ff440c0 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -435,6 +435,6 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap_ldp_init, .init_late = omap3430_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 0abb30f..f6eeb87 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -731,7 +731,7 @@ MACHINE_START(NOKIA_N800, "Nokia N800") .handle_irq = omap2_intc_handle_irq, .init_machine = n8x0_init_machine, .init_late = omap2420_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END @@ -744,7 +744,7 @@ MACHINE_START(NOKIA_N810, "Nokia N810") .handle_irq = omap2_intc_handle_irq, .init_machine = n8x0_init_machine, .init_late = omap2420_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END @@ -757,6 +757,6 @@ MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX") .handle_irq = omap2_intc_handle_irq, .init_machine = n8x0_init_machine, .init_late = omap2420_init_late, - .timer = &omap2_timer, + .init_time = omap2_sync32k_timer_init, .restart = omap2xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 22c483d..b81b458 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -544,6 +544,6 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3_beagle_init, .init_late = omap3_init_late, - .timer = &omap3_secure_timer, + .init_time = omap3_secure_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 3985f35..f2f636b 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -757,6 +757,6 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3_evm_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c index 2a065ba..0fba43a 100644 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ b/arch/arm/mach-omap2/board-omap3logic.c @@ -231,7 +231,7 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3logic_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END @@ -244,6 +244,6 @@ MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3logic_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index a53a668..12e1816 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -618,6 +618,6 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3pandora_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 53a6cbc..13ee405 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -427,6 +427,6 @@ MACHINE_START(SBC3530, "OMAP3 STALKER") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3_stalker_init, .init_late = omap35xx_init_late, - .timer = &omap3_secure_timer, + .init_time = omap3_secure_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 263cb9c..36c455c 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -386,6 +386,6 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap3_touchbook_init, .init_late = omap3430_init_late, - .timer = &omap3_secure_timer, + .init_time = omap3_secure_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 769c1fe..b623179 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -31,9 +31,9 @@ #include <linux/ti_wilink_st.h> #include <linux/usb/musb.h> #include <linux/wl12xx.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/omap-abe-twl6040.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -459,9 +459,8 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, .init_machine = omap4_panda_init, .init_late = omap4430_init_late, - .timer = &omap4_timer, + .init_time = omap4_local_timer_init, .restart = omap44xx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index c8fde3e..233a37d 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -551,6 +551,6 @@ MACHINE_START(OVERO, "Gumstix Overo") .handle_irq = omap3_intc_handle_irq, .init_machine = overo_init, .init_late = omap35xx_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c index 0c777b7..386a2dd 100644 --- a/arch/arm/mach-omap2/board-rm680.c +++ b/arch/arm/mach-omap2/board-rm680.c @@ -147,7 +147,7 @@ MACHINE_START(NOKIA_RM680, "Nokia RM-680 board") .handle_irq = omap3_intc_handle_irq, .init_machine = rm680_init, .init_late = omap3630_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END @@ -160,6 +160,6 @@ MACHINE_START(NOKIA_RM696, "Nokia RM-696 board") .handle_irq = omap3_intc_handle_irq, .init_machine = rm680_init, .init_late = omap3630_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index d0374ea..f7c4616 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -123,6 +123,6 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board") .handle_irq = omap3_intc_handle_irq, .init_machine = rx51_init, .init_late = omap3430_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c index 1a3e056..6273c28 100644 --- a/arch/arm/mach-omap2/board-ti8168evm.c +++ b/arch/arm/mach-omap2/board-ti8168evm.c @@ -43,7 +43,7 @@ MACHINE_START(TI8168EVM, "ti8168evm") .map_io = ti81xx_map_io, .init_early = ti81xx_init_early, .init_irq = ti81xx_init_irq, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .init_machine = ti81xx_evm_init, .init_late = ti81xx_init_late, .restart = omap44xx_restart, @@ -55,7 +55,7 @@ MACHINE_START(TI8148EVM, "ti8148evm") .map_io = ti81xx_map_io, .init_early = ti81xx_init_early, .init_irq = ti81xx_init_irq, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .init_machine = ti81xx_evm_init, .init_late = ti81xx_init_late, .restart = omap44xx_restart, diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c index d7fa31e..d257cf1 100644 --- a/arch/arm/mach-omap2/board-zoom.c +++ b/arch/arm/mach-omap2/board-zoom.c @@ -137,7 +137,7 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap_zoom_init, .init_late = omap3430_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END @@ -150,6 +150,6 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board") .handle_irq = omap3_intc_handle_irq, .init_machine = omap_zoom_init, .init_late = omap3630_init_late, - .timer = &omap3_timer, + .init_time = omap3_sync32k_timer_init, .restart = omap3xxx_restart, MACHINE_END diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c index ab7e952..0f0a97c 100644 --- a/arch/arm/mach-omap2/cclock2420_data.c +++ b/arch/arm/mach-omap2/cclock2420_data.c @@ -622,15 +622,10 @@ static struct clk_hw_omap gpios_fck_hw = { DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops); -static struct clk wu_l4_ick; - -DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm"); -DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops); - static struct clk gpios_ick; static const char *gpios_ick_parent_names[] = { - "wu_l4_ick", + "sys_ck", }; static struct clk_hw_omap gpios_ick_hw = { @@ -1682,13 +1677,6 @@ static struct clk_hw_omap wdt1_ick_hw = { DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops); -static struct clk wdt1_osc_ck; - -static const struct clk_ops wdt1_osc_ck_ops = {}; - -DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL); -DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops); - static struct clk wdt3_fck; static struct clk_hw_omap wdt3_fck_hw = { @@ -1767,7 +1755,6 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "func_96m_ck", &func_96m_ck, CK_242X), CLK(NULL, "func_48m_ck", &func_48m_ck, CK_242X), CLK(NULL, "func_12m_ck", &func_12m_ck, CK_242X), - CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_242X), CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_242X), CLK(NULL, "sys_clkout", &sys_clkout, CK_242X), CLK(NULL, "sys_clkout2_src", &sys_clkout2_src, CK_242X), @@ -1797,7 +1784,6 @@ static struct omap_clk omap2420_clks[] = { /* L4 domain clocks */ CLK(NULL, "l4_ck", &l4_ck, CK_242X), CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X), - CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_242X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X), /* general l4 interface ck, multi-parent functional clk */ diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c index eb3dab6..aed8f74 100644 --- a/arch/arm/mach-omap2/cclock2430_data.c +++ b/arch/arm/mach-omap2/cclock2430_data.c @@ -601,15 +601,10 @@ static struct clk_hw_omap gpios_fck_hw = { DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops); -static struct clk wu_l4_ick; - -DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm"); -DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops); - static struct clk gpios_ick; static const char *gpios_ick_parent_names[] = { - "wu_l4_ick", + "sys_ck", }; static struct clk_hw_omap gpios_ick_hw = { @@ -1811,13 +1806,6 @@ static struct clk_hw_omap wdt1_ick_hw = { DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops); -static struct clk wdt1_osc_ck; - -static const struct clk_ops wdt1_osc_ck_ops = {}; - -DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL); -DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops); - static struct clk wdt4_fck; static struct clk_hw_omap wdt4_fck_hw = { @@ -1869,7 +1857,6 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "func_96m_ck", &func_96m_ck, CK_243X), CLK(NULL, "func_48m_ck", &func_48m_ck, CK_243X), CLK(NULL, "func_12m_ck", &func_12m_ck, CK_243X), - CLK(NULL, "ck_wdt1_osc", &wdt1_osc_ck, CK_243X), CLK(NULL, "sys_clkout_src", &sys_clkout_src, CK_243X), CLK(NULL, "sys_clkout", &sys_clkout, CK_243X), CLK(NULL, "emul_ck", &emul_ck, CK_243X), @@ -1898,7 +1885,6 @@ static struct omap_clk omap2430_clks[] = { /* L4 domain clocks */ CLK(NULL, "l4_ck", &l4_ck, CK_243X), CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X), - CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_243X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X), /* general l4 interface ck, multi-parent functional clk */ diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index a2cc046..cebe2b3 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -16,6 +16,10 @@ * XXX Some of the ES1 clocks have been removed/changed; once support * is added for discriminating clocks by ES level, these should be added back * in. + * + * XXX All of the remaining MODULEMODE clock nodes should be removed + * once the drivers are updated to use pm_runtime or to use the appropriate + * upstream clock node for rate/parent selection. */ #include <linux/kernel.h> @@ -315,7 +319,7 @@ DEFINE_CLK_DIVIDER(dpll_abe_m2_ck, "dpll_abe_ck", &dpll_abe_ck, 0x0, OMAP4430_CM_DIV_M2_DPLL_ABE, OMAP4430_DPLL_CLKOUT_DIV_SHIFT, OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -static const struct clk_ops dmic_fck_ops = { +static const struct clk_ops dpll_hsd_ops = { .enable = &omap2_dflt_clk_enable, .disable = &omap2_dflt_clk_disable, .is_enabled = &omap2_dflt_clk_is_enabled, @@ -325,6 +329,12 @@ static const struct clk_ops dmic_fck_ops = { .init = &omap2_init_clk_clkdm, }; +static const struct clk_ops func_dmic_abe_gfclk_ops = { + .recalc_rate = &omap2_clksel_recalc, + .get_parent = &omap2_clksel_find_parent_index, + .set_parent = &omap2_clksel_set_parent, +}; + static const char *dpll_core_m3x2_ck_parents[] = { "dpll_core_x2_ck", }; @@ -340,7 +350,7 @@ DEFINE_CLK_OMAP_MUX_GATE(dpll_core_m3x2_ck, NULL, dpll_core_m3x2_div, OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, OMAP4430_CM_DIV_M3_DPLL_CORE, OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL, - dpll_core_m3x2_ck_parents, dmic_fck_ops); + dpll_core_m3x2_ck_parents, dpll_hsd_ops); DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m7x2_ck, "dpll_core_x2_ck", &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M7_DPLL_CORE, @@ -547,7 +557,7 @@ DEFINE_CLK_OMAP_MUX_GATE(dpll_per_m3x2_ck, NULL, dpll_per_m3x2_div, OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, OMAP4430_CM_DIV_M3_DPLL_PER, OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL, - dpll_per_m3x2_ck_parents, dmic_fck_ops); + dpll_per_m3x2_ck_parents, dpll_hsd_ops); DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m4x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck, 0x0, OMAP4430_CM_DIV_M4_DPLL_PER, @@ -749,10 +759,6 @@ DEFINE_CLK_GATE(aes2_fck, "l3_div_ck", &l3_div_ck, 0x0, OMAP4430_CM_L4SEC_AES2_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(aess_fck, "aess_fclk", &aess_fclk, 0x0, - OMAP4430_CM1_ABE_AESS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - DEFINE_CLK_GATE(bandgap_fclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, 0x0, NULL); @@ -774,11 +780,6 @@ DEFINE_CLK_GATE(bandgap_ts_fclk, "div_ts_ck", &div_ts_ck, 0x0, OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(des3des_fck, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4SEC_DES3DES_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - static const char *dmic_sync_mux_ck_parents[] = { "abe_24m_fclk", "syc_clk_div_ck", "func_24m_clk", }; @@ -795,23 +796,13 @@ static const struct clksel func_dmic_abe_gfclk_sel[] = { { .parent = NULL }, }; -static const char *dmic_fck_parents[] = { +static const char *func_dmic_abe_gfclk_parents[] = { "dmic_sync_mux_ck", "pad_clks_ck", "slimbus_clk", }; -/* Merged func_dmic_abe_gfclk into dmic */ -static struct clk dmic_fck; - -DEFINE_CLK_OMAP_MUX_GATE(dmic_fck, "abe_clkdm", func_dmic_abe_gfclk_sel, - OMAP4430_CM1_ABE_DMIC_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_MASK, - OMAP4430_CM1_ABE_DMIC_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - dmic_fck_parents, dmic_fck_ops); - -DEFINE_CLK_GATE(dsp_fck, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, 0x0, - OMAP4430_CM_TESLA_TESLA_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(func_dmic_abe_gfclk, "abe_clkdm", func_dmic_abe_gfclk_sel, + OMAP4430_CM1_ABE_DMIC_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK, + func_dmic_abe_gfclk_parents, func_dmic_abe_gfclk_ops); DEFINE_CLK_GATE(dss_sys_clk, "syc_clk_div_ck", &syc_clk_div_ck, 0x0, OMAP4430_CM_DSS_DSS_CLKCTRL, @@ -833,177 +824,57 @@ DEFINE_CLK_GATE(dss_fck, "l3_div_ck", &l3_div_ck, 0x0, OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(efuse_ctrl_cust_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0, - OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(emif1_fck, "ddrphy_ck", &ddrphy_ck, 0x0, - OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(emif2_fck, "ddrphy_ck", &ddrphy_ck, 0x0, - OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_DIVIDER(fdif_fck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0, OMAP4430_CM_CAM_FDIF_CLKCTRL, OMAP4430_CLKSEL_FCLK_SHIFT, OMAP4430_CLKSEL_FCLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL); -DEFINE_CLK_GATE(fpka_fck, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio1_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_WKUP_GPIO1_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio1_ick, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, 0x0, - OMAP4430_CM_WKUP_GPIO1_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio2_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_L4PER_GPIO2_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio2_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_GPIO2_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio3_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_L4PER_GPIO3_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio3_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_GPIO3_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio4_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_L4PER_GPIO4_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio4_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_GPIO4_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio5_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_L4PER_GPIO5_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio5_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_GPIO5_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(gpio6_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0, OMAP4430_CM_L4PER_GPIO6_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(gpio6_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_GPIO6_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(gpmc_ick, "l3_div_ck", &l3_div_ck, 0x0, - OMAP4430_CM_L3_2_GPMC_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT, - 0x0, NULL); - static const struct clksel sgx_clk_mux_sel[] = { { .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates }, { .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates }, { .parent = NULL }, }; -static const char *gpu_fck_parents[] = { +static const char *sgx_clk_mux_parents[] = { "dpll_core_m7x2_ck", "dpll_per_m7x2_ck", }; -/* Merged sgx_clk_mux into gpu */ -DEFINE_CLK_OMAP_MUX_GATE(gpu_fck, "l3_gfx_clkdm", sgx_clk_mux_sel, - OMAP4430_CM_GFX_GFX_CLKCTRL, - OMAP4430_CLKSEL_SGX_FCLK_MASK, - OMAP4430_CM_GFX_GFX_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - gpu_fck_parents, dmic_fck_ops); - -DEFINE_CLK_GATE(hdq1w_fck, "func_12m_fclk", &func_12m_fclk, 0x0, - OMAP4430_CM_L4PER_HDQ1W_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(sgx_clk_mux, "l3_gfx_clkdm", sgx_clk_mux_sel, + OMAP4430_CM_GFX_GFX_CLKCTRL, OMAP4430_CLKSEL_SGX_FCLK_MASK, + sgx_clk_mux_parents, func_dmic_abe_gfclk_ops); DEFINE_CLK_DIVIDER(hsi_fck, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0, OMAP4430_CM_L3INIT_HSI_CLKCTRL, OMAP4430_CLKSEL_24_25_SHIFT, OMAP4430_CLKSEL_24_25_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL); -DEFINE_CLK_GATE(i2c1_fck, "func_96m_fclk", &func_96m_fclk, 0x0, - OMAP4430_CM_L4PER_I2C1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(i2c2_fck, "func_96m_fclk", &func_96m_fclk, 0x0, - OMAP4430_CM_L4PER_I2C2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(i2c3_fck, "func_96m_fclk", &func_96m_fclk, 0x0, - OMAP4430_CM_L4PER_I2C3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(i2c4_fck, "func_96m_fclk", &func_96m_fclk, 0x0, - OMAP4430_CM_L4PER_I2C4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(ipu_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0, - OMAP4430_CM_DUCATI_DUCATI_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(iss_ctrlclk, "func_96m_fclk", &func_96m_fclk, 0x0, OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(iss_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0, - OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - -DEFINE_CLK_GATE(iva_fck, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0, - OMAP4430_CM_IVAHD_IVAHD_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(kbd_fck, "sys_32k_ck", &sys_32k_ck, 0x0, - OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -static struct clk l3_instr_ick; - -static const char *l3_instr_ick_parent_names[] = { - "l3_div_ck", -}; - -static const struct clk_ops l3_instr_ick_ops = { - .enable = &omap2_dflt_clk_enable, - .disable = &omap2_dflt_clk_disable, - .is_enabled = &omap2_dflt_clk_is_enabled, - .init = &omap2_init_clk_clkdm, -}; - -static struct clk_hw_omap l3_instr_ick_hw = { - .hw = { - .clk = &l3_instr_ick, - }, - .enable_reg = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL, - .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT, - .clkdm_name = "l3_instr_clkdm", -}; - -DEFINE_STRUCT_CLK(l3_instr_ick, l3_instr_ick_parent_names, l3_instr_ick_ops); - -static struct clk l3_main_3_ick; -static struct clk_hw_omap l3_main_3_ick_hw = { - .hw = { - .clk = &l3_main_3_ick, - }, - .enable_reg = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL, - .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT, - .clkdm_name = "l3_instr_clkdm", -}; - -DEFINE_STRUCT_CLK(l3_main_3_ick, l3_instr_ick_parent_names, l3_instr_ick_ops); - DEFINE_CLK_MUX(mcasp_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0, OMAP4430_CM1_ABE_MCASP_CLKCTRL, OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT, @@ -1016,17 +887,13 @@ static const struct clksel func_mcasp_abe_gfclk_sel[] = { { .parent = NULL }, }; -static const char *mcasp_fck_parents[] = { +static const char *func_mcasp_abe_gfclk_parents[] = { "mcasp_sync_mux_ck", "pad_clks_ck", "slimbus_clk", }; -/* Merged func_mcasp_abe_gfclk into mcasp */ -DEFINE_CLK_OMAP_MUX_GATE(mcasp_fck, "abe_clkdm", func_mcasp_abe_gfclk_sel, - OMAP4430_CM1_ABE_MCASP_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_MASK, - OMAP4430_CM1_ABE_MCASP_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mcasp_fck_parents, dmic_fck_ops); +DEFINE_CLK_OMAP_MUX(func_mcasp_abe_gfclk, "abe_clkdm", func_mcasp_abe_gfclk_sel, + OMAP4430_CM1_ABE_MCASP_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK, + func_mcasp_abe_gfclk_parents, func_dmic_abe_gfclk_ops); DEFINE_CLK_MUX(mcbsp1_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0, OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, @@ -1040,17 +907,14 @@ static const struct clksel func_mcbsp1_gfclk_sel[] = { { .parent = NULL }, }; -static const char *mcbsp1_fck_parents[] = { +static const char *func_mcbsp1_gfclk_parents[] = { "mcbsp1_sync_mux_ck", "pad_clks_ck", "slimbus_clk", }; -/* Merged func_mcbsp1_gfclk into mcbsp1 */ -DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "abe_clkdm", func_mcbsp1_gfclk_sel, - OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_MASK, - OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mcbsp1_fck_parents, dmic_fck_ops); +DEFINE_CLK_OMAP_MUX(func_mcbsp1_gfclk, "abe_clkdm", func_mcbsp1_gfclk_sel, + OMAP4430_CM1_ABE_MCBSP1_CLKCTRL, + OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp1_gfclk_parents, + func_dmic_abe_gfclk_ops); DEFINE_CLK_MUX(mcbsp2_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0, OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, @@ -1064,17 +928,14 @@ static const struct clksel func_mcbsp2_gfclk_sel[] = { { .parent = NULL }, }; -static const char *mcbsp2_fck_parents[] = { +static const char *func_mcbsp2_gfclk_parents[] = { "mcbsp2_sync_mux_ck", "pad_clks_ck", "slimbus_clk", }; -/* Merged func_mcbsp2_gfclk into mcbsp2 */ -DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "abe_clkdm", func_mcbsp2_gfclk_sel, - OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_MASK, - OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mcbsp2_fck_parents, dmic_fck_ops); +DEFINE_CLK_OMAP_MUX(func_mcbsp2_gfclk, "abe_clkdm", func_mcbsp2_gfclk_sel, + OMAP4430_CM1_ABE_MCBSP2_CLKCTRL, + OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp2_gfclk_parents, + func_dmic_abe_gfclk_ops); DEFINE_CLK_MUX(mcbsp3_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0, OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, @@ -1088,17 +949,14 @@ static const struct clksel func_mcbsp3_gfclk_sel[] = { { .parent = NULL }, }; -static const char *mcbsp3_fck_parents[] = { +static const char *func_mcbsp3_gfclk_parents[] = { "mcbsp3_sync_mux_ck", "pad_clks_ck", "slimbus_clk", }; -/* Merged func_mcbsp3_gfclk into mcbsp3 */ -DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "abe_clkdm", func_mcbsp3_gfclk_sel, - OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_MASK, - OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mcbsp3_fck_parents, dmic_fck_ops); +DEFINE_CLK_OMAP_MUX(func_mcbsp3_gfclk, "abe_clkdm", func_mcbsp3_gfclk_sel, + OMAP4430_CM1_ABE_MCBSP3_CLKCTRL, + OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp3_gfclk_parents, + func_dmic_abe_gfclk_ops); static const char *mcbsp4_sync_mux_ck_parents[] = { "func_96m_fclk", "per_abe_nc_fclk", @@ -1115,37 +973,14 @@ static const struct clksel per_mcbsp4_gfclk_sel[] = { { .parent = NULL }, }; -static const char *mcbsp4_fck_parents[] = { +static const char *per_mcbsp4_gfclk_parents[] = { "mcbsp4_sync_mux_ck", "pad_clks_ck", }; -/* Merged per_mcbsp4_gfclk into mcbsp4 */ -DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "l4_per_clkdm", per_mcbsp4_gfclk_sel, - OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, - OMAP4430_CLKSEL_SOURCE_24_24_MASK, - OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mcbsp4_fck_parents, dmic_fck_ops); - -DEFINE_CLK_GATE(mcpdm_fck, "pad_clks_ck", &pad_clks_ck, 0x0, - OMAP4430_CM1_ABE_PDM_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - -DEFINE_CLK_GATE(mcspi1_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MCSPI1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(mcspi2_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MCSPI2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(mcspi3_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MCSPI3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(mcspi4_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MCSPI4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(per_mcbsp4_gfclk, "l4_per_clkdm", per_mcbsp4_gfclk_sel, + OMAP4430_CM_L4PER_MCBSP4_CLKCTRL, + OMAP4430_CLKSEL_SOURCE_24_24_MASK, per_mcbsp4_gfclk_parents, + func_dmic_abe_gfclk_ops); static const struct clksel hsmmc1_fclk_sel[] = { { .parent = &func_64m_fclk, .rates = div_1_0_rates }, @@ -1153,69 +988,22 @@ static const struct clksel hsmmc1_fclk_sel[] = { { .parent = NULL }, }; -static const char *mmc1_fck_parents[] = { +static const char *hsmmc1_fclk_parents[] = { "func_64m_fclk", "func_96m_fclk", }; -/* Merged hsmmc1_fclk into mmc1 */ -DEFINE_CLK_OMAP_MUX_GATE(mmc1_fck, "l3_init_clkdm", hsmmc1_fclk_sel, - OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L3INIT_MMC1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mmc1_fck_parents, dmic_fck_ops); - -/* Merged hsmmc2_fclk into mmc2 */ -DEFINE_CLK_OMAP_MUX_GATE(mmc2_fck, "l3_init_clkdm", hsmmc1_fclk_sel, - OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L3INIT_MMC2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - mmc1_fck_parents, dmic_fck_ops); - -DEFINE_CLK_GATE(mmc3_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MMCSD3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(mmc4_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MMCSD4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(mmc5_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_MMCSD5_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, - OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL); - -DEFINE_CLK_GATE(ocp2scp_usb_phy_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, - OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL); - -static struct clk ocp_wp_noc_ick; - -static struct clk_hw_omap ocp_wp_noc_ick_hw = { - .hw = { - .clk = &ocp_wp_noc_ick, - }, - .enable_reg = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL, - .enable_bit = OMAP4430_MODULEMODE_HWCTRL_SHIFT, - .clkdm_name = "l3_instr_clkdm", -}; - -DEFINE_STRUCT_CLK(ocp_wp_noc_ick, l3_instr_ick_parent_names, l3_instr_ick_ops); +DEFINE_CLK_OMAP_MUX(hsmmc1_fclk, "l3_init_clkdm", hsmmc1_fclk_sel, + OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK, + hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops); -DEFINE_CLK_GATE(rng_ick, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4SEC_RNG_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT, - 0x0, NULL); +DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel, + OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK, + hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops); DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0, OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(sl2if_ick, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0, - OMAP4430_CM_IVAHD_SL2_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT, - 0x0, NULL); - DEFINE_CLK_GATE(slimbus1_fclk_1, "func_24m_clk", &func_24m_clk, 0x0, OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK1_SHIFT, 0x0, NULL); @@ -1232,10 +1020,6 @@ DEFINE_CLK_GATE(slimbus1_slimbus_clk, "slimbus_clk", &slimbus_clk, 0x0, OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(slimbus1_fck, "ocp_abe_iclk", &ocp_abe_iclk, 0x0, - OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(slimbus2_fclk_1, "per_abe_24m_fclk", &per_abe_24m_fclk, 0x0, OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, 0x0, NULL); @@ -1249,10 +1033,6 @@ DEFINE_CLK_GATE(slimbus2_slimbus_clk, "pad_slimbus_core_clks_ck", OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(slimbus2_fck, "l4_div_ck", &l4_div_ck, 0x0, - OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); - DEFINE_CLK_GATE(smartreflex_core_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, 0x0, OMAP4430_CM_ALWON_SR_CORE_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); @@ -1271,52 +1051,35 @@ static const struct clksel dmt1_clk_mux_sel[] = { { .parent = NULL }, }; -/* Merged dmt1_clk_mux into timer1 */ -DEFINE_CLK_OMAP_MUX_GATE(timer1_fck, "l4_wkup_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM_WKUP_TIMER1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -/* Merged cm2_dm10_mux into timer10 */ -DEFINE_CLK_OMAP_MUX_GATE(timer10_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -/* Merged cm2_dm11_mux into timer11 */ -DEFINE_CLK_OMAP_MUX_GATE(timer11_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -/* Merged cm2_dm2_mux into timer2 */ -DEFINE_CLK_OMAP_MUX_GATE(timer2_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -/* Merged cm2_dm3_mux into timer3 */ -DEFINE_CLK_OMAP_MUX_GATE(timer3_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -/* Merged cm2_dm4_mux into timer4 */ -DEFINE_CLK_OMAP_MUX_GATE(timer4_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); +DEFINE_CLK_OMAP_MUX(dmt1_clk_mux, "l4_wkup_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm10_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm11_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm2_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm3_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm4_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); static const struct clksel timer5_sync_mux_sel[] = { { .parent = &syc_clk_div_ck, .rates = div_1_0_rates }, @@ -1324,61 +1087,30 @@ static const struct clksel timer5_sync_mux_sel[] = { { .parent = NULL }, }; -static const char *timer5_fck_parents[] = { +static const char *timer5_sync_mux_parents[] = { "syc_clk_div_ck", "sys_32k_ck", }; -/* Merged timer5_sync_mux into timer5 */ -DEFINE_CLK_OMAP_MUX_GATE(timer5_fck, "abe_clkdm", timer5_sync_mux_sel, - OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM1_ABE_TIMER5_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - timer5_fck_parents, dmic_fck_ops); - -/* Merged timer6_sync_mux into timer6 */ -DEFINE_CLK_OMAP_MUX_GATE(timer6_fck, "abe_clkdm", timer5_sync_mux_sel, - OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM1_ABE_TIMER6_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - timer5_fck_parents, dmic_fck_ops); - -/* Merged timer7_sync_mux into timer7 */ -DEFINE_CLK_OMAP_MUX_GATE(timer7_fck, "abe_clkdm", timer5_sync_mux_sel, - OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM1_ABE_TIMER7_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - timer5_fck_parents, dmic_fck_ops); - -/* Merged timer8_sync_mux into timer8 */ -DEFINE_CLK_OMAP_MUX_GATE(timer8_fck, "abe_clkdm", timer5_sync_mux_sel, - OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK, - OMAP4430_CM1_ABE_TIMER8_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - timer5_fck_parents, dmic_fck_ops); - -/* Merged cm2_dm9_mux into timer9 */ -DEFINE_CLK_OMAP_MUX_GATE(timer9_fck, "l4_per_clkdm", dmt1_clk_mux_sel, - OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, - OMAP4430_CLKSEL_MASK, - OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL, - abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops); - -DEFINE_CLK_GATE(uart1_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_UART1_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(timer5_sync_mux, "abe_clkdm", timer5_sync_mux_sel, + OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK, + timer5_sync_mux_parents, func_dmic_abe_gfclk_ops); -DEFINE_CLK_GATE(uart2_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_UART2_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(timer6_sync_mux, "abe_clkdm", timer5_sync_mux_sel, + OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK, + timer5_sync_mux_parents, func_dmic_abe_gfclk_ops); -DEFINE_CLK_GATE(uart3_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_UART3_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(timer7_sync_mux, "abe_clkdm", timer5_sync_mux_sel, + OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK, + timer5_sync_mux_parents, func_dmic_abe_gfclk_ops); -DEFINE_CLK_GATE(uart4_fck, "func_48m_fclk", &func_48m_fclk, 0x0, - OMAP4430_CM_L4PER_UART4_CLKCTRL, - OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +DEFINE_CLK_OMAP_MUX(timer8_sync_mux, "abe_clkdm", timer5_sync_mux_sel, + OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK, + timer5_sync_mux_parents, func_dmic_abe_gfclk_ops); + +DEFINE_CLK_OMAP_MUX(cm2_dm9_mux, "l4_per_clkdm", dmt1_clk_mux_sel, + OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, OMAP4430_CLKSEL_MASK, + abe_dpll_bypass_clk_mux_ck_parents, + func_dmic_abe_gfclk_ops); static struct clk usb_host_fs_fck; @@ -1512,18 +1244,6 @@ DEFINE_CLK_GATE(usim_fclk, "usim_ck", &usim_ck, 0x0, OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK_SHIFT, 0x0, NULL); -DEFINE_CLK_GATE(usim_fck, "sys_32k_ck", &sys_32k_ck, 0x0, - OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT, - 0x0, NULL); - -DEFINE_CLK_GATE(wd_timer2_fck, "sys_32k_ck", &sys_32k_ck, 0x0, - OMAP4430_CM_WKUP_WDT2_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - -DEFINE_CLK_GATE(wd_timer3_fck, "sys_32k_ck", &sys_32k_ck, 0x0, - OMAP4430_CM1_ABE_WDT3_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT, - 0x0, NULL); - /* Remaining optional clocks */ static const char *pmd_stm_clock_mux_ck_parents[] = { "sys_clkin_ck", "dpll_core_m6x2_ck", "tie_low_clock_ck", @@ -1774,106 +1494,61 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "syc_clk_div_ck", &syc_clk_div_ck, CK_443X), CLK(NULL, "aes1_fck", &aes1_fck, CK_443X), CLK(NULL, "aes2_fck", &aes2_fck, CK_443X), - CLK(NULL, "aess_fck", &aess_fck, CK_443X), CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X), CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X), CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X), - CLK(NULL, "des3des_fck", &des3des_fck, CK_443X), CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), - CLK(NULL, "dmic_fck", &dmic_fck, CK_443X), - CLK(NULL, "dsp_fck", &dsp_fck, CK_443X), + CLK(NULL, "func_dmic_abe_gfclk", &func_dmic_abe_gfclk, CK_443X), CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X), CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X), CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X), CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X), CLK(NULL, "dss_fck", &dss_fck, CK_443X), CLK("omapdss_dss", "ick", &dss_fck, CK_443X), - CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), - CLK(NULL, "emif1_fck", &emif1_fck, CK_443X), - CLK(NULL, "emif2_fck", &emif2_fck, CK_443X), CLK(NULL, "fdif_fck", &fdif_fck, CK_443X), - CLK(NULL, "fpka_fck", &fpka_fck, CK_443X), CLK(NULL, "gpio1_dbclk", &gpio1_dbclk, CK_443X), - CLK(NULL, "gpio1_ick", &gpio1_ick, CK_443X), CLK(NULL, "gpio2_dbclk", &gpio2_dbclk, CK_443X), - CLK(NULL, "gpio2_ick", &gpio2_ick, CK_443X), CLK(NULL, "gpio3_dbclk", &gpio3_dbclk, CK_443X), - CLK(NULL, "gpio3_ick", &gpio3_ick, CK_443X), CLK(NULL, "gpio4_dbclk", &gpio4_dbclk, CK_443X), - CLK(NULL, "gpio4_ick", &gpio4_ick, CK_443X), CLK(NULL, "gpio5_dbclk", &gpio5_dbclk, CK_443X), - CLK(NULL, "gpio5_ick", &gpio5_ick, CK_443X), CLK(NULL, "gpio6_dbclk", &gpio6_dbclk, CK_443X), - CLK(NULL, "gpio6_ick", &gpio6_ick, CK_443X), - CLK(NULL, "gpmc_ick", &gpmc_ick, CK_443X), - CLK(NULL, "gpu_fck", &gpu_fck, CK_443X), - CLK(NULL, "hdq1w_fck", &hdq1w_fck, CK_443X), + CLK(NULL, "sgx_clk_mux", &sgx_clk_mux, CK_443X), CLK(NULL, "hsi_fck", &hsi_fck, CK_443X), - CLK(NULL, "i2c1_fck", &i2c1_fck, CK_443X), - CLK(NULL, "i2c2_fck", &i2c2_fck, CK_443X), - CLK(NULL, "i2c3_fck", &i2c3_fck, CK_443X), - CLK(NULL, "i2c4_fck", &i2c4_fck, CK_443X), - CLK(NULL, "ipu_fck", &ipu_fck, CK_443X), CLK(NULL, "iss_ctrlclk", &iss_ctrlclk, CK_443X), - CLK(NULL, "iss_fck", &iss_fck, CK_443X), - CLK(NULL, "iva_fck", &iva_fck, CK_443X), - CLK(NULL, "kbd_fck", &kbd_fck, CK_443X), - CLK(NULL, "l3_instr_ick", &l3_instr_ick, CK_443X), - CLK(NULL, "l3_main_3_ick", &l3_main_3_ick, CK_443X), CLK(NULL, "mcasp_sync_mux_ck", &mcasp_sync_mux_ck, CK_443X), - CLK(NULL, "mcasp_fck", &mcasp_fck, CK_443X), + CLK(NULL, "func_mcasp_abe_gfclk", &func_mcasp_abe_gfclk, CK_443X), CLK(NULL, "mcbsp1_sync_mux_ck", &mcbsp1_sync_mux_ck, CK_443X), - CLK(NULL, "mcbsp1_fck", &mcbsp1_fck, CK_443X), + CLK(NULL, "func_mcbsp1_gfclk", &func_mcbsp1_gfclk, CK_443X), CLK(NULL, "mcbsp2_sync_mux_ck", &mcbsp2_sync_mux_ck, CK_443X), - CLK(NULL, "mcbsp2_fck", &mcbsp2_fck, CK_443X), + CLK(NULL, "func_mcbsp2_gfclk", &func_mcbsp2_gfclk, CK_443X), CLK(NULL, "mcbsp3_sync_mux_ck", &mcbsp3_sync_mux_ck, CK_443X), - CLK(NULL, "mcbsp3_fck", &mcbsp3_fck, CK_443X), + CLK(NULL, "func_mcbsp3_gfclk", &func_mcbsp3_gfclk, CK_443X), CLK(NULL, "mcbsp4_sync_mux_ck", &mcbsp4_sync_mux_ck, CK_443X), - CLK(NULL, "mcbsp4_fck", &mcbsp4_fck, CK_443X), - CLK(NULL, "mcpdm_fck", &mcpdm_fck, CK_443X), - CLK(NULL, "mcspi1_fck", &mcspi1_fck, CK_443X), - CLK(NULL, "mcspi2_fck", &mcspi2_fck, CK_443X), - CLK(NULL, "mcspi3_fck", &mcspi3_fck, CK_443X), - CLK(NULL, "mcspi4_fck", &mcspi4_fck, CK_443X), - CLK(NULL, "mmc1_fck", &mmc1_fck, CK_443X), - CLK(NULL, "mmc2_fck", &mmc2_fck, CK_443X), - CLK(NULL, "mmc3_fck", &mmc3_fck, CK_443X), - CLK(NULL, "mmc4_fck", &mmc4_fck, CK_443X), - CLK(NULL, "mmc5_fck", &mmc5_fck, CK_443X), - CLK(NULL, "ocp2scp_usb_phy_phy_48m", &ocp2scp_usb_phy_phy_48m, CK_443X), - CLK(NULL, "ocp2scp_usb_phy_ick", &ocp2scp_usb_phy_ick, CK_443X), - CLK(NULL, "ocp_wp_noc_ick", &ocp_wp_noc_ick, CK_443X), - CLK(NULL, "rng_ick", &rng_ick, CK_443X), - CLK("omap_rng", "ick", &rng_ick, CK_443X), + CLK(NULL, "per_mcbsp4_gfclk", &per_mcbsp4_gfclk, CK_443X), + CLK(NULL, "hsmmc1_fclk", &hsmmc1_fclk, CK_443X), + CLK(NULL, "hsmmc2_fclk", &hsmmc2_fclk, CK_443X), CLK(NULL, "sha2md5_fck", &sha2md5_fck, CK_443X), - CLK(NULL, "sl2if_ick", &sl2if_ick, CK_443X), CLK(NULL, "slimbus1_fclk_1", &slimbus1_fclk_1, CK_443X), CLK(NULL, "slimbus1_fclk_0", &slimbus1_fclk_0, CK_443X), CLK(NULL, "slimbus1_fclk_2", &slimbus1_fclk_2, CK_443X), CLK(NULL, "slimbus1_slimbus_clk", &slimbus1_slimbus_clk, CK_443X), - CLK(NULL, "slimbus1_fck", &slimbus1_fck, CK_443X), CLK(NULL, "slimbus2_fclk_1", &slimbus2_fclk_1, CK_443X), CLK(NULL, "slimbus2_fclk_0", &slimbus2_fclk_0, CK_443X), CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_443X), - CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_443X), CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X), CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X), CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X), - CLK(NULL, "timer1_fck", &timer1_fck, CK_443X), - CLK(NULL, "timer10_fck", &timer10_fck, CK_443X), - CLK(NULL, "timer11_fck", &timer11_fck, CK_443X), - CLK(NULL, "timer2_fck", &timer2_fck, CK_443X), - CLK(NULL, "timer3_fck", &timer3_fck, CK_443X), - CLK(NULL, "timer4_fck", &timer4_fck, CK_443X), - CLK(NULL, "timer5_fck", &timer5_fck, CK_443X), - CLK(NULL, "timer6_fck", &timer6_fck, CK_443X), - CLK(NULL, "timer7_fck", &timer7_fck, CK_443X), - CLK(NULL, "timer8_fck", &timer8_fck, CK_443X), - CLK(NULL, "timer9_fck", &timer9_fck, CK_443X), - CLK(NULL, "uart1_fck", &uart1_fck, CK_443X), - CLK(NULL, "uart2_fck", &uart2_fck, CK_443X), - CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), - CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), + CLK(NULL, "dmt1_clk_mux", &dmt1_clk_mux, CK_443X), + CLK(NULL, "cm2_dm10_mux", &cm2_dm10_mux, CK_443X), + CLK(NULL, "cm2_dm11_mux", &cm2_dm11_mux, CK_443X), + CLK(NULL, "cm2_dm2_mux", &cm2_dm2_mux, CK_443X), + CLK(NULL, "cm2_dm3_mux", &cm2_dm3_mux, CK_443X), + CLK(NULL, "cm2_dm4_mux", &cm2_dm4_mux, CK_443X), + CLK(NULL, "timer5_sync_mux", &timer5_sync_mux, CK_443X), + CLK(NULL, "timer6_sync_mux", &timer6_sync_mux, CK_443X), + CLK(NULL, "timer7_sync_mux", &timer7_sync_mux, CK_443X), + CLK(NULL, "timer8_sync_mux", &timer8_sync_mux, CK_443X), + CLK(NULL, "cm2_dm9_mux", &cm2_dm9_mux, CK_443X), CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X), CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X), CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), @@ -1901,9 +1576,6 @@ static struct omap_clk omap44xx_clks[] = { CLK("usbhs_tll", "usbtll_ick", &usb_tll_hs_ick, CK_443X), CLK(NULL, "usim_ck", &usim_ck, CK_443X), CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), - CLK(NULL, "usim_fck", &usim_fck, CK_443X), - CLK(NULL, "wd_timer2_fck", &wd_timer2_fck, CK_443X), - CLK(NULL, "wd_timer3_fck", &wd_timer3_fck, CK_443X), CLK(NULL, "pmd_stm_clock_mux_ck", &pmd_stm_clock_mux_ck, CK_443X), CLK(NULL, "pmd_trace_clk_mux_ck", &pmd_trace_clk_mux_ck, CK_443X), CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck, CK_443X), @@ -1980,15 +1652,6 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X), }; -static const char *enable_init_clks[] = { - "emif1_fck", - "emif2_fck", - "gpmc_ick", - "l3_instr_ick", - "l3_main_3_ick", - "ocp_wp_noc_ick", -}; - int __init omap4xxx_clk_init(void) { u32 cpu_clkflg; @@ -2019,9 +1682,6 @@ int __init omap4xxx_clk_init(void) omap2_clk_disable_autoidle_all(); - omap2_clk_enable_init_clocks(enable_init_clks, - ARRAY_SIZE(enable_init_clks)); - /* * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power * state when turning the ABE clock domain. Workaround this by diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 7faf82d..2da3b5e 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -92,8 +92,6 @@ static int _clkdm_register(struct clockdomain *clkdm) pwrdm_add_clkdm(pwrdm, clkdm); - spin_lock_init(&clkdm->lock); - pr_debug("clockdomain: registered %s\n", clkdm->name); return 0; @@ -122,7 +120,7 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, return cd; } -/* +/** * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store * @autodep: struct clkdm_autodep * to resolve * @@ -154,88 +152,206 @@ static void _autodep_lookup(struct clkdm_autodep *autodep) autodep->clkdm.ptr = clkdm; } -/* - * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable - * @clkdm: struct clockdomain * +/** + * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms + * @clkdm: clockdomain that we are resolving dependencies for + * @clkdm_deps: ptr to array of struct clkdm_deps to resolve * - * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' - * in hardware-supervised mode. Meant to be called from clock framework - * when a clock inside clockdomain 'clkdm' is enabled. No return value. + * Iterates through @clkdm_deps, looking up the struct clockdomain named by + * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep. + * No return value. + */ +static void _resolve_clkdm_deps(struct clockdomain *clkdm, + struct clkdm_dep *clkdm_deps) +{ + struct clkdm_dep *cd; + + for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { + if (cd->clkdm) + continue; + cd->clkdm = _clkdm_lookup(cd->clkdm_name); + + WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen", + clkdm->name, cd->clkdm_name); + } +} + +/** + * _clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 (lockless) + * @clkdm1: wake this struct clockdomain * up (dependent) + * @clkdm2: when this struct clockdomain * wakes up (source) * - * XXX autodeps are deprecated and should be removed at the earliest - * opportunity + * When the clockdomain represented by @clkdm2 wakes up, wake up + * @clkdm1. Implemented in hardware on the OMAP, this feature is + * designed to reduce wakeup latency of the dependent clockdomain @clkdm1. + * Returns -EINVAL if presented with invalid clockdomain pointers, + * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon + * success. */ -void _clkdm_add_autodeps(struct clockdomain *clkdm) +static int _clkdm_add_wkdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) { - struct clkdm_autodep *autodep; + struct clkdm_dep *cd; + int ret = 0; - if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) - return; + if (!clkdm1 || !clkdm2) + return -EINVAL; - for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { - if (IS_ERR(autodep->clkdm.ptr)) - continue; + cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); + if (IS_ERR(cd)) + ret = PTR_ERR(cd); - pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n", - clkdm->name, autodep->clkdm.ptr->name); + if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep) + ret = -EINVAL; + + if (ret) { + pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", + clkdm1->name, clkdm2->name); + return ret; + } + + cd->wkdep_usecount++; + if (cd->wkdep_usecount == 1) { + pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", + clkdm1->name, clkdm2->name); - clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr); - clkdm_add_wkdep(clkdm, autodep->clkdm.ptr); + ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2); } + + return ret; } -/* - * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm - * @clkdm: struct clockdomain * +/** + * _clkdm_del_wkdep - remove a wakeup dep from clkdm2 to clkdm1 (lockless) + * @clkdm1: wake this struct clockdomain * up (dependent) + * @clkdm2: when this struct clockdomain * wakes up (source) * - * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' - * in hardware-supervised mode. Meant to be called from clock framework - * when a clock inside clockdomain 'clkdm' is disabled. No return value. + * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2 + * wakes up. Returns -EINVAL if presented with invalid clockdomain + * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or + * 0 upon success. + */ +static int _clkdm_del_wkdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + struct clkdm_dep *cd; + int ret = 0; + + if (!clkdm1 || !clkdm2) + return -EINVAL; + + cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep) + ret = -EINVAL; + + if (ret) { + pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", + clkdm1->name, clkdm2->name); + return ret; + } + + cd->wkdep_usecount--; + if (cd->wkdep_usecount == 0) { + pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n", + clkdm1->name, clkdm2->name); + + ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2); + } + + return ret; +} + +/** + * _clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 (lockless) + * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) + * @clkdm2: when this struct clockdomain * is active (source) * - * XXX autodeps are deprecated and should be removed at the earliest - * opportunity + * Prevent @clkdm1 from automatically going inactive (and then to + * retention or off) if @clkdm2 is active. Returns -EINVAL if + * presented with invalid clockdomain pointers or called on a machine + * that does not support software-configurable hardware sleep + * dependencies, -ENOENT if the specified dependency cannot be set in + * hardware, or 0 upon success. */ -void _clkdm_del_autodeps(struct clockdomain *clkdm) +static int _clkdm_add_sleepdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) { - struct clkdm_autodep *autodep; + struct clkdm_dep *cd; + int ret = 0; - if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) - return; + if (!clkdm1 || !clkdm2) + return -EINVAL; - for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { - if (IS_ERR(autodep->clkdm.ptr)) - continue; + cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); + if (IS_ERR(cd)) + ret = PTR_ERR(cd); - pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n", - clkdm->name, autodep->clkdm.ptr->name); + if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep) + ret = -EINVAL; - clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr); - clkdm_del_wkdep(clkdm, autodep->clkdm.ptr); + if (ret) { + pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", + clkdm1->name, clkdm2->name); + return ret; + } + + cd->sleepdep_usecount++; + if (cd->sleepdep_usecount == 1) { + pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", + clkdm1->name, clkdm2->name); + + ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2); } + + return ret; } /** - * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms - * @clkdm: clockdomain that we are resolving dependencies for - * @clkdm_deps: ptr to array of struct clkdm_deps to resolve + * _clkdm_del_sleepdep - remove a sleep dep from clkdm2 to clkdm1 (lockless) + * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) + * @clkdm2: when this struct clockdomain * is active (source) * - * Iterates through @clkdm_deps, looking up the struct clockdomain named by - * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep. - * No return value. + * Allow @clkdm1 to automatically go inactive (and then to retention or + * off), independent of the activity state of @clkdm2. Returns -EINVAL + * if presented with invalid clockdomain pointers or called on a machine + * that does not support software-configurable hardware sleep dependencies, + * -ENOENT if the specified dependency cannot be cleared in hardware, or + * 0 upon success. */ -static void _resolve_clkdm_deps(struct clockdomain *clkdm, - struct clkdm_dep *clkdm_deps) +static int _clkdm_del_sleepdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) { struct clkdm_dep *cd; + int ret = 0; - for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { - if (cd->clkdm) - continue; - cd->clkdm = _clkdm_lookup(cd->clkdm_name); + if (!clkdm1 || !clkdm2) + return -EINVAL; - WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen", - clkdm->name, cd->clkdm_name); + cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep) + ret = -EINVAL; + + if (ret) { + pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", + clkdm1->name, clkdm2->name); + return ret; } + + cd->sleepdep_usecount--; + if (cd->sleepdep_usecount == 0) { + pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n", + clkdm1->name, clkdm2->name); + + ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2); + } + + return ret; } /* Public functions */ @@ -456,30 +572,18 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - int ret = 0; + int ret; if (!clkdm1 || !clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) - ret = PTR_ERR(cd); + return PTR_ERR(cd); - if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep) - ret = -EINVAL; - - if (ret) { - pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", - clkdm1->name, clkdm2->name); - return ret; - } - - if (atomic_inc_return(&cd->wkdep_usecount) == 1) { - pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", - clkdm1->name, clkdm2->name); - - ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2); - } + pwrdm_lock(cd->clkdm->pwrdm.ptr); + ret = _clkdm_add_wkdep(clkdm1, clkdm2); + pwrdm_unlock(cd->clkdm->pwrdm.ptr); return ret; } @@ -497,30 +601,18 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - int ret = 0; + int ret; if (!clkdm1 || !clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) - ret = PTR_ERR(cd); + return PTR_ERR(cd); - if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep) - ret = -EINVAL; - - if (ret) { - pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", - clkdm1->name, clkdm2->name); - return ret; - } - - if (atomic_dec_return(&cd->wkdep_usecount) == 0) { - pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n", - clkdm1->name, clkdm2->name); - - ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2); - } + pwrdm_lock(cd->clkdm->pwrdm.ptr); + ret = _clkdm_del_wkdep(clkdm1, clkdm2); + pwrdm_unlock(cd->clkdm->pwrdm.ptr); return ret; } @@ -560,7 +652,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) return ret; } - /* XXX It's faster to return the atomic wkdep_usecount */ + /* XXX It's faster to return the wkdep_usecount */ return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); } @@ -600,30 +692,18 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - int ret = 0; + int ret; if (!clkdm1 || !clkdm2) return -EINVAL; - cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); + cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) - ret = PTR_ERR(cd); + return PTR_ERR(cd); - if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep) - ret = -EINVAL; - - if (ret) { - pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", - clkdm1->name, clkdm2->name); - return ret; - } - - if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { - pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", - clkdm1->name, clkdm2->name); - - ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2); - } + pwrdm_lock(cd->clkdm->pwrdm.ptr); + ret = _clkdm_add_sleepdep(clkdm1, clkdm2); + pwrdm_unlock(cd->clkdm->pwrdm.ptr); return ret; } @@ -643,30 +723,18 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - int ret = 0; + int ret; if (!clkdm1 || !clkdm2) return -EINVAL; - cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); + cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) - ret = PTR_ERR(cd); + return PTR_ERR(cd); - if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep) - ret = -EINVAL; - - if (ret) { - pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", - clkdm1->name, clkdm2->name); - return ret; - } - - if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { - pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n", - clkdm1->name, clkdm2->name); - - ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2); - } + pwrdm_lock(cd->clkdm->pwrdm.ptr); + ret = _clkdm_del_sleepdep(clkdm1, clkdm2); + pwrdm_unlock(cd->clkdm->pwrdm.ptr); return ret; } @@ -708,7 +776,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) return ret; } - /* XXX It's faster to return the atomic sleepdep_usecount */ + /* XXX It's faster to return the sleepdep_usecount */ return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); } @@ -734,18 +802,17 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) } /** - * clkdm_sleep - force clockdomain sleep transition + * clkdm_sleep_nolock - force clockdomain sleep transition (lockless) * @clkdm: struct clockdomain * * * Instruct the CM to force a sleep transition on the specified - * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if - * clockdomain does not support software-initiated sleep; 0 upon - * success. + * clockdomain @clkdm. Only for use by the powerdomain code. Returns + * -EINVAL if @clkdm is NULL or if clockdomain does not support + * software-initiated sleep; 0 upon success. */ -int clkdm_sleep(struct clockdomain *clkdm) +int clkdm_sleep_nolock(struct clockdomain *clkdm) { int ret; - unsigned long flags; if (!clkdm) return -EINVAL; @@ -761,26 +828,45 @@ int clkdm_sleep(struct clockdomain *clkdm) pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); - spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; ret = arch_clkdm->clkdm_sleep(clkdm); - spin_unlock_irqrestore(&clkdm->lock, flags); + ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); + return ret; } /** - * clkdm_wakeup - force clockdomain wakeup transition + * clkdm_sleep - force clockdomain sleep transition * @clkdm: struct clockdomain * * - * Instruct the CM to force a wakeup transition on the specified - * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if the - * clockdomain does not support software-controlled wakeup; 0 upon + * Instruct the CM to force a sleep transition on the specified + * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if + * clockdomain does not support software-initiated sleep; 0 upon * success. */ -int clkdm_wakeup(struct clockdomain *clkdm) +int clkdm_sleep(struct clockdomain *clkdm) +{ + int ret; + + pwrdm_lock(clkdm->pwrdm.ptr); + ret = clkdm_sleep_nolock(clkdm); + pwrdm_unlock(clkdm->pwrdm.ptr); + + return ret; +} + +/** + * clkdm_wakeup_nolock - force clockdomain wakeup transition (lockless) + * @clkdm: struct clockdomain * + * + * Instruct the CM to force a wakeup transition on the specified + * clockdomain @clkdm. Only for use by the powerdomain code. Returns + * -EINVAL if @clkdm is NULL or if the clockdomain does not support + * software-controlled wakeup; 0 upon success. + */ +int clkdm_wakeup_nolock(struct clockdomain *clkdm) { int ret; - unsigned long flags; if (!clkdm) return -EINVAL; @@ -796,28 +882,46 @@ int clkdm_wakeup(struct clockdomain *clkdm) pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); - spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; ret = arch_clkdm->clkdm_wakeup(clkdm); - ret |= pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); + ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); + return ret; } /** - * clkdm_allow_idle - enable hwsup idle transitions for clkdm + * clkdm_wakeup - force clockdomain wakeup transition * @clkdm: struct clockdomain * * - * Allow the hardware to automatically switch the clockdomain @clkdm into - * active or idle states, as needed by downstream clocks. If the + * Instruct the CM to force a wakeup transition on the specified + * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if the + * clockdomain does not support software-controlled wakeup; 0 upon + * success. + */ +int clkdm_wakeup(struct clockdomain *clkdm) +{ + int ret; + + pwrdm_lock(clkdm->pwrdm.ptr); + ret = clkdm_wakeup_nolock(clkdm); + pwrdm_unlock(clkdm->pwrdm.ptr); + + return ret; +} + +/** + * clkdm_allow_idle_nolock - enable hwsup idle transitions for clkdm + * @clkdm: struct clockdomain * + * + * Allow the hardware to automatically switch the clockdomain @clkdm + * into active or idle states, as needed by downstream clocks. If the * clockdomain has any downstream clocks enabled in the clock * framework, wkdep/sleepdep autodependencies are added; this is so - * device drivers can read and write to the device. No return value. + * device drivers can read and write to the device. Only for use by + * the powerdomain code. No return value. */ -void clkdm_allow_idle(struct clockdomain *clkdm) +void clkdm_allow_idle_nolock(struct clockdomain *clkdm) { - unsigned long flags; - if (!clkdm) return; @@ -833,11 +937,26 @@ void clkdm_allow_idle(struct clockdomain *clkdm) pr_debug("clockdomain: enabling automatic idle transitions for %s\n", clkdm->name); - spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED; arch_clkdm->clkdm_allow_idle(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); + pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); +} + +/** + * clkdm_allow_idle - enable hwsup idle transitions for clkdm + * @clkdm: struct clockdomain * + * + * Allow the hardware to automatically switch the clockdomain @clkdm into + * active or idle states, as needed by downstream clocks. If the + * clockdomain has any downstream clocks enabled in the clock + * framework, wkdep/sleepdep autodependencies are added; this is so + * device drivers can read and write to the device. No return value. + */ +void clkdm_allow_idle(struct clockdomain *clkdm) +{ + pwrdm_lock(clkdm->pwrdm.ptr); + clkdm_allow_idle_nolock(clkdm); + pwrdm_unlock(clkdm->pwrdm.ptr); } /** @@ -847,12 +966,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm) * Prevent the hardware from automatically switching the clockdomain * @clkdm into inactive or idle states. If the clockdomain has * downstream clocks enabled in the clock framework, wkdep/sleepdep - * autodependencies are removed. No return value. + * autodependencies are removed. Only for use by the powerdomain + * code. No return value. */ -void clkdm_deny_idle(struct clockdomain *clkdm) +void clkdm_deny_idle_nolock(struct clockdomain *clkdm) { - unsigned long flags; - if (!clkdm) return; @@ -868,11 +986,25 @@ void clkdm_deny_idle(struct clockdomain *clkdm) pr_debug("clockdomain: disabling automatic idle transitions for %s\n", clkdm->name); - spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; arch_clkdm->clkdm_deny_idle(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); + pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); +} + +/** + * clkdm_deny_idle - disable hwsup idle transitions for clkdm + * @clkdm: struct clockdomain * + * + * Prevent the hardware from automatically switching the clockdomain + * @clkdm into inactive or idle states. If the clockdomain has + * downstream clocks enabled in the clock framework, wkdep/sleepdep + * autodependencies are removed. No return value. + */ +void clkdm_deny_idle(struct clockdomain *clkdm) +{ + pwrdm_lock(clkdm->pwrdm.ptr); + clkdm_deny_idle_nolock(clkdm); + pwrdm_unlock(clkdm->pwrdm.ptr); } /** @@ -889,14 +1021,11 @@ void clkdm_deny_idle(struct clockdomain *clkdm) bool clkdm_in_hwsup(struct clockdomain *clkdm) { bool ret; - unsigned long flags; if (!clkdm) return false; - spin_lock_irqsave(&clkdm->lock, flags); ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false; - spin_unlock_irqrestore(&clkdm->lock, flags); return ret; } @@ -918,30 +1047,91 @@ bool clkdm_missing_idle_reporting(struct clockdomain *clkdm) return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false; } +/* Public autodep handling functions (deprecated) */ + +/** + * clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable + * @clkdm: struct clockdomain * + * + * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' + * in hardware-supervised mode. Meant to be called from clock framework + * when a clock inside clockdomain 'clkdm' is enabled. No return value. + * + * XXX autodeps are deprecated and should be removed at the earliest + * opportunity + */ +void clkdm_add_autodeps(struct clockdomain *clkdm) +{ + struct clkdm_autodep *autodep; + + if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) + return; + + for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { + if (IS_ERR(autodep->clkdm.ptr)) + continue; + + pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n", + clkdm->name, autodep->clkdm.ptr->name); + + _clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr); + _clkdm_add_wkdep(clkdm, autodep->clkdm.ptr); + } +} + +/** + * clkdm_del_autodeps - remove auto sleepdeps/wkdeps from clkdm + * @clkdm: struct clockdomain * + * + * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' + * in hardware-supervised mode. Meant to be called from clock framework + * when a clock inside clockdomain 'clkdm' is disabled. No return value. + * + * XXX autodeps are deprecated and should be removed at the earliest + * opportunity + */ +void clkdm_del_autodeps(struct clockdomain *clkdm) +{ + struct clkdm_autodep *autodep; + + if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) + return; + + for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { + if (IS_ERR(autodep->clkdm.ptr)) + continue; + + pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n", + clkdm->name, autodep->clkdm.ptr->name); + + _clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr); + _clkdm_del_wkdep(clkdm, autodep->clkdm.ptr); + } +} + /* Clockdomain-to-clock/hwmod framework interface code */ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) { - unsigned long flags; - if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) return -EINVAL; - spin_lock_irqsave(&clkdm->lock, flags); + pwrdm_lock(clkdm->pwrdm.ptr); /* * For arch's with no autodeps, clkcm_clk_enable * should be called for every clock instance or hwmod that is * enabled, so the clkdm can be force woken up. */ - if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) { - spin_unlock_irqrestore(&clkdm->lock, flags); + clkdm->usecount++; + if (clkdm->usecount > 1 && autodeps) { + pwrdm_unlock(clkdm->pwrdm.ptr); return 0; } arch_clkdm->clkdm_clk_enable(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); + pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); + pwrdm_unlock(clkdm->pwrdm.ptr); pr_debug("clockdomain: %s: enabled\n", clkdm->name); @@ -990,36 +1180,34 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) */ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) { - unsigned long flags; - if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; - spin_lock_irqsave(&clkdm->lock, flags); + pwrdm_lock(clkdm->pwrdm.ptr); /* corner case: disabling unused clocks */ - if ((__clk_get_enable_count(clk) == 0) && - (atomic_read(&clkdm->usecount) == 0)) + if ((__clk_get_enable_count(clk) == 0) && clkdm->usecount == 0) goto ccd_exit; - if (atomic_read(&clkdm->usecount) == 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); + if (clkdm->usecount == 0) { + pwrdm_unlock(clkdm->pwrdm.ptr); WARN_ON(1); /* underflow */ return -ERANGE; } - if (atomic_dec_return(&clkdm->usecount) > 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); + clkdm->usecount--; + if (clkdm->usecount > 0) { + pwrdm_unlock(clkdm->pwrdm.ptr); return 0; } arch_clkdm->clkdm_clk_disable(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); + pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); pr_debug("clockdomain: %s: disabled\n", clkdm->name); ccd_exit: - spin_unlock_irqrestore(&clkdm->lock, flags); + pwrdm_unlock(clkdm->pwrdm.ptr); return 0; } @@ -1072,8 +1260,6 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh) */ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) { - unsigned long flags; - /* The clkdm attribute does not exist yet prior OMAP4 */ if (cpu_is_omap24xx() || cpu_is_omap34xx()) return 0; @@ -1086,22 +1272,23 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; - spin_lock_irqsave(&clkdm->lock, flags); + pwrdm_lock(clkdm->pwrdm.ptr); - if (atomic_read(&clkdm->usecount) == 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); + if (clkdm->usecount == 0) { + pwrdm_unlock(clkdm->pwrdm.ptr); WARN_ON(1); /* underflow */ return -ERANGE; } - if (atomic_dec_return(&clkdm->usecount) > 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); + clkdm->usecount--; + if (clkdm->usecount > 0) { + pwrdm_unlock(clkdm->pwrdm.ptr); return 0; } arch_clkdm->clkdm_clk_disable(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); + pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); + pwrdm_unlock(clkdm->pwrdm.ptr); pr_debug("clockdomain: %s: disabled\n", clkdm->name); diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index bc42446..2da3765 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -15,7 +15,6 @@ #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H #include <linux/init.h> -#include <linux/spinlock.h> #include "powerdomain.h" #include "clock.h" @@ -92,8 +91,8 @@ struct clkdm_autodep { struct clkdm_dep { const char *clkdm_name; struct clockdomain *clkdm; - atomic_t wkdep_usecount; - atomic_t sleepdep_usecount; + s16 wkdep_usecount; + s16 sleepdep_usecount; }; /* Possible flags for struct clockdomain._flags */ @@ -137,9 +136,8 @@ struct clockdomain { const u16 clkdm_offs; struct clkdm_dep *wkdep_srcs; struct clkdm_dep *sleepdep_srcs; - atomic_t usecount; + int usecount; struct list_head node; - spinlock_t lock; }; /** @@ -196,12 +194,16 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); +void clkdm_allow_idle_nolock(struct clockdomain *clkdm); void clkdm_allow_idle(struct clockdomain *clkdm); +void clkdm_deny_idle_nolock(struct clockdomain *clkdm); void clkdm_deny_idle(struct clockdomain *clkdm); bool clkdm_in_hwsup(struct clockdomain *clkdm); bool clkdm_missing_idle_reporting(struct clockdomain *clkdm); +int clkdm_wakeup_nolock(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); +int clkdm_sleep_nolock(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); @@ -214,8 +216,9 @@ extern void __init omap243x_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); extern void __init am33xx_clockdomains_init(void); extern void __init omap44xx_clockdomains_init(void); -extern void _clkdm_add_autodeps(struct clockdomain *clkdm); -extern void _clkdm_del_autodeps(struct clockdomain *clkdm); + +extern void clkdm_add_autodeps(struct clockdomain *clkdm); +extern void clkdm_del_autodeps(struct clockdomain *clkdm); extern struct clkdm_ops omap2_clkdm_operations; extern struct clkdm_ops omap3_clkdm_operations; diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c index db65069..6774a53 100644 --- a/arch/arm/mach-omap2/cm2xxx.c +++ b/arch/arm/mach-omap2/cm2xxx.c @@ -273,9 +273,6 @@ int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift) static void omap2xxx_clkdm_allow_idle(struct clockdomain *clkdm) { - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_add_autodeps(clkdm); - omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); } @@ -284,9 +281,6 @@ static void omap2xxx_clkdm_deny_idle(struct clockdomain *clkdm) { omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_del_autodeps(clkdm); } static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm) @@ -298,18 +292,8 @@ static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm) hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - _clkdm_add_autodeps(clkdm); - omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - } else { - if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) - omap2xxx_clkdm_wakeup(clkdm); - } + if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) + omap2xxx_clkdm_wakeup(clkdm); return 0; } @@ -324,17 +308,8 @@ static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm) hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - _clkdm_del_autodeps(clkdm); - omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - } else { - if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) - omap2xxx_clkdm_sleep(clkdm); - } + if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_SLEEP) + omap2xxx_clkdm_sleep(clkdm); return 0; } diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index c2086f2..9061c30 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -186,7 +186,7 @@ static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) continue; /* only happens if data is erroneous */ mask |= 1 << cd->clkdm->dep_bit; - atomic_set(&cd->sleepdep_usecount, 0); + cd->sleepdep_usecount = 0; } omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, OMAP3430_CM_SLEEPDEP); @@ -209,8 +209,8 @@ static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm) static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm) { - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_add_autodeps(clkdm); + if (clkdm->usecount > 0) + clkdm_add_autodeps(clkdm); omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); @@ -221,8 +221,8 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm) omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_del_autodeps(clkdm); + if (clkdm->usecount > 0) + clkdm_del_autodeps(clkdm); } static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm) @@ -250,7 +250,7 @@ static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm) /* Disable HW transitions when we are changing deps */ omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - _clkdm_add_autodeps(clkdm); + clkdm_add_autodeps(clkdm); omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); } else { @@ -287,7 +287,7 @@ static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm) /* Disable HW transitions when we are changing deps */ omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); - _clkdm_del_autodeps(clkdm); + clkdm_del_autodeps(clkdm); omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); } else { diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 7f9a464..f0290f5 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -393,7 +393,7 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) continue; /* only happens if data is erroneous */ mask |= 1 << cd->clkdm->dep_bit; - atomic_set(&cd->wkdep_usecount, 0); + cd->wkdep_usecount = 0; } omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 948bcaa..b435027 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -79,13 +79,13 @@ static inline int omap_mux_late_init(void) extern void omap2_init_common_infrastructure(void); -extern struct sys_timer omap2_timer; -extern struct sys_timer omap3_timer; -extern struct sys_timer omap3_secure_timer; -extern struct sys_timer omap3_gp_timer; -extern struct sys_timer omap3_am33xx_timer; -extern struct sys_timer omap4_timer; -extern struct sys_timer omap5_timer; +extern void omap2_sync32k_timer_init(void); +extern void omap3_sync32k_timer_init(void); +extern void omap3_secure_sync32k_timer_init(void); +extern void omap3_gp_gptimer_timer_init(void); +extern void omap3_am33xx_gptimer_timer_init(void); +extern void omap4_local_timer_init(void); +extern void omap5_realtime_timer_init(void); void omap2420_init_early(void); void omap2430_init_early(void); diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 22590db..80392fc 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -36,40 +36,66 @@ /* Mach specific information to be recorded in the C-state driver_data */ struct omap3_idle_statedata { - u32 mpu_state; - u32 core_state; + u8 mpu_state; + u8 core_state; + u8 per_min_state; + u8 flags; }; static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; +/* + * Possible flag bits for struct omap3_idle_statedata.flags: + * + * OMAP_CPUIDLE_CX_NO_CLKDM_IDLE: don't allow the MPU clockdomain to go + * inactive. This in turn prevents the MPU DPLL from entering autoidle + * mode, so wakeup latency is greatly reduced, at the cost of additional + * energy consumption. This also prevents the CORE clockdomain from + * entering idle. + */ +#define OMAP_CPUIDLE_CX_NO_CLKDM_IDLE BIT(0) + +/* + * Prevent PER OFF if CORE is not in RETention or OFF as this would + * disable PER wakeups completely. + */ static struct omap3_idle_statedata omap3_idle_data[] = { { .mpu_state = PWRDM_POWER_ON, .core_state = PWRDM_POWER_ON, + /* In C1 do not allow PER state lower than CORE state */ + .per_min_state = PWRDM_POWER_ON, + .flags = OMAP_CPUIDLE_CX_NO_CLKDM_IDLE, }, { .mpu_state = PWRDM_POWER_ON, .core_state = PWRDM_POWER_ON, + .per_min_state = PWRDM_POWER_RET, }, { .mpu_state = PWRDM_POWER_RET, .core_state = PWRDM_POWER_ON, + .per_min_state = PWRDM_POWER_RET, }, { .mpu_state = PWRDM_POWER_OFF, .core_state = PWRDM_POWER_ON, + .per_min_state = PWRDM_POWER_RET, }, { .mpu_state = PWRDM_POWER_RET, .core_state = PWRDM_POWER_RET, + .per_min_state = PWRDM_POWER_OFF, }, { .mpu_state = PWRDM_POWER_OFF, .core_state = PWRDM_POWER_RET, + .per_min_state = PWRDM_POWER_OFF, }, { .mpu_state = PWRDM_POWER_OFF, .core_state = PWRDM_POWER_OFF, + .per_min_state = PWRDM_POWER_OFF, }, }; @@ -80,27 +106,25 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = &omap3_idle_data[index]; - u32 mpu_state = cx->mpu_state, core_state = cx->core_state; local_fiq_disable(); - pwrdm_set_next_pwrst(mpu_pd, mpu_state); - pwrdm_set_next_pwrst(core_pd, core_state); - if (omap_irq_pending() || need_resched()) goto return_sleep_time; /* Deny idle for C1 */ - if (index == 0) { + if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) { clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); - clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); + } else { + pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state); + pwrdm_set_next_pwrst(core_pd, cx->core_state); } /* * Call idle CPU PM enter notifier chain so that * VFP context is saved. */ - if (mpu_state == PWRDM_POWER_OFF) + if (cx->mpu_state == PWRDM_POWER_OFF) cpu_pm_enter(); /* Execute ARM wfi */ @@ -110,17 +134,15 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain to restore * VFP context. */ - if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) + if (cx->mpu_state == PWRDM_POWER_OFF && + pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) cpu_pm_exit(); /* Re-allow idle for C1 */ - if (index == 0) { + if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); - clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); - } return_sleep_time: - local_fiq_enable(); return index; @@ -185,7 +207,7 @@ static int next_valid_state(struct cpuidle_device *dev, * Start search from the next (lower) state. */ for (idx = index - 1; idx >= 0; idx--) { - cx = &omap3_idle_data[idx]; + cx = &omap3_idle_data[idx]; if ((cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { next_index = idx; @@ -209,10 +231,9 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - int new_state_idx; - u32 core_next_state, per_next_state = 0, per_saved_state = 0; + int new_state_idx, ret; + u8 per_next_state, per_saved_state; struct omap3_idle_statedata *cx; - int ret; /* * Use only C1 if CAM is active. @@ -233,25 +254,13 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, /* Program PER state */ cx = &omap3_idle_data[new_state_idx]; - core_next_state = cx->core_state; - per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); - if (new_state_idx == 0) { - /* In C1 do not allow PER state lower than CORE state */ - if (per_next_state < core_next_state) - per_next_state = core_next_state; - } else { - /* - * Prevent PER OFF if CORE is not in RETention or OFF as this - * would disable PER wakeups completely. - */ - if ((per_next_state == PWRDM_POWER_OFF) && - (core_next_state > PWRDM_POWER_RET)) - per_next_state = PWRDM_POWER_RET; - } - /* Are we changing PER target state? */ - if (per_next_state != per_saved_state) + per_next_state = pwrdm_read_next_pwrst(per_pd); + per_saved_state = per_next_state; + if (per_next_state < cx->per_min_state) { + per_next_state = cx->per_min_state; pwrdm_set_next_pwrst(per_pd, per_next_state); + } ret = omap3_enter_idle(dev, drv, new_state_idx); diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 626f3ea..d8a0cc3 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -61,8 +61,7 @@ static int __init omap3_l3_init(void) if (!oh) pr_err("could not look up %s\n", oh_name); - pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0, - NULL, 0, 0); + pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0); WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); @@ -96,8 +95,7 @@ static int __init omap4_l3_init(void) pr_err("could not look up %s\n", oh_name); } - pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL, - 0, NULL, 0, 0); + pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL, 0); WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); @@ -273,7 +271,7 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data keypad_data = sdp4430_keypad_data; pdev = omap_device_build(name, id, oh, keypad_data, - sizeof(struct omap4_keypad_platform_data), NULL, 0, 0); + sizeof(struct omap4_keypad_platform_data)); if (IS_ERR(pdev)) { WARN(1, "Can't build omap_device for %s:%s.\n", @@ -297,7 +295,7 @@ static inline void __init omap_init_mbox(void) return; } - pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n", __func__, PTR_ERR(pdev)); } @@ -337,7 +335,7 @@ static void __init omap_init_mcpdm(void) return; } - pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n"); } #else @@ -358,7 +356,7 @@ static void __init omap_init_dmic(void) return; } - pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap-dmic.\n"); } #else @@ -384,8 +382,7 @@ static void __init omap_init_hdmi_audio(void) return; } - pdev = omap_device_build("omap-hdmi-audio-dai", - -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build("omap-hdmi-audio-dai", -1, oh, NULL, 0, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap-hdmi-audio-dai.\n"); @@ -429,8 +426,7 @@ static int __init omap_mcspi_init(struct omap_hwmod *oh, void *unused) } spi_num++; - pdev = omap_device_build(name, spi_num, oh, pdata, - sizeof(*pdata), NULL, 0, 0); + pdev = omap_device_build(name, spi_num, oh, pdata, sizeof(*pdata)); WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n", name, oh->name); kfree(pdata); @@ -460,7 +456,7 @@ static void omap_init_rng(void) if (!oh) return; - pdev = omap_device_build("omap_rng", -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build("omap_rng", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n"); } @@ -689,8 +685,7 @@ static void __init omap_init_ocp2scp(void) pdata->dev_cnt = dev_cnt; - pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL, - 0, false); + pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata)); if (IS_ERR(pdev)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index cc75aaf..ff37be1 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -226,7 +226,7 @@ static struct platform_device *create_dss_pdev(const char *pdev_name, dev_set_name(&pdev->dev, "%s", pdev->name); ohs[0] = oh; - od = omap_device_alloc(pdev, ohs, 1, NULL, 0); + od = omap_device_alloc(pdev, ohs, 1); if (IS_ERR(od)) { pr_err("Could not alloc omap_device for %s\n", pdev_name); r = -ENOMEM; diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 612b982..491c5c8 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -248,7 +248,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) p->errata = configure_dma_errata(); - pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0); + pdev = omap_device_build(name, 0, oh, p, sizeof(*p)); kfree(p); if (IS_ERR(pdev)) { pr_err("%s: Can't build omap_device for %s:%s.\n", diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 2a2cfa8..4d8d1a5 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c @@ -51,8 +51,7 @@ static int __init omap_init_drm(void) oh = omap_hwmod_lookup("dmm"); if (oh) { - pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 0, - false); + pdev = omap_device_build(oh->name, -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", oh->name); } diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 399acab..482ade1 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -131,8 +131,7 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pwrdm = omap_hwmod_get_pwrdm(oh); pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); - pdev = omap_device_build(name, id - 1, oh, pdata, - sizeof(*pdata), NULL, 0, false); + pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata)); kfree(pdata); if (IS_ERR(pdev)) { diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 8033cb7..bc07833 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1220,7 +1220,7 @@ static int __init omap_gpmc_init(void) return -ENODEV; } - pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0); WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c index ab7bf18..b7aa8ba 100644 --- a/arch/arm/mach-omap2/hdq1w.c +++ b/arch/arm/mach-omap2/hdq1w.c @@ -87,7 +87,7 @@ static int __init omap_init_hdq(void) if (!oh) return 0; - pdev = omap_device_build(devname, id, oh, NULL, 0, NULL, 0, 0); + pdev = omap_device_build(devname, id, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n", devname, oh->name); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 4a96433..2ef1f87 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -522,7 +522,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, } dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - od = omap_device_alloc(pdev, ohs, 1, NULL, 0); + od = omap_device_alloc(pdev, ohs, 1); if (IS_ERR(od)) { pr_err("Could not allocate od for %s\n", name); goto put_pdev; diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c index 1df9b5f..c368890 100644 --- a/arch/arm/mach-omap2/hwspinlock.c +++ b/arch/arm/mach-omap2/hwspinlock.c @@ -46,8 +46,7 @@ static int __init hwspinlocks_init(void) return -EINVAL; pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata, - sizeof(struct hwspinlock_pdata), - NULL, 0, false); + sizeof(struct hwspinlock_pdata)); if (IS_ERR(pdev)) { pr_err("Can't build omap_device for %s:%s\n", dev_name, oh_name); diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c index b9074dd..c11a23f 100644 --- a/arch/arm/mach-omap2/i2c.c +++ b/arch/arm/mach-omap2/i2c.c @@ -178,8 +178,7 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata, if (cpu_is_omap34xx()) pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; pdev = omap_device_build(name, bus_id, oh, pdata, - sizeof(struct omap_i2c_bus_platform_data), - NULL, 0, 0); + sizeof(struct omap_i2c_bus_platform_data)); WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name); return PTR_RET(pdev); diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index df49f2a..4535804 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -101,7 +101,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) count++; } pdev = omap_device_build_ss(name, id, oh_device, count, pdata, - sizeof(*pdata), NULL, 0, false); + sizeof(*pdata)); kfree(pdata); if (IS_ERR(pdev)) { pr_err("%s: Can't build omap_device for %s:%s.\n", __func__, diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c index aafdd4c..c52d8b4 100644 --- a/arch/arm/mach-omap2/msdi.c +++ b/arch/arm/mach-omap2/msdi.c @@ -150,7 +150,7 @@ void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) return; } pdev = omap_device_build(dev_name, id, oh, mmc_data[0], - sizeof(struct omap_mmc_platform_data), NULL, 0, 0); + sizeof(struct omap_mmc_platform_data)); if (IS_ERR(pdev)) WARN(1, "Can'd build omap_device for %s:%s.\n", dev_name, oh->name); diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index 6da4f7a..f7f38c7 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -41,8 +41,7 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused) pdata->deassert_reset = omap_device_deassert_hardreset; } - pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata), - NULL, 0, 0); + pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata)); kfree(pdata); diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index aac46bf..8bcb64b 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -87,37 +87,6 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr) } /* - * Set the CPUx powerdomain's previous power state - */ -static inline void set_cpu_next_pwrst(unsigned int cpu_id, - unsigned int power_state) -{ - struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - - pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); -} - -/* - * Read CPU's previous power state - */ -static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id) -{ - struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - - return pwrdm_read_prev_pwrst(pm_info->pwrdm); -} - -/* - * Clear the CPUx powerdomain's previous power state - */ -static inline void clear_cpu_prev_pwrst(unsigned int cpu_id) -{ - struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - - pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); -} - -/* * Store the SCU power status value to scratchpad memory */ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) @@ -230,6 +199,7 @@ static void save_l2x0_context(void) */ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) { + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); unsigned int save_state = 0; unsigned int wakeup_cpu; @@ -268,7 +238,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) save_state = 2; cpu_clear_prev_logic_pwrst(cpu); - set_cpu_next_pwrst(cpu, power_state); + pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); scu_pwrst_prepare(cpu, power_state); l2x0_pwrst_prepare(cpu, save_state); @@ -286,7 +256,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) * domain transition */ wakeup_cpu = smp_processor_id(); - set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); pwrdm_post_transition(NULL); @@ -300,8 +270,8 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) */ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) { - unsigned int cpu_state = 0; struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); + unsigned int cpu_state = 0; if (omap_rev() == OMAP4430_REV_ES1_0) return -ENXIO; @@ -309,8 +279,8 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) if (power_state == PWRDM_POWER_OFF) cpu_state = 1; - clear_cpu_prev_pwrst(cpu); - set_cpu_next_pwrst(cpu, power_state); + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); + pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); scu_pwrst_prepare(cpu, power_state); @@ -321,7 +291,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) */ omap4_finish_suspend(cpu_state); - set_cpu_next_pwrst(cpu, PWRDM_POWER_ON); + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); return 0; } diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index cd42d92..d972721 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -19,9 +19,9 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include "omap-secure.h" @@ -157,7 +157,7 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * booted = true; } - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); /* * Now the secondary core is starting up let it run its @@ -215,7 +215,7 @@ static void __init omap4_smp_init_cpus(void) * Currently we can't call ioremap here because * SoC detection won't work until after init_early. */ - scu_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE); + scu_base = OMAP2_L4_IO_ADDRESS(scu_a9_get_base()); BUG_ON(!scu_base); ncores = scu_get_core_count(scu_base); } else if (cpu_id == CPU_CORTEX_A15) { @@ -231,8 +231,6 @@ static void __init omap4_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 5d3b4f4..8c5b5e3 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -24,8 +24,7 @@ #include <linux/cpu.h> #include <linux/notifier.h> #include <linux/cpu_pm.h> - -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include "omap-wakeupgen.h" #include "omap-secure.h" diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 6897ae2..5470948 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -15,13 +15,14 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/platform_device.h> #include <linux/memblock.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/export.h> +#include <linux/irqchip/arm-gic.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/map.h> #include <asm/memblock.h> @@ -255,16 +256,10 @@ static int __init omap4_sar_ram_init(void) } early_initcall(omap4_sar_ram_init); -static struct of_device_id irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, }, - { } -}; - void __init omap_gic_of_init(void) { omap_wakeupgen_init(); - of_irq_init(irq_match); + irqchip_init(); } #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) diff --git a/arch/arm/mach-omap2/omap44xx.h b/arch/arm/mach-omap2/omap44xx.h index 43b927b..8a515bb 100644 --- a/arch/arm/mach-omap2/omap44xx.h +++ b/arch/arm/mach-omap2/omap44xx.h @@ -40,7 +40,6 @@ #define OMAP44XX_GIC_DIST_BASE 0x48241000 #define OMAP44XX_GIC_CPU_BASE 0x48240100 #define OMAP44XX_IRQ_GIC_START 32 -#define OMAP44XX_SCU_BASE 0x48240000 #define OMAP44XX_LOCAL_TWD_BASE 0x48240600 #define OMAP44XX_L2CACHE_BASE 0x48242000 #define OMAP44XX_WKUPGEN_BASE 0x48281000 diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e065daa..6ee3ad3 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -17,68 +17,15 @@ * to control power management and interconnect properties of their * devices. * - * In the medium- to long-term, this code should either be - * a) implemented via arch-specific pointers in platform_data - * or - * b) implemented as a proper omap_bus/omap_device in Linux, no more - * platform_data func pointers + * In the medium- to long-term, this code should be implemented as a + * proper omap_bus/omap_device in Linux, no more platform_data func + * pointers * * - * Guidelines for usage by driver authors: - * - * 1. These functions are intended to be used by device drivers via - * function pointers in struct platform_data. As an example, - * omap_device_enable() should be passed to the driver as - * - * struct foo_driver_platform_data { - * ... - * int (*device_enable)(struct platform_device *pdev); - * ... - * } - * - * Note that the generic "device_enable" name is used, rather than - * "omap_device_enable". This is so other architectures can pass in their - * own enable/disable functions here. - * - * This should be populated during device setup: - * - * ... - * pdata->device_enable = omap_device_enable; - * ... - * - * 2. Drivers should first check to ensure the function pointer is not null - * before calling it, as in: - * - * if (pdata->device_enable) - * pdata->device_enable(pdev); - * - * This allows other architectures that don't use similar device_enable()/ - * device_shutdown() functions to execute normally. - * - * ... - * - * Suggested usage by device drivers: - * - * During device initialization: - * device_enable() - * - * During device idle: - * (save remaining device context if necessary) - * device_idle(); - * - * During device resume: - * device_enable(); - * (restore context if necessary) - * - * During device shutdown: - * device_shutdown() - * (device must be reinitialized at this point to use it again) - * */ #undef DEBUG #include <linux/kernel.h> -#include <linux/export.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/err.h> @@ -92,155 +39,8 @@ #include "omap_device.h" #include "omap_hwmod.h" -/* These parameters are passed to _omap_device_{de,}activate() */ -#define USE_WAKEUP_LAT 0 -#define IGNORE_WAKEUP_LAT 1 - -static int omap_early_device_register(struct platform_device *pdev); - -static struct omap_device_pm_latency omap_default_latency[] = { - { - .deactivate_func = omap_device_idle_hwmods, - .activate_func = omap_device_enable_hwmods, - .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, - } -}; - /* Private functions */ -/** - * _omap_device_activate - increase device readiness - * @od: struct omap_device * - * @ignore_lat: increase to latency target (0) or full readiness (1)? - * - * Increase readiness of omap_device @od (thus decreasing device - * wakeup latency, but consuming more power). If @ignore_lat is - * IGNORE_WAKEUP_LAT, make the omap_device fully active. Otherwise, - * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup - * latency is greater than the requested maximum wakeup latency, step - * backwards in the omap_device_pm_latency table to ensure the - * device's maximum wakeup latency is less than or equal to the - * requested maximum wakeup latency. Returns 0. - */ -static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) -{ - struct timespec a, b, c; - - dev_dbg(&od->pdev->dev, "omap_device: activating\n"); - - while (od->pm_lat_level > 0) { - struct omap_device_pm_latency *odpl; - unsigned long long act_lat = 0; - - od->pm_lat_level--; - - odpl = od->pm_lats + od->pm_lat_level; - - if (!ignore_lat && - (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit)) - break; - - read_persistent_clock(&a); - - /* XXX check return code */ - odpl->activate_func(od); - - read_persistent_clock(&b); - - c = timespec_sub(b, a); - act_lat = timespec_to_ns(&c); - - dev_dbg(&od->pdev->dev, - "omap_device: pm_lat %d: activate: elapsed time %llu nsec\n", - od->pm_lat_level, act_lat); - - if (act_lat > odpl->activate_lat) { - odpl->activate_lat_worst = act_lat; - if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { - odpl->activate_lat = act_lat; - dev_dbg(&od->pdev->dev, - "new worst case activate latency %d: %llu\n", - od->pm_lat_level, act_lat); - } else - dev_warn(&od->pdev->dev, - "activate latency %d higher than expected. (%llu > %d)\n", - od->pm_lat_level, act_lat, - odpl->activate_lat); - } - - od->dev_wakeup_lat -= odpl->activate_lat; - } - - return 0; -} - -/** - * _omap_device_deactivate - decrease device readiness - * @od: struct omap_device * - * @ignore_lat: decrease to latency target (0) or full inactivity (1)? - * - * Decrease readiness of omap_device @od (thus increasing device - * wakeup latency, but conserving power). If @ignore_lat is - * IGNORE_WAKEUP_LAT, make the omap_device fully inactive. Otherwise, - * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup - * latency is less than the requested maximum wakeup latency, step - * forwards in the omap_device_pm_latency table to ensure the device's - * maximum wakeup latency is less than or equal to the requested - * maximum wakeup latency. Returns 0. - */ -static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) -{ - struct timespec a, b, c; - - dev_dbg(&od->pdev->dev, "omap_device: deactivating\n"); - - while (od->pm_lat_level < od->pm_lats_cnt) { - struct omap_device_pm_latency *odpl; - unsigned long long deact_lat = 0; - - odpl = od->pm_lats + od->pm_lat_level; - - if (!ignore_lat && - ((od->dev_wakeup_lat + odpl->activate_lat) > - od->_dev_wakeup_lat_limit)) - break; - - read_persistent_clock(&a); - - /* XXX check return code */ - odpl->deactivate_func(od); - - read_persistent_clock(&b); - - c = timespec_sub(b, a); - deact_lat = timespec_to_ns(&c); - - dev_dbg(&od->pdev->dev, - "omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n", - od->pm_lat_level, deact_lat); - - if (deact_lat > odpl->deactivate_lat) { - odpl->deactivate_lat_worst = deact_lat; - if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) { - odpl->deactivate_lat = deact_lat; - dev_dbg(&od->pdev->dev, - "new worst case deactivate latency %d: %llu\n", - od->pm_lat_level, deact_lat); - } else - dev_warn(&od->pdev->dev, - "deactivate latency %d higher than expected. (%llu > %d)\n", - od->pm_lat_level, deact_lat, - odpl->deactivate_lat); - } - - od->dev_wakeup_lat += odpl->activate_lat; - - od->pm_lat_level++; - } - - return 0; -} - static void _add_clkdev(struct omap_device *od, const char *clk_alias, const char *clk_name) { @@ -315,9 +115,6 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od, * @oh: ptr to the single omap_hwmod that backs this omap_device * @pdata: platform_data ptr to associate with the platform_device * @pdata_len: amount of memory pointed to by @pdata - * @pm_lats: pointer to a omap_device_pm_latency array for this device - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats - * @is_early_device: should the device be registered as an early device or not * * Function for building an omap_device already registered from device-tree * @@ -356,7 +153,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) hwmods[i] = oh; } - od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0); + od = omap_device_alloc(pdev, hwmods, oh_cnt); if (!od) { dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n", oh_name); @@ -407,6 +204,39 @@ static int _omap_device_notifier_call(struct notifier_block *nb, return NOTIFY_DONE; } +/** + * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods + * @od: struct omap_device *od + * + * Enable all underlying hwmods. Returns 0. + */ +static int _omap_device_enable_hwmods(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_enable(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} + +/** + * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods + * @od: struct omap_device *od + * + * Idle all underlying hwmods. Returns 0. + */ +static int _omap_device_idle_hwmods(struct omap_device *od) +{ + int i; + + for (i = 0; i < od->hwmods_cnt; i++) + omap_hwmod_idle(od->hwmods[i]); + + /* XXX pass along return value here? */ + return 0; +} /* Public functions for use by core code */ @@ -526,18 +356,14 @@ static int _od_fill_dma_resources(struct omap_device *od, * @oh: ptr to the single omap_hwmod that backs this omap_device * @pdata: platform_data ptr to associate with the platform_device * @pdata_len: amount of memory pointed to by @pdata - * @pm_lats: pointer to a omap_device_pm_latency array for this device - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats * * Convenience function for allocating an omap_device structure and filling - * hwmods, resources and pm_latency attributes. + * hwmods, and resources. * * Returns an struct omap_device pointer or ERR_PTR() on error; */ struct omap_device *omap_device_alloc(struct platform_device *pdev, - struct omap_hwmod **ohs, int oh_cnt, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt) + struct omap_hwmod **ohs, int oh_cnt) { int ret = -ENOMEM; struct omap_device *od; @@ -626,18 +452,6 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, goto oda_exit3; have_everything: - if (!pm_lats) { - pm_lats = omap_default_latency; - pm_lats_cnt = ARRAY_SIZE(omap_default_latency); - } - - od->pm_lats_cnt = pm_lats_cnt; - od->pm_lats = kmemdup(pm_lats, - sizeof(struct omap_device_pm_latency) * pm_lats_cnt, - GFP_KERNEL); - if (!od->pm_lats) - goto oda_exit3; - pdev->archdata.od = od; for (i = 0; i < oh_cnt; i++) { @@ -663,7 +477,6 @@ void omap_device_delete(struct omap_device *od) return; od->pdev->archdata.od = NULL; - kfree(od->pm_lats); kfree(od->hwmods); kfree(od); } @@ -675,9 +488,6 @@ void omap_device_delete(struct omap_device *od) * @oh: ptr to the single omap_hwmod that backs this omap_device * @pdata: platform_data ptr to associate with the platform_device * @pdata_len: amount of memory pointed to by @pdata - * @pm_lats: pointer to a omap_device_pm_latency array for this device - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats - * @is_early_device: should the device be registered as an early device or not * * Convenience function for building and registering a single * omap_device record, which in turn builds and registers a @@ -685,11 +495,10 @@ void omap_device_delete(struct omap_device *od) * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise, * passes along the return value of omap_device_build_ss(). */ -struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id, - struct omap_hwmod *oh, void *pdata, - int pdata_len, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt, int is_early_device) +struct platform_device __init *omap_device_build(const char *pdev_name, + int pdev_id, + struct omap_hwmod *oh, + void *pdata, int pdata_len) { struct omap_hwmod *ohs[] = { oh }; @@ -697,8 +506,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev return ERR_PTR(-EINVAL); return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata, - pdata_len, pm_lats, pm_lats_cnt, - is_early_device); + pdata_len); } /** @@ -708,9 +516,6 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev * @oh: ptr to the single omap_hwmod that backs this omap_device * @pdata: platform_data ptr to associate with the platform_device * @pdata_len: amount of memory pointed to by @pdata - * @pm_lats: pointer to a omap_device_pm_latency array for this device - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats - * @is_early_device: should the device be registered as an early device or not * * Convenience function for building and registering an omap_device * subsystem record. Subsystem records consist of multiple @@ -718,11 +523,11 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev * platform_device record. Returns an ERR_PTR() on error, or passes * along the return value of omap_device_register(). */ -struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id, - struct omap_hwmod **ohs, int oh_cnt, - void *pdata, int pdata_len, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt, int is_early_device) +struct platform_device __init *omap_device_build_ss(const char *pdev_name, + int pdev_id, + struct omap_hwmod **ohs, + int oh_cnt, void *pdata, + int pdata_len) { int ret = -ENOMEM; struct platform_device *pdev; @@ -746,7 +551,7 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name, int p else dev_set_name(&pdev->dev, "%s", pdev->name); - od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt); + od = omap_device_alloc(pdev, ohs, oh_cnt); if (IS_ERR(od)) goto odbs_exit1; @@ -754,10 +559,7 @@ struct platform_device __init *omap_device_build_ss(const char *pdev_name, int p if (ret) goto odbs_exit2; - if (is_early_device) - ret = omap_early_device_register(pdev); - else - ret = omap_device_register(pdev); + ret = omap_device_register(pdev); if (ret) goto odbs_exit2; @@ -774,24 +576,6 @@ odbs_exit: return ERR_PTR(ret); } -/** - * omap_early_device_register - register an omap_device as an early platform - * device. - * @od: struct omap_device * to register - * - * Register the omap_device structure. This currently just calls - * platform_early_add_device() on the underlying platform_device. - * Returns 0 by default. - */ -static int __init omap_early_device_register(struct platform_device *pdev) -{ - struct platform_device *devices[1]; - - devices[0] = pdev; - early_platform_add_devices(devices, 1); - return 0; -} - #ifdef CONFIG_PM_RUNTIME static int _od_runtime_suspend(struct device *dev) { @@ -902,10 +686,9 @@ int omap_device_register(struct platform_device *pdev) * to be accessible and ready to operate. This generally involves * enabling clocks, setting SYSCONFIG registers; and in the future may * involve remuxing pins. Device drivers should call this function - * (through platform_data function pointers) where they would normally - * enable clocks, etc. Returns -EINVAL if called when the omap_device - * is already enabled, or passes along the return value of - * _omap_device_activate(). + * indirectly via pm_runtime_get*(). Returns -EINVAL if called when + * the omap_device is already enabled, or passes along the return + * value of _omap_device_enable_hwmods(). */ int omap_device_enable(struct platform_device *pdev) { @@ -921,14 +704,8 @@ int omap_device_enable(struct platform_device *pdev) return -EINVAL; } - /* Enable everything if we're enabling this device from scratch */ - if (od->_state == OMAP_DEVICE_STATE_UNKNOWN) - od->pm_lat_level = od->pm_lats_cnt; - - ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT); + ret = _omap_device_enable_hwmods(od); - od->dev_wakeup_lat = 0; - od->_dev_wakeup_lat_limit = UINT_MAX; od->_state = OMAP_DEVICE_STATE_ENABLED; return ret; @@ -938,14 +715,10 @@ int omap_device_enable(struct platform_device *pdev) * omap_device_idle - idle an omap_device * @od: struct omap_device * to idle * - * Idle omap_device @od by calling as many .deactivate_func() entries - * in the omap_device's pm_lats table as is possible without exceeding - * the device's maximum wakeup latency limit, pm_lat_limit. Device - * drivers should call this function (through platform_data function - * pointers) where they would normally disable clocks after operations - * complete, etc.. Returns -EINVAL if the omap_device is not + * Idle omap_device @od. Device drivers call this function indirectly + * via pm_runtime_put*(). Returns -EINVAL if the omap_device is not * currently enabled, or passes along the return value of - * _omap_device_deactivate(). + * _omap_device_idle_hwmods(). */ int omap_device_idle(struct platform_device *pdev) { @@ -961,7 +734,7 @@ int omap_device_idle(struct platform_device *pdev) return -EINVAL; } - ret = _omap_device_deactivate(od, USE_WAKEUP_LAT); + ret = _omap_device_idle_hwmods(od); od->_state = OMAP_DEVICE_STATE_IDLE; @@ -969,42 +742,6 @@ int omap_device_idle(struct platform_device *pdev) } /** - * omap_device_shutdown - shut down an omap_device - * @od: struct omap_device * to shut down - * - * Shut down omap_device @od by calling all .deactivate_func() entries - * in the omap_device's pm_lats table and then shutting down all of - * the underlying omap_hwmods. Used when a device is being "removed" - * or a device driver is being unloaded. Returns -EINVAL if the - * omap_device is not currently enabled or idle, or passes along the - * return value of _omap_device_deactivate(). - */ -int omap_device_shutdown(struct platform_device *pdev) -{ - int ret, i; - struct omap_device *od; - - od = to_omap_device(pdev); - - if (od->_state != OMAP_DEVICE_STATE_ENABLED && - od->_state != OMAP_DEVICE_STATE_IDLE) { - dev_warn(&pdev->dev, - "omap_device: %s() called from invalid state %d\n", - __func__, od->_state); - return -EINVAL; - } - - ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT); - - for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_shutdown(od->hwmods[i]); - - od->_state = OMAP_DEVICE_STATE_SHUTDOWN; - - return ret; -} - -/** * omap_device_assert_hardreset - set a device's hardreset line * @pdev: struct platform_device * to reset * @name: const char * name of the reset line @@ -1060,86 +797,6 @@ int omap_device_deassert_hardreset(struct platform_device *pdev, } /** - * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim - * @od: struct omap_device * - * - * When a device's maximum wakeup latency limit changes, call some of - * the .activate_func or .deactivate_func function pointers in the - * omap_device's pm_lats array to ensure that the device's maximum - * wakeup latency is less than or equal to the new latency limit. - * Intended to be called by OMAP PM code whenever a device's maximum - * wakeup latency limit changes (e.g., via - * omap_pm_set_dev_wakeup_lat()). Returns 0 if nothing needs to be - * done (e.g., if the omap_device is not currently idle, or if the - * wakeup latency is already current with the new limit) or passes - * along the return value of _omap_device_deactivate() or - * _omap_device_activate(). - */ -int omap_device_align_pm_lat(struct platform_device *pdev, - u32 new_wakeup_lat_limit) -{ - int ret = -EINVAL; - struct omap_device *od; - - od = to_omap_device(pdev); - - if (new_wakeup_lat_limit == od->dev_wakeup_lat) - return 0; - - od->_dev_wakeup_lat_limit = new_wakeup_lat_limit; - - if (od->_state != OMAP_DEVICE_STATE_IDLE) - return 0; - else if (new_wakeup_lat_limit > od->dev_wakeup_lat) - ret = _omap_device_deactivate(od, USE_WAKEUP_LAT); - else if (new_wakeup_lat_limit < od->dev_wakeup_lat) - ret = _omap_device_activate(od, USE_WAKEUP_LAT); - - return ret; -} - -/** - * omap_device_get_pwrdm - return the powerdomain * associated with @od - * @od: struct omap_device * - * - * Return the powerdomain associated with the first underlying - * omap_hwmod for this omap_device. Intended for use by core OMAP PM - * code. Returns NULL on error or a struct powerdomain * upon - * success. - */ -struct powerdomain *omap_device_get_pwrdm(struct omap_device *od) -{ - /* - * XXX Assumes that all omap_hwmod powerdomains are identical. - * This may not necessarily be true. There should be a sanity - * check in here to WARN() if any difference appears. - */ - if (!od->hwmods_cnt) - return NULL; - - return omap_hwmod_get_pwrdm(od->hwmods[0]); -} - -/** - * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base - * @od: struct omap_device * - * - * Return the MPU's virtual address for the base of the hwmod, from - * the ioremap() that the hwmod code does. Only valid if there is one - * hwmod associated with this device. Returns NULL if there are zero - * or more than one hwmods associated with this omap_device; - * otherwise, passes along the return value from - * omap_hwmod_get_mpu_rt_va(). - */ -void __iomem *omap_device_get_rt_va(struct omap_device *od) -{ - if (od->hwmods_cnt != 1) - return NULL; - - return omap_hwmod_get_mpu_rt_va(od->hwmods[0]); -} - -/** * omap_device_get_by_hwmod_name() - convert a hwmod name to * device pointer. * @oh_name: name of the hwmod device @@ -1173,82 +830,6 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name) return &oh->od->pdev->dev; } -EXPORT_SYMBOL(omap_device_get_by_hwmod_name); - -/* - * Public functions intended for use in omap_device_pm_latency - * .activate_func and .deactivate_func function pointers - */ - -/** - * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods - * @od: struct omap_device *od - * - * Enable all underlying hwmods. Returns 0. - */ -int omap_device_enable_hwmods(struct omap_device *od) -{ - int i; - - for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_enable(od->hwmods[i]); - - /* XXX pass along return value here? */ - return 0; -} - -/** - * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods - * @od: struct omap_device *od - * - * Idle all underlying hwmods. Returns 0. - */ -int omap_device_idle_hwmods(struct omap_device *od) -{ - int i; - - for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_idle(od->hwmods[i]); - - /* XXX pass along return value here? */ - return 0; -} - -/** - * omap_device_disable_clocks - disable all main and interface clocks - * @od: struct omap_device *od - * - * Disable the main functional clock and interface clock for all of the - * omap_hwmods associated with the omap_device. Returns 0. - */ -int omap_device_disable_clocks(struct omap_device *od) -{ - int i; - - for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_disable_clocks(od->hwmods[i]); - - /* XXX pass along return value here? */ - return 0; -} - -/** - * omap_device_enable_clocks - enable all main and interface clocks - * @od: struct omap_device *od - * - * Enable the main functional clock and interface clock for all of the - * omap_hwmods associated with the omap_device. Returns 0. - */ -int omap_device_enable_clocks(struct omap_device *od) -{ - int i; - - for (i = 0; i < od->hwmods_cnt; i++) - omap_hwmod_enable_clocks(od->hwmods[i]); - - /* XXX pass along return value here? */ - return 0; -} static struct notifier_block platform_nb = { .notifier_call = _omap_device_notifier_call, diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h index 0933c59..044c31d 100644 --- a/arch/arm/mach-omap2/omap_device.h +++ b/arch/arm/mach-omap2/omap_device.h @@ -13,20 +13,12 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Eventually this type of functionality should either be - * a) implemented via arch-specific pointers in platform_device - * or - * b) implemented as a proper omap_bus/omap_device in Linux, no more - * platform_device + * This type of functionality should be implemented as a proper + * omap_bus/omap_device in Linux. * * omap_device differs from omap_hwmod in that it includes external * (e.g., board- and system-level) integration details. omap_hwmod * stores hardware data that is invariant for a given OMAP chip. - * - * To do: - * - GPIO integration - * - regulator integration - * */ #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H @@ -45,19 +37,14 @@ extern struct dev_pm_domain omap_device_pm_domain; #define OMAP_DEVICE_STATE_SHUTDOWN 3 /* omap_device.flags values */ -#define OMAP_DEVICE_SUSPENDED BIT(0) -#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1) +#define OMAP_DEVICE_SUSPENDED BIT(0) +#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1) /** * struct omap_device - omap_device wrapper for platform_devices * @pdev: platform_device * @hwmods: (one .. many per omap_device) * @hwmods_cnt: ARRAY_SIZE() of @hwmods - * @pm_lats: ptr to an omap_device_pm_latency table - * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats - * @pm_lat_level: array index of the last odpl entry executed - -1 if never - * @dev_wakeup_lat: dev wakeup latency in nanoseconds - * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM * @_state: one of OMAP_DEVICE_STATE_* (see above) * @flags: device flags * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h> @@ -71,12 +58,7 @@ extern struct dev_pm_domain omap_device_pm_domain; struct omap_device { struct platform_device *pdev; struct omap_hwmod **hwmods; - struct omap_device_pm_latency *pm_lats; - u32 dev_wakeup_lat; - u32 _dev_wakeup_lat_limit; unsigned long _driver_status; - u8 pm_lats_cnt; - s8 pm_lat_level; u8 hwmods_cnt; u8 _state; u8 flags; @@ -86,36 +68,25 @@ struct omap_device { int omap_device_enable(struct platform_device *pdev); int omap_device_idle(struct platform_device *pdev); -int omap_device_shutdown(struct platform_device *pdev); /* Core code interface */ struct platform_device *omap_device_build(const char *pdev_name, int pdev_id, - struct omap_hwmod *oh, void *pdata, - int pdata_len, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt, int is_early_device); + struct omap_hwmod *oh, void *pdata, + int pdata_len); struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, struct omap_hwmod **oh, int oh_cnt, - void *pdata, int pdata_len, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt, int is_early_device); + void *pdata, int pdata_len); struct omap_device *omap_device_alloc(struct platform_device *pdev, - struct omap_hwmod **ohs, int oh_cnt, - struct omap_device_pm_latency *pm_lats, - int pm_lats_cnt); + struct omap_hwmod **ohs, int oh_cnt); void omap_device_delete(struct omap_device *od); int omap_device_register(struct platform_device *pdev); -void __iomem *omap_device_get_rt_va(struct omap_device *od); struct device *omap_device_get_by_hwmod_name(const char *oh_name); /* OMAP PM interface */ -int omap_device_align_pm_lat(struct platform_device *pdev, - u32 new_wakeup_lat_limit); -struct powerdomain *omap_device_get_pwrdm(struct omap_device *od); int omap_device_get_context_loss_count(struct platform_device *pdev); /* Other */ @@ -124,40 +95,6 @@ int omap_device_assert_hardreset(struct platform_device *pdev, const char *name); int omap_device_deassert_hardreset(struct platform_device *pdev, const char *name); -int omap_device_idle_hwmods(struct omap_device *od); -int omap_device_enable_hwmods(struct omap_device *od); - -int omap_device_disable_clocks(struct omap_device *od); -int omap_device_enable_clocks(struct omap_device *od); - -/* - * Entries should be kept in latency order ascending - * - * deact_lat is the maximum number of microseconds required to complete - * deactivate_func() at the device's slowest OPP. - * - * act_lat is the maximum number of microseconds required to complete - * activate_func() at the device's slowest OPP. - * - * This will result in some suboptimal power management decisions at fast - * OPPs, but avoids having to recompute all device power management decisions - * if the system shifts from a fast OPP to a slow OPP (in order to meet - * latency requirements). - * - * XXX should deactivate_func/activate_func() take platform_device pointers - * rather than omap_device pointers? - */ -struct omap_device_pm_latency { - u32 deactivate_lat; - u32 deactivate_lat_worst; - int (*deactivate_func)(struct omap_device *od); - u32 activate_lat; - u32 activate_lat_worst; - int (*activate_func)(struct omap_device *od); - u32 flags; -}; - -#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1) /* Get omap_device pointer from platform_device pointer */ static inline struct omap_device *to_omap_device(struct platform_device *pdev) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 4653efb..6804d47 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -139,6 +139,8 @@ #include <linux/slab.h> #include <linux/bootmem.h> +#include <asm/system_misc.h> + #include "clock.h" #include "omap_hwmod.h" @@ -2134,6 +2136,8 @@ static int _enable(struct omap_hwmod *oh) _enable_clocks(oh); if (soc_ops.enable_module) soc_ops.enable_module(oh); + if (oh->flags & HWMOD_BLOCK_WFI) + disable_hlt(); if (soc_ops.update_context_lost) soc_ops.update_context_lost(oh); @@ -2195,6 +2199,8 @@ static int _idle(struct omap_hwmod *oh) _idle_sysc(oh); _del_initiator_dep(oh, mpu_oh); + if (oh->flags & HWMOD_BLOCK_WFI) + enable_hlt(); if (soc_ops.disable_module) soc_ops.disable_module(oh); @@ -2303,6 +2309,8 @@ static int _shutdown(struct omap_hwmod *oh) if (oh->_state == _HWMOD_STATE_ENABLED) { _del_initiator_dep(oh, mpu_oh); /* XXX what about the other system initiators here? dma, dsp */ + if (oh->flags & HWMOD_BLOCK_WFI) + enable_hlt(); if (soc_ops.disable_module) soc_ops.disable_module(oh); _disable_clocks(oh); diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 3ae852a..80c00e7 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -451,6 +451,14 @@ struct omap_hwmod_omap4_prcm { * enabled. This prevents the hwmod code from being able to * enable and reset the IP block early. XXX Eventually it should * be possible to query the clock framework for this information. + * HWMOD_BLOCK_WFI: Some OMAP peripherals apparently don't work + * correctly if the MPU is allowed to go idle while the + * peripherals are active. This is apparently true for the I2C on + * OMAP2420, and also the EMAC on AM3517/3505. It's unlikely that + * this is really true -- we're probably not configuring something + * correctly, or this is being abused to deal with some PM latency + * issues -- but we're currently suffering from a shortage of + * folks who are able to track these issues down properly. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -462,6 +470,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7) #define HWMOD_16BIT_REG (1 << 8) #define HWMOD_EXT_OPT_MAIN_CLK (1 << 9) +#define HWMOD_BLOCK_WFI (1 << 10) /* * omap_hwmod._int_flags definitions diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index b5efe58..6a764af 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -121,7 +121,12 @@ static struct omap_hwmod omap2420_i2c1_hwmod = { }, .class = &i2c_class, .dev_attr = &i2c_dev_attr, - .flags = HWMOD_16BIT_REG, + /* + * From mach-omap2/pm24xx.c: "Putting MPU into the WFI state + * while a transfer is active seems to cause the I2C block to + * timeout. Why? Good question." + */ + .flags = (HWMOD_16BIT_REG | HWMOD_BLOCK_WFI), }; /* I2C2 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 793f54a..a1849a8 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -616,7 +616,7 @@ static struct omap_hwmod omap44xx_dmic_hwmod = { .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_dmic_irqs, .sdma_reqs = omap44xx_dmic_sdma_reqs, - .main_clk = "dmic_fck", + .main_clk = "func_dmic_abe_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET, @@ -1161,7 +1161,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = { .class = &omap44xx_gpio_hwmod_class, .clkdm_name = "l4_wkup_clkdm", .mpu_irqs = omap44xx_gpio1_irqs, - .main_clk = "gpio1_ick", + .main_clk = "l4_wkup_clk_mux_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET, @@ -1190,7 +1190,7 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_gpio2_irqs, - .main_clk = "gpio2_ick", + .main_clk = "l4_div_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET, @@ -1219,7 +1219,7 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_gpio3_irqs, - .main_clk = "gpio3_ick", + .main_clk = "l4_div_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET, @@ -1248,7 +1248,7 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_gpio4_irqs, - .main_clk = "gpio4_ick", + .main_clk = "l4_div_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET, @@ -1277,7 +1277,7 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_gpio5_irqs, - .main_clk = "gpio5_ick", + .main_clk = "l4_div_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET, @@ -1306,7 +1306,7 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_gpio6_irqs, - .main_clk = "gpio6_ick", + .main_clk = "l4_div_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET, @@ -1405,7 +1405,7 @@ static struct omap_hwmod omap44xx_gpu_hwmod = { .class = &omap44xx_gpu_hwmod_class, .clkdm_name = "l3_gfx_clkdm", .mpu_irqs = omap44xx_gpu_irqs, - .main_clk = "gpu_fck", + .main_clk = "sgx_clk_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET, @@ -1446,7 +1446,7 @@ static struct omap_hwmod omap44xx_hdq1w_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_INIT_NO_RESET, /* XXX temporary */ .mpu_irqs = omap44xx_hdq1w_irqs, - .main_clk = "hdq1w_fck", + .main_clk = "func_12m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET, @@ -1550,7 +1550,7 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = { .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c1_irqs, .sdma_reqs = omap44xx_i2c1_sdma_reqs, - .main_clk = "i2c1_fck", + .main_clk = "func_96m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET, @@ -1580,7 +1580,7 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = { .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c2_irqs, .sdma_reqs = omap44xx_i2c2_sdma_reqs, - .main_clk = "i2c2_fck", + .main_clk = "func_96m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET, @@ -1610,7 +1610,7 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = { .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c3_irqs, .sdma_reqs = omap44xx_i2c3_sdma_reqs, - .main_clk = "i2c3_fck", + .main_clk = "func_96m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET, @@ -1640,7 +1640,7 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = { .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c4_irqs, .sdma_reqs = omap44xx_i2c4_sdma_reqs, - .main_clk = "i2c4_fck", + .main_clk = "func_96m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET, @@ -1743,7 +1743,7 @@ static struct omap_hwmod omap44xx_iss_hwmod = { .clkdm_name = "iss_clkdm", .mpu_irqs = omap44xx_iss_irqs, .sdma_reqs = omap44xx_iss_sdma_reqs, - .main_clk = "iss_fck", + .main_clk = "ducati_clk_mux_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET, @@ -1785,7 +1785,7 @@ static struct omap_hwmod omap44xx_iva_hwmod = { .mpu_irqs = omap44xx_iva_irqs, .rst_lines = omap44xx_iva_resets, .rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_resets), - .main_clk = "iva_fck", + .main_clk = "dpll_iva_m5x2_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET, @@ -1829,7 +1829,7 @@ static struct omap_hwmod omap44xx_kbd_hwmod = { .class = &omap44xx_kbd_hwmod_class, .clkdm_name = "l4_wkup_clkdm", .mpu_irqs = omap44xx_kbd_irqs, - .main_clk = "kbd_fck", + .main_clk = "sys_32k_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET, @@ -1920,7 +1920,7 @@ static struct omap_hwmod omap44xx_mcasp_hwmod = { .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_mcasp_irqs, .sdma_reqs = omap44xx_mcasp_sdma_reqs, - .main_clk = "mcasp_fck", + .main_clk = "func_mcasp_abe_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET, @@ -1972,7 +1972,7 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = { .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_mcbsp1_irqs, .sdma_reqs = omap44xx_mcbsp1_sdma_reqs, - .main_clk = "mcbsp1_fck", + .main_clk = "func_mcbsp1_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET, @@ -2007,7 +2007,7 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = { .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_mcbsp2_irqs, .sdma_reqs = omap44xx_mcbsp2_sdma_reqs, - .main_clk = "mcbsp2_fck", + .main_clk = "func_mcbsp2_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET, @@ -2042,7 +2042,7 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = { .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_mcbsp3_irqs, .sdma_reqs = omap44xx_mcbsp3_sdma_reqs, - .main_clk = "mcbsp3_fck", + .main_clk = "func_mcbsp3_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET, @@ -2077,7 +2077,7 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mcbsp4_irqs, .sdma_reqs = omap44xx_mcbsp4_sdma_reqs, - .main_clk = "mcbsp4_fck", + .main_clk = "per_mcbsp4_gfclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET, @@ -2140,7 +2140,7 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = { .flags = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE, .mpu_irqs = omap44xx_mcpdm_irqs, .sdma_reqs = omap44xx_mcpdm_sdma_reqs, - .main_clk = "mcpdm_fck", + .main_clk = "pad_clks_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET, @@ -2201,7 +2201,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mcspi1_irqs, .sdma_reqs = omap44xx_mcspi1_sdma_reqs, - .main_clk = "mcspi1_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET, @@ -2237,7 +2237,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mcspi2_irqs, .sdma_reqs = omap44xx_mcspi2_sdma_reqs, - .main_clk = "mcspi2_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET, @@ -2273,7 +2273,7 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mcspi3_irqs, .sdma_reqs = omap44xx_mcspi3_sdma_reqs, - .main_clk = "mcspi3_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET, @@ -2307,7 +2307,7 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mcspi4_irqs, .sdma_reqs = omap44xx_mcspi4_sdma_reqs, - .main_clk = "mcspi4_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET, @@ -2363,7 +2363,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = { .clkdm_name = "l3_init_clkdm", .mpu_irqs = omap44xx_mmc1_irqs, .sdma_reqs = omap44xx_mmc1_sdma_reqs, - .main_clk = "mmc1_fck", + .main_clk = "hsmmc1_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET, @@ -2392,7 +2392,7 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = { .clkdm_name = "l3_init_clkdm", .mpu_irqs = omap44xx_mmc2_irqs, .sdma_reqs = omap44xx_mmc2_sdma_reqs, - .main_clk = "mmc2_fck", + .main_clk = "hsmmc2_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET, @@ -2420,7 +2420,7 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mmc3_irqs, .sdma_reqs = omap44xx_mmc3_sdma_reqs, - .main_clk = "mmc3_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET, @@ -2448,7 +2448,7 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mmc4_irqs, .sdma_reqs = omap44xx_mmc4_sdma_reqs, - .main_clk = "mmc4_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET, @@ -2476,7 +2476,7 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_mmc5_irqs, .sdma_reqs = omap44xx_mmc5_sdma_reqs, - .main_clk = "mmc5_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET, @@ -2725,7 +2725,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { .name = "ocp2scp_usb_phy", .class = &omap44xx_ocp2scp_hwmod_class, .clkdm_name = "l3_init_clkdm", - .main_clk = "ocp2scp_usb_phy_phy_48m", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET, @@ -3162,7 +3162,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = { .clkdm_name = "l4_wkup_clkdm", .flags = HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_timer1_irqs, - .main_clk = "timer1_fck", + .main_clk = "dmt1_clk_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET, @@ -3185,7 +3185,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_timer2_irqs, - .main_clk = "timer2_fck", + .main_clk = "cm2_dm2_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET, @@ -3206,7 +3206,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_timer3_irqs, - .main_clk = "timer3_fck", + .main_clk = "cm2_dm3_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET, @@ -3227,7 +3227,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_timer4_irqs, - .main_clk = "timer4_fck", + .main_clk = "cm2_dm4_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET, @@ -3248,7 +3248,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_timer5_irqs, - .main_clk = "timer5_fck", + .main_clk = "timer5_sync_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET, @@ -3270,8 +3270,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_timer6_irqs, - - .main_clk = "timer6_fck", + .main_clk = "timer6_sync_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET, @@ -3293,7 +3292,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_timer7_irqs, - .main_clk = "timer7_fck", + .main_clk = "timer7_sync_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET, @@ -3315,7 +3314,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_timer8_irqs, - .main_clk = "timer8_fck", + .main_clk = "timer8_sync_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET, @@ -3337,7 +3336,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_timer9_irqs, - .main_clk = "timer9_fck", + .main_clk = "cm2_dm9_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET, @@ -3360,7 +3359,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = { .clkdm_name = "l4_per_clkdm", .flags = HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_timer10_irqs, - .main_clk = "timer10_fck", + .main_clk = "cm2_dm10_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET, @@ -3382,7 +3381,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = { .class = &omap44xx_timer_hwmod_class, .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_timer11_irqs, - .main_clk = "timer11_fck", + .main_clk = "cm2_dm11_mux", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET, @@ -3433,7 +3432,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_uart1_irqs, .sdma_reqs = omap44xx_uart1_sdma_reqs, - .main_clk = "uart1_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET, @@ -3461,7 +3460,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_uart2_irqs, .sdma_reqs = omap44xx_uart2_sdma_reqs, - .main_clk = "uart2_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET, @@ -3490,7 +3489,7 @@ static struct omap_hwmod omap44xx_uart3_hwmod = { .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, .mpu_irqs = omap44xx_uart3_irqs, .sdma_reqs = omap44xx_uart3_sdma_reqs, - .main_clk = "uart3_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET, @@ -3518,7 +3517,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = { .clkdm_name = "l4_per_clkdm", .mpu_irqs = omap44xx_uart4_irqs, .sdma_reqs = omap44xx_uart4_sdma_reqs, - .main_clk = "uart4_fck", + .main_clk = "func_48m_fclk", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET, @@ -3797,7 +3796,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = { .class = &omap44xx_wd_timer_hwmod_class, .clkdm_name = "l4_wkup_clkdm", .mpu_irqs = omap44xx_wd_timer2_irqs, - .main_clk = "wd_timer2_fck", + .main_clk = "sys_32k_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET, @@ -3818,7 +3817,7 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { .class = &omap44xx_wd_timer_hwmod_class, .clkdm_name = "abe_clkdm", .mpu_irqs = omap44xx_wd_timer3_irqs, - .main_clk = "wd_timer3_fck", + .main_clk = "sys_32k_ck", .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET, diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index e2c291f..6db89ae 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -83,10 +83,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) strncmp(clkdm->name, "dpll", 4) == 0) return 0; - seq_printf(s, "%s->%s (%d)", clkdm->name, - clkdm->pwrdm.ptr->name, - atomic_read(&clkdm->usecount)); - seq_printf(s, "\n"); + seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name, + clkdm->usecount); return 0; } diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index f4b3143..9a9be3c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -32,8 +32,6 @@ #include "pm.h" #include "twl-common.h" -static struct omap_device_pm_latency *pm_lats; - /* * omap_pm_suspend: points to a function that does the SoC-specific * suspend work @@ -82,7 +80,7 @@ static int __init _init_omap_device(char *name) __func__, name)) return -ENODEV; - pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false); + pdev = omap_device_build(oh->name, 0, oh, NULL, 0); if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n", __func__, name)) return -ENODEV; @@ -108,80 +106,19 @@ static void __init omap2_init_processor_devices(void) } } -/* Types of sleep_switch used in omap_set_pwrdm_state */ -#define FORCEWAKEUP_SWITCH 0 -#define LOWPOWERSTATE_SWITCH 1 - int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) { + /* XXX The usecount test is racy */ if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) && !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)) clkdm_allow_idle(clkdm); else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && - atomic_read(&clkdm->usecount) == 0) + clkdm->usecount == 0) clkdm_sleep(clkdm); return 0; } /* - * This sets pwrdm state (other than mpu & core. Currently only ON & - * RET are supported. - */ -int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst) -{ - u8 curr_pwrst, next_pwrst; - int sleep_switch = -1, ret = 0, hwsup = 0; - - if (!pwrdm || IS_ERR(pwrdm)) - return -EINVAL; - - while (!(pwrdm->pwrsts & (1 << pwrst))) { - if (pwrst == PWRDM_POWER_OFF) - return ret; - pwrst--; - } - - next_pwrst = pwrdm_read_next_pwrst(pwrdm); - if (next_pwrst == pwrst) - return ret; - - curr_pwrst = pwrdm_read_pwrst(pwrdm); - if (curr_pwrst < PWRDM_POWER_ON) { - if ((curr_pwrst > pwrst) && - (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { - sleep_switch = LOWPOWERSTATE_SWITCH; - } else { - hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); - clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); - sleep_switch = FORCEWAKEUP_SWITCH; - } - } - - ret = pwrdm_set_next_pwrst(pwrdm, pwrst); - if (ret) - pr_err("%s: unable to set power state of powerdomain: %s\n", - __func__, pwrdm->name); - - switch (sleep_switch) { - case FORCEWAKEUP_SWITCH: - if (hwsup) - clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); - else - clkdm_sleep(pwrdm->pwrdm_clkdms[0]); - break; - case LOWPOWERSTATE_SWITCH: - pwrdm_set_lowpwrstchange(pwrdm); - pwrdm_wait_transition(pwrdm); - pwrdm_state_switch(pwrdm); - break; - } - - return ret; -} - - - -/* * This API is to be called during init to set the various voltage * domains to the voltage as per the opp table. Typically we boot up * at the nominal voltage. So this function finds out the rate of diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index c22503b..7bdd22a 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -33,7 +33,6 @@ static inline int omap4_idle_init(void) extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); extern void omap_sram_idle(void); -extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused); extern int (*omap_pm_suspend)(void); diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index c333fa6..b2a4df6 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -90,11 +90,7 @@ static int omap2_enter_full_retention(void) omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST); - /* - * Set MPU powerdomain's next power state to RETENTION; - * preserve logic state during retention - */ - pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); + pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); /* Workaround to kill USB */ @@ -137,15 +133,10 @@ no_sleep: /* Mask future PRCM-to-MPU interrupts */ omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); - return 0; -} - -static int omap2_i2c_active(void) -{ - u32 l; + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); + pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON); - l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); - return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK); + return 0; } static int sti_console_enabled; @@ -172,11 +163,6 @@ static int omap2_allow_mpu_retention(void) static void omap2_enter_mpu_retention(void) { - /* Putting MPU into the WFI state while a transfer is active - * seems to cause the I2C block to timeout. Why? Good question. */ - if (omap2_i2c_active()) - return; - /* The peripherals seem not to be able to wake up the MPU when * it is in retention mode. */ if (omap2_allow_mpu_retention()) { @@ -186,17 +172,16 @@ static void omap2_enter_mpu_retention(void) omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST); /* Try to enter MPU retention */ - omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) | - OMAP_LOGICRETSTATE_MASK, - MPU_MOD, OMAP2_PM_PWSTCTRL); + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); + } else { /* Block MPU retention */ - - omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD, - OMAP2_PM_PWSTCTRL); + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); } omap2_sram_idle(); + + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); } static int omap2_can_sleep(void) @@ -251,25 +236,17 @@ static void __init prcm_setup_regs(void) for (i = 0; i < num_mem_banks; i++) pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); - /* Set CORE powerdomain's next power state to RETENTION */ - pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); + pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET); - /* - * Set MPU powerdomain's next power state to RETENTION; - * preserve logic state during retention - */ pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); - pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); /* Force-power down DSP, GFX powerdomains */ pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); - clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); - clkdm_sleep(gfx_clkdm); /* Enable hardware-supervised idle for all clkdms */ clkdm_for_each(omap_pm_clkdms_setup, NULL); diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index eb78ae7..0ef4d6a 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -48,8 +48,7 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[]) } } - omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0, - NULL, 0, 0); + omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0); WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n", dev_name); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index dea62a9..8e61d80 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -19,6 +19,7 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/string.h> +#include <linux/spinlock.h> #include <trace/events/power.h> #include "cm2xxx_3xxx.h" @@ -42,6 +43,16 @@ enum { PWRDM_STATE_PREV, }; +/* + * Types of sleep_switch used internally in omap_set_pwrdm_state() + * and its associated static functions + * + * XXX Better documentation is needed here + */ +#define ALREADYACTIVE_SWITCH 0 +#define FORCEWAKEUP_SWITCH 1 +#define LOWPOWERSTATE_SWITCH 2 +#define ERROR_SWITCH 3 /* pwrdm_list contains all registered struct powerdomains */ static LIST_HEAD(pwrdm_list); @@ -101,6 +112,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm) pwrdm->voltdm.ptr = voltdm; INIT_LIST_HEAD(&pwrdm->voltdm_node); voltdm_add_pwrdm(voltdm, pwrdm); + spin_lock_init(&pwrdm->_lock); list_add(&pwrdm->node, &pwrdm_list); @@ -112,7 +124,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm) for (i = 0; i < pwrdm->banks; i++) pwrdm->ret_mem_off_counter[i] = 0; - pwrdm_wait_transition(pwrdm); + arch_pwrdm->pwrdm_wait_transition(pwrdm); pwrdm->state = pwrdm_read_pwrst(pwrdm); pwrdm->state_counter[pwrdm->state] = 1; @@ -143,7 +155,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm) static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) { - int prev, state, trace_state = 0; + int prev, next, state, trace_state = 0; if (pwrdm == NULL) return -EINVAL; @@ -164,9 +176,10 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) * If the power domain did not hit the desired state, * generate a trace event with both the desired and hit states */ - if (state != prev) { + next = pwrdm_read_next_pwrst(pwrdm); + if (next != prev) { trace_state = (PWRDM_TRACE_STATES_FLAG | - ((state & OMAP_POWERSTATE_MASK) << 8) | + ((next & OMAP_POWERSTATE_MASK) << 8) | ((prev & OMAP_POWERSTATE_MASK) << 0)); trace_power_domain_target(pwrdm->name, trace_state, smp_processor_id()); @@ -199,6 +212,80 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) return 0; } +/** + * _pwrdm_save_clkdm_state_and_activate - prepare for power state change + * @pwrdm: struct powerdomain * to operate on + * @curr_pwrst: current power state of @pwrdm + * @pwrst: power state to switch to + * @hwsup: ptr to a bool to return whether the clkdm is hardware-supervised + * + * Determine whether the powerdomain needs to be turned on before + * attempting to switch power states. Called by + * omap_set_pwrdm_state(). NOTE that if the powerdomain contains + * multiple clockdomains, this code assumes that the first clockdomain + * supports software-supervised wakeup mode - potentially a problem. + * Returns the power state switch mode currently in use (see the + * "Types of sleep_switch" comment above). + */ +static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm, + u8 curr_pwrst, u8 pwrst, + bool *hwsup) +{ + u8 sleep_switch; + + if (curr_pwrst < 0) { + WARN_ON(1); + sleep_switch = ERROR_SWITCH; + } else if (curr_pwrst < PWRDM_POWER_ON) { + if (curr_pwrst > pwrst && + pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE && + arch_pwrdm->pwrdm_set_lowpwrstchange) { + sleep_switch = LOWPOWERSTATE_SWITCH; + } else { + *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); + clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]); + sleep_switch = FORCEWAKEUP_SWITCH; + } + } else { + sleep_switch = ALREADYACTIVE_SWITCH; + } + + return sleep_switch; +} + +/** + * _pwrdm_restore_clkdm_state - restore the clkdm hwsup state after pwrst change + * @pwrdm: struct powerdomain * to operate on + * @sleep_switch: return value from _pwrdm_save_clkdm_state_and_activate() + * @hwsup: should @pwrdm's first clockdomain be set to hardware-supervised mode? + * + * Restore the clockdomain state perturbed by + * _pwrdm_save_clkdm_state_and_activate(), and call the power state + * bookkeeping code. Called by omap_set_pwrdm_state(). NOTE that if + * the powerdomain contains multiple clockdomains, this assumes that + * the first associated clockdomain supports either + * hardware-supervised idle control in the register, or + * software-supervised sleep. No return value. + */ +static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm, + u8 sleep_switch, bool hwsup) +{ + switch (sleep_switch) { + case FORCEWAKEUP_SWITCH: + if (hwsup) + clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]); + else + clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]); + break; + case LOWPOWERSTATE_SWITCH: + if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE && + arch_pwrdm->pwrdm_set_lowpwrstchange) + arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); + pwrdm_state_switch_nolock(pwrdm); + break; + } +} + /* Public functions */ /** @@ -275,6 +362,30 @@ int pwrdm_complete_init(void) } /** + * pwrdm_lock - acquire a Linux spinlock on a powerdomain + * @pwrdm: struct powerdomain * to lock + * + * Acquire the powerdomain spinlock on @pwrdm. No return value. + */ +void pwrdm_lock(struct powerdomain *pwrdm) + __acquires(&pwrdm->_lock) +{ + spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags); +} + +/** + * pwrdm_unlock - release a Linux spinlock on a powerdomain + * @pwrdm: struct powerdomain * to unlock + * + * Release the powerdomain spinlock on @pwrdm. No return value. + */ +void pwrdm_unlock(struct powerdomain *pwrdm) + __releases(&pwrdm->_lock) +{ + spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags); +} + +/** * pwrdm_lookup - look up a powerdomain by name, return a pointer * @name: name of powerdomain * @@ -920,65 +1031,27 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0; } -/** - * pwrdm_set_lowpwrstchange - Request a low power state change - * @pwrdm: struct powerdomain * - * - * Allows a powerdomain to transtion to a lower power sleep state - * from an existing sleep state without waking up the powerdomain. - * Returns -EINVAL if the powerdomain pointer is null or if the - * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0 - * upon success. - */ -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) -{ - int ret = -EINVAL; - - if (!pwrdm) - return -EINVAL; - - if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) - return -EINVAL; - - pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", - pwrdm->name); - - if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange) - ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); - - return ret; -} - -/** - * pwrdm_wait_transition - wait for powerdomain power transition to finish - * @pwrdm: struct powerdomain * to wait for - * - * If the powerdomain @pwrdm is in the process of a state transition, - * spin until it completes the power transition, or until an iteration - * bailout value is reached. Returns -EINVAL if the powerdomain - * pointer is null, -EAGAIN if the bailout value was reached, or - * returns 0 upon success. - */ -int pwrdm_wait_transition(struct powerdomain *pwrdm) +int pwrdm_state_switch_nolock(struct powerdomain *pwrdm) { - int ret = -EINVAL; + int ret; - if (!pwrdm) + if (!pwrdm || !arch_pwrdm) return -EINVAL; - if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition) - ret = arch_pwrdm->pwrdm_wait_transition(pwrdm); + ret = arch_pwrdm->pwrdm_wait_transition(pwrdm); + if (!ret) + ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); return ret; } -int pwrdm_state_switch(struct powerdomain *pwrdm) +int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm) { int ret; - ret = pwrdm_wait_transition(pwrdm); - if (!ret) - ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); + pwrdm_lock(pwrdm); + ret = pwrdm_state_switch_nolock(pwrdm); + pwrdm_unlock(pwrdm); return ret; } @@ -1004,6 +1077,61 @@ int pwrdm_post_transition(struct powerdomain *pwrdm) } /** + * omap_set_pwrdm_state - change a powerdomain's current power state + * @pwrdm: struct powerdomain * to change the power state of + * @pwrst: power state to change to + * + * Change the current hardware power state of the powerdomain + * represented by @pwrdm to the power state represented by @pwrst. + * Returns -EINVAL if @pwrdm is null or invalid or if the + * powerdomain's current power state could not be read, or returns 0 + * upon success or if @pwrdm does not support @pwrst or any + * lower-power state. XXX Should not return 0 if the @pwrdm does not + * support @pwrst or any lower-power state: this should be an error. + */ +int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst) +{ + u8 curr_pwrst, next_pwrst, sleep_switch; + int ret = 0; + bool hwsup = false; + + if (!pwrdm || IS_ERR(pwrdm)) + return -EINVAL; + + while (!(pwrdm->pwrsts & (1 << pwrst))) { + if (pwrst == PWRDM_POWER_OFF) + return ret; + pwrst--; + } + + pwrdm_lock(pwrdm); + + curr_pwrst = pwrdm_read_pwrst(pwrdm); + next_pwrst = pwrdm_read_next_pwrst(pwrdm); + if (curr_pwrst == pwrst && next_pwrst == pwrst) + goto osps_out; + + sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst, + pwrst, &hwsup); + if (sleep_switch == ERROR_SWITCH) { + ret = -EINVAL; + goto osps_out; + } + + ret = pwrdm_set_next_pwrst(pwrdm, pwrst); + if (ret) + pr_err("%s: unable to set power state of powerdomain: %s\n", + __func__, pwrdm->name); + + _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup); + +osps_out: + pwrdm_unlock(pwrdm); + + return ret; +} + +/** * pwrdm_get_context_loss_count - get powerdomain's context loss count * @pwrdm: struct powerdomain * to wait for * diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 5277d56eb..140c360 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -19,8 +19,7 @@ #include <linux/types.h> #include <linux/list.h> - -#include <linux/atomic.h> +#include <linux/spinlock.h> #include "voltage.h" @@ -44,18 +43,20 @@ #define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON) -/* Powerdomain flags */ -#define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */ -#define PWRDM_HAS_MPU_QUIRK (1 << 1) /* MPU pwr domain has MEM bank 0 bits - * in MEM bank 1 position. This is - * true for OMAP3430 - */ -#define PWRDM_HAS_LOWPOWERSTATECHANGE (1 << 2) /* - * support to transition from a - * sleep state to a lower sleep - * state without waking up the - * powerdomain - */ +/* + * Powerdomain flags (struct powerdomain.flags) + * + * PWRDM_HAS_HDWR_SAR - powerdomain has hardware save-and-restore support + * + * PWRDM_HAS_MPU_QUIRK - MPU pwr domain has MEM bank 0 bits in MEM + * bank 1 position. This is true for OMAP3430 + * + * PWRDM_HAS_LOWPOWERSTATECHANGE - can transition from a sleep state + * to a lower sleep state without waking up the powerdomain + */ +#define PWRDM_HAS_HDWR_SAR BIT(0) +#define PWRDM_HAS_MPU_QUIRK BIT(1) +#define PWRDM_HAS_LOWPOWERSTATECHANGE BIT(2) /* * Number of memory banks that are power-controllable. On OMAP4430, the @@ -103,6 +104,8 @@ struct powerdomain; * @state_counter: * @timer: * @state_timer: + * @_lock: spinlock used to serialize powerdomain and some clockdomain ops + * @_lock_flags: stored flags when @_lock is taken * * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. */ @@ -127,7 +130,8 @@ struct powerdomain { unsigned state_counter[PWRDM_MAX_PWRSTS]; unsigned ret_logic_off_counter; unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS]; - + spinlock_t _lock; + unsigned long _lock_flags; const u8 pwrstctrl_offs; const u8 pwrstst_offs; const u32 logicretstate_mask; @@ -162,6 +166,16 @@ struct powerdomain { * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep * @pwrdm_wait_transition: Wait for a pd state transition to complete + * + * Regarding @pwrdm_set_lowpwrstchange: On the OMAP2 and 3-family + * chips, a powerdomain's power state is not allowed to directly + * transition from one low-power state (e.g., CSWR) to another + * low-power state (e.g., OFF) without first waking up the + * powerdomain. This wastes energy. So OMAP4 chips support the + * ability to transition a powerdomain power state directly from one + * low-power state to another. The function pointed to by + * @pwrdm_set_lowpwrstchange is intended to configure the OMAP4 + * hardware powerdomain state machine to enable this feature. */ struct pwrdm_ops { int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); @@ -225,15 +239,15 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm); int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm); bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); -int pwrdm_wait_transition(struct powerdomain *pwrdm); - +int pwrdm_state_switch_nolock(struct powerdomain *pwrdm); int pwrdm_state_switch(struct powerdomain *pwrdm); int pwrdm_pre_transition(struct powerdomain *pwrdm); int pwrdm_post_transition(struct powerdomain *pwrdm); -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); + extern void omap242x_powerdomains_init(void); extern void omap243x_powerdomains_init(void); extern void omap3xxx_powerdomains_init(void); @@ -253,5 +267,7 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); extern struct powerdomain wkup_omap2_pwrdm; extern struct powerdomain gfx_omap2_pwrdm; +extern void pwrdm_lock(struct powerdomain *pwrdm); +extern void pwrdm_unlock(struct powerdomain *pwrdm); #endif diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c index d3a5399..7b946f1 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c @@ -54,12 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; struct powerdomain wkup_omap2_pwrdm = { .name = "wkup_pwrdm", .prcm_offs = WKUP_MOD, .pwrsts = PWRSTS_ON, - .voltdm = { .name = "wakeup" }, + .voltdm = { .name = "wakeup" }, }; diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c index ba520d4..578eef8 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c @@ -38,7 +38,7 @@ static struct powerdomain dsp_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain mpu_24xx_pwrdm = { @@ -53,13 +53,14 @@ static struct powerdomain mpu_24xx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain core_24xx_pwrdm = { .name = "core_pwrdm", .prcm_offs = CORE_MOD, .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 3, .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, /* MEM1RETSTATE */ @@ -71,7 +72,7 @@ static struct powerdomain core_24xx_pwrdm = { [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; @@ -93,7 +94,7 @@ static struct powerdomain mdm_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; /* diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index 8b23d23..f0e14e9 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -50,7 +50,7 @@ static struct powerdomain iva2_pwrdm = { [2] = PWRSTS_OFF_ON, [3] = PWRSTS_ON, }, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain mpu_3xxx_pwrdm = { @@ -66,7 +66,7 @@ static struct powerdomain mpu_3xxx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_OFF_ON, }, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain mpu_am35x_pwrdm = { @@ -82,7 +82,7 @@ static struct powerdomain mpu_am35x_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, }, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; /* @@ -109,7 +109,7 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = { [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain core_3xxx_es3_1_pwrdm = { @@ -131,7 +131,7 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = { [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */ [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain core_am35x_pwrdm = { @@ -148,7 +148,7 @@ static struct powerdomain core_am35x_pwrdm = { [0] = PWRSTS_ON, /* MEM1ONSTATE */ [1] = PWRSTS_ON, /* MEM2ONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain dss_pwrdm = { @@ -163,7 +163,7 @@ static struct powerdomain dss_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain dss_am35x_pwrdm = { @@ -178,7 +178,7 @@ static struct powerdomain dss_am35x_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; /* @@ -199,7 +199,7 @@ static struct powerdomain sgx_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain sgx_am35x_pwrdm = { @@ -214,7 +214,7 @@ static struct powerdomain sgx_am35x_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain cam_pwrdm = { @@ -229,7 +229,7 @@ static struct powerdomain cam_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain per_pwrdm = { @@ -244,7 +244,7 @@ static struct powerdomain per_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain per_am35x_pwrdm = { @@ -259,13 +259,13 @@ static struct powerdomain per_am35x_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain emu_pwrdm = { .name = "emu_pwrdm", .prcm_offs = OMAP3430_EMU_MOD, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain neon_pwrdm = { @@ -273,7 +273,7 @@ static struct powerdomain neon_pwrdm = { .prcm_offs = OMAP3430_NEON_MOD, .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRSTS_RET, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain neon_am35x_pwrdm = { @@ -281,7 +281,7 @@ static struct powerdomain neon_am35x_pwrdm = { .prcm_offs = OMAP3430_NEON_MOD, .pwrsts = PWRSTS_ON, .pwrsts_logic_ret = PWRSTS_ON, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain usbhost_pwrdm = { @@ -303,37 +303,37 @@ static struct powerdomain usbhost_pwrdm = { .pwrsts_mem_on = { [0] = PWRSTS_ON, /* MEMONSTATE */ }, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain dpll1_pwrdm = { .name = "dpll1_pwrdm", .prcm_offs = MPU_MOD, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain dpll2_pwrdm = { .name = "dpll2_pwrdm", .prcm_offs = OMAP3430_IVA2_MOD, - .voltdm = { .name = "mpu_iva" }, + .voltdm = { .name = "mpu_iva" }, }; static struct powerdomain dpll3_pwrdm = { .name = "dpll3_pwrdm", .prcm_offs = PLL_MOD, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain dpll4_pwrdm = { .name = "dpll4_pwrdm", .prcm_offs = PLL_MOD, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; static struct powerdomain dpll5_pwrdm = { .name = "dpll5_pwrdm", .prcm_offs = PLL_MOD, - .voltdm = { .name = "core" }, + .voltdm = { .name = "core" }, }; /* As powerdomains are added or removed above, this list must also be changed */ diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index a3e121f..947f6ad 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -210,6 +210,7 @@ int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, PM_WKDEP, (1 << clkdm2->dep_bit)); } +/* XXX Caller must hold the clkdm's powerdomain lock */ int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) { struct clkdm_dep *cd; @@ -221,7 +222,7 @@ int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) /* PRM accesses are slow, so minimize them */ mask |= 1 << cd->clkdm->dep_bit; - atomic_set(&cd->wkdep_usecount, 0); + cd->wkdep_usecount = 0; } omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 04fdbc4..d01c373 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -316,8 +316,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, if (WARN_ON(!oh)) return; - pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size, - NULL, 0, false); + pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size); if (IS_ERR(pdev)) { WARN(1, "Could not build omap_device for %s: %s.\n", name, oh->name); diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index b9753fe..bb829e0 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -152,8 +152,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user) sr_data->enable_on_init = sr_enable_on_init; - pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data), - NULL, 0, 0); + pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data), 0); if (IS_ERR(pdev)) pr_warning("%s: Could not build omap_device for %s: %s.\n\n", __func__, name, oh->name); diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index b8ad6e6..6d1f7b1 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -131,7 +131,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, static struct clock_event_device clockevent_gpt = { .name = "gp_timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, .set_mode = omap2_gp_timer_set_mode, @@ -336,17 +335,11 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); - clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC, - clockevent_gpt.shift); - clockevent_gpt.max_delta_ns = - clockevent_delta2ns(0xffffffff, &clockevent_gpt); - clockevent_gpt.min_delta_ns = - clockevent_delta2ns(3, &clockevent_gpt); - /* Timer internal resynch latency. */ - clockevent_gpt.cpumask = cpu_possible_mask; clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev); - clockevents_register_device(&clockevent_gpt); + clockevents_config_and_register(&clockevent_gpt, clkev.rate, + 3, /* Timer internal resynch latency */ + 0xffffffff); pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n", gptimer_id, clkev.rate); @@ -552,7 +545,7 @@ static inline void __init realtime_counter_init(void) #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ clksrc_nr, clksrc_src) \ -static void __init omap##name##_gptimer_timer_init(void) \ +void __init omap##name##_gptimer_timer_init(void) \ { \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ @@ -561,7 +554,7 @@ static void __init omap##name##_gptimer_timer_init(void) \ #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \ clksrc_nr, clksrc_src) \ -static void __init omap##name##_sync32k_timer_init(void) \ +void __init omap##name##_sync32k_timer_init(void) \ { \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ @@ -572,33 +565,23 @@ static void __init omap##name##_sync32k_timer_init(void) \ omap2_sync32k_clocksource_init(); \ } -#define OMAP_SYS_TIMER(name, clksrc) \ -struct sys_timer omap##name##_timer = { \ - .init = omap##name##_##clksrc##_timer_init, \ -}; - #ifdef CONFIG_ARCH_OMAP2 OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon", 2, OMAP2_MPU_SOURCE); -OMAP_SYS_TIMER(2, sync32k); #endif /* CONFIG_ARCH_OMAP2 */ #ifdef CONFIG_ARCH_OMAP3 OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon", 2, OMAP3_MPU_SOURCE); -OMAP_SYS_TIMER(3, sync32k); OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure", 2, OMAP3_MPU_SOURCE); -OMAP_SYS_TIMER(3_secure, sync32k); OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon", 2, OMAP3_MPU_SOURCE); -OMAP_SYS_TIMER(3_gp, gptimer); #endif /* CONFIG_ARCH_OMAP3 */ #ifdef CONFIG_SOC_AM33XX OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon", 2, OMAP4_MPU_SOURCE); -OMAP_SYS_TIMER(3_am33xx, gptimer); #endif /* CONFIG_SOC_AM33XX */ #ifdef CONFIG_ARCH_OMAP4 @@ -606,7 +589,7 @@ OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon", 2, OMAP4_MPU_SOURCE); #ifdef CONFIG_LOCAL_TIMERS static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29); -static void __init omap4_local_timer_init(void) +void __init omap4_local_timer_init(void) { omap4_sync32k_timer_init(); /* Local timers are not supprted on OMAP4430 ES1.0 */ @@ -624,18 +607,17 @@ static void __init omap4_local_timer_init(void) } } #else /* CONFIG_LOCAL_TIMERS */ -static void __init omap4_local_timer_init(void) +void __init omap4_local_timer_init(void) { omap4_sync32k_timer_init(); } #endif /* CONFIG_LOCAL_TIMERS */ -OMAP_SYS_TIMER(4, local); #endif /* CONFIG_ARCH_OMAP4 */ #ifdef CONFIG_SOC_OMAP5 OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon", 2, OMAP4_MPU_SOURCE); -static void __init omap5_realtime_timer_init(void) +void __init omap5_realtime_timer_init(void) { int err; @@ -646,7 +628,6 @@ static void __init omap5_realtime_timer_init(void) if (err) pr_err("%s: arch_timer_register failed %d\n", __func__, err); } -OMAP_SYS_TIMER(5, realtime); #endif /* CONFIG_SOC_OMAP5 */ /** @@ -702,8 +683,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) pdata->timer_errata = omap_dm_timer_get_errata(); pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; - pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata), - NULL, 0, 0); + pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata)); if (IS_ERR(pdev)) { pr_err("%s: Can't build omap_device for %s: %s.\n", diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 2e44e8a..99f04de 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -42,14 +42,6 @@ static struct usbtll_omap_platform_data usbtll_data; static struct ehci_hcd_omap_platform_data ehci_data; static struct ohci_hcd_omap_platform_data ohci_data; -static struct omap_device_pm_latency omap_uhhtll_latency[] = { - { - .deactivate_func = omap_device_idle_hwmods, - .activate_func = omap_device_enable_hwmods, - .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, - }, -}; - /* MUX settings for EHCI pins */ /* * setup_ehci_io_mux - initialize IO pad mux for USBHOST @@ -530,9 +522,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) } pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm, - &usbtll_data, sizeof(usbtll_data), - omap_uhhtll_latency, - ARRAY_SIZE(omap_uhhtll_latency), false); + &usbtll_data, sizeof(usbtll_data)); if (IS_ERR(pdev)) { pr_err("Could not build hwmod device %s\n", USBHS_TLL_HWMODNAME); @@ -540,9 +530,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) } pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm, - &usbhs_data, sizeof(usbhs_data), - omap_uhhtll_latency, - ARRAY_SIZE(omap_uhhtll_latency), false); + &usbhs_data, sizeof(usbhs_data)); if (IS_ERR(pdev)) { pr_err("Could not build hwmod devices %s\n", USBHS_UHH_HWMODNAME); diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 7b33b37..8c4de27 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -102,7 +102,7 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) return; pdev = omap_device_build(name, bus_id, oh, &musb_plat, - sizeof(musb_plat), NULL, 0, false); + sizeof(musb_plat)); if (IS_ERR(pdev)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c index 7c2b4ed..910243f 100644 --- a/arch/arm/mach-omap2/wd_timer.c +++ b/arch/arm/mach-omap2/wd_timer.c @@ -124,8 +124,7 @@ static int __init omap_init_wdt(void) pdata.read_reset_sources = prm_read_reset_sources; pdev = omap_device_build(dev_name, id, oh, &pdata, - sizeof(struct omap_wd_timer_platform_data), - NULL, 0, 0); + sizeof(struct omap_wd_timer_platform_data)); WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n", dev_name, oh->name); return 0; diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 32e5c21..35a8014 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -72,7 +72,7 @@ DT_MACHINE_START(ORION5X_DT, "Marvell Orion5x (Flattened Device Tree)") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion_dt_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .init_machine = orion5x_dt_init, .restart = orion5x_restart, .dt_compat = orion5x_dt_compat, diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 550f923..d068f14 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -217,7 +217,7 @@ int __init orion5x_find_tclk(void) return 166666667; } -static void __init orion5x_timer_init(void) +void __init orion5x_timer_init(void) { orion5x_tclk = orion5x_find_tclk(); @@ -225,10 +225,6 @@ static void __init orion5x_timer_init(void) IRQ_ORION5X_BRIDGE, orion5x_tclk); } -struct sys_timer orion5x_timer = { - .init = orion5x_timer_init, -}; - /***************************************************************************** * General diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index 7db5cdd..e603457 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -15,7 +15,7 @@ void orion5x_init(void); void orion5x_id(u32 *dev, u32 *rev, char **dev_name); void clk_init(void); extern int orion5x_tclk; -extern struct sys_timer orion5x_timer; +extern void orion5x_timer_init(void); /* * Enumerations and functions for Orion windows mapping. Used by Orion core diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c index e3629c0..57d0af7 100644 --- a/arch/arm/mach-orion5x/d2net-setup.c +++ b/arch/arm/mach-orion5x/d2net-setup.c @@ -342,7 +342,7 @@ MACHINE_START(D2NET, "LaCie d2 Network") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END @@ -355,7 +355,7 @@ MACHINE_START(BIGDISK, "LaCie Big Disk Network") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index 41fe2b1..7666564 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -362,6 +362,6 @@ MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index e533588..6eb1732 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -714,7 +714,7 @@ MACHINE_START(DNS323, "D-Link DNS-323") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index f1ae10a..b984035 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -383,7 +383,7 @@ MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END @@ -397,7 +397,7 @@ MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c index 0c9e413..044da5b 100644 --- a/arch/arm/mach-orion5x/ls-chl-setup.c +++ b/arch/arm/mach-orion5x/ls-chl-setup.c @@ -322,7 +322,7 @@ MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c index c1b5d8a..d49f934 100644 --- a/arch/arm/mach-orion5x/ls_hgl-setup.c +++ b/arch/arm/mach-orion5x/ls_hgl-setup.c @@ -269,7 +269,7 @@ MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c index 949eaa8..8e3965c 100644 --- a/arch/arm/mach-orion5x/lsmini-setup.c +++ b/arch/arm/mach-orion5x/lsmini-setup.c @@ -271,7 +271,7 @@ MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c index 1c16d04..0ec94a1 100644 --- a/arch/arm/mach-orion5x/mss2-setup.c +++ b/arch/arm/mach-orion5x/mss2-setup.c @@ -265,7 +265,7 @@ MACHINE_START(MSS2, "Maxtor Shared Storage II") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index c87fde4..18143f2 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -233,7 +233,7 @@ MACHINE_START(MV2120, "HP Media Vault mv2120") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c index 3506f16..282e503 100644 --- a/arch/arm/mach-orion5x/net2big-setup.c +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -425,7 +425,7 @@ MACHINE_START(NET2BIG, "LaCie 2Big Network") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index 9b1c953..d6e72f67 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -171,7 +171,7 @@ MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index 51ba2b8..c8b7913 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -183,7 +183,7 @@ MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index 0a56b94..f9e1567 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -281,6 +281,6 @@ MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c index ed50910..78a1e6a 100644 --- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c @@ -123,7 +123,7 @@ MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c index 90e571d..acc0877 100644 --- a/arch/arm/mach-orion5x/terastation_pro2-setup.c +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -361,7 +361,7 @@ MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index b184f68..9c17f0c 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -326,7 +326,7 @@ MACHINE_START(TS209, "QNAP TS-109/TS-209") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c index a5c2e64..8cc5ab6 100644 --- a/arch/arm/mach-orion5x/ts409-setup.c +++ b/arch/arm/mach-orion5x/ts409-setup.c @@ -315,7 +315,7 @@ MACHINE_START(TS409, "QNAP TS-409") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index b0727dc..e960855 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -619,6 +619,6 @@ MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") .map_io = ts78xx_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c index 754c12b..66552ca 100644 --- a/arch/arm/mach-orion5x/wnr854t-setup.c +++ b/arch/arm/mach-orion5x/wnr854t-setup.c @@ -176,7 +176,7 @@ MACHINE_START(WNR854T, "Netgear WNR854T") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index 45c2125..2c5408e 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -264,7 +264,7 @@ MACHINE_START(WRT350N_V2, "Linksys WRT350N v2") .map_io = orion5x_map_io, .init_early = orion5x_init_early, .init_irq = orion5x_init_irq, - .timer = &orion5x_timer, + .init_time = orion5x_timer_init, .fixup = tag_fixup_mem32, .restart = orion5x_restart, MACHINE_END diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c index f6c0849..70b441a 100644 --- a/arch/arm/mach-picoxcell/common.c +++ b/arch/arm/mach-picoxcell/common.c @@ -9,6 +9,7 @@ */ #include <linux/delay.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/of_address.h> @@ -17,7 +18,6 @@ #include <linux/dw_apb_timer.h> #include <asm/mach/arch.h> -#include <asm/hardware/vic.h> #include <asm/mach/map.h> #include "common.h" @@ -70,16 +70,6 @@ static const char *picoxcell_dt_match[] = { NULL }; -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl192-vic", .data = vic_of_init, }, - { /* Sentinel */ } -}; - -static void __init picoxcell_init_irq(void) -{ - of_irq_init(vic_of_match); -} - static void picoxcell_wdt_restart(char mode, const char *cmd) { /* @@ -97,9 +87,8 @@ static void picoxcell_wdt_restart(char mode, const char *cmd) DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") .map_io = picoxcell_map_io, .nr_irqs = NR_IRQS_LEGACY, - .init_irq = picoxcell_init_irq, - .handle_irq = vic_handle_irq, - .timer = &dw_apb_timer, + .init_irq = irqchip_init, + .init_time = dw_apb_timer_init, .init_machine = picoxcell_init_machine, .dt_compat = picoxcell_dt_match, .restart = picoxcell_wdt_restart, diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h index a65cb02..481b42a 100644 --- a/arch/arm/mach-picoxcell/common.h +++ b/arch/arm/mach-picoxcell/common.h @@ -12,6 +12,6 @@ #include <asm/mach/time.h> -extern struct sys_timer dw_apb_timer; +extern void dw_apb_timer_init(void); #endif /* __PICOXCELL_COMMON_H__ */ diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index 558ccfb..4f7379f 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -11,6 +11,16 @@ config ARCH_PRIMA2 help Support for CSR SiRFSoC ARM Cortex A9 Platform +config ARCH_MARCO + bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform" + default y + select ARM_GIC + select CPU_V7 + select HAVE_SMP + select SMP_ON_UP + help + Support for CSR SiRFSoC ARM Cortex A9 Platform + endmenu config SIRF_IRQ diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile index fc9ce22..bfe360c 100644 --- a/arch/arm/mach-prima2/Makefile +++ b/arch/arm/mach-prima2/Makefile @@ -1,4 +1,3 @@ -obj-y := timer.o obj-y += rstc.o obj-y += common.o obj-y += rtciobrg.o @@ -6,3 +5,7 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o obj-$(CONFIG_CACHE_L2X0) += l2x0.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o obj-$(CONFIG_SIRF_IRQ) += irq.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o +obj-$(CONFIG_ARCH_MARCO) += timer-marco.o diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c index f25a541..2d57aa4 100644 --- a/arch/arm/mach-prima2/common.c +++ b/arch/arm/mach-prima2/common.c @@ -8,6 +8,7 @@ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/irqchip.h> #include <asm/sizes.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -30,6 +31,12 @@ void __init sirfsoc_init_late(void) sirfsoc_pm_init(); } +static __init void sirfsoc_map_io(void) +{ + sirfsoc_map_lluart(); + sirfsoc_map_scu(); +} + #ifdef CONFIG_ARCH_PRIMA2 static const char *prima2_dt_match[] __initdata = { "sirf,prima2", @@ -38,9 +45,12 @@ static const char *prima2_dt_match[] __initdata = { DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") /* Maintainer: Barry Song <baohua.song@csr.com> */ - .map_io = sirfsoc_map_lluart, + .map_io = sirfsoc_map_io, .init_irq = sirfsoc_of_irq_init, - .timer = &sirfsoc_timer, + .init_time = sirfsoc_prima2_timer_init, +#ifdef CONFIG_MULTI_IRQ_HANDLER + .handle_irq = sirfsoc_handle_irq, +#endif .dma_zone_size = SZ_256M, .init_machine = sirfsoc_mach_init, .init_late = sirfsoc_init_late, @@ -48,3 +58,22 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") .restart = sirfsoc_restart, MACHINE_END #endif + +#ifdef CONFIG_ARCH_MARCO +static const char *marco_dt_match[] __initdata = { + "sirf,marco", + NULL +}; + +DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)") + /* Maintainer: Barry Song <baohua.song@csr.com> */ + .smp = smp_ops(sirfsoc_smp_ops), + .map_io = sirfsoc_map_io, + .init_irq = irqchip_init, + .init_time = sirfsoc_marco_timer_init, + .init_machine = sirfsoc_mach_init, + .init_late = sirfsoc_init_late, + .dt_compat = marco_dt_match, + .restart = sirfsoc_restart, +MACHINE_END +#endif diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h index 60d826f..b7c26b6 100644 --- a/arch/arm/mach-prima2/common.h +++ b/arch/arm/mach-prima2/common.h @@ -11,12 +11,19 @@ #include <linux/init.h> #include <asm/mach/time.h> +#include <asm/exception.h> -extern struct sys_timer sirfsoc_timer; +extern void sirfsoc_prima2_timer_init(void); +extern void sirfsoc_marco_timer_init(void); + +extern struct smp_operations sirfsoc_smp_ops; +extern void sirfsoc_secondary_startup(void); +extern void sirfsoc_cpu_die(unsigned int cpu); extern void __init sirfsoc_of_irq_init(void); extern void __init sirfsoc_of_clk_init(void); extern void sirfsoc_restart(char, const char *); +extern asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs); #ifndef CONFIG_DEBUG_LL static inline void sirfsoc_map_lluart(void) {} @@ -24,6 +31,12 @@ static inline void sirfsoc_map_lluart(void) {} extern void __init sirfsoc_map_lluart(void); #endif +#ifndef CONFIG_SMP +static inline void sirfsoc_map_scu(void) {} +#else +extern void sirfsoc_map_scu(void); +#endif + #ifdef CONFIG_SUSPEND extern int sirfsoc_pm_init(void); #else diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S new file mode 100644 index 0000000..6ec19d5 --- /dev/null +++ b/arch/arm/mach-prima2/headsmp.S @@ -0,0 +1,79 @@ +/* + * Entry of the second core for CSR Marco dual-core SMP SoCs + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/linkage.h> +#include <linux/init.h> + + __INIT +/* + * Cold boot and hardware reset show different behaviour, + * system will be always panic if we warm-reset the board + * Here we invalidate L1 of CPU1 to make sure there isn't + * uninitialized data written into memory later + */ +ENTRY(v7_invalidate_l1) + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 2, r0, c0, c0, 0 + mrc p15, 1, r0, c0, c0, 0 + + ldr r1, =0x7fff + and r2, r1, r0, lsr #13 + + ldr r1, =0x3ff + + and r3, r1, r0, lsr #3 @ NumWays - 1 + add r2, r2, #1 @ NumSets + + and r0, r0, #0x7 + add r0, r0, #4 @ SetShift + + clz r1, r3 @ WayShift + add r4, r3, #1 @ NumWays +1: sub r2, r2, #1 @ NumSets-- + mov r3, r4 @ Temp = NumWays +2: subs r3, r3, #1 @ Temp-- + mov r5, r3, lsl r1 + mov r6, r2, lsl r0 + orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) + mcr p15, 0, r5, c7, c6, 2 + bgt 2b + cmp r2, #0 + bgt 1b + dsb + isb + mov pc, lr +ENDPROC(v7_invalidate_l1) + +/* + * SIRFSOC specific entry point for secondary CPUs. This provides + * a "holding pen" into which all secondary cores are held until we're + * ready for them to initialise. + */ +ENTRY(sirfsoc_secondary_startup) + bl v7_invalidate_l1 + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup +ENDPROC(sirfsoc_secondary_startup) + + .align +1: .long . + .long pen_release diff --git a/arch/arm/mach-prima2/hotplug.c b/arch/arm/mach-prima2/hotplug.c new file mode 100644 index 0000000..97c1ee5 --- /dev/null +++ b/arch/arm/mach-prima2/hotplug.c @@ -0,0 +1,41 @@ +/* + * CPU hotplug support for CSR Marco dual-core SMP SoCs + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> + +static inline void platform_do_lowpower(unsigned int cpu) +{ + flush_cache_all(); + + /* we put the platform to just WFI */ + for (;;) { + __asm__ __volatile__("dsb\n\t" "wfi\n\t" + : : : "memory"); + if (pen_release == cpu_logical_map(cpu)) { + /* + * OK, proper wakeup, we're done + */ + break; + } + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void sirfsoc_cpu_die(unsigned int cpu) +{ + platform_do_lowpower(cpu); +} diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h index f6014a0..b778a0f 100644 --- a/arch/arm/mach-prima2/include/mach/irqs.h +++ b/arch/arm/mach-prima2/include/mach/irqs.h @@ -10,8 +10,8 @@ #define __ASM_ARCH_IRQS_H #define SIRFSOC_INTENAL_IRQ_START 0 -#define SIRFSOC_INTENAL_IRQ_END 59 +#define SIRFSOC_INTENAL_IRQ_END 127 #define SIRFSOC_GPIO_IRQ_START (SIRFSOC_INTENAL_IRQ_END + 1) -#define NR_IRQS 220 +#define NR_IRQS 288 #endif diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h index c98b4d5..c10510d 100644 --- a/arch/arm/mach-prima2/include/mach/uart.h +++ b/arch/arm/mach-prima2/include/mach/uart.h @@ -10,7 +10,13 @@ #define __MACH_PRIMA2_SIRFSOC_UART_H /* UART-1: used as serial debug port */ +#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1) #define SIRFSOC_UART1_PA_BASE 0xb0060000 +#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1) +#define SIRFSOC_UART1_PA_BASE 0xcc060000 +#else +#define SIRFSOC_UART1_PA_BASE 0 +#endif #define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000) #define SIRFSOC_UART1_SIZE SZ_4K diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h index 0c898fc..15f3edc 100644 --- a/arch/arm/mach-prima2/include/mach/uncompress.h +++ b/arch/arm/mach-prima2/include/mach/uncompress.h @@ -25,6 +25,9 @@ static __inline__ void putc(char c) * during kernel decompression, all mappings are flat: * virt_addr == phys_addr */ + if (!SIRFSOC_UART1_PA_BASE) + return; + while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS) & SIRFSOC_UART1_TXFIFO_FULL) barrier(); diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c index 7dee917..6c0f3e9 100644 --- a/arch/arm/mach-prima2/irq.c +++ b/arch/arm/mach-prima2/irq.c @@ -9,17 +9,19 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> -#include <mach/hardware.h> -#include <asm/mach/irq.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/irqdomain.h> #include <linux/syscore_ops.h> +#include <asm/mach/irq.h> +#include <asm/exception.h> +#include <mach/hardware.h> #define SIRFSOC_INT_RISC_MASK0 0x0018 #define SIRFSOC_INT_RISC_MASK1 0x001C #define SIRFSOC_INT_RISC_LEVEL0 0x0020 #define SIRFSOC_INT_RISC_LEVEL1 0x0024 +#define SIRFSOC_INIT_IRQ_ID 0x0038 void __iomem *sirfsoc_intc_base; @@ -52,6 +54,16 @@ static __init void sirfsoc_irq_init(void) writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); } +asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) +{ + u32 irqstat, irqnr; + + irqstat = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INIT_IRQ_ID); + irqnr = irqstat & 0xff; + + handle_IRQ(irqnr, regs); +} + static struct of_device_id intc_ids[] = { { .compatible = "sirf,prima2-intc" }, {}, diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c index c998377..cbcbe9c 100644 --- a/arch/arm/mach-prima2/l2x0.c +++ b/arch/arm/mach-prima2/l2x0.c @@ -11,19 +11,38 @@ #include <linux/of.h> #include <asm/hardware/cache-l2x0.h> -static struct of_device_id prima2_l2x0_ids[] = { - { .compatible = "sirf,prima2-pl310-cache" }, +struct l2x0_aux +{ + u32 val; + u32 mask; +}; + +static struct l2x0_aux prima2_l2x0_aux __initconst = { + .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT, + .mask = 0, +}; + +static struct l2x0_aux marco_l2x0_aux __initconst = { + .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | + (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT), + .mask = L2X0_AUX_CTRL_MASK, +}; + +static struct of_device_id sirf_l2x0_ids[] __initconst = { + { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, }, + { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, }, {}, }; static int __init sirfsoc_l2x0_init(void) { struct device_node *np; + const struct l2x0_aux *aux; - np = of_find_matching_node(NULL, prima2_l2x0_ids); + np = of_find_matching_node(NULL, sirf_l2x0_ids); if (np) { - pr_info("Initializing prima2 L2 cache\n"); - return l2x0_of_init(0x40000, 0); + aux = of_match_node(sirf_l2x0_ids, np)->data; + return l2x0_of_init(aux->val, aux->mask); } return 0; diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c new file mode 100644 index 0000000..4b78831 --- /dev/null +++ b/arch/arm/mach-prima2/platsmp.c @@ -0,0 +1,157 @@ +/* + * plat smp support for CSR Marco dual-core SMP SoCs + * + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/irqchip/arm-gic.h> +#include <asm/page.h> +#include <asm/mach/map.h> +#include <asm/smp_plat.h> +#include <asm/smp_scu.h> +#include <asm/cacheflush.h> +#include <asm/cputype.h> +#include <mach/map.h> + +#include "common.h" + +static void __iomem *scu_base; +static void __iomem *rsc_base; + +static DEFINE_SPINLOCK(boot_lock); + +static struct map_desc scu_io_desc __initdata = { + .length = SZ_4K, + .type = MT_DEVICE, +}; + +void __init sirfsoc_map_scu(void) +{ + unsigned long base; + + /* Get SCU base */ + asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); + + scu_io_desc.virtual = SIRFSOC_VA(base); + scu_io_desc.pfn = __phys_to_pfn(base); + iotable_init(&scu_io_desc, 1); + + scu_base = (void __iomem *)SIRFSOC_VA(base); +} + +static void __cpuinit sirfsoc_secondary_init(unsigned int cpu) +{ + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_secondary_init(0); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +static struct of_device_id rsc_ids[] = { + { .compatible = "sirf,marco-rsc" }, + {}, +}; + +static int __cpuinit sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + struct device_node *np; + + np = of_find_matching_node(NULL, rsc_ids); + if (!np) + return -ENODEV; + + rsc_base = of_iomap(np, 0); + if (!rsc_base) + return -ENOMEM; + + /* + * write the address of secondary startup into the sram register + * at offset 0x2C, then write the magic number 0x3CAF5D62 to the + * RSC register at offset 0x28, which is what boot rom code is + * waiting for. This would wake up the secondary core from WFE + */ +#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C + __raw_writel(virt_to_phys(sirfsoc_secondary_startup), + rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET); + +#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28 + __raw_writel(0x3CAF5D62, + rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET); + + /* make sure write buffer is drained */ + mb(); + + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu_logical_map(cpu); + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); + + /* + * Send the secondary CPU SEV, thereby causing the boot monitor to read + * the JUMPADDR and WAKEMAGIC, and branch to the address found there. + */ + dsb_sev(); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus) +{ + scu_enable(scu_base); +} + +struct smp_operations sirfsoc_smp_ops __initdata = { + .smp_prepare_cpus = sirfsoc_smp_prepare_cpus, + .smp_secondary_init = sirfsoc_secondary_init, + .smp_boot_secondary = sirfsoc_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = sirfsoc_cpu_die, +#endif +}; diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c index 762adb7..435019c 100644 --- a/arch/arm/mach-prima2/rstc.c +++ b/arch/arm/mach-prima2/rstc.c @@ -19,6 +19,7 @@ static DEFINE_MUTEX(rstc_lock); static struct of_device_id rstc_ids[] = { { .compatible = "sirf,prima2-rstc" }, + { .compatible = "sirf,marco-rstc" }, {}, }; @@ -42,27 +43,37 @@ early_initcall(sirfsoc_of_rstc_init); int sirfsoc_reset_device(struct device *dev) { - const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL); - unsigned int reset_bit; + u32 reset_bit; - if (!prop) - return -ENODEV; - - reset_bit = be32_to_cpup(prop); + if (of_property_read_u32(dev->of_node, "reset-bit", &reset_bit)) + return -EINVAL; mutex_lock(&rstc_lock); - /* - * Writing 1 to this bit resets corresponding block. Writing 0 to this - * bit de-asserts reset signal of the corresponding block. - * datasheet doesn't require explicit delay between the set and clear - * of reset bit. it could be shorter if tests pass. - */ - writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit, - sirfsoc_rstc_base + (reset_bit / 32) * 4); - msleep(10); - writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, - sirfsoc_rstc_base + (reset_bit / 32) * 4); + if (of_device_is_compatible(dev->of_node, "sirf,prima2-rstc")) { + /* + * Writing 1 to this bit resets corresponding block. Writing 0 to this + * bit de-asserts reset signal of the corresponding block. + * datasheet doesn't require explicit delay between the set and clear + * of reset bit. it could be shorter if tests pass. + */ + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 4); + msleep(10); + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 4); + } else { + /* + * For MARCO and POLO + * Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR + * register de-asserts reset signal of the corresponding block. + * datasheet doesn't require explicit delay between the set and clear + * of reset bit. it could be shorter if tests pass. + */ + writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8); + msleep(10); + writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); + } mutex_unlock(&rstc_lock); diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c index 5573536..9f2da2e 100644 --- a/arch/arm/mach-prima2/rtciobrg.c +++ b/arch/arm/mach-prima2/rtciobrg.c @@ -104,6 +104,7 @@ EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel); static const struct of_device_id rtciobrg_ids[] = { { .compatible = "sirf,prima2-rtciobg" }, + { .compatible = "sirf,marco-rtciobg" }, {} }; diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c new file mode 100644 index 0000000..f4eea2e --- /dev/null +++ b/arch/arm/mach-prima2/timer-marco.c @@ -0,0 +1,316 @@ +/* + * System timer for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/clockchips.h> +#include <linux/clocksource.h> +#include <linux/bitops.h> +#include <linux/irq.h> +#include <linux/clk.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> +#include <asm/sched_clock.h> +#include <asm/localtimer.h> +#include <asm/mach/time.h> + +#include "common.h" + +#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 +#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 +#define SIRFSOC_TIMER_MATCH_0 0x0018 +#define SIRFSOC_TIMER_MATCH_1 0x001c +#define SIRFSOC_TIMER_COUNTER_0 0x0048 +#define SIRFSOC_TIMER_COUNTER_1 0x004c +#define SIRFSOC_TIMER_INTR_STATUS 0x0060 +#define SIRFSOC_TIMER_WATCHDOG_EN 0x0064 +#define SIRFSOC_TIMER_64COUNTER_CTRL 0x0068 +#define SIRFSOC_TIMER_64COUNTER_LO 0x006c +#define SIRFSOC_TIMER_64COUNTER_HI 0x0070 +#define SIRFSOC_TIMER_64COUNTER_LOAD_LO 0x0074 +#define SIRFSOC_TIMER_64COUNTER_LOAD_HI 0x0078 +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO 0x007c +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI 0x0080 + +#define SIRFSOC_TIMER_REG_CNT 6 + +static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { + SIRFSOC_TIMER_WATCHDOG_EN, + SIRFSOC_TIMER_32COUNTER_0_CTRL, + SIRFSOC_TIMER_32COUNTER_1_CTRL, + SIRFSOC_TIMER_64COUNTER_CTRL, + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO, + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI, +}; + +static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT]; + +static void __iomem *sirfsoc_timer_base; +static void __init sirfsoc_of_timer_map(void); + +/* disable count and interrupt */ +static inline void sirfsoc_timer_count_disable(int idx) +{ + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7, + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); +} + +/* enable count and interrupt */ +static inline void sirfsoc_timer_count_enable(int idx) +{ + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7, + sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); +} + +/* timer interrupt handler */ +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *ce = dev_id; + int cpu = smp_processor_id(); + + /* clear timer interrupt */ + writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); + + if (ce->mode == CLOCK_EVT_MODE_ONESHOT) + sirfsoc_timer_count_disable(cpu); + + ce->event_handler(ce); + + return IRQ_HANDLED; +} + +/* read 64-bit timer counter */ +static cycle_t sirfsoc_timer_read(struct clocksource *cs) +{ + u64 cycles; + + writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + + cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI); + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO); + + return cycles; +} + +static int sirfsoc_timer_set_next_event(unsigned long delta, + struct clock_event_device *ce) +{ + int cpu = smp_processor_id(); + + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 + + 4 * cpu); + writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 + + 4 * cpu); + + /* enable the tick */ + sirfsoc_timer_count_enable(cpu); + + return 0; +} + +static void sirfsoc_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *ce) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + /* enable in set_next_event */ + break; + default: + break; + } + + sirfsoc_timer_count_disable(smp_processor_id()); +} + +static void sirfsoc_clocksource_suspend(struct clocksource *cs) +{ + int i; + + for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++) + sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); +} + +static void sirfsoc_clocksource_resume(struct clocksource *cs) +{ + int i; + + for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++) + writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); + + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], + sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); + + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); +} + +static struct clock_event_device sirfsoc_clockevent = { + .name = "sirfsoc_clockevent", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = sirfsoc_timer_set_mode, + .set_next_event = sirfsoc_timer_set_next_event, +}; + +static struct clocksource sirfsoc_clocksource = { + .name = "sirfsoc_clocksource", + .rating = 200, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .read = sirfsoc_timer_read, + .suspend = sirfsoc_clocksource_suspend, + .resume = sirfsoc_clocksource_resume, +}; + +static struct irqaction sirfsoc_timer_irq = { + .name = "sirfsoc_timer0", + .flags = IRQF_TIMER | IRQF_NOBALANCING, + .handler = sirfsoc_timer_interrupt, + .dev_id = &sirfsoc_clockevent, +}; + +#ifdef CONFIG_LOCAL_TIMERS + +static struct irqaction sirfsoc_timer1_irq = { + .name = "sirfsoc_timer1", + .flags = IRQF_TIMER | IRQF_NOBALANCING, + .handler = sirfsoc_timer_interrupt, +}; + +static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce) +{ + /* Use existing clock_event for cpu 0 */ + if (!smp_processor_id()) + return 0; + + ce->irq = sirfsoc_timer1_irq.irq; + ce->name = "local_timer"; + ce->features = sirfsoc_clockevent.features; + ce->rating = sirfsoc_clockevent.rating; + ce->set_mode = sirfsoc_timer_set_mode; + ce->set_next_event = sirfsoc_timer_set_next_event; + ce->shift = sirfsoc_clockevent.shift; + ce->mult = sirfsoc_clockevent.mult; + ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns; + ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns; + + sirfsoc_timer1_irq.dev_id = ce; + BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq)); + irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1)); + + clockevents_register_device(ce); + return 0; +} + +static void sirfsoc_local_timer_stop(struct clock_event_device *ce) +{ + sirfsoc_timer_count_disable(1); + + remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); +} + +static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = { + .setup = sirfsoc_local_timer_setup, + .stop = sirfsoc_local_timer_stop, +}; +#endif /* CONFIG_LOCAL_TIMERS */ + +static void __init sirfsoc_clockevent_init(void) +{ + clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60); + + sirfsoc_clockevent.max_delta_ns = + clockevent_delta2ns(-2, &sirfsoc_clockevent); + sirfsoc_clockevent.min_delta_ns = + clockevent_delta2ns(2, &sirfsoc_clockevent); + + sirfsoc_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&sirfsoc_clockevent); +#ifdef CONFIG_LOCAL_TIMERS + local_timer_register(&sirfsoc_local_timer_ops); +#endif +} + +/* initialize the kernel jiffy timer source */ +void __init sirfsoc_marco_timer_init(void) +{ + unsigned long rate; + u32 timer_div; + struct clk *clk; + + /* initialize clocking early, we want to set the OS timer */ + sirfsoc_of_clk_init(); + + /* timer's input clock is io clock */ + clk = clk_get_sys("io", NULL); + + BUG_ON(IS_ERR(clk)); + rate = clk_get_rate(clk); + + BUG_ON(rate < CLOCK_TICK_RATE); + BUG_ON(rate % CLOCK_TICK_RATE); + + sirfsoc_of_timer_map(); + + /* Initialize the timer dividers */ + timer_div = rate / CLOCK_TICK_RATE - 1; + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); + writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL); + + /* Initialize timer counters to 0 */ + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI); + writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) | + BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0); + writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1); + + /* Clear all interrupts */ + writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); + + BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE)); + + BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq)); + + sirfsoc_clockevent_init(); +} + +static struct of_device_id timer_ids[] = { + { .compatible = "sirf,marco-tick" }, + {}, +}; + +static void __init sirfsoc_of_timer_map(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, timer_ids); + if (!np) + return; + sirfsoc_timer_base = of_iomap(np, 0); + if (!sirfsoc_timer_base) + panic("unable to map timer cpu registers\n"); + + sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0); + if (!sirfsoc_timer_irq.irq) + panic("No irq passed for timer0 via DT\n"); + +#ifdef CONFIG_LOCAL_TIMERS + sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1); + if (!sirfsoc_timer1_irq.irq) + panic("No irq passed for timer1 via DT\n"); +#endif + + of_node_put(np); +} diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer-prima2.c index d95bf25..6da584f 100644 --- a/arch/arm/mach-prima2/timer.c +++ b/arch/arm/mach-prima2/timer-prima2.c @@ -175,19 +175,13 @@ static u32 notrace sirfsoc_read_sched_clock(void) static void __init sirfsoc_clockevent_init(void) { - clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60); - - sirfsoc_clockevent.max_delta_ns = - clockevent_delta2ns(-2, &sirfsoc_clockevent); - sirfsoc_clockevent.min_delta_ns = - clockevent_delta2ns(2, &sirfsoc_clockevent); - sirfsoc_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&sirfsoc_clockevent); + clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE, + 2, -2); } /* initialize the kernel jiffy timer source */ -static void __init sirfsoc_timer_init(void) +void __init sirfsoc_prima2_timer_init(void) { unsigned long rate; struct clk *clk; @@ -233,7 +227,7 @@ static void __init sirfsoc_of_timer_map(void) np = of_find_matching_node(NULL, timer_ids); if (!np) - panic("unable to find compatible timer node in dtb\n"); + return; sirfsoc_timer_base = of_iomap(np, 0); if (!sirfsoc_timer_base) panic("unable to map timer cpu registers\n"); @@ -245,7 +239,3 @@ static void __init sirfsoc_of_timer_map(void) of_node_put(np); } - -struct sys_timer sirfsoc_timer = { - .init = sirfsoc_timer_init, -}; diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 2082293..2f71b3f 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -822,7 +822,7 @@ MACHINE_START(BALLOON3, "Balloon3") .nr_irqs = BALLOON3_NR_IRQS, .init_irq = balloon3_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = balloon3_init, .atag_offset = 0x100, .restart = pxa_restart, diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c index 9a8760b..c092730 100644 --- a/arch/arm/mach-pxa/capc7117.c +++ b/arch/arm/mach-pxa/capc7117.c @@ -153,7 +153,7 @@ MACHINE_START(CAPC7117, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = capc7117_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c index a103c8f..bb99f59 100644 --- a/arch/arm/mach-pxa/cm-x2xx.c +++ b/arch/arm/mach-pxa/cm-x2xx.c @@ -520,7 +520,7 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX") .init_irq = cmx2xx_init_irq, /* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */ .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = cmx2xx_init, #ifdef CONFIG_PCI .dma_zone_size = SZ_64M, diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index cc2b23a..8091aac 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -854,7 +854,7 @@ MACHINE_START(CM_X300, "CM-X300 module") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = cm_x300_init, .fixup = cm_x300_fixup, .restart = pxa_restart, diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c index b2f227d..5f9d930 100644 --- a/arch/arm/mach-pxa/colibri-pxa270.c +++ b/arch/arm/mach-pxa/colibri-pxa270.c @@ -313,7 +313,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END @@ -324,7 +324,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index a9c9c16..f1a1ac1 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -189,7 +189,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index 25515cd..f6cc8b0 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -259,7 +259,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 7c83f52..a5b8fead 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -733,7 +733,7 @@ MACHINE_START(CORGI, "SHARP Corgi") .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, .init_machine = corgi_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = corgi_restart, MACHINE_END #endif @@ -746,7 +746,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd") .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, .init_machine = corgi_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = corgi_restart, MACHINE_END #endif @@ -759,7 +759,7 @@ MACHINE_START(HUSKY, "SHARP Husky") .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, .init_machine = corgi_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = corgi_restart, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c index 7039f44..fadfff8 100644 --- a/arch/arm/mach-pxa/csb726.c +++ b/arch/arm/mach-pxa/csb726.c @@ -278,6 +278,6 @@ MACHINE_START(CSB726, "Cogent CSB726") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = csb726_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 1b64114..446563a 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -1298,7 +1298,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = em_x270_init, .restart = pxa_restart, MACHINE_END @@ -1309,7 +1309,7 @@ MACHINE_START(EXEDA, "Compulab eXeda") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = em_x270_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index be2ee9b..8280ebc 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -195,7 +195,7 @@ MACHINE_START(E330, "Toshiba e330") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e330_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -246,7 +246,7 @@ MACHINE_START(E350, "Toshiba e350") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e350_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -370,7 +370,7 @@ MACHINE_START(E400, "Toshiba e400") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e400_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -566,7 +566,7 @@ MACHINE_START(E740, "Toshiba e740") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e740_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -765,7 +765,7 @@ MACHINE_START(E750, "Toshiba e750") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e750_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -977,7 +977,7 @@ MACHINE_START(E800, "Toshiba e800") .handle_irq = pxa25x_handle_irq, .fixup = eseries_fixup, .init_machine = e800_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index dc58fa0..dca10709 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -802,7 +802,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = a780_init, .restart = pxa_restart, MACHINE_END @@ -869,7 +869,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = e680_init, .restart = pxa_restart, MACHINE_END @@ -936,7 +936,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = a1200_init, .restart = pxa_restart, MACHINE_END @@ -1128,7 +1128,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = a910_init, .restart = pxa_restart, MACHINE_END @@ -1195,7 +1195,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = e6_init, .restart = pxa_restart, MACHINE_END @@ -1236,7 +1236,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2") .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = e2_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 42d5cca..fd7ea39 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -10,9 +10,8 @@ */ struct irq_data; -struct sys_timer; -extern struct sys_timer pxa_timer; +extern void pxa_timer_init(void); extern void __init pxa_map_io(void); diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index 60755a6..00b92da 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -238,7 +238,7 @@ MACHINE_START(GUMSTIX, "Gumstix") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = gumstix_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c index e7dec58..875ec33 100644 --- a/arch/arm/mach-pxa/h5000.c +++ b/arch/arm/mach-pxa/h5000.c @@ -208,7 +208,7 @@ MACHINE_START(H5400, "HP iPAQ H5000") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = h5000_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c index 2962de8..7a8d749 100644 --- a/arch/arm/mach-pxa/himalaya.c +++ b/arch/arm/mach-pxa/himalaya.c @@ -164,6 +164,6 @@ MACHINE_START(HIMALAYA, "HTC Himalaya") .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, .init_machine = himalaya_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index e2c6391..133109e 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -900,6 +900,6 @@ MACHINE_START(H4700, "HP iPAQ HX4700") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = hx4700_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 1d02eab..fe31bfc 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -196,7 +196,7 @@ MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = icontrol_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 64507cd..343c4e3 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -279,7 +279,7 @@ MACHINE_START(PXA_IDP, "Vibren PXA255 IDP") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = idp_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 402874f..e848c46 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -443,7 +443,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto .nr_irqs = LITTLETON_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = littleton_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index 1a63eaa..1255ee0 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -503,7 +503,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine") .nr_irqs = LPD270_NR_IRQS, .init_irq = lpd270_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = lpd270_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 553056d..d8a1be6 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -650,7 +650,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") .nr_irqs = LUBBOCK_NR_IRQS, .init_irq = lubbock_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = lubbock_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index f792240..f44532f 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -774,6 +774,6 @@ MACHINE_START(MAGICIAN, "HTC Magician") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = magician_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index f27a61e..7a12c1b 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -714,7 +714,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") .nr_irqs = MAINSTONE_NR_IRQS, .init_irq = mainstone_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = mainstone_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 2831308..f8979b94 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -762,6 +762,6 @@ MACHINE_START(MIOA701, "MIO A701") .init_irq = &pxa27x_init_irq, .handle_irq = &pxa27x_handle_irq, .init_machine = mioa701_machine_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = mioa701_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c index 152efbf..854f1f5 100644 --- a/arch/arm/mach-pxa/mp900.c +++ b/arch/arm/mach-pxa/mp900.c @@ -93,7 +93,7 @@ static void __init mp900c_init(void) /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */ MACHINE_START(NEC_MP900, "MobilePro900/C") .atag_offset = 0x220100, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .map_io = pxa25x_map_io, .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index 8bcc96e..909b713 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -347,7 +347,7 @@ MACHINE_START(PALMLD, "Palm LifeDrive") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmld_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index 5ca7b90..5033fd0 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -208,7 +208,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmt5_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c index ca924cf..100b176f 100644 --- a/arch/arm/mach-pxa/palmtc.c +++ b/arch/arm/mach-pxa/palmtc.c @@ -542,7 +542,7 @@ MACHINE_START(PALMTC, "Palm Tungsten|C") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmtc_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c index 32e0d79..0742721 100644 --- a/arch/arm/mach-pxa/palmte2.c +++ b/arch/arm/mach-pxa/palmte2.c @@ -363,7 +363,7 @@ MACHINE_START(PALMTE2, "Palm Tungsten|E2") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmte2_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index 3f3c48f..d17bda2 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -451,7 +451,7 @@ MACHINE_START(TREO680, "Palm Treo 680") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = treo680_init, .restart = pxa_restart, MACHINE_END @@ -465,7 +465,7 @@ MACHINE_START(CENTRO, "Palm Centro 685") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = centro_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 8b43666..627c93a 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -366,7 +366,7 @@ MACHINE_START(PALMTX, "Palm T|X") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmtx_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 8cdd4f5..18b7fcd 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -404,7 +404,7 @@ MACHINE_START(PALMZ72, "Palm Zire72") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = palmz72_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c index fe90544..69918c7 100644 --- a/arch/arm/mach-pxa/pcm027.c +++ b/arch/arm/mach-pxa/pcm027.c @@ -263,7 +263,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270") .nr_irqs = PCM027_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = pcm027_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 2910bb9..50ccd5f 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -469,7 +469,7 @@ MACHINE_START(POODLE, "SHARP Poodle") .nr_irqs = POODLE_NR_IRQS, /* 4 for LoCoMo */ .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = poodle_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c index c9192ce..3835979 100644 --- a/arch/arm/mach-pxa/pxa-dt.c +++ b/arch/arm/mach-pxa/pxa-dt.c @@ -55,7 +55,7 @@ DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)") .map_io = pxa3xx_map_io, .init_irq = pxa3xx_dt_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, .init_machine = pxa3xx_dt_init, .dt_compat = pxa3xx_dt_board_compat, diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 25b08bfa..af41888 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -1095,7 +1095,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -1108,7 +1108,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif @@ -1121,7 +1121,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index 08d87a5..710c493 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -601,7 +601,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = saar_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 2073f0e..f90aa27 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -986,7 +986,7 @@ MACHINE_START(SPITZ, "SHARP Spitz") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = spitz_restart, MACHINE_END #endif @@ -1000,7 +1000,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = spitz_restart, MACHINE_END #endif @@ -1014,7 +1014,7 @@ MACHINE_START(AKITA, "SHARP Akita") .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, .init_machine = spitz_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = spitz_restart, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 456560b..88fde43 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -1006,7 +1006,7 @@ MACHINE_START(INTELMOTE2, "IMOTE 2") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = imote2_init, .atag_offset = 0x100, .restart = pxa_restart, @@ -1019,7 +1019,7 @@ MACHINE_START(STARGATE2, "Stargate 2") .nr_irqs = STARGATE_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = stargate2_init, .atag_offset = 0x100, .restart = pxa_restart, diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index 1a25f8a..f55979c 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -494,7 +494,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = tavorevb_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 4bc47d6..8f1ee92 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -89,48 +89,10 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) } } -static struct clock_event_device ckevt_pxa_osmr0 = { - .name = "osmr0", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = pxa_osmr0_set_next_event, - .set_mode = pxa_osmr0_set_mode, -}; - -static struct irqaction pxa_ost0_irq = { - .name = "ost0", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = pxa_ost0_interrupt, - .dev_id = &ckevt_pxa_osmr0, -}; - -static void __init pxa_timer_init(void) -{ - unsigned long clock_tick_rate = get_clock_tick_rate(); - - writel_relaxed(0, OIER); - writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); - - setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); - - clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); - ckevt_pxa_osmr0.max_delta_ns = - clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); - ckevt_pxa_osmr0.min_delta_ns = - clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; - ckevt_pxa_osmr0.cpumask = cpumask_of(0); - - setup_irq(IRQ_OST0, &pxa_ost0_irq); - - clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32, - clocksource_mmio_readl_up); - clockevents_register_device(&ckevt_pxa_osmr0); -} - #ifdef CONFIG_PM static unsigned long osmr[4], oier, oscr; -static void pxa_timer_suspend(void) +static void pxa_timer_suspend(struct clock_event_device *cedev) { osmr[0] = readl_relaxed(OSMR0); osmr[1] = readl_relaxed(OSMR1); @@ -140,7 +102,7 @@ static void pxa_timer_suspend(void) oscr = readl_relaxed(OSCR); } -static void pxa_timer_resume(void) +static void pxa_timer_resume(struct clock_event_device *cedev) { /* * Ensure that we have at least MIN_OSCR_DELTA between match @@ -163,8 +125,38 @@ static void pxa_timer_resume(void) #define pxa_timer_resume NULL #endif -struct sys_timer pxa_timer = { - .init = pxa_timer_init, +static struct clock_event_device ckevt_pxa_osmr0 = { + .name = "osmr0", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = pxa_osmr0_set_next_event, + .set_mode = pxa_osmr0_set_mode, .suspend = pxa_timer_suspend, .resume = pxa_timer_resume, }; + +static struct irqaction pxa_ost0_irq = { + .name = "ost0", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = pxa_ost0_interrupt, + .dev_id = &ckevt_pxa_osmr0, +}; + +void __init pxa_timer_init(void) +{ + unsigned long clock_tick_rate = get_clock_tick_rate(); + + writel_relaxed(0, OIER); + writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); + + setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); + + ckevt_pxa_osmr0.cpumask = cpumask_of(0); + + setup_irq(IRQ_OST0, &pxa_ost0_irq); + + clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32, + clocksource_mmio_readl_up); + clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate, + MIN_OSCR_DELTA * 2, 0x7fffffff); +} diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 233629e..9e7998d 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -982,6 +982,6 @@ MACHINE_START(TOSA, "SHARP Tosa") .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, .init_machine = tosa_init, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = tosa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index fbbcbed..c580434 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -561,7 +561,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END @@ -573,6 +573,6 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index c773e4d..9c363c0 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -997,7 +997,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC") .nr_irqs = PXA_NR_IRQS, .init_irq = viper_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = viper_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 491b6c9..aa89488 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -719,7 +719,7 @@ MACHINE_START(VPAC270, "Voipac PXA270") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = vpac270_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c index 4275713..13b1d45 100644 --- a/arch/arm/mach-pxa/xcep.c +++ b/arch/arm/mach-pxa/xcep.c @@ -185,7 +185,7 @@ MACHINE_START(XCEP, "Iskratel XCEP") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa25x_init_irq, .handle_irq = pxa25x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index 97529fa..989903a 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -722,7 +722,7 @@ MACHINE_START(ZIPIT2, "Zipit Z2") .nr_irqs = PXA_NR_IRQS, .init_irq = pxa27x_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = z2_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index abd3aa1..f5d4364 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -910,7 +910,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS") .nr_irqs = ZEUS_NR_IRQS, .init_irq = zeus_init_irq, .handle_irq = pxa27x_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = zeus_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 226279f..1f00d65 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -428,7 +428,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") .nr_irqs = ZYLONITE_NR_IRQS, .init_irq = pxa3xx_init_irq, .handle_irq = pxa3xx_handle_irq, - .timer = &pxa_timer, + .init_time = pxa_timer_init, .init_machine = zylonite_init, .restart = pxa_restart, MACHINE_END diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 6824674..1d5ee5c 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -42,7 +42,6 @@ #include <asm/mach/irq.h> #include <asm/mach/map.h> -#include <asm/hardware/gic.h> #include <mach/platform.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 300f706..98e3052 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -14,7 +14,6 @@ #include <linux/io.h> #include <mach/hardware.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> @@ -59,8 +58,6 @@ static void __init realview_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init realview_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 28511d4..5b1c8bf 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -27,13 +27,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/smp_twd.h> @@ -418,10 +418,6 @@ static void __init realview_eb_timer_init(void) realview_eb_twd_init(); } -static struct sys_timer realview_eb_timer = { - .init = realview_eb_timer_init, -}; - static void realview_eb_restart(char mode, const char *cmd) { void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL); @@ -472,8 +468,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") .map_io = realview_eb_map_io, .init_early = realview_init_early, .init_irq = gic_init_irq, - .timer = &realview_eb_timer, - .handle_irq = gic_handle_irq, + .init_time = realview_eb_timer_init, .init_machine = realview_eb_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index 07d6672..d5e83a1 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -29,13 +29,13 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/partitions.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> @@ -329,10 +329,6 @@ static void __init realview_pb1176_timer_init(void) realview_timer_init(IRQ_DC1176_TIMER0); } -static struct sys_timer realview_pb1176_timer = { - .init = realview_pb1176_timer_init, -}; - static void realview_pb1176_restart(char mode, const char *cmd) { void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL); @@ -384,8 +380,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") .map_io = realview_pb1176_map_io, .init_early = realview_init_early, .init_irq = gic_init_irq, - .timer = &realview_pb1176_timer, - .handle_irq = gic_handle_irq, + .init_time = realview_pb1176_timer_init, .init_machine = realview_pb1176_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 7ed53d7..c3cfe21 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -27,13 +27,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/smp_twd.h> @@ -316,10 +316,6 @@ static void __init realview_pb11mp_timer_init(void) realview_pb11mp_twd_init(); } -static struct sys_timer realview_pb11mp_timer = { - .init = realview_pb11mp_timer_init, -}; - static void realview_pb11mp_restart(char mode, const char *cmd) { void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL); @@ -367,8 +363,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") .map_io = realview_pb11mp_map_io, .init_early = realview_init_early, .init_irq = gic_init_irq, - .timer = &realview_pb11mp_timer, - .handle_irq = gic_handle_irq, + .init_time = realview_pb11mp_timer_init, .init_machine = realview_pb11mp_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 9992431..dde652a 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -27,12 +27,12 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -264,10 +264,6 @@ static void __init realview_pba8_timer_init(void) realview_timer_init(IRQ_PBA8_TIMER0_1); } -static struct sys_timer realview_pba8_timer = { - .init = realview_pba8_timer_init, -}; - static void realview_pba8_restart(char mode, const char *cmd) { void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL); @@ -308,8 +304,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") .map_io = realview_pba8_map_io, .init_early = realview_init_early, .init_irq = gic_init_irq, - .timer = &realview_pba8_timer, - .handle_irq = gic_handle_irq, + .init_time = realview_pba8_timer_init, .init_machine = realview_pba8_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 4f486f0..54f0185 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -26,13 +26,13 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-realview.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/smp_twd.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> @@ -324,10 +324,6 @@ static void __init realview_pbx_timer_init(void) realview_pbx_twd_init(); } -static struct sys_timer realview_pbx_timer = { - .init = realview_pbx_timer_init, -}; - static void realview_pbx_fixup(struct tag *tags, char **from, struct meminfo *meminfo) { @@ -404,8 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") .map_io = realview_pbx_map_io, .init_early = realview_init_early, .init_irq = gic_init_irq, - .timer = &realview_pbx_timer, - .handle_irq = gic_handle_irq, + .init_time = realview_pbx_timer_init, .init_machine = realview_pbx_init, #ifdef CONFIG_ZONE_DMA .dma_zone_size = SZ_256M, diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index f3fa259c..a302cf5 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -211,7 +211,7 @@ static void rpc_restart(char mode, const char *cmd) soft_restart(0); } -extern struct sys_timer ioc_timer; +void ioc_timer_init(void); MACHINE_START(RISCPC, "Acorn-RiscPC") /* Maintainer: Russell King */ @@ -220,6 +220,6 @@ MACHINE_START(RISCPC, "Acorn-RiscPC") .reserve_lp1 = 1, .map_io = rpc_map_io, .init_irq = rpc_init_irq, - .timer = &ioc_timer, + .init_time = ioc_timer_init, .restart = rpc_restart, MACHINE_END diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c index 581fca9..9a6def1 100644 --- a/arch/arm/mach-rpc/time.c +++ b/arch/arm/mach-rpc/time.c @@ -24,7 +24,7 @@ #include <asm/mach/time.h> -unsigned long ioc_timer_gettimeoffset(void) +static u32 ioc_timer_gettimeoffset(void) { unsigned int count1, count2, status; long offset; @@ -56,7 +56,7 @@ unsigned long ioc_timer_gettimeoffset(void) } offset = (LATCH - offset) * (tick_nsec / 1000); - return (offset + LATCH/2) / LATCH; + return ((offset + LATCH/2) / LATCH) * 1000; } void __init ioctime_init(void) @@ -82,14 +82,9 @@ static struct irqaction ioc_timer_irq = { /* * Set up timer interrupt. */ -static void __init ioc_timer_init(void) +void __init ioc_timer_init(void) { + arch_gettimeoffset = ioc_timer_gettimeoffset; ioctime_init(); setup_irq(IRQ_TIMER0, &ioc_timer_irq); } - -struct sys_timer ioc_timer = { - .init = ioc_timer_init, - .offset = ioc_timer_gettimeoffset, -}; - diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c index f4ad99c..0e0279e 100644 --- a/arch/arm/mach-s3c24xx/mach-amlm5900.c +++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c @@ -237,6 +237,6 @@ MACHINE_START(AML_M5900, "AML_M5900") .map_io = amlm5900_map_io, .init_irq = s3c24xx_init_irq, .init_machine = amlm5900_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 1ee8c46..85eefab 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -448,6 +448,6 @@ MACHINE_START(ANUBIS, "Simtec-Anubis") .map_io = anubis_map_io, .init_machine = anubis_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c index 00381fe..b31c4aa 100644 --- a/arch/arm/mach-s3c24xx/mach-at2440evb.c +++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c @@ -210,6 +210,6 @@ MACHINE_START(AT2440EVB, "AT2440EVB") .map_io = at2440evb_map_io, .init_machine = at2440evb_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index 6a30ce7..526964c 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -612,6 +612,6 @@ MACHINE_START(BAST, "Simtec-BAST") .map_io = bast_map_io, .init_irq = s3c24xx_init_irq, .init_machine = bast_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index 973b87c..fb5d3b3 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -595,6 +595,6 @@ MACHINE_START(NEO1973_GTA02, "GTA02") .map_io = gta02_map_io, .init_irq = s3c24xx_init_irq, .init_machine = gta02_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c index b23dd1b..2eb09e2 100644 --- a/arch/arm/mach-s3c24xx/mach-h1940.c +++ b/arch/arm/mach-s3c24xx/mach-h1940.c @@ -746,6 +746,6 @@ MACHINE_START(H1940, "IPAQ-H1940") .reserve = h1940_reserve, .init_irq = h1940_init_irq, .init_machine = h1940_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c index c9954e2..d7a1725 100644 --- a/arch/arm/mach-s3c24xx/mach-jive.c +++ b/arch/arm/mach-s3c24xx/mach-jive.c @@ -661,6 +661,6 @@ MACHINE_START(JIVE, "JIVE") .init_irq = s3c24xx_init_irq, .map_io = jive_map_io, .init_machine = jive_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index a31d5b8..2db09ade 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -688,6 +688,6 @@ MACHINE_START(MINI2440, "MINI2440") .map_io = mini2440_map_io, .init_machine = mini2440_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c index c53a9bf..d9d04b2 100644 --- a/arch/arm/mach-s3c24xx/mach-n30.c +++ b/arch/arm/mach-s3c24xx/mach-n30.c @@ -589,7 +589,7 @@ MACHINE_START(N30, "Acer-N30") Ben Dooks <ben-linux@fluff.org> */ .atag_offset = 0x100, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .init_machine = n30_init, .init_irq = s3c24xx_init_irq, .map_io = n30_map_io, @@ -600,7 +600,7 @@ MACHINE_START(N35, "Acer-N35") /* Maintainer: Christer Weinigel <christer@weinigel.se> */ .atag_offset = 0x100, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .init_machine = n30_init, .init_irq = s3c24xx_init_irq, .map_io = n30_map_io, diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c index a2b92b0..a454e24 100644 --- a/arch/arm/mach-s3c24xx/mach-nexcoder.c +++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c @@ -153,6 +153,6 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") .map_io = nexcoder_map_io, .init_machine = nexcoder_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index bb36d83..ba0f5b5 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -428,6 +428,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS") .map_io = osiris_map_io, .init_irq = s3c24xx_init_irq, .init_machine = osiris_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c index bca39f0..e0fdae9 100644 --- a/arch/arm/mach-s3c24xx/mach-otom.c +++ b/arch/arm/mach-s3c24xx/mach-otom.c @@ -118,6 +118,6 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1") .map_io = otom11_map_io, .init_machine = otom11_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c index 7b6ba13..56175f0 100644 --- a/arch/arm/mach-s3c24xx/mach-qt2410.c +++ b/arch/arm/mach-s3c24xx/mach-qt2410.c @@ -343,6 +343,6 @@ MACHINE_START(QT2410, "QT2410") .map_io = qt2410_map_io, .init_irq = s3c24xx_init_irq, .init_machine = qt2410_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index 0606f2f..e14ec71 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -814,6 +814,6 @@ MACHINE_START(RX1950, "HP iPAQ RX1950") .reserve = rx1950_reserve, .init_irq = s3c24xx_init_irq, .init_machine = rx1950_init_machine, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c index dacbb9a..d00caa8 100644 --- a/arch/arm/mach-s3c24xx/mach-rx3715.c +++ b/arch/arm/mach-s3c24xx/mach-rx3715.c @@ -212,6 +212,6 @@ MACHINE_START(RX3715, "IPAQ-RX3715") .reserve = rx3715_reserve, .init_irq = rx3715_init_irq, .init_machine = rx3715_init_machine, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c index 82796b9..e184bfa 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2410.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c @@ -117,6 +117,6 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc .map_io = smdk2410_map_io, .init_irq = s3c24xx_init_irq, .init_machine = smdk2410_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c index ce99fd8..69f356e 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2413.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c @@ -133,7 +133,7 @@ MACHINE_START(S3C2413, "S3C2413") .init_irq = s3c24xx_init_irq, .map_io = smdk2413_map_io, .init_machine = smdk2413_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2412_restart, MACHINE_END @@ -145,7 +145,7 @@ MACHINE_START(SMDK2412, "SMDK2412") .init_irq = s3c24xx_init_irq, .map_io = smdk2413_map_io, .init_machine = smdk2413_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2412_restart, MACHINE_END @@ -157,6 +157,6 @@ MACHINE_START(SMDK2413, "SMDK2413") .init_irq = s3c24xx_init_irq, .map_io = smdk2413_map_io, .init_machine = smdk2413_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index f30d7fc..fe160c7 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -254,6 +254,6 @@ MACHINE_START(SMDK2416, "SMDK2416") .init_irq = s3c24xx_init_irq, .map_io = smdk2416_map_io, .init_machine = smdk2416_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2416_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c index b7ff882..a8fdafe 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2440.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c @@ -182,6 +182,6 @@ MACHINE_START(S3C2440, "SMDK2440") .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index 2568656..7830d70 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c @@ -144,6 +144,6 @@ MACHINE_START(SMDK2443, "SMDK2443") .init_irq = s3c24xx_init_irq, .map_io = smdk2443_map_io, .init_machine = smdk2443_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2443_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c index 495bf5c..24b3d79 100644 --- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c +++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c @@ -149,6 +149,6 @@ MACHINE_START(TCT_HAMMER, "TCT_HAMMER") .map_io = tct_hammer_map_io, .init_irq = s3c24xx_init_irq, .init_machine = tct_hammer_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index 14d5b12..dda21a0 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -357,6 +357,6 @@ MACHINE_START(VR1000, "Thorcom-VR1000") .map_io = vr1000_map_io, .init_machine = vr1000_init, .init_irq = s3c24xx_init_irq, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c index f1d44ae..7fe7d4f 100644 --- a/arch/arm/mach-s3c24xx/mach-vstms.c +++ b/arch/arm/mach-s3c24xx/mach-vstms.c @@ -161,6 +161,6 @@ MACHINE_START(VSTMS, "VSTMS") .init_irq = s3c24xx_init_irq, .init_machine = vstms_init, .map_io = vstms_map_io, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index aef303b..0b9c0ba 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -25,10 +25,10 @@ #include <linux/dma-mapping.h> #include <linux/irq.h> #include <linux/gpio.h> +#include <linux/irqchip/arm-vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <asm/system_misc.h> #include <mach/map.h> diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h index bcce68a..6a112789 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h +++ b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h @@ -15,6 +15,5 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #endif /* __ASM_ARCH_6400_REGS_IRQ_H */ diff --git a/arch/arm/mach-s3c64xx/include/mach/tick.h b/arch/arm/mach-s3c64xx/include/mach/tick.h index ebe18a9..db9c1b1 100644 --- a/arch/arm/mach-s3c64xx/include/mach/tick.h +++ b/arch/arm/mach-s3c64xx/include/mach/tick.h @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_TICK_H #define __ASM_ARCH_TICK_H __FILE__ +#include <linux/irqchip/arm-vic.h> + /* note, the timer interrutps turn up in 2 places, the vic and then * the timer block. We take the VIC as the base at the moment. */ diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c index 99e82ac..afeae0b 100644 --- a/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -31,7 +31,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -230,10 +229,9 @@ MACHINE_START(ANW6410, "A&W6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = anw6410_map_io, .init_machine = anw6410_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index bf6311a..5b6adc7 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -42,7 +42,6 @@ #include <sound/wm1250-ev1.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> @@ -867,10 +866,9 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410") /* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = crag6410_map_io, .init_machine = crag6410_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c index 2b14489..7212eb9 100644 --- a/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/arch/arm/mach-s3c64xx/mach-hmt.c @@ -30,7 +30,6 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -273,10 +272,9 @@ MACHINE_START(HMT, "Airgoo-HMT") /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = hmt_map_io, .init_machine = hmt_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index 07c349c..e173e6e 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -24,7 +24,6 @@ #include <linux/serial_core.h> #include <linux/types.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -352,10 +351,9 @@ MACHINE_START(MINI6410, "MINI6410") /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = mini6410_map_io, .init_machine = mini6410_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c index e5f9a79..8d3cedd 100644 --- a/arch/arm/mach-s3c64xx/mach-ncp.c +++ b/arch/arm/mach-s3c64xx/mach-ncp.c @@ -26,7 +26,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -101,10 +100,9 @@ MACHINE_START(NCP, "NCP") /* Maintainer: Samsung Electronics */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = ncp_map_io, .init_machine = ncp_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 7476f7c..4d0d47a 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -25,7 +25,6 @@ #include <linux/serial_core.h> #include <linux/types.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -331,10 +330,9 @@ MACHINE_START(REAL6410, "REAL6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = real6410_map_io, .init_machine = real6410_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index 96d6da2..ca2afcf 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -17,7 +17,6 @@ #include <linux/leds.h> #include <linux/platform_device.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -153,10 +152,9 @@ MACHINE_START(SMARTQ5, "SmartQ 5") /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq5_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index 7d1167b..37bb0c6 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -17,7 +17,6 @@ #include <linux/leds.h> #include <linux/platform_device.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -169,10 +168,9 @@ MACHINE_START(SMARTQ7, "SmartQ 7") /* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq7_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c index a928fae..a392869 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6400.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c @@ -22,7 +22,6 @@ #include <asm/mach-types.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -90,10 +89,9 @@ MACHINE_START(SMDK6400, "SMDK6400") .atag_offset = 0x100, .init_irq = s3c6400_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6400_map_io, .init_machine = smdk6400_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index 574a9ee..1663d10 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -45,7 +45,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -700,10 +699,9 @@ MACHINE_START(SMDK6410, "SMDK6410") .atag_offset = 0x100, .init_irq = s3c6410_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6410_map_io, .init_machine = smdk6410_machine_init, .init_late = s3c64xx_init_late, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s3c64xx_restart, MACHINE_END diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h index 4aaebda..d60397d 100644 --- a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h deleted file mode 100644 index 00aa7f1..0000000 --- a/arch/arm/mach-s5p64x0/include/mach/tick.h +++ /dev/null @@ -1,29 +0,0 @@ -/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h - * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@simtec.co.uk> - * - * S5P64X0 - Timer tick support definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_TICK_H -#define __ASM_ARCH_TICK_H __FILE__ - -static inline u32 s3c24xx_ostimer_pending(void) -{ - u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS); - return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0))); -} - -#define TICK_MAX (0xffffffff) - -#endif /* __ASM_ARCH_TICK_H */ diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 1af8235..a40d5eb 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -29,7 +29,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -272,9 +271,8 @@ MACHINE_START(SMDK6440, "SMDK6440") .atag_offset = 0x100, .init_irq = s5p6440_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6440_map_io, .init_machine = smdk6440_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5p64x0_restart, MACHINE_END diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 62526cc..703e576 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -29,7 +29,6 @@ #include <video/platform_lcd.h> #include <video/samsung_fimd.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h> @@ -291,9 +290,8 @@ MACHINE_START(SMDK6450, "SMDK6450") .atag_offset = 0x100, .init_irq = s5p6450_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdk6450_map_io, .init_machine = smdk6450_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5p64x0_restart, MACHINE_END diff --git a/arch/arm/mach-s5pc100/include/mach/regs-irq.h b/arch/arm/mach-s5pc100/include/mach/regs-irq.h index 4d9036d..7616278 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-irq.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-irq.h @@ -14,6 +14,5 @@ #define __ASM_ARCH_REGS_IRQ_H __FILE__ #include <mach/map.h> -#include <asm/hardware/vic.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h index 20f6873..0af8e41 100644 --- a/arch/arm/mach-s5pc100/include/mach/tick.h +++ b/arch/arm/mach-s5pc100/include/mach/tick.h @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_TICK_H #define __ASM_ARCH_TICK_H __FILE__ +#include <linux/irqchip/arm-vic.h> + /* note, the timer interrutps turn up in 2 places, the vic and then * the timer block. We take the VIC as the base at the moment. */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 9abe95e..185a195 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -25,7 +25,6 @@ #include <linux/input.h> #include <linux/pwm_backlight.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -254,9 +253,8 @@ MACHINE_START(SMDKC100, "SMDKC100") /* Maintainer: Byungho Min <bhmin@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pc100_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkc100_map_io, .init_machine = smdkc100_machine_init, - .timer = &s3c24xx_timer, + .init_time = s3c24xx_timer_init, .restart = s5pc100_restart, MACHINE_END diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h index 5c3b104..d8bc1e6 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-irq.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-irq.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_REGS_IRQ_H #define __ASM_ARCH_REGS_IRQ_H __FILE__ -#include <asm/hardware/vic.h> #include <mach/map.h> #endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/tick.h b/arch/arm/mach-s5pv210/include/mach/tick.h deleted file mode 100644 index 7993b36..0000000 --- a/arch/arm/mach-s5pv210/include/mach/tick.h +++ /dev/null @@ -1,26 +0,0 @@ -/* linux/arch/arm/mach-s5pv210/include/mach/tick.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Based on arch/arm/mach-s3c6400/include/mach/tick.h - * - * S5PV210 - Timer tick support definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_TICK_H -#define __ASM_ARCH_TICK_H __FILE__ - -static inline u32 s3c24xx_ostimer_pending(void) -{ - u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS); - return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0))); -} - -#define TICK_MAX (0xffffffff) - -#endif /* __ASM_ARCH_TICK_H */ diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index ee9fa5c..11900a8 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -22,7 +22,6 @@ #include <linux/input.h> #include <linux/gpio.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -685,9 +684,8 @@ MACHINE_START(AQUILA, "Aquila") Kyungmin Park <kyungmin.park@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = aquila_map_io, .init_machine = aquila_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5pv210_restart, MACHINE_END diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index c72b310..5704815 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -29,7 +29,6 @@ #include <linux/interrupt.h> #include <linux/platform_data/s3c-hsotg.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -972,10 +971,9 @@ MACHINE_START(GONI, "GONI") /* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = goni_map_io, .init_machine = goni_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .reserve = &goni_reserve, .restart = s5pv210_restart, MACHINE_END diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index f1f3bd3..28bd024 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -15,7 +15,6 @@ #include <linux/i2c.h> #include <linux/device.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -152,10 +151,9 @@ MACHINE_START(SMDKC110, "SMDKC110") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkc110_map_io, .init_machine = smdkc110_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5pv210_restart, .reserve = &smdkc110_reserve, MACHINE_END diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 6bc8404..3c73f36 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -21,7 +21,6 @@ #include <linux/pwm_backlight.h> #include <linux/platform_data/s3c-hsotg.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -328,10 +327,9 @@ MACHINE_START(SMDKV210, "SMDKV210") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = smdkv210_map_io, .init_machine = smdkv210_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5pv210_restart, .reserve = &smdkv210_reserve, MACHINE_END diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c index 18785cb..2d4c553 100644 --- a/arch/arm/mach-s5pv210/mach-torbreck.c +++ b/arch/arm/mach-s5pv210/mach-torbreck.c @@ -14,7 +14,6 @@ #include <linux/init.h> #include <linux/serial_core.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h> @@ -129,9 +128,8 @@ MACHINE_START(TORBRECK, "TORBRECK") /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */ .atag_offset = 0x100, .init_irq = s5pv210_init_irq, - .handle_irq = vic_handle_irq, .map_io = torbreck_map_io, .init_machine = torbreck_machine_init, - .timer = &s5p_timer, + .init_time = s5p_timer_init, .restart = s5pv210_restart, MACHINE_END diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 9a23739..b38d252 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -621,7 +621,7 @@ MACHINE_START(ASSABET, "Intel-Assabet") .map_io = assabet_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = assabet_init, .init_late = sa11x0_init_late, #ifdef CONFIG_SA1111 diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index b2dadf3..63361b6 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -336,7 +336,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, .init_late = sa11x0_init_late, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, #ifdef CONFIG_SA1111 .dma_zone_size = SZ_1M, #endif diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 304bca4..2d25ece 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -174,7 +174,7 @@ MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") .map_io = cerf_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = cerf_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = cerf_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 45f424f..612a456 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -399,7 +399,7 @@ MACHINE_START(COLLIE, "Sharp-Collie") .map_io = collie_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = collie_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index a5b7c13..2abc6a1 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -4,9 +4,7 @@ * Author: Nicolas Pitre */ -struct sys_timer; - -extern struct sys_timer sa1100_timer; +extern void sa1100_timer_init(void); extern void __init sa1100_map_io(void); extern void __init sa1100_init_irq(void); extern void __init sa1100_init_gpio(void); diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c index e1571ea..b8f2b15 100644 --- a/arch/arm/mach-sa1100/h3100.c +++ b/arch/arm/mach-sa1100/h3100.c @@ -108,7 +108,7 @@ MACHINE_START(H3100, "Compaq iPAQ H3100") .map_io = h3100_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = h3100_mach_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index ba7a290..b8dc5bd 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -158,7 +158,7 @@ MACHINE_START(H3600, "Compaq iPAQ H3600") .map_io = h3600_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = h3600_mach_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index d005939..643d5f2 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -229,7 +229,7 @@ MACHINE_START(HACKKIT, "HackKit Cpu Board") .map_io = hackkit_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = hackkit_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 35cfc42..c0b1f5b 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -346,7 +346,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720") .map_io = jornada720_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = jornada720_mach_init, .init_late = sa11x0_init_late, #ifdef CONFIG_SA1111 diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index f69f78f..a899176 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -174,6 +174,6 @@ MACHINE_START(LART, "LART") .init_irq = sa1100_init_irq, .init_machine = lart_init, .init_late = sa11x0_init_late, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .restart = sa11x0_restart, MACHINE_END diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c index 102e08f..f1cb378 100644 --- a/arch/arm/mach-sa1100/nanoengine.c +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -110,7 +110,7 @@ MACHINE_START(NANOENGINE, "BSE nanoEngine") .map_io = nanoengine_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = nanoengine_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index c51bb63..0912618 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -133,7 +133,7 @@ MACHINE_START(PLEB, "PLEB") .map_io = pleb_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = pleb_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 6460d25..c8866bc 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -102,7 +102,7 @@ MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") .map_io = shannon_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .init_machine = shannon_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 6d65f65..bcbc945 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -396,6 +396,6 @@ MACHINE_START(SIMPAD, "Simpad") .nr_irqs = SA1100_NR_IRQS, .init_irq = sa1100_init_irq, .init_late = sa11x0_init_late, - .timer = &sa1100_timer, + .init_time = sa1100_timer_init, .restart = sa11x0_restart, MACHINE_END diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 80702c9..a59a13a 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -69,46 +69,10 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) } } -static struct clock_event_device ckevt_sa1100_osmr0 = { - .name = "osmr0", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = sa1100_osmr0_set_next_event, - .set_mode = sa1100_osmr0_set_mode, -}; - -static struct irqaction sa1100_timer_irq = { - .name = "ost0", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = sa1100_ost0_interrupt, - .dev_id = &ckevt_sa1100_osmr0, -}; - -static void __init sa1100_timer_init(void) -{ - writel_relaxed(0, OIER); - writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); - - setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); - - clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); - ckevt_sa1100_osmr0.max_delta_ns = - clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0); - ckevt_sa1100_osmr0.min_delta_ns = - clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1; - ckevt_sa1100_osmr0.cpumask = cpumask_of(0); - - setup_irq(IRQ_OST0, &sa1100_timer_irq); - - clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, - clocksource_mmio_readl_up); - clockevents_register_device(&ckevt_sa1100_osmr0); -} - #ifdef CONFIG_PM unsigned long osmr[4], oier; -static void sa1100_timer_suspend(void) +static void sa1100_timer_suspend(struct clock_event_device *cedev) { osmr[0] = readl_relaxed(OSMR0); osmr[1] = readl_relaxed(OSMR1); @@ -117,7 +81,7 @@ static void sa1100_timer_suspend(void) oier = readl_relaxed(OIER); } -static void sa1100_timer_resume(void) +static void sa1100_timer_resume(struct clock_event_device *cedev) { writel_relaxed(0x0f, OSSR); writel_relaxed(osmr[0], OSMR0); @@ -136,8 +100,36 @@ static void sa1100_timer_resume(void) #define sa1100_timer_resume NULL #endif -struct sys_timer sa1100_timer = { - .init = sa1100_timer_init, +static struct clock_event_device ckevt_sa1100_osmr0 = { + .name = "osmr0", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = sa1100_osmr0_set_next_event, + .set_mode = sa1100_osmr0_set_mode, .suspend = sa1100_timer_suspend, .resume = sa1100_timer_resume, }; + +static struct irqaction sa1100_timer_irq = { + .name = "ost0", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = sa1100_ost0_interrupt, + .dev_id = &ckevt_sa1100_osmr0, +}; + +void __init sa1100_timer_init(void) +{ + writel_relaxed(0, OIER); + writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); + + setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); + + ckevt_sa1100_osmr0.cpumask = cpumask_of(0); + + setup_irq(IRQ_OST0, &sa1100_timer_irq); + + clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, + clocksource_mmio_readl_up); + clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400, + MIN_OSCR_DELTA * 2, 0x7fffffff); +} diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 9ad2e97..b63dec8 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -128,10 +128,6 @@ static void __init shark_timer_init(void) setup_irq(IRQ_TIMER, &shark_timer_irq); } -static struct sys_timer shark_timer = { - .init = shark_timer_init, -}; - static void shark_init_early(void) { disable_hlt(); @@ -142,7 +138,7 @@ MACHINE_START(SHARK, "Shark") .atag_offset = 0x3000, .init_early = shark_init_early, .init_irq = shark_init_irq, - .timer = &shark_timer, + .init_time = shark_timer_init, .dma_zone_size = SZ_4M, .restart = shark_restart, MACHINE_END diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 0b71479..700e662 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o # SMP objects smp-y := platsmp.o headsmp.o smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o -smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o +smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o @@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o +obj-$(CONFIG_ARCH_SH73A0) += pm-sh73a0.o # Board objects obj-$(CONFIG_MACH_AP4EVB) += board-ap4evb.o diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 032d108..705bc63 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -40,6 +40,7 @@ #include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mfd/tmio.h> #include <linux/sh_clk.h> +#include <linux/irqchip/arm-gic.h> #include <video/sh_mobile_lcdc.h> #include <video/sh_mipi_dsi.h> #include <sound/sh_fsi.h> @@ -49,7 +50,6 @@ #include <mach/common.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> @@ -668,8 +668,7 @@ MACHINE_START(AG5EVM, "ag5evm") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = ag5evm_init, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = sh73a0_earlytimer_init, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 99ef190..c1d4ab6 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -1350,5 +1350,5 @@ MACHINE_START(AP4EVB, "ap4evb") .handle_irq = shmobile_handle_irq_intc, .init_machine = ap4evb_init, .init_late = sh7372_pm_init_late, - .timer = &shmobile_timer, + .init_time = sh7372_earlytimer_init, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 5353adf..6573137 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1181,6 +1181,8 @@ static void __init eva_init(void) rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device); if (usb) rmobile_add_device_to_domain("A3SP", usb); + + r8a7740_pm_init(); } static void __init eva_earlytimer_init(void) @@ -1192,9 +1194,6 @@ static void __init eva_earlytimer_init(void) static void __init eva_add_early_devices(void) { r8a7740_add_early_devices(); - - /* override timer setup with board-specific code */ - shmobile_timer.init = eva_earlytimer_init; } #define RESCNT2 IOMEM(0xe6188020) @@ -1216,7 +1215,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") .handle_irq = shmobile_handle_irq_intc, .init_machine = eva_init, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = eva_earlytimer_init, .dt_compat = eva_boards_compat_dt, .restart = eva_restart, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c index cb8c994..331b7ce 100644 --- a/arch/arm/mach-shmobile/board-bonito.c +++ b/arch/arm/mach-shmobile/board-bonito.c @@ -499,9 +499,6 @@ static void __init bonito_earlytimer_init(void) static void __init bonito_add_early_devices(void) { r8a7740_add_early_devices(); - - /* override timer setup with board-specific code */ - shmobile_timer.init = bonito_earlytimer_init; } MACHINE_START(BONITO, "bonito") @@ -511,5 +508,5 @@ MACHINE_START(BONITO, "bonito") .handle_irq = shmobile_handle_irq_intc, .init_machine = bonito_init, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = bonito_earlytimer_init, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index bf88f9a..d759a9c 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -35,6 +35,7 @@ #include <linux/input/sh_keysc.h> #include <linux/gpio_keys.h> #include <linux/leds.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/leds-renesas-tpu.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> @@ -47,7 +48,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> @@ -550,8 +550,7 @@ MACHINE_START(KOTA2, "kota2") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kota2_init, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = sh73a0_earlytimer_init, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index b52bc0d..c254782 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -28,7 +28,6 @@ #include <mach/emev2.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> /* Dummy supplies, where voltage doesn't matter */ static struct regulator_consumer_supply dummy_supplies[] = { @@ -89,9 +88,8 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d") .init_early = emev2_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = emev2_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kzm9d_add_standard_devices, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = shmobile_timer_init, .dt_compat = kzm9d_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index c02448d..363c6ed 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -25,6 +25,7 @@ #include <linux/i2c.h> #include <linux/i2c/pcf857x.h> #include <linux/input.h> +#include <linux/irqchip/arm-gic.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mobile_sdhi.h> @@ -42,7 +43,6 @@ #include <mach/sh73a0.h> #include <mach/common.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <video/sh_mobile_lcdc.h> @@ -772,6 +772,8 @@ static void __init kzm_init(void) sh73a0_add_standard_devices(); platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); + + sh73a0_pm_init(); } static void kzm9g_restart(char mode, const char *cmd) @@ -792,10 +794,9 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g") .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = sh73a0_init_irq, - .handle_irq = gic_handle_irq, .init_machine = kzm_init, .init_late = shmobile_init_late, - .timer = &shmobile_timer, + .init_time = sh73a0_earlytimer_init, .restart = kzm9g_restart, .dt_compat = kzm9g_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 2fed62f..fe4917f 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -1593,6 +1593,6 @@ DT_MACHINE_START(MACKEREL_DT, "mackerel") .handle_irq = shmobile_handle_irq_intc, .init_machine = mackerel_init, .init_late = sh7372_pm_init_late, - .timer = &shmobile_timer, + .init_time = sh7372_earlytimer_init, .dt_compat = mackerel_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index 449f928..cdcb799 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -44,7 +44,6 @@ #include <mach/irqs.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <asm/traps.h> /* Fixed 3.3V regulator to be used by SDHI0 */ @@ -382,8 +381,7 @@ MACHINE_START(MARZEN, "marzen") .init_early = r8a7779_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, .init_irq = r8a7779_init_irq, - .handle_irq = gic_handle_irq, .init_machine = marzen_init, .init_late = marzen_init_late, - .timer = &shmobile_timer, + .init_time = r8a7779_earlytimer_init, MACHINE_END diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index eac49d5..19ce885 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -581,10 +581,14 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), - CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP111]), + CLKDEV_DEV_ID("sh_tmu.3", &mstp_clks[MSTP111]), + CLKDEV_DEV_ID("sh_tmu.4", &mstp_clks[MSTP111]), + CLKDEV_DEV_ID("sh_tmu.5", &mstp_clks[MSTP111]), CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), + CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), + CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP125]), CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index c019609..202370d 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -161,7 +161,8 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ CLKDEV_DEV_ID("ohci-platform.0", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */ CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */ - CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */ + CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */ + CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP014]), /* TMU02 */ CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */ CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */ CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */ diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 3ca6757b..45d21fe 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -544,6 +544,7 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ + CLKDEV_DEV_ID("fff30000.i2c", &mstp_clks[MSTP001]), /* IIC2 */ CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */ CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */ CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */ @@ -556,6 +557,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ + CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), /* IIC0 */ CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */ CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */ CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */ @@ -577,18 +579,25 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ + CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), /* IIC1 */ CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ + CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ + CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */ + CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMC */ CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */ + CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), /* SDHI2 */ CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */ + CLKDEV_DEV_ID("e6d20000.i2c", &mstp_clks[MSTP411]), /* IIC3 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */ + CLKDEV_DEV_ID("e6d30000.i2c", &mstp_clks[MSTP410]), /* IIC4 */ CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */ CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 516ff7f..afa5423 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -264,17 +264,17 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2, SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags) static struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT), - [DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT), - [DIV4_M3] = DIV4(FRQCRA, 12, 0xfff, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT), - [DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0), - [DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0), - [DIV4_Z] = DIV4(FRQCRB, 24, 0xbff, 0), - [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xfff, 0), - [DIV4_ZT] = DIV4(FRQCRB, 16, 0xfff, 0), - [DIV4_ZX] = DIV4(FRQCRB, 12, 0xfff, 0), - [DIV4_HP] = DIV4(FRQCRB, 4, 0xfff, 0), + [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT), + [DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT), + [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT), + [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0), + [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0), + [DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0), + [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0), + [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0), + [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0), + [DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0), }; enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, @@ -525,6 +525,13 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ }; +/* The lookups structure below includes duplicate entries for some clocks + * with alternate names. + * - The traditional name used when a device is initialised with platform data + * - The name used when a device is initialised using device tree + * The longer-term aim is to remove these duplicates, and indeed the + * lookups table entirely, by describing clocks using device tree. + */ static struct clk_lookup lookups[] = { /* main clocks */ CLKDEV_CON_ID("r_clk", &r_clk), @@ -545,6 +552,7 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ + CLKDEV_DEV_ID("e6824000.i2c", &mstp_clks[MSTP001]), /* I2C2 */ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */ CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */ @@ -553,6 +561,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */ CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */ + CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */ @@ -569,17 +578,21 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ + CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ + CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */ CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */ CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */ CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ + CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ + CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ }; diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S new file mode 100644 index 0000000..bec4c0d --- /dev/null +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S @@ -0,0 +1,50 @@ +/* + * SMP support for SoC sh73a0 + * + * Copyright (C) 2012 Bastian Hecht + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/memory.h> + + __CPUINIT +/* + * Reset vector for secondary CPUs. + * + * First we turn on L1 cache coherency for our CPU. Then we jump to + * shmobile_invalidate_start that invalidates the cache and hands over control + * to the common ARM startup code. + * This function will be mapped to address 0 by the SBAR register. + * A normal branch is out of range here so we need a long jump. We jump to + * the physical address as the MMU is still turned off. + */ + .align 12 +ENTRY(sh73a0_secondary_vector) + mrc p15, 0, r0, c0, c0, 5 @ read MIPDR + and r0, r0, #3 @ mask out cpu ID + lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits + mov r1, #0xf0000000 @ SCU base address + ldr r2, [r1, #8] @ SCU Power Status Register + mov r3, #3 + bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode) + str r2, [r1, #8] @ write back + + ldr pc, 1f +1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET +ENDPROC(sh73a0_secondary_vector) diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index b09a0bd..a1524e3 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c @@ -56,6 +56,12 @@ int shmobile_cpu_disable(unsigned int cpu) return cpu == 0 ? -EPERM : 0; } +int shmobile_cpu_disable_any(unsigned int cpu) +{ + cpumask_clear_cpu(cpu, &dead_cpus); + return 0; +} + int shmobile_cpu_is_dead(unsigned int cpu) { return cpumask_test_cpu(cpu, &dead_cpus); diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index dfeca79..e48606d 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -2,7 +2,7 @@ #define __ARCH_MACH_COMMON_H extern void shmobile_earlytimer_init(void); -extern struct sys_timer shmobile_timer; +extern void shmobile_timer_init(void); extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz, unsigned int mult, unsigned int div); struct twd_local_timer; @@ -20,8 +20,11 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); extern void sh7372_init_irq(void); extern void sh7372_map_io(void); +extern void sh7372_earlytimer_init(void); extern void sh7372_add_early_devices(void); extern void sh7372_add_standard_devices(void); +extern void sh7372_add_early_devices_dt(void); +extern void sh7372_add_standard_devices_dt(void); extern void sh7372_clock_init(void); extern void sh7372_pinmux_init(void); extern void sh7372_pm_init(void); @@ -31,11 +34,17 @@ extern struct clk sh7372_extal1_clk; extern struct clk sh7372_extal2_clk; extern void sh73a0_init_irq(void); +extern void sh73a0_init_irq_dt(void); extern void sh73a0_map_io(void); +extern void sh73a0_earlytimer_init(void); extern void sh73a0_add_early_devices(void); +extern void sh73a0_add_early_devices_dt(void); extern void sh73a0_add_standard_devices(void); +extern void sh73a0_add_standard_devices_dt(void); extern void sh73a0_clock_init(void); extern void sh73a0_pinmux_init(void); +extern void sh73a0_pm_init(void); +extern void sh73a0_secondary_vector(void); extern struct clk sh73a0_extal1_clk; extern struct clk sh73a0_extal2_clk; extern struct clk sh73a0_extcki_clk; @@ -47,9 +56,11 @@ extern void r8a7740_add_early_devices(void); extern void r8a7740_add_standard_devices(void); extern void r8a7740_clock_init(u8 md_ck); extern void r8a7740_pinmux_init(void); +extern void r8a7740_pm_init(void); extern void r8a7779_init_irq(void); extern void r8a7779_map_io(void); +extern void r8a7779_earlytimer_init(void); extern void r8a7779_add_early_devices(void); extern void r8a7779_add_standard_devices(void); extern void r8a7779_clock_init(void); @@ -73,6 +84,7 @@ static inline int shmobile_cpuidle_init(void) { return 0; } extern void shmobile_cpu_die(unsigned int cpu); extern int shmobile_cpu_disable(unsigned int cpu); +extern int shmobile_cpu_disable_any(unsigned int cpu); #ifdef CONFIG_HOTPLUG_CPU extern int shmobile_cpu_is_dead(unsigned int cpu); diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c index ef66f1a..8807c27 100644 --- a/arch/arm/mach-shmobile/intc-r8a7779.c +++ b/arch/arm/mach-shmobile/intc-r8a7779.c @@ -22,10 +22,10 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/intc.h> #include <mach/r8a7779.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index f0c5e51..91faba6 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -23,10 +23,11 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/sh_intc.h> +#include <linux/irqchip.h> +#include <linux/irqchip/arm-gic.h> #include <mach/intc.h> #include <mach/irqs.h> #include <mach/sh73a0.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -315,11 +316,6 @@ static int intca_gic_set_type(struct irq_data *data, unsigned int type) return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type); } -static int intca_gic_set_wake(struct irq_data *data, unsigned int on) -{ - return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on); -} - #ifdef CONFIG_SMP static int intca_gic_set_affinity(struct irq_data *data, const struct cpumask *cpumask, @@ -339,7 +335,7 @@ struct irq_chip intca_gic_irq_chip = { .irq_disable = intca_gic_disable, .irq_shutdown = intca_gic_disable, .irq_set_type = intca_gic_set_type, - .irq_set_wake = intca_gic_set_wake, + .irq_set_wake = sh73a0_set_wake, #ifdef CONFIG_SMP .irq_set_affinity = intca_gic_set_affinity, #endif @@ -464,3 +460,11 @@ void __init sh73a0_init_irq(void) sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; setup_irq(gic_spi(34), &sh73a0_pint1_cascade); } + +#ifdef CONFIG_OF +void __init sh73a0_init_irq_dt(void) +{ + irqchip_init(); + gic_arch_extn.irq_set_wake = sh73a0_set_wake; +} +#endif diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index ed8d235..1f958d7 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -12,7 +12,6 @@ */ #include <linux/init.h> #include <linux/smp.h> -#include <asm/hardware/gic.h> void __init shmobile_smp_init_cpus(unsigned int ncores) { @@ -26,6 +25,4 @@ void __init shmobile_smp_init_cpus(unsigned int ncores) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index 21e5316d..40b87aa 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -9,7 +9,9 @@ * for more details. */ #include <linux/console.h> +#include <linux/suspend.h> #include <mach/pm-rmobile.h> +#include <mach/common.h> #ifdef CONFIG_PM static int r8a7740_pd_a4s_suspend(void) @@ -58,3 +60,23 @@ void __init r8a7740_init_pm_domains(void) } #endif /* CONFIG_PM */ + +#ifdef CONFIG_SUSPEND +static int r8a7740_enter_suspend(suspend_state_t suspend_state) +{ + cpu_do_idle(); + return 0; +} + +static void r8a7740_suspend_init(void) +{ + shmobile_suspend_ops.enter = r8a7740_enter_suspend; +} +#else +static void r8a7740_suspend_init(void) {} +#endif + +void __init r8a7740_pm_init(void) +{ + r8a7740_suspend_init(); +} diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c new file mode 100644 index 0000000..99086e9 --- /dev/null +++ b/arch/arm/mach-shmobile/pm-sh73a0.c @@ -0,0 +1,32 @@ +/* + * sh73a0 Power management support + * + * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/suspend.h> +#include <mach/common.h> + +#ifdef CONFIG_SUSPEND +static int sh73a0_enter_suspend(suspend_state_t suspend_state) +{ + cpu_do_idle(); + return 0; +} + +static void sh73a0_suspend_init(void) +{ + shmobile_suspend_ops.enter = sh73a0_enter_suspend; +} +#else +static void sh73a0_suspend_init(void) {} +#endif + +void __init sh73a0_pm_init(void) +{ + sh73a0_suspend_init(); +} diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index a47beeb..47662a5 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c @@ -20,13 +20,14 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/platform_device.h> #include <linux/platform_data/gpio-em.h> #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> -#include <linux/of_irq.h> +#include <linux/irqchip/arm-gic.h> #include <mach/hardware.h> #include <mach/common.h> #include <mach/emev2.h> @@ -35,7 +36,6 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/gic.h> static struct map_desc emev2_io_desc[] __initdata = { #ifdef CONFIG_SMP @@ -445,29 +445,18 @@ void __init emev2_add_standard_devices_dt(void) emev2_auxdata_lookup, NULL); } -static const struct of_device_id emev2_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {}, -}; - static const char *emev2_boards_compat_dt[] __initdata = { "renesas,emev2", NULL, }; -void __init emev2_init_irq_dt(void) -{ - of_irq_init(emev2_dt_irq_match); -} - DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") .smp = smp_ops(emev2_smp_ops), .init_early = emev2_init_delay, .nr_irqs = NR_IRQS_LEGACY, - .init_irq = emev2_init_irq_dt, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = emev2_add_standard_devices_dt, - .timer = &shmobile_timer, + .init_time = shmobile_timer_init, .dt_compat = emev2_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 0952224..847567d 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -27,7 +27,6 @@ #include <linux/serial_sci.h> #include <linux/sh_dma.h> #include <linux/sh_timer.h> -#include <linux/dma-mapping.h> #include <mach/dma-register.h> #include <mach/r8a7740.h> #include <mach/pm-rmobile.h> @@ -262,6 +261,97 @@ static struct platform_device cmt10_device = { .num_resources = ARRAY_SIZE(cmt10_resources), }; +/* TMU */ +static struct sh_timer_config tmu00_platform_data = { + .name = "TMU00", + .channel_offset = 0x4, + .timer_bit = 0, + .clockevent_rating = 200, +}; + +static struct resource tmu00_resources[] = { + [0] = { + .name = "TMU00", + .start = 0xfff80008, + .end = 0xfff80014 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0xe80), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tmu00_device = { + .name = "sh_tmu", + .id = 0, + .dev = { + .platform_data = &tmu00_platform_data, + }, + .resource = tmu00_resources, + .num_resources = ARRAY_SIZE(tmu00_resources), +}; + +static struct sh_timer_config tmu01_platform_data = { + .name = "TMU01", + .channel_offset = 0x10, + .timer_bit = 1, + .clocksource_rating = 200, +}; + +static struct resource tmu01_resources[] = { + [0] = { + .name = "TMU01", + .start = 0xfff80014, + .end = 0xfff80020 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0xea0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tmu01_device = { + .name = "sh_tmu", + .id = 1, + .dev = { + .platform_data = &tmu01_platform_data, + }, + .resource = tmu01_resources, + .num_resources = ARRAY_SIZE(tmu01_resources), +}; + +static struct sh_timer_config tmu02_platform_data = { + .name = "TMU02", + .channel_offset = 0x1C, + .timer_bit = 2, + .clocksource_rating = 200, +}; + +static struct resource tmu02_resources[] = { + [0] = { + .name = "TMU02", + .start = 0xfff80020, + .end = 0xfff8002C - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0xec0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tmu02_device = { + .name = "sh_tmu", + .id = 2, + .dev = { + .platform_data = &tmu02_platform_data, + }, + .resource = tmu02_resources, + .num_resources = ARRAY_SIZE(tmu02_resources), +}; + static struct platform_device *r8a7740_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -273,6 +363,9 @@ static struct platform_device *r8a7740_early_devices[] __initdata = { &scif7_device, &scifb_device, &cmt10_device, + &tmu00_device, + &tmu01_device, + &tmu02_device, }; /* DMA */ @@ -705,12 +798,6 @@ void __init r8a7740_add_standard_devices(void) rmobile_add_device_to_domain("A3SP", &i2c1_device); } -static void __init r8a7740_earlytimer_init(void) -{ - r8a7740_clock_init(0); - shmobile_earlytimer_init(); -} - void __init r8a7740_add_early_devices(void) { early_platform_add_devices(r8a7740_early_devices, @@ -718,9 +805,6 @@ void __init r8a7740_add_early_devices(void) /* setup early console here as well */ shmobile_setup_console(); - - /* override timer setup with soc-specific code */ - shmobile_timer.init = r8a7740_earlytimer_init; } #ifdef CONFIG_USE_OF @@ -763,7 +847,7 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)") .init_irq = r8a7740_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = r8a7740_add_standard_devices_dt, - .timer = &shmobile_timer, + .init_time = shmobile_timer_init, .dt_compat = r8a7740_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 7a1ad4f..7e87ab3 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -66,8 +66,7 @@ static struct plat_sci_port scif0_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(88), gic_spi(88), - gic_spi(88), gic_spi(88) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(88)), }; static struct platform_device scif0_device = { @@ -84,8 +83,7 @@ static struct plat_sci_port scif1_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(89), gic_spi(89), - gic_spi(89), gic_spi(89) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(89)), }; static struct platform_device scif1_device = { @@ -102,8 +100,7 @@ static struct plat_sci_port scif2_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(90), gic_spi(90), - gic_spi(90), gic_spi(90) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(90)), }; static struct platform_device scif2_device = { @@ -120,8 +117,7 @@ static struct plat_sci_port scif3_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(91), gic_spi(91), - gic_spi(91), gic_spi(91) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(91)), }; static struct platform_device scif3_device = { @@ -138,8 +134,7 @@ static struct plat_sci_port scif4_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(92), gic_spi(92), - gic_spi(92), gic_spi(92) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(92)), }; static struct platform_device scif4_device = { @@ -156,8 +151,7 @@ static struct plat_sci_port scif5_platform_data = { .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { gic_spi(93), gic_spi(93), - gic_spi(93), gic_spi(93) }, + .irqs = SCIx_IRQ_MUXED(gic_spi(93)), }; static struct platform_device scif5_device = { @@ -339,7 +333,7 @@ void __init r8a7779_add_standard_devices(void) /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ void __init __weak r8a7779_register_twd(void) { } -static void __init r8a7779_earlytimer_init(void) +void __init r8a7779_earlytimer_init(void) { r8a7779_clock_init(); shmobile_earlytimer_init(); @@ -366,7 +360,4 @@ void __init r8a7779_add_early_devices(void) * As a final step pass earlyprint=sh-sci.2,115200 on the kernel * command line in case of the marzen board. */ - - /* override timer setup with soc-specific code */ - shmobile_timer.init = r8a7779_earlytimer_init; } diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index c917882..191ae72 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1054,7 +1054,7 @@ void __init sh7372_add_standard_devices(void) ARRAY_SIZE(domain_devices)); } -static void __init sh7372_earlytimer_init(void) +void __init sh7372_earlytimer_init(void) { sh7372_clock_init(); shmobile_earlytimer_init(); @@ -1067,9 +1067,6 @@ void __init sh7372_add_early_devices(void) /* setup early console here as well */ shmobile_setup_console(); - - /* override timer setup with soc-specific code */ - shmobile_timer.init = sh7372_earlytimer_init; } #ifdef CONFIG_USE_OF @@ -1113,7 +1110,7 @@ DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)") .init_irq = sh7372_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = sh7372_add_standard_devices_dt, - .timer = &shmobile_timer, + .init_time = shmobile_timer_init, .dt_compat = sh7372_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index db99a4a..f7ecb0b 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/io.h> @@ -754,7 +755,7 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; -static struct platform_device *sh73a0_early_devices[] __initdata = { +static struct platform_device *sh73a0_early_devices_dt[] __initdata = { &scif0_device, &scif1_device, &scif2_device, @@ -765,6 +766,9 @@ static struct platform_device *sh73a0_early_devices[] __initdata = { &scif7_device, &scif8_device, &cmt10_device, +}; + +static struct platform_device *sh73a0_early_devices[] __initdata = { &tmu00_device, &tmu01_device, }; @@ -787,6 +791,8 @@ void __init sh73a0_add_standard_devices(void) /* Clear software reset bit on SY-DMAC module */ __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); + platform_add_devices(sh73a0_early_devices_dt, + ARRAY_SIZE(sh73a0_early_devices_dt)); platform_add_devices(sh73a0_early_devices, ARRAY_SIZE(sh73a0_early_devices)); platform_add_devices(sh73a0_late_devices, @@ -796,7 +802,7 @@ void __init sh73a0_add_standard_devices(void) /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ void __init __weak sh73a0_register_twd(void) { } -static void __init sh73a0_earlytimer_init(void) +void __init sh73a0_earlytimer_init(void) { sh73a0_clock_init(); shmobile_earlytimer_init(); @@ -805,12 +811,63 @@ static void __init sh73a0_earlytimer_init(void) void __init sh73a0_add_early_devices(void) { + early_platform_add_devices(sh73a0_early_devices_dt, + ARRAY_SIZE(sh73a0_early_devices_dt)); early_platform_add_devices(sh73a0_early_devices, ARRAY_SIZE(sh73a0_early_devices)); /* setup early console here as well */ shmobile_setup_console(); +} + +#ifdef CONFIG_USE_OF + +/* Please note that the clock initialisation shcheme used in + * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt() + * does not work with SMP as there is a yet to be resolved lock-up in + * workqueue initialisation. + * + * CONFIG_SMP should be disabled when using this code. + */ + +void __init sh73a0_add_early_devices_dt(void) +{ + shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */ + + early_platform_add_devices(sh73a0_early_devices_dt, + ARRAY_SIZE(sh73a0_early_devices_dt)); + + /* setup early console here as well */ + shmobile_setup_console(); +} - /* override timer setup with soc-specific code */ - shmobile_timer.init = sh73a0_earlytimer_init; +static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = { + {}, +}; + +void __init sh73a0_add_standard_devices_dt(void) +{ + /* clocks are setup late during boot in the case of DT */ + sh73a0_clock_init(); + + platform_add_devices(sh73a0_early_devices_dt, + ARRAY_SIZE(sh73a0_early_devices_dt)); + of_platform_populate(NULL, of_default_bus_match_table, + sh73a0_auxdata_lookup, NULL); } + +static const char *sh73a0_boards_compat_dt[] __initdata = { + "renesas,sh73a0", + NULL, +}; + +DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") + .map_io = sh73a0_map_io, + .init_early = sh73a0_add_early_devices_dt, + .nr_irqs = NR_IRQS_LEGACY, + .init_irq = sh73a0_init_irq_dt, + .init_machine = sh73a0_add_standard_devices_dt, + .init_time = shmobile_timer_init, + .dt_compat = sh73a0_boards_compat_dt, +MACHINE_END +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S index 1d56467..a9df53b 100644 --- a/arch/arm/mach-shmobile/sleep-sh7372.S +++ b/arch/arm/mach-shmobile/sleep-sh7372.S @@ -59,17 +59,19 @@ sh7372_do_idle_sysc: mcr p15, 0, r0, c1, c0, 0 isb + /* + * Clean and invalidate data cache again. + */ + ldr r1, kernel_flush + blx r1 + /* disable L2 cache in the aux control register */ mrc p15, 0, r10, c1, c0, 1 bic r10, r10, #2 mcr p15, 0, r10, c1, c0, 1 + isb /* - * Invalidate data cache again. - */ - ldr r1, kernel_flush - blx r1 - /* * The kernel doesn't interwork: v7_flush_dcache_all in particluar will * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled. * This sequence switches back to ARM. Note that .align may insert a diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c index f674562..953eb1f 100644 --- a/arch/arm/mach-shmobile/smp-emev2.c +++ b/arch/arm/mach-shmobile/smp-emev2.c @@ -23,11 +23,11 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/emev2.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/cacheflush.h> #define EMEV2_SCU_BASE 0x1e000000 @@ -100,7 +100,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct * /* Tell ROM loader about our vector (in headsmp.S) */ emev2_set_boot_vector(__pa(shmobile_secondary_vector)); - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; } diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 2ce6af9..3a4acf2 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -23,12 +23,12 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> #include <mach/r8a7779.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> -#include <asm/hardware/gic.h> #define AVECR IOMEM(0xfe700040) diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 624f00f..acb46a9 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -23,12 +23,13 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/delay.h> +#include <linux/irqchip/arm-gic.h> #include <mach/common.h> +#include <asm/cacheflush.h> #include <asm/smp_plat.h> #include <mach/sh73a0.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> -#include <asm/hardware/gic.h> #define WUPCR IOMEM(0xe6151010) #define SRESCR IOMEM(0xe6151018) @@ -36,14 +37,13 @@ #define SBAR IOMEM(0xe6180020) #define APARMBAREA IOMEM(0xe6f10020) +#define PSTR_SHUTDOWN_MODE 3 + static void __iomem *scu_base_addr(void) { return (void __iomem *)0xf0000000; } -static DEFINE_SPINLOCK(scu_lock); -static unsigned long tmp; - #ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); void __init sh73a0_register_twd(void) @@ -52,20 +52,6 @@ void __init sh73a0_register_twd(void) } #endif -static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) -{ - void __iomem *scu_base = scu_base_addr(); - - spin_lock(&scu_lock); - tmp = __raw_readl(scu_base + 8); - tmp &= ~clr; - tmp |= set; - spin_unlock(&scu_lock); - - /* disable cache coherency after releasing the lock */ - __raw_writel(tmp, scu_base + 8); -} - static unsigned int __init sh73a0_get_core_count(void) { void __iomem *scu_base = scu_base_addr(); @@ -82,9 +68,6 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct { cpu = cpu_logical_map(cpu); - /* enable cache coherency */ - modify_scu_cpu_psr(0, 3 << (cpu * 8)); - if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3) __raw_writel(1 << cpu, WUPCR); /* wake up */ else @@ -95,16 +78,14 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) { - int cpu = cpu_logical_map(0); - scu_enable(scu_base_addr()); - /* Map the reset vector (in headsmp.S) */ + /* Map the reset vector (in headsmp-sh73a0.S) */ __raw_writel(0, APARMBAREA); /* 4k */ - __raw_writel(__pa(shmobile_secondary_vector), SBAR); + __raw_writel(__pa(sh73a0_secondary_vector), SBAR); - /* enable cache coherency on CPU0 */ - modify_scu_cpu_psr(0, 3 << (cpu * 8)); + /* enable cache coherency on booting CPU */ + scu_power_mode(scu_base_addr(), SCU_PM_NORMAL); } static void __init sh73a0_smp_init_cpus(void) @@ -114,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void) shmobile_smp_init_cpus(ncores); } -static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) +#ifdef CONFIG_HOTPLUG_CPU +static int sh73a0_cpu_kill(unsigned int cpu) { + int k; + u32 pstr; - /* this function is running on another CPU than the offline target, - * here we need wait for shutdown code in platform_cpu_die() to - * finish before asking SoC-specific code to power off the CPU core. + /* + * wait until the power status register confirms the shutdown of the + * offline target */ for (k = 0; k < 1000; k++) { - if (shmobile_cpu_is_dead(cpu)) + pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3; + if (pstr == PSTR_SHUTDOWN_MODE) return 1; mdelay(1); @@ -132,6 +117,23 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) return 0; } +static void sh73a0_cpu_die(unsigned int cpu) +{ + /* + * The ARM MPcore does not issue a cache coherency request for the L1 + * cache when powering off single CPUs. We must take care of this and + * further caches. + */ + dsb(); + flush_cache_all(); + + /* Set power off mode. This takes the CPU out of the MP cluster */ + scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF); + + /* Enter shutdown mode */ + cpu_do_idle(); +} +#endif /* CONFIG_HOTPLUG_CPU */ struct smp_operations sh73a0_smp_ops __initdata = { .smp_init_cpus = sh73a0_smp_init_cpus, @@ -140,7 +142,7 @@ struct smp_operations sh73a0_smp_ops __initdata = { .smp_boot_secondary = sh73a0_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_kill = sh73a0_cpu_kill, - .cpu_die = shmobile_cpu_die, - .cpu_disable = shmobile_cpu_disable, + .cpu_die = sh73a0_cpu_die, + .cpu_disable = shmobile_cpu_disable_any, #endif }; diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index a689197..fdbe54a 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -60,10 +60,6 @@ void __init shmobile_earlytimer_init(void) late_time_init = shmobile_late_time_init; } -static void __init shmobile_timer_init(void) +void __init shmobile_timer_init(void) { } - -struct sys_timer shmobile_timer = { - .init = shmobile_timer_init, -}; diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index 68dd1b6..4e9e69d 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -22,9 +22,9 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> @@ -83,8 +83,6 @@ static void __init socfpga_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index 6732924..27d6846 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -15,12 +15,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/dw_apb_timer.h> +#include <linux/irqchip.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -62,11 +62,6 @@ static void __init socfpga_map_io(void) early_printk("Early printk initialized\n"); } -const static struct of_device_id irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - void __init socfpga_sysmgr_init(void) { struct device_node *np; @@ -78,9 +73,9 @@ void __init socfpga_sysmgr_init(void) rst_manager_base_addr = of_iomap(np, 0); } -static void __init gic_init_irq(void) +static void __init socfpga_init_irq(void) { - of_irq_init(irq_match); + irqchip_init(); socfpga_sysmgr_init(); } @@ -105,9 +100,8 @@ static const char *altera_dt_match[] = { DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") .smp = smp_ops(socfpga_smp_ops), .map_io = socfpga_map_io, - .init_irq = gic_init_irq, - .handle_irq = gic_handle_irq, - .timer = &dw_apb_timer, + .init_irq = socfpga_init_irq, + .init_time = dw_apb_timer_init, .init_machine = socfpga_cyclone5_init, .restart = socfpga_cyclone5_restart, .dt_compat = altera_dt_match, diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h index c33f4d9..633e678 100644 --- a/arch/arm/mach-spear13xx/include/mach/generic.h +++ b/arch/arm/mach-spear13xx/include/mach/generic.h @@ -18,7 +18,7 @@ #include <asm/mach/time.h> /* Add spear13xx structure declarations here */ -extern struct sys_timer spear13xx_timer; +extern void spear13xx_timer_init(void); extern struct pl022_ssp_controller pl022_plat_data; extern struct dw_dma_platform_data dmac_plat_data; extern struct dw_dma_slave cf_dma_priv; @@ -28,7 +28,6 @@ extern struct dw_dma_slave nand_write_dma_priv; /* Add spear13xx family function declarations here */ void __init spear_setup_of_timer(void); void __init spear13xx_map_io(void); -void __init spear13xx_dt_init_irq(void); void __init spear13xx_l2x0_init(void); bool dw_dma_filter(struct dma_chan *chan, void *slave); void spear_restart(char, const char *); diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c index 2eaa3fa..af4ade6 100644 --- a/arch/arm/mach-spear13xx/platsmp.c +++ b/arch/arm/mach-spear13xx/platsmp.c @@ -15,8 +15,8 @@ #include <linux/jiffies.h> #include <linux/io.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <mach/spear.h> #include <mach/generic.h> @@ -104,8 +104,6 @@ static void __init spear13xx_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c index 02f4724..56214d1 100644 --- a/arch/arm/mach-spear13xx/spear1310.c +++ b/arch/arm/mach-spear13xx/spear1310.c @@ -14,9 +14,9 @@ #define pr_fmt(fmt) "SPEAr1310: " fmt #include <linux/amba/pl022.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> #include <linux/pata_arasan_cf_data.h> -#include <asm/hardware/gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <mach/generic.h> @@ -90,9 +90,8 @@ static void __init spear1310_map_io(void) DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree") .smp = smp_ops(spear13xx_smp_ops), .map_io = spear1310_map_io, - .init_irq = spear13xx_dt_init_irq, - .handle_irq = gic_handle_irq, - .timer = &spear13xx_timer, + .init_irq = irqchip_init, + .init_time = spear13xx_timer_init, .init_machine = spear1310_dt_init, .restart = spear_restart, .dt_compat = spear1310_dt_board_compat, diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c index 081014f..9a28beb 100644 --- a/arch/arm/mach-spear13xx/spear1340.c +++ b/arch/arm/mach-spear13xx/spear1340.c @@ -18,7 +18,7 @@ #include <linux/delay.h> #include <linux/dw_dmac.h> #include <linux/of_platform.h> -#include <asm/hardware/gic.h> +#include <linux/irqchip.h> #include <asm/mach/arch.h> #include <mach/dma.h> #include <mach/generic.h> @@ -184,9 +184,8 @@ static const char * const spear1340_dt_board_compat[] = { DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree") .smp = smp_ops(spear13xx_smp_ops), .map_io = spear13xx_map_io, - .init_irq = spear13xx_dt_init_irq, - .handle_irq = gic_handle_irq, - .timer = &spear13xx_timer, + .init_irq = irqchip_init, + .init_time = spear13xx_timer_init, .init_machine = spear1340_dt_init, .restart = spear_restart, .dt_compat = spear1340_dt_board_compat, diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c index c4af775..c7d2b4a 100644 --- a/arch/arm/mach-spear13xx/spear13xx.c +++ b/arch/arm/mach-spear13xx/spear13xx.c @@ -17,9 +17,8 @@ #include <linux/clk.h> #include <linux/dw_dmac.h> #include <linux/err.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <asm/smp_twd.h> #include <mach/dma.h> @@ -153,7 +152,7 @@ static void __init spear13xx_clk_init(void) pr_err("%s: Unknown machine\n", __func__); } -static void __init spear13xx_timer_init(void) +void __init spear13xx_timer_init(void) { char pclk_name[] = "osc_24m_clk"; struct clk *gpt_clk, *pclk; @@ -182,17 +181,3 @@ static void __init spear13xx_timer_init(void) spear_setup_of_timer(); twd_local_timer_of_register(); } - -struct sys_timer spear13xx_timer = { - .init = spear13xx_timer_init, -}; - -static const struct of_device_id gic_of_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init }, - { /* Sentinel */ } -}; - -void __init spear13xx_dt_init_irq(void) -{ - of_irq_init(gic_of_match); -} diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h index ce19113..df31079 100644 --- a/arch/arm/mach-spear3xx/include/mach/generic.h +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -22,7 +22,7 @@ #include <asm/mach/map.h> /* Add spear3xx family device structure declarations here */ -extern struct sys_timer spear3xx_timer; +extern void spear3xx_timer_init(void); extern struct pl022_ssp_controller pl022_plat_data; extern struct pl08x_platform_data pl080_plat_data; @@ -30,7 +30,6 @@ extern struct pl08x_platform_data pl080_plat_data; void __init spear_setup_of_timer(void); void __init spear3xx_clk_init(void); void __init spear3xx_map_io(void); -void __init spear3xx_dt_init_irq(void); void spear_restart(char, const char *); diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index a69cbfd..bbc9b7e 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -14,8 +14,8 @@ #define pr_fmt(fmt) "SPEAr300: " fmt #include <linux/amba/pl08x.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -212,9 +212,8 @@ static void __init spear300_map_io(void) DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree") .map_io = spear300_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, - .timer = &spear3xx_timer, + .init_irq = irqchip_init, + .init_time = spear3xx_timer_init, .init_machine = spear300_dt_init, .restart = spear_restart, .dt_compat = spear300_dt_board_compat, diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index b963ebb..c13a434 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -15,8 +15,8 @@ #include <linux/amba/pl08x.h> #include <linux/amba/serial.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -254,9 +254,8 @@ static void __init spear310_map_io(void) DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree") .map_io = spear310_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, - .timer = &spear3xx_timer, + .init_irq = irqchip_init, + .init_time = spear3xx_timer_init, .init_machine = spear310_dt_init, .restart = spear_restart, .dt_compat = spear310_dt_board_compat, diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index 66e3a0c..e1c7707 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -16,8 +16,8 @@ #include <linux/amba/pl022.h> #include <linux/amba/pl08x.h> #include <linux/amba/serial.h> +#include <linux/irqchip.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <mach/generic.h> #include <mach/spear.h> @@ -268,9 +268,8 @@ static void __init spear320_map_io(void) DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree") .map_io = spear320_map_io, - .init_irq = spear3xx_dt_init_irq, - .handle_irq = vic_handle_irq, - .timer = &spear3xx_timer, + .init_irq = irqchip_init, + .init_time = spear3xx_timer_init, .init_machine = spear320_dt_init, .restart = spear_restart, .dt_compat = spear320_dt_board_compat, diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c index 38fe95d..b2ba516 100644 --- a/arch/arm/mach-spear3xx/spear3xx.c +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -15,11 +15,8 @@ #include <linux/amba/pl022.h> #include <linux/amba/pl08x.h> -#include <linux/irqchip/spear-shirq.h> -#include <linux/of_irq.h> #include <linux/io.h> #include <asm/hardware/pl080.h> -#include <asm/hardware/vic.h> #include <plat/pl080.h> #include <mach/generic.h> #include <mach/spear.h> @@ -87,7 +84,7 @@ void __init spear3xx_map_io(void) iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc)); } -static void __init spear3xx_timer_init(void) +void __init spear3xx_timer_init(void) { char pclk_name[] = "pll3_clk"; struct clk *gpt_clk, *pclk; @@ -115,20 +112,3 @@ static void __init spear3xx_timer_init(void) spear_setup_of_timer(); } - -struct sys_timer spear3xx_timer = { - .init = spear3xx_timer_init, -}; - -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl190-vic", .data = vic_of_init, }, - { .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, }, - { .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, }, - { .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, }, - { /* Sentinel */ } -}; - -void __init spear3xx_dt_init_irq(void) -{ - of_irq_init(vic_of_match); -} diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c index 5a5a52d..b8bd33c 100644 --- a/arch/arm/mach-spear6xx/spear6xx.c +++ b/arch/arm/mach-spear6xx/spear6xx.c @@ -16,12 +16,11 @@ #include <linux/amba/pl08x.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/irqchip.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/hardware/pl080.h> -#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include <asm/mach/map.h> @@ -374,7 +373,7 @@ void __init spear6xx_map_io(void) iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc)); } -static void __init spear6xx_timer_init(void) +void __init spear6xx_timer_init(void) { char pclk_name[] = "pll3_clk"; struct clk *gpt_clk, *pclk; @@ -403,10 +402,6 @@ static void __init spear6xx_timer_init(void) spear_setup_of_timer(); } -struct sys_timer spear6xx_timer = { - .init = spear6xx_timer_init, -}; - /* Add auxdata to pass platform data */ struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL, @@ -425,21 +420,10 @@ static const char *spear600_dt_board_compat[] = { NULL }; -static const struct of_device_id vic_of_match[] __initconst = { - { .compatible = "arm,pl190-vic", .data = vic_of_init, }, - { /* Sentinel */ } -}; - -static void __init spear6xx_dt_init_irq(void) -{ - of_irq_init(vic_of_match); -} - DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)") .map_io = spear6xx_map_io, - .init_irq = spear6xx_dt_init_irq, - .handle_irq = vic_handle_irq, - .timer = &spear6xx_timer, + .init_irq = irqchip_init, + .init_time = spear6xx_timer_init, .init_machine = spear600_dt_init, .restart = spear_restart, .dt_compat = spear600_dt_board_compat, diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1dc8a92..fb8fbce 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -21,8 +21,6 @@ #include <linux/irqchip/sunxi.h> -#include <asm/hardware/vic.h> - #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -91,6 +89,6 @@ DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") .init_irq = sunxi_init_irq, .handle_irq = sunxi_handle_irq, .restart = sunxi_restart, - .timer = &sunxi_timer, + .init_time = &sunxi_timer_init, .dt_compat = sunxi_board_dt_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index b442f15..bde8197 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -4,11 +4,12 @@ comment "NVIDIA Tegra options" config ARCH_TEGRA_2x_SOC bool "Enable support for Tegra20 family" + select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_720789 - select ARM_ERRATA_742230 + select ARM_ERRATA_742230 if SMP select ARM_ERRATA_751472 - select ARM_ERRATA_754327 + select ARM_ERRATA_754327 if SMP select ARM_ERRATA_764369 if SMP select ARM_GIC select CPU_FREQ_TABLE if CPU_FREQ @@ -44,6 +45,18 @@ config ARCH_TEGRA_3x_SOC Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller +config ARCH_TEGRA_114_SOC + bool "Enable support for Tegra114 family" + select ARM_GIC + select CPU_V7 + select ARM_L1_CACHE_SHIFT_6 + select ARM_ARCH_TIMER + select PINCTRL + select PINCTRL_TEGRA114 + help + Support for NVIDIA Tegra T114 processor family, based on the + ARM CortexA15MP CPU + config TEGRA_PCI bool "PCI Express support" depends on ARCH_TEGRA_2x_SOC diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 0979e8b..f6b46ae 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -1,39 +1,38 @@ obj-y += common.o obj-y += io.o obj-y += irq.o -obj-y += clock.o -obj-y += timer.o obj-y += fuse.o obj-y += pmc.o obj-y += flowctrl.o obj-y += powergate.o obj-y += apbio.o obj-y += pm.o +obj-y += reset.o +obj-y += reset-handler.o +obj-y += sleep.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o -obj-$(CONFIG_CPU_IDLE) += sleep.o -obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o -obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o endif -obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o -obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks_data.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o endif obj-$(CONFIG_SMP) += platsmp.o headsmp.o -obj-$(CONFIG_SMP) += reset.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o obj-$(CONFIG_TEGRA_PCI) += pcie.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o +obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o +ifeq ($(CONFIG_CPU_IDLE),y) +obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o +endif obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-harmony-pcie.o diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c index d091675..d7aa52e 100644 --- a/arch/arm/mach-tegra/apbio.c +++ b/arch/arm/mach-tegra/apbio.c @@ -38,7 +38,7 @@ static void tegra_apb_writel_direct(u32 value, unsigned long offset); static struct dma_chan *tegra_apb_dma_chan; static struct dma_slave_config dma_sconfig; -bool tegra_apb_dma_init(void) +static bool tegra_apb_dma_init(void) { dma_cap_mask_t mask; diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c new file mode 100644 index 0000000..72598e2 --- /dev/null +++ b/arch/arm/mach-tegra/board-dt-tegra114.c @@ -0,0 +1,46 @@ +/* + * NVIDIA Tegra114 device tree board support + * + * Copyright (C) 2013 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clocksource.h> + +#include <asm/mach/arch.h> + +#include "board.h" +#include "common.h" + +static void __init tegra114_dt_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char * const tegra114_dt_board_compat[] = { + "nvidia,tegra114", + NULL, +}; + +DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)") + .smp = smp_ops(tegra_smp_ops), + .map_io = tegra_map_common_io, + .init_early = tegra30_init_early, + .init_irq = tegra_dt_init_irq, + .init_time = clocksource_of_init, + .init_machine = tegra114_dt_init, + .init_late = tegra_init_late, + .restart = tegra_assert_system_reset, + .dt_compat = tegra114_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 734d9cc..a0edf25 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -15,6 +15,7 @@ * */ +#include <linux/clocksource.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> @@ -25,7 +26,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_fdt.h> -#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/pda_power.h> #include <linux/platform_data/tegra_usb.h> @@ -34,106 +34,51 @@ #include <linux/i2c-tegra.h> #include <linux/usb/tegra_usb_phy.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include <asm/setup.h> #include "board.h" -#include "clock.h" #include "common.h" #include "iomap.h" -struct tegra_ehci_platform_data tegra_ehci1_pdata = { +static struct tegra_ehci_platform_data tegra_ehci1_pdata = { .operating_mode = TEGRA_USB_OTG, .power_down_on_bus_suspend = 1, .vbus_gpio = -1, }; -struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { +static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { .reset_gpio = -1, .clk = "cdev2", }; -struct tegra_ehci_platform_data tegra_ehci2_pdata = { +static struct tegra_ehci_platform_data tegra_ehci2_pdata = { .phy_config = &tegra_ehci2_ulpi_phy_config, .operating_mode = TEGRA_USB_HOST, .power_down_on_bus_suspend = 1, .vbus_gpio = -1, }; -struct tegra_ehci_platform_data tegra_ehci3_pdata = { +static struct tegra_ehci_platform_data tegra_ehci3_pdata = { .operating_mode = TEGRA_USB_HOST, .power_down_on_bus_suspend = 1, .vbus_gpio = -1, }; -struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c-dvc", TEGRA_DVC_BASE, "tegra-i2c.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra20-i2s.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra20-i2s.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra20-das", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0", +static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { + OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0", &tegra_ehci1_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1", + OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1", &tegra_ehci2_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2", + OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2", &tegra_ehci3_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sflash", 0x7000c380, "spi", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D400, "spi_tegra.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D600, "spi_tegra.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D800, "spi_tegra.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000DA00, "spi_tegra.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-host1x", 0x50000000, "host1x", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54200000, "tegradc.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54240000, "tegradc.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-hdmi", 0x54280000, "hdmi", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-dsi", 0x54300000, "dsi", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-tvo", 0x542c0000, "tvo", NULL), {} }; -static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { - /* name parent rate enabled */ - { "uarta", "pll_p", 216000000, true }, - { "uartd", "pll_p", 216000000, true }, - { "usbd", "clk_m", 12000000, false }, - { "usb2", "clk_m", 12000000, false }, - { "usb3", "clk_m", 12000000, false }, - { "pll_a", "pll_p_out1", 56448000, true }, - { "pll_a_out0", "pll_a", 11289600, true }, - { "cdev1", NULL, 0, true }, - { "blink", "clk_32k", 32768, true }, - { "i2s1", "pll_a_out0", 11289600, false}, - { "i2s2", "pll_a_out0", 11289600, false}, - { "sdmmc1", "pll_p", 48000000, false}, - { "sdmmc3", "pll_p", 48000000, false}, - { "sdmmc4", "pll_p", 48000000, false}, - { "spi", "pll_p", 20000000, false }, - { "sbc1", "pll_p", 100000000, false }, - { "sbc2", "pll_p", 100000000, false }, - { "sbc3", "pll_p", 100000000, false }, - { "sbc4", "pll_p", 100000000, false }, - { "host1x", "pll_c", 150000000, false }, - { "disp1", "pll_p", 600000000, false }, - { "disp2", "pll_p", 600000000, false }, - { NULL, NULL, 0, 0}, -}; - static void __init tegra_dt_init(void) { - tegra_clk_init_from_table(tegra_dt_clk_init_table); - /* * Finished with the static registrations now; fill in the missing * devices @@ -202,8 +147,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") .smp = smp_ops(tegra_smp_ops), .init_early = tegra20_init_early, .init_irq = tegra_dt_init_irq, - .handle_irq = gic_handle_irq, - .timer = &tegra_sys_timer, + .init_time = clocksource_of_init, .init_machine = tegra_dt_init, .init_late = tegra_dt_init_late, .restart = tegra_assert_system_reset, diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index 6497d12..bf68567 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -23,6 +23,7 @@ * */ +#include <linux/clocksource.h> #include <linux/kernel.h> #include <linux/of.h> #include <linux/of_address.h> @@ -31,75 +32,14 @@ #include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include "board.h" -#include "clock.h" #include "common.h" #include "iomap.h" -struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000600, "sdhci-tegra.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C000, "tegra-i2c.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C400, "tegra-i2c.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D400, "spi_tegra.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D600, "spi_tegra.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D800, "spi_tegra.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DA00, "spi_tegra.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DC00, "spi_tegra.4", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DE00, "spi_tegra.5", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-host1x", 0x50000000, "host1x", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54200000, "tegradc.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54240000, "tegradc.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-hdmi", 0x54280000, "hdmi", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-dsi", 0x54300000, "dsi", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-tvo", 0x542c0000, "tvo", NULL), - {} -}; - -static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = { - /* name parent rate enabled */ - { "uarta", "pll_p", 408000000, true }, - { "pll_a", "pll_p_out1", 564480000, true }, - { "pll_a_out0", "pll_a", 11289600, true }, - { "extern1", "pll_a_out0", 0, true }, - { "clk_out_1", "extern1", 0, true }, - { "blink", "clk_32k", 32768, true }, - { "i2s0", "pll_a_out0", 11289600, false}, - { "i2s1", "pll_a_out0", 11289600, false}, - { "i2s2", "pll_a_out0", 11289600, false}, - { "i2s3", "pll_a_out0", 11289600, false}, - { "i2s4", "pll_a_out0", 11289600, false}, - { "sdmmc1", "pll_p", 48000000, false}, - { "sdmmc3", "pll_p", 48000000, false}, - { "sdmmc4", "pll_p", 48000000, false}, - { "sbc1", "pll_p", 100000000, false}, - { "sbc2", "pll_p", 100000000, false}, - { "sbc3", "pll_p", 100000000, false}, - { "sbc4", "pll_p", 100000000, false}, - { "sbc5", "pll_p", 100000000, false}, - { "sbc6", "pll_p", 100000000, false}, - { "host1x", "pll_c", 150000000, false}, - { "disp1", "pll_p", 600000000, false}, - { "disp2", "pll_p", 600000000, false}, - { NULL, NULL, 0, 0}, -}; - static void __init tegra30_dt_init(void) { - tegra_clk_init_from_table(tegra_dt_clk_init_table); - - of_platform_populate(NULL, of_default_bus_match_table, - tegra30_auxdata_lookup, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } static const char *tegra30_dt_board_compat[] = { @@ -112,8 +52,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)") .map_io = tegra_map_common_io, .init_early = tegra30_init_early, .init_irq = tegra_dt_init_irq, - .handle_irq = gic_handle_irq, - .timer = &tegra_sys_timer, + .init_time = clocksource_of_init, .init_machine = tegra30_dt_init, .init_late = tegra_init_late, .restart = tegra_assert_system_reset, diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 91fbe73..da8f5a3 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -55,5 +55,4 @@ static inline int harmony_pcie_init(void) { return 0; } void __init tegra_paz00_wifikill_init(void); -extern struct sys_timer tegra_sys_timer; #endif diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c deleted file mode 100644 index 867bf8b..0000000 --- a/arch/arm/mach-tegra/clock.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/clkdev.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/seq_file.h> -#include <linux/slab.h> - -#include "board.h" -#include "clock.h" -#include "tegra_cpu_car.h" - -/* Global data of Tegra CPU CAR ops */ -struct tegra_cpu_car_ops *tegra_cpu_car_ops; - -/* - * Locking: - * - * An additional mutex, clock_list_lock, is used to protect the list of all - * clocks. - * - */ -static DEFINE_MUTEX(clock_list_lock); -static LIST_HEAD(clocks); - -void tegra_clk_add(struct clk *clk) -{ - struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk)); - - mutex_lock(&clock_list_lock); - list_add(&c->node, &clocks); - mutex_unlock(&clock_list_lock); -} - -struct clk *tegra_get_clock_by_name(const char *name) -{ - struct clk_tegra *c; - struct clk *ret = NULL; - mutex_lock(&clock_list_lock); - list_for_each_entry(c, &clocks, node) { - if (strcmp(__clk_get_name(c->hw.clk), name) == 0) { - ret = c->hw.clk; - break; - } - } - mutex_unlock(&clock_list_lock); - return ret; -} - -static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) -{ - struct clk *c; - struct clk *p; - struct clk *parent; - - int ret = 0; - - c = tegra_get_clock_by_name(table->name); - - if (!c) { - pr_warn("Unable to initialize clock %s\n", - table->name); - return -ENODEV; - } - - parent = clk_get_parent(c); - - if (table->parent) { - p = tegra_get_clock_by_name(table->parent); - if (!p) { - pr_warn("Unable to find parent %s of clock %s\n", - table->parent, table->name); - return -ENODEV; - } - - if (parent != p) { - ret = clk_set_parent(c, p); - if (ret) { - pr_warn("Unable to set parent %s of clock %s: %d\n", - table->parent, table->name, ret); - return -EINVAL; - } - } - } - - if (table->rate && table->rate != clk_get_rate(c)) { - ret = clk_set_rate(c, table->rate); - if (ret) { - pr_warn("Unable to set clock %s to rate %lu: %d\n", - table->name, table->rate, ret); - return -EINVAL; - } - } - - if (table->enabled) { - ret = clk_prepare_enable(c); - if (ret) { - pr_warn("Unable to enable clock %s: %d\n", - table->name, ret); - return -EINVAL; - } - } - - return 0; -} - -void tegra_clk_init_from_table(struct tegra_clk_init_table *table) -{ - for (; table->name; table++) - tegra_clk_init_one_from_table(table); -} - -void tegra_periph_reset_deassert(struct clk *c) -{ - struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); - BUG_ON(!clk->reset); - clk->reset(__clk_get_hw(c), false); -} -EXPORT_SYMBOL(tegra_periph_reset_deassert); - -void tegra_periph_reset_assert(struct clk *c) -{ - struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); - BUG_ON(!clk->reset); - clk->reset(__clk_get_hw(c), true); -} -EXPORT_SYMBOL(tegra_periph_reset_assert); - -/* Several extended clock configuration bits (e.g., clock routing, clock - * phase control) are included in PLL and peripheral clock source - * registers. */ -int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting) -{ - int ret = 0; - struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); - - if (!clk->clk_cfg_ex) { - ret = -ENOSYS; - goto out; - } - ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting); - -out: - return ret; -} diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h deleted file mode 100644 index 2aa37f5..0000000 --- a/arch/arm/mach-tegra/clock.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/clock.h - * - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __MACH_TEGRA_CLOCK_H -#define __MACH_TEGRA_CLOCK_H - -#include <linux/clk-provider.h> -#include <linux/clkdev.h> -#include <linux/list.h> - -#include <mach/clk.h> - -#define DIV_BUS (1 << 0) -#define DIV_U71 (1 << 1) -#define DIV_U71_FIXED (1 << 2) -#define DIV_2 (1 << 3) -#define DIV_U16 (1 << 4) -#define PLL_FIXED (1 << 5) -#define PLL_HAS_CPCON (1 << 6) -#define MUX (1 << 7) -#define PLLD (1 << 8) -#define PERIPH_NO_RESET (1 << 9) -#define PERIPH_NO_ENB (1 << 10) -#define PERIPH_EMC_ENB (1 << 11) -#define PERIPH_MANUAL_RESET (1 << 12) -#define PLL_ALT_MISC_REG (1 << 13) -#define PLLU (1 << 14) -#define PLLX (1 << 15) -#define MUX_PWM (1 << 16) -#define MUX8 (1 << 17) -#define DIV_U71_UART (1 << 18) -#define MUX_CLK_OUT (1 << 19) -#define PLLM (1 << 20) -#define DIV_U71_INT (1 << 21) -#define DIV_U71_IDLE (1 << 22) -#define ENABLE_ON_INIT (1 << 28) -#define PERIPH_ON_APB (1 << 29) - -struct clk_tegra; -#define to_clk_tegra(_hw) container_of(_hw, struct clk_tegra, hw) - -struct clk_mux_sel { - struct clk *input; - u32 value; -}; - -struct clk_pll_freq_table { - unsigned long input_rate; - unsigned long output_rate; - u16 n; - u16 m; - u8 p; - u8 cpcon; -}; - -enum clk_state { - UNINITIALIZED = 0, - ON, - OFF, -}; - -struct clk_tegra { - /* node for master clocks list */ - struct list_head node; /* node for list of all clocks */ - struct clk_lookup lookup; - struct clk_hw hw; - - bool set; - unsigned long fixed_rate; - unsigned long max_rate; - unsigned long min_rate; - u32 flags; - const char *name; - - enum clk_state state; - u32 div; - u32 mul; - - u32 reg; - u32 reg_shift; - - struct list_head shared_bus_list; - - union { - struct { - unsigned int clk_num; - } periph; - struct { - unsigned long input_min; - unsigned long input_max; - unsigned long cf_min; - unsigned long cf_max; - unsigned long vco_min; - unsigned long vco_max; - const struct clk_pll_freq_table *freq_table; - int lock_delay; - unsigned long fixed_rate; - } pll; - struct { - u32 sel; - u32 reg_mask; - } mux; - struct { - struct clk *main; - struct clk *backup; - } cpu; - struct { - struct list_head node; - bool enabled; - unsigned long rate; - } shared_bus_user; - } u; - - void (*reset)(struct clk_hw *, bool); - int (*clk_cfg_ex)(struct clk_hw *, enum tegra_clk_ex_param, u32); -}; - -struct clk_duplicate { - const char *name; - struct clk_lookup lookup; -}; - -struct tegra_clk_init_table { - const char *name; - const char *parent; - unsigned long rate; - bool enabled; -}; - -void tegra_clk_add(struct clk *c); -void tegra2_init_clocks(void); -void tegra30_init_clocks(void); -struct clk *tegra_get_clock_by_name(const char *name); -void tegra_clk_init_from_table(struct tegra_clk_init_table *table); - -#endif diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index d54cfc5..46c0718 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -21,15 +21,14 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/delay.h> -#include <linux/of_irq.h> +#include <linux/irqchip.h> +#include <linux/clk/tegra.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <mach/powergate.h> #include "board.h" -#include "clock.h" #include "common.h" #include "fuse.h" #include "iomap.h" @@ -37,6 +36,7 @@ #include "apbio.h" #include "sleep.h" #include "pm.h" +#include "reset.h" /* * Storage for debug-macro.S's state. @@ -57,15 +57,11 @@ u32 tegra_uart_config[4] = { }; #ifdef CONFIG_OF -static const struct of_device_id tegra_dt_irq_match[] __initconst = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init }, - { } -}; - void __init tegra_dt_init_irq(void) { + tegra_clocks_init(); tegra_init_irq(); - of_irq_init(tegra_dt_irq_match); + irqchip_init(); } #endif @@ -79,43 +75,6 @@ void tegra_assert_system_reset(char mode, const char *cmd) writel_relaxed(reg, reset); } -#ifdef CONFIG_ARCH_TEGRA_2x_SOC -static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { - /* name parent rate enabled */ - { "clk_m", NULL, 0, true }, - { "pll_p", "clk_m", 216000000, true }, - { "pll_p_out1", "pll_p", 28800000, true }, - { "pll_p_out2", "pll_p", 48000000, true }, - { "pll_p_out3", "pll_p", 72000000, true }, - { "pll_p_out4", "pll_p", 24000000, true }, - { "pll_c", "clk_m", 600000000, true }, - { "pll_c_out1", "pll_c", 120000000, true }, - { "sclk", "pll_c_out1", 120000000, true }, - { "hclk", "sclk", 120000000, true }, - { "pclk", "hclk", 60000000, true }, - { "csite", NULL, 0, true }, - { "emc", NULL, 0, true }, - { "cpu", NULL, 0, true }, - { NULL, NULL, 0, 0}, -}; -#endif - -#ifdef CONFIG_ARCH_TEGRA_3x_SOC -static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = { - /* name parent rate enabled */ - { "clk_m", NULL, 0, true }, - { "pll_p", "pll_ref", 408000000, true }, - { "pll_p_out1", "pll_p", 9600000, true }, - { "pll_p_out4", "pll_p", 102000000, true }, - { "sclk", "pll_p_out4", 102000000, true }, - { "hclk", "sclk", 102000000, true }, - { "pclk", "hclk", 51000000, true }, - { "csite", NULL, 0, true }, - { NULL, NULL, 0, 0}, -}; -#endif - - static void __init tegra_init_cache(void) { #ifdef CONFIG_CACHE_L2X0 @@ -137,10 +96,9 @@ static void __init tegra_init_cache(void) #ifdef CONFIG_ARCH_TEGRA_2x_SOC void __init tegra20_init_early(void) { + tegra_cpu_reset_handler_init(); tegra_apb_io_init(); tegra_init_fuse(); - tegra2_init_clocks(); - tegra_clk_init_from_table(tegra20_clk_init_table); tegra_init_cache(); tegra_pmc_init(); tegra_powergate_init(); @@ -150,10 +108,9 @@ void __init tegra20_init_early(void) #ifdef CONFIG_ARCH_TEGRA_3x_SOC void __init tegra30_init_early(void) { + tegra_cpu_reset_handler_init(); tegra_apb_io_init(); tegra_init_fuse(); - tegra30_init_clocks(); - tegra_clk_init_from_table(tegra30_clk_init_table); tegra_init_cache(); tegra_pmc_init(); tegra_powergate_init(); diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h index 02f71b4..32f8eb3 100644 --- a/arch/arm/mach-tegra/common.h +++ b/arch/arm/mach-tegra/common.h @@ -1,4 +1,5 @@ extern struct smp_operations tegra_smp_ops; +extern int tegra_cpu_kill(unsigned int cpu); extern void tegra_cpu_die(unsigned int cpu); extern int tegra_cpu_disable(unsigned int cpu); diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index a74d3c7..ebffed6 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -214,24 +214,6 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) if (policy->cpu >= NUM_CPUS) return -EINVAL; - cpu_clk = clk_get_sys(NULL, "cpu"); - if (IS_ERR(cpu_clk)) - return PTR_ERR(cpu_clk); - - pll_x_clk = clk_get_sys(NULL, "pll_x"); - if (IS_ERR(pll_x_clk)) - return PTR_ERR(pll_x_clk); - - pll_p_clk = clk_get_sys(NULL, "pll_p"); - if (IS_ERR(pll_p_clk)) - return PTR_ERR(pll_p_clk); - - emc_clk = clk_get_sys("cpu", "emc"); - if (IS_ERR(emc_clk)) { - clk_put(cpu_clk); - return PTR_ERR(emc_clk); - } - clk_prepare_enable(emc_clk); clk_prepare_enable(cpu_clk); @@ -256,8 +238,6 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_cpuinfo(policy, freq_table); clk_disable_unprepare(emc_clk); - clk_put(emc_clk); - clk_put(cpu_clk); return 0; } @@ -278,12 +258,32 @@ static struct cpufreq_driver tegra_cpufreq_driver = { static int __init tegra_cpufreq_init(void) { + cpu_clk = clk_get_sys(NULL, "cpu"); + if (IS_ERR(cpu_clk)) + return PTR_ERR(cpu_clk); + + pll_x_clk = clk_get_sys(NULL, "pll_x"); + if (IS_ERR(pll_x_clk)) + return PTR_ERR(pll_x_clk); + + pll_p_clk = clk_get_sys(NULL, "pll_p_cclk"); + if (IS_ERR(pll_p_clk)) + return PTR_ERR(pll_p_clk); + + emc_clk = clk_get_sys("cpu", "emc"); + if (IS_ERR(emc_clk)) { + clk_put(cpu_clk); + return PTR_ERR(emc_clk); + } + return cpufreq_register_driver(&tegra_cpufreq_driver); } static void __exit tegra_cpufreq_exit(void) { cpufreq_unregister_driver(&tegra_cpufreq_driver); + clk_put(emc_clk); + clk_put(cpu_clk); } diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c new file mode 100644 index 0000000..0f4e8c4 --- /dev/null +++ b/arch/arm/mach-tegra/cpuidle-tegra114.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/cpuidle.h> + +#include <asm/cpuidle.h> + +static struct cpuidle_driver tegra_idle_driver = { + .name = "tegra_idle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .state_count = 1, + .states = { + [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), + }, +}; + +static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device); + +int __init tegra114_cpuidle_init(void) +{ + int ret; + unsigned int cpu; + struct cpuidle_device *dev; + struct cpuidle_driver *drv = &tegra_idle_driver; + + ret = cpuidle_register_driver(&tegra_idle_driver); + if (ret) { + pr_err("CPUidle driver registration failed\n"); + return ret; + } + + for_each_possible_cpu(cpu) { + dev = &per_cpu(tegra_idle_device, cpu); + dev->cpu = cpu; + + dev->state_count = drv->state_count; + ret = cpuidle_register_device(dev); + if (ret) { + pr_err("CPU%u: CPUidle device registration failed\n", + cpu); + return ret; + } + } + return 0; +} diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index d32e8b0..825ced4 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -22,21 +22,199 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/cpuidle.h> +#include <linux/cpu_pm.h> +#include <linux/clockchips.h> +#include <linux/clk/tegra.h> #include <asm/cpuidle.h> +#include <asm/proc-fns.h> +#include <asm/suspend.h> +#include <asm/smp_plat.h> + +#include "pm.h" +#include "sleep.h" +#include "iomap.h" +#include "irq.h" +#include "flowctrl.h" + +#ifdef CONFIG_PM_SLEEP +static bool abort_flag; +static atomic_t abort_barrier; +static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index); +#endif + +static struct cpuidle_state tegra_idle_states[] = { + [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), +#ifdef CONFIG_PM_SLEEP + [1] = { + .enter = tegra20_idle_lp2_coupled, + .exit_latency = 5000, + .target_residency = 10000, + .power_usage = 0, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_COUPLED, + .name = "powered-down", + .desc = "CPU power gated", + }, +#endif +}; static struct cpuidle_driver tegra_idle_driver = { .name = "tegra_idle", .owner = THIS_MODULE, .en_core_tk_irqen = 1, - .state_count = 1, - .states = { - [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), - }, }; static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device); +#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_SMP +static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); + +static int tegra20_reset_sleeping_cpu_1(void) +{ + int ret = 0; + + tegra_pen_lock(); + + if (readl(pmc + PMC_SCRATCH41) == CPU_RESETTABLE) + tegra20_cpu_shutdown(1); + else + ret = -EINVAL; + + tegra_pen_unlock(); + + return ret; +} + +static void tegra20_wake_cpu1_from_reset(void) +{ + tegra_pen_lock(); + + tegra20_cpu_clear_resettable(); + + /* enable cpu clock on cpu */ + tegra_enable_cpu_clock(1); + + /* take the CPU out of reset */ + tegra_cpu_out_of_reset(1); + + /* unhalt the cpu */ + flowctrl_write_cpu_halt(1, 0); + + tegra_pen_unlock(); +} + +static int tegra20_reset_cpu_1(void) +{ + if (!cpu_online(1) || !tegra20_reset_sleeping_cpu_1()) + return 0; + + tegra20_wake_cpu1_from_reset(); + return -EBUSY; +} +#else +static inline void tegra20_wake_cpu1_from_reset(void) +{ +} + +static inline int tegra20_reset_cpu_1(void) +{ + return 0; +} +#endif + +static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + struct cpuidle_state *state = &drv->states[index]; + u32 cpu_on_time = state->exit_latency; + u32 cpu_off_time = state->target_residency - state->exit_latency; + + while (tegra20_cpu_is_resettable_soon()) + cpu_relax(); + + if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready()) + return false; + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); + + tegra_idle_lp2_last(cpu_on_time, cpu_off_time); + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); + + if (cpu_online(1)) + tegra20_wake_cpu1_from_reset(); + + return true; +} + +#ifdef CONFIG_SMP +static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); + + cpu_suspend(0, tegra20_sleep_cpu_secondary_finish); + + tegra20_cpu_clear_resettable(); + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); + + return true; +} +#else +static inline bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + return true; +} +#endif + +static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; + bool entered_lp2 = false; + + if (tegra_pending_sgi()) + ACCESS_ONCE(abort_flag) = true; + + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + + if (abort_flag) { + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + abort_flag = false; /* clean flag for next coming */ + return -EINTR; + } + + local_fiq_disable(); + + tegra_set_cpu_in_lp2(cpu); + cpu_pm_enter(); + + if (cpu == 0) + entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, index); + else + entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index); + + cpu_pm_exit(); + tegra_clear_cpu_in_lp2(cpu); + + local_fiq_enable(); + + smp_rmb(); + + return entered_lp2 ? index : 0; +} +#endif + int __init tegra20_cpuidle_init(void) { int ret; @@ -44,6 +222,14 @@ int __init tegra20_cpuidle_init(void) struct cpuidle_device *dev; struct cpuidle_driver *drv = &tegra_idle_driver; +#ifdef CONFIG_PM_SLEEP + tegra_tear_down_cpu = tegra20_tear_down_cpu; +#endif + + drv->state_count = ARRAY_SIZE(tegra_idle_states); + memcpy(drv->states, tegra_idle_states, + drv->state_count * sizeof(drv->states[0])); + ret = cpuidle_register_driver(&tegra_idle_driver); if (ret) { pr_err("CPUidle driver registration failed\n"); @@ -53,6 +239,9 @@ int __init tegra20_cpuidle_init(void) for_each_possible_cpu(cpu) { dev = &per_cpu(tegra_idle_device, cpu); dev->cpu = cpu; +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED + dev->coupled_cpus = *cpu_possible_mask; +#endif dev->state_count = drv->state_count; ret = cpuidle_register_device(dev); diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c index 5e8cbf5..8b50cf4 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra30.c +++ b/arch/arm/mach-tegra/cpuidle-tegra30.c @@ -24,6 +24,7 @@ #include <linux/cpuidle.h> #include <linux/cpu_pm.h> #include <linux/clockchips.h> +#include <linux/clk/tegra.h> #include <asm/cpuidle.h> #include <asm/proc-fns.h> @@ -32,7 +33,6 @@ #include "pm.h" #include "sleep.h" -#include "tegra_cpu_car.h" #ifdef CONFIG_PM_SLEEP static int tegra30_idle_lp2(struct cpuidle_device *dev, @@ -121,9 +121,9 @@ static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev, } #endif -static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) +static int tegra30_idle_lp2(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) { u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu; bool entered_lp2 = false; diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c index d065139..4b744c4 100644 --- a/arch/arm/mach-tegra/cpuidle.c +++ b/arch/arm/mach-tegra/cpuidle.c @@ -38,6 +38,9 @@ static int __init tegra_cpuidle_init(void) case TEGRA30: ret = tegra30_cpuidle_init(); break; + case TEGRA114: + ret = tegra114_cpuidle_init(); + break; default: ret = -ENODEV; break; diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h index 496204d..d733f75d 100644 --- a/arch/arm/mach-tegra/cpuidle.h +++ b/arch/arm/mach-tegra/cpuidle.h @@ -29,4 +29,10 @@ int tegra30_cpuidle_init(void); static inline int tegra30_cpuidle_init(void) { return -ENODEV; } #endif +#ifdef CONFIG_ARCH_TEGRA_114_SOC +int tegra114_cpuidle_init(void); +#else +static inline int tegra114_cpuidle_init(void) { return -ENODEV; } +#endif + #endif diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c index a2250dd..b477ef3 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/arch/arm/mach-tegra/flowctrl.c @@ -25,15 +25,16 @@ #include "flowctrl.h" #include "iomap.h" +#include "fuse.h" -u8 flowctrl_offset_halt_cpu[] = { +static u8 flowctrl_offset_halt_cpu[] = { FLOW_CTRL_HALT_CPU0_EVENTS, FLOW_CTRL_HALT_CPU1_EVENTS, FLOW_CTRL_HALT_CPU1_EVENTS + 8, FLOW_CTRL_HALT_CPU1_EVENTS + 16, }; -u8 flowctrl_offset_cpu_csr[] = { +static u8 flowctrl_offset_cpu_csr[] = { FLOW_CTRL_CPU0_CSR, FLOW_CTRL_CPU1_CSR, FLOW_CTRL_CPU1_CSR + 8, @@ -75,11 +76,26 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid) int i; reg = flowctrl_read_cpu_csr(cpuid); - reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */ - reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */ + switch (tegra_chip_id) { + case TEGRA20: + /* clear wfe bitmap */ + reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; + /* clear wfi bitmap */ + reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP; + /* pwr gating on wfe */ + reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid; + break; + case TEGRA30: + /* clear wfe bitmap */ + reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; + /* clear wfi bitmap */ + reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; + /* pwr gating on wfi */ + reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; + break; + } reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */ reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */ - reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; /* pwr gating on wfi */ reg |= FLOW_CTRL_CSR_ENABLE; /* pwr gating */ flowctrl_write_cpu_csr(cpuid, reg); @@ -99,8 +115,20 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid) /* Disable powergating via flow controller for CPU0 */ reg = flowctrl_read_cpu_csr(cpuid); - reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */ - reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */ + switch (tegra_chip_id) { + case TEGRA20: + /* clear wfe bitmap */ + reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; + /* clear wfi bitmap */ + reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP; + break; + case TEGRA30: + /* clear wfe bitmap */ + reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; + /* clear wfi bitmap */ + reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; + break; + } reg &= ~FLOW_CTRL_CSR_ENABLE; /* clear enable */ reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr */ reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event */ diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h index 0798dec..67eab56 100644 --- a/arch/arm/mach-tegra/flowctrl.h +++ b/arch/arm/mach-tegra/flowctrl.h @@ -34,6 +34,10 @@ #define FLOW_CTRL_HALT_CPU1_EVENTS 0x14 #define FLOW_CTRL_CPU1_CSR 0x18 +#define TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 (1 << 4) +#define TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP (3 << 4) +#define TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP 0 + #define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 (1 << 8) #define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4) #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8) diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index 8121742..f7db078 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -20,6 +20,7 @@ #include <linux/kernel.h> #include <linux/io.h> #include <linux/export.h> +#include <linux/tegra-soc.h> #include "fuse.h" #include "iomap.h" @@ -105,6 +106,11 @@ static void tegra_get_process_id(void) tegra_core_process_id = (reg >> 12) & 3; } +u32 tegra_read_chipid(void) +{ + return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804); +} + void tegra_init_fuse(void) { u32 id; @@ -119,7 +125,7 @@ void tegra_init_fuse(void) reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT); tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; - id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804); + id = tegra_read_chipid(); tegra_chip_id = (id >> 8) & 0xff; switch (tegra_chip_id) { diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h index ff1383d..da78434 100644 --- a/arch/arm/mach-tegra/fuse.h +++ b/arch/arm/mach-tegra/fuse.h @@ -37,6 +37,7 @@ enum tegra_revision { #define TEGRA20 0x20 #define TEGRA30 0x30 +#define TEGRA114 0x35 extern int tegra_sku_id; extern int tegra_cpu_process_id; diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 4a317fa..b283481 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -1,22 +1,9 @@ #include <linux/linkage.h> #include <linux/init.h> -#include <asm/cache.h> -#include <asm/asm-offsets.h> -#include <asm/hardware/cache-l2x0.h> - -#include "flowctrl.h" -#include "iomap.h" -#include "reset.h" #include "sleep.h" -#define APB_MISC_GP_HIDREV 0x804 -#define PMC_SCRATCH41 0x140 - -#define RESET_DATA(x) ((TEGRA_RESET_##x)*4) - .section ".text.head", "ax" - __CPUINIT /* * Tegra specific entry point for secondary CPUs. @@ -61,7 +48,6 @@ ENTRY(v7_invalidate_l1) mov pc, lr ENDPROC(v7_invalidate_l1) - ENTRY(tegra_secondary_startup) bl v7_invalidate_l1 /* Enable coresight */ @@ -69,210 +55,3 @@ ENTRY(tegra_secondary_startup) mcr p14, 0, r0, c7, c12, 6 b secondary_startup ENDPROC(tegra_secondary_startup) - -#ifdef CONFIG_PM_SLEEP -/* - * tegra_resume - * - * CPU boot vector when restarting the a CPU following - * an LP2 transition. Also branched to by LP0 and LP1 resume after - * re-enabling sdram. - */ -ENTRY(tegra_resume) - bl v7_invalidate_l1 - /* Enable coresight */ - mov32 r0, 0xC5ACCE55 - mcr p14, 0, r0, c7, c12, 6 - - cpu_id r0 - cmp r0, #0 @ CPU0? - bne cpu_resume @ no - -#ifdef CONFIG_ARCH_TEGRA_3x_SOC - /* Are we on Tegra20? */ - mov32 r6, TEGRA_APB_MISC_BASE - ldr r0, [r6, #APB_MISC_GP_HIDREV] - and r0, r0, #0xff00 - cmp r0, #(0x20 << 8) - beq 1f @ Yes - /* Clear the flow controller flags for this CPU. */ - mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR - ldr r1, [r2] - /* Clear event & intr flag */ - orr r1, r1, \ - #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG - movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps - bic r1, r1, r0 - str r1, [r2] -1: -#endif - -#ifdef CONFIG_HAVE_ARM_SCU - /* enable SCU */ - mov32 r0, TEGRA_ARM_PERIF_BASE - ldr r1, [r0] - orr r1, r1, #1 - str r1, [r0] -#endif - - /* L2 cache resume & re-enable */ - l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr - - b cpu_resume -ENDPROC(tegra_resume) -#endif - -#ifdef CONFIG_CACHE_L2X0 - .globl l2x0_saved_regs_addr -l2x0_saved_regs_addr: - .long 0 -#endif - - .align L1_CACHE_SHIFT -ENTRY(__tegra_cpu_reset_handler_start) - -/* - * __tegra_cpu_reset_handler: - * - * Common handler for all CPU reset events. - * - * Register usage within the reset handler: - * - * R7 = CPU present (to the OS) mask - * R8 = CPU in LP1 state mask - * R9 = CPU in LP2 state mask - * R10 = CPU number - * R11 = CPU mask - * R12 = pointer to reset handler data - * - * NOTE: This code is copied to IRAM. All code and data accesses - * must be position-independent. - */ - - .align L1_CACHE_SHIFT -ENTRY(__tegra_cpu_reset_handler) - - cpsid aif, 0x13 @ SVC mode, interrupts disabled - mrc p15, 0, r10, c0, c0, 5 @ MPIDR - and r10, r10, #0x3 @ R10 = CPU number - mov r11, #1 - mov r11, r11, lsl r10 @ R11 = CPU mask - adr r12, __tegra_cpu_reset_handler_data - -#ifdef CONFIG_SMP - /* Does the OS know about this CPU? */ - ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] - tst r7, r11 @ if !present - bleq __die @ CPU not present (to OS) -#endif - -#ifdef CONFIG_ARCH_TEGRA_2x_SOC - /* Are we on Tegra20? */ - mov32 r6, TEGRA_APB_MISC_BASE - ldr r0, [r6, #APB_MISC_GP_HIDREV] - and r0, r0, #0xff00 - cmp r0, #(0x20 << 8) - bne 1f - /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ - mov32 r6, TEGRA_PMC_BASE - mov r0, #0 - cmp r10, #0 - strne r0, [r6, #PMC_SCRATCH41] -1: -#endif - - /* Waking up from LP2? */ - ldr r9, [r12, #RESET_DATA(MASK_LP2)] - tst r9, r11 @ if in_lp2 - beq __is_not_lp2 - ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] - cmp lr, #0 - bleq __die @ no LP2 startup handler - bx lr - -__is_not_lp2: - -#ifdef CONFIG_SMP - /* - * Can only be secondary boot (initial or hotplug) but CPU 0 - * cannot be here. - */ - cmp r10, #0 - bleq __die @ CPU0 cannot be here - ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] - cmp lr, #0 - bleq __die @ no secondary startup handler - bx lr -#endif - -/* - * We don't know why the CPU reset. Just kill it. - * The LR register will contain the address we died at + 4. - */ - -__die: - sub lr, lr, #4 - mov32 r7, TEGRA_PMC_BASE - str lr, [r7, #PMC_SCRATCH41] - - mov32 r7, TEGRA_CLK_RESET_BASE - - /* Are we on Tegra20? */ - mov32 r6, TEGRA_APB_MISC_BASE - ldr r0, [r6, #APB_MISC_GP_HIDREV] - and r0, r0, #0xff00 - cmp r0, #(0x20 << 8) - bne 1f - -#ifdef CONFIG_ARCH_TEGRA_2x_SOC - mov32 r0, 0x1111 - mov r1, r0, lsl r10 - str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET -#endif -1: -#ifdef CONFIG_ARCH_TEGRA_3x_SOC - mov32 r6, TEGRA_FLOW_CTRL_BASE - - cmp r10, #0 - moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS - moveq r2, #FLOW_CTRL_CPU0_CSR - movne r1, r10, lsl #3 - addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) - addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) - - /* Clear CPU "event" and "interrupt" flags and power gate - it when halting but not before it is in the "WFI" state. */ - ldr r0, [r6, +r2] - orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG - orr r0, r0, #FLOW_CTRL_CSR_ENABLE - str r0, [r6, +r2] - - /* Unconditionally halt this CPU */ - mov r0, #FLOW_CTRL_WAITEVENT - str r0, [r6, +r1] - ldr r0, [r6, +r1] @ memory barrier - - dsb - isb - wfi @ CPU should be power gated here - - /* If the CPU didn't power gate above just kill it's clock. */ - - mov r0, r11, lsl #8 - str r0, [r7, #348] @ CLK_CPU_CMPLX_SET -#endif - - /* If the CPU still isn't dead, just spin here. */ - b . -ENDPROC(__tegra_cpu_reset_handler) - - .align L1_CACHE_SHIFT - .type __tegra_cpu_reset_handler_data, %object - .globl __tegra_cpu_reset_handler_data -__tegra_cpu_reset_handler_data: - .rept TEGRA_RESET_DATA_SIZE - .long 0 - .endr - .align L1_CACHE_SHIFT - -ENTRY(__tegra_cpu_reset_handler_end) diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index dca5141..a599f6e 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c @@ -10,15 +10,26 @@ */ #include <linux/kernel.h> #include <linux/smp.h> +#include <linux/clk/tegra.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> #include "sleep.h" -#include "tegra_cpu_car.h" static void (*tegra_hotplug_shutdown)(void); +int tegra_cpu_kill(unsigned cpu) +{ + cpu = cpu_logical_map(cpu); + + /* Clock gate the CPU */ + tegra_wait_cpu_in_reset(cpu); + tegra_disable_cpu_clock(cpu); + + return 1; +} + /* * platform-specific code to shutdown a CPU * @@ -26,18 +37,12 @@ static void (*tegra_hotplug_shutdown)(void); */ void __ref tegra_cpu_die(unsigned int cpu) { - cpu = cpu_logical_map(cpu); - - /* Flush the L1 data cache. */ - flush_cache_all(); + /* Clean L1 data cache */ + tegra_disable_clean_inv_dcache(); /* Shut down the current CPU. */ tegra_hotplug_shutdown(); - /* Clock gate the CPU */ - tegra_wait_cpu_in_reset(cpu); - tegra_disable_cpu_clock(cpu); - /* Should never return here. */ BUG(); } diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h deleted file mode 100644 index 95f3a54..0000000 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/clk.h - * - * Copyright (C) 2010 Google, Inc. - * - * Author: - * Erik Gilling <konkers@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __MACH_CLK_H -#define __MACH_CLK_H - -struct clk; - -enum tegra_clk_ex_param { - TEGRA_CLK_VI_INP_SEL, - TEGRA_CLK_DTV_INVERT, - TEGRA_CLK_NAND_PAD_DIV2_ENB, - TEGRA_CLK_PLLD_CSI_OUT_ENB, - TEGRA_CLK_PLLD_DSI_OUT_ENB, - TEGRA_CLK_PLLD_MIPI_MUX_SEL, -}; - -void tegra_periph_reset_deassert(struct clk *c); -void tegra_periph_reset_assert(struct clk *c); - -#ifndef CONFIG_COMMON_CLK -unsigned long clk_get_rate_all_locked(struct clk *c); -#endif - -void tegra2_sdmmc_tap_delay(struct clk *c, int delay); -int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting); - -#endif diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h index db8be51..399fbca 100644 --- a/arch/arm/mach-tegra/iomap.h +++ b/arch/arm/mach-tegra/iomap.h @@ -240,15 +240,6 @@ #define TEGRA_CSITE_BASE 0x70040000 #define TEGRA_CSITE_SIZE SZ_256K -#define TEGRA_USB_BASE 0xC5000000 -#define TEGRA_USB_SIZE SZ_16K - -#define TEGRA_USB2_BASE 0xC5004000 -#define TEGRA_USB2_SIZE SZ_16K - -#define TEGRA_USB3_BASE 0xC5008000 -#define TEGRA_USB3_SIZE SZ_16K - #define TEGRA_SDMMC1_BASE 0xC8000000 #define TEGRA_SDMMC1_SIZE SZ_512 diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index b7886f1..1952e82 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -22,8 +22,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/of.h> - -#include <asm/hardware/gic.h> +#include <linux/irqchip/arm-gic.h> #include "board.h" #include "iomap.h" @@ -45,6 +44,8 @@ #define FIRST_LEGACY_IRQ 32 +#define SGI_MASK 0xFFFF + static int num_ictlrs; static void __iomem *ictlr_reg_base[] = { @@ -55,6 +56,19 @@ static void __iomem *ictlr_reg_base[] = { IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE), }; +bool tegra_pending_sgi(void) +{ + u32 pending_set; + void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE); + + pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET); + + if (pending_set & SGI_MASK) + return true; + + return false; +} + static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg) { void __iomem *base; diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h new file mode 100644 index 0000000..5142649 --- /dev/null +++ b/arch/arm/mach-tegra/irq.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __TEGRA_IRQ_H +#define __TEGRA_IRQ_H + +bool tegra_pending_sgi(void); + +#endif diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index bffcd64..b60165f 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -33,11 +33,11 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/export.h> +#include <linux/clk/tegra.h> #include <asm/sizes.h> #include <asm/mach/pci.h> -#include <mach/clk.h> #include <mach/powergate.h> #include "board.h" diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 1b926df..2c6b3d5 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -18,25 +18,26 @@ #include <linux/jiffies.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> +#include <linux/clk/tegra.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/smp_plat.h> #include <mach/powergate.h> #include "fuse.h" #include "flowctrl.h" #include "reset.h" -#include "tegra_cpu_car.h" #include "common.h" #include "iomap.h" extern void tegra_secondary_startup(void); -static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); +static cpumask_t tegra_cpu_init_mask; #define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) @@ -50,6 +51,7 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu) */ gic_secondary_init(0); + cpumask_set_cpu(cpu, &tegra_cpu_init_mask); } static int tegra20_power_up_cpu(unsigned int cpu) @@ -72,14 +74,42 @@ static int tegra30_power_up_cpu(unsigned int cpu) if (pwrgateid < 0) return pwrgateid; - /* If this is the first boot, toggle powergates directly. */ + /* + * The power up sequence of cold boot CPU and warm boot CPU + * was different. + * + * For warm boot CPU that was resumed from CPU hotplug, the + * power will be resumed automatically after un-halting the + * flow controller of the warm boot CPU. We need to wait for + * the confirmaiton that the CPU is powered then removing + * the IO clamps. + * For cold boot CPU, do not wait. After the cold boot CPU be + * booted, it will run to tegra_secondary_init() and set + * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() + * next time around. + */ + if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { + timeout = jiffies + msecs_to_jiffies(50); + do { + if (!tegra_powergate_is_powered(pwrgateid)) + goto remove_clamps; + udelay(10); + } while (time_before(jiffies, timeout)); + } + + /* + * The power status of the cold boot CPU is power gated as + * default. To power up the cold boot CPU, the power should + * be un-gated by un-toggling the power gate register + * manually. + */ if (!tegra_powergate_is_powered(pwrgateid)) { ret = tegra_powergate_power_on(pwrgateid); if (ret) return ret; /* Wait for the power to come up. */ - timeout = jiffies + 10*HZ; + timeout = jiffies + msecs_to_jiffies(100); while (tegra_powergate_is_powered(pwrgateid)) { if (time_after(jiffies, timeout)) return -ETIMEDOUT; @@ -87,6 +117,7 @@ static int tegra30_power_up_cpu(unsigned int cpu) } } +remove_clamps: /* CPU partition is powered. Enable the CPU clock. */ tegra_enable_cpu_clock(cpu); udelay(10); @@ -105,6 +136,8 @@ static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct * { int status; + cpu = cpu_logical_map(cpu); + /* * Force the CPU into reset. The CPU must remain in reset when the * flow controller state is cleared (which will cause the flow @@ -143,38 +176,21 @@ done: return status; } -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. - */ -static void __init tegra_smp_init_cpus(void) -{ - unsigned int i, ncores = scu_get_core_count(scu_base); - - if (ncores > nr_cpu_ids) { - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; - } - - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); -} - static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) { - tegra_cpu_reset_handler_init(); - scu_enable(scu_base); + /* Always mark the boot CPU (CPU0) as initialized. */ + cpumask_set_cpu(0, &tegra_cpu_init_mask); + + if (scu_a9_has_base()) + scu_enable(IO_ADDRESS(scu_a9_get_base())); } struct smp_operations tegra_smp_ops __initdata = { - .smp_init_cpus = tegra_smp_init_cpus, .smp_prepare_cpus = tegra_smp_prepare_cpus, .smp_secondary_init = tegra_secondary_init, .smp_boot_secondary = tegra_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = tegra_cpu_kill, .cpu_die = tegra_cpu_die, .cpu_disable = tegra_cpu_disable, #endif diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 1b11707..523604d 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -24,6 +24,7 @@ #include <linux/cpu_pm.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/clk/tegra.h> #include <asm/smp_plat.h> #include <asm/cacheflush.h> @@ -35,8 +36,8 @@ #include "iomap.h" #include "reset.h" #include "flowctrl.h" +#include "fuse.h" #include "sleep.h" -#include "tegra_cpu_car.h" #define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ @@ -148,7 +149,7 @@ static void suspend_cpu_complex(void) save_cpu_arch_register(); } -void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id) +void tegra_clear_cpu_in_lp2(int phy_cpu_id) { u32 *cpu_in_lp2 = tegra_cpu_lp2_mask; @@ -160,7 +161,7 @@ void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id) spin_unlock(&tegra_lp2_lock); } -bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id) +bool tegra_set_cpu_in_lp2(int phy_cpu_id) { bool last_cpu = false; cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask; @@ -173,6 +174,8 @@ bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id) if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask)) last_cpu = true; + else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1) + tegra20_cpu_set_resettable_soon(); spin_unlock(&tegra_lp2_lock); return last_cpu; diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 2cc1185..c6bc8f8 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -26,8 +26,8 @@ #include <linux/io.h> #include <linux/seq_file.h> #include <linux/spinlock.h> +#include <linux/clk/tegra.h> -#include <mach/clk.h> #include <mach/powergate.h> #include "fuse.h" diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S new file mode 100644 index 0000000..54382ce --- /dev/null +++ b/arch/arm/mach-tegra/reset-handler.S @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/linkage.h> +#include <linux/init.h> + +#include <asm/cache.h> +#include <asm/asm-offsets.h> +#include <asm/hardware/cache-l2x0.h> + +#include "flowctrl.h" +#include "iomap.h" +#include "reset.h" +#include "sleep.h" + +#define APB_MISC_GP_HIDREV 0x804 +#define PMC_SCRATCH41 0x140 + +#define RESET_DATA(x) ((TEGRA_RESET_##x)*4) + +#ifdef CONFIG_PM_SLEEP +/* + * tegra_resume + * + * CPU boot vector when restarting the a CPU following + * an LP2 transition. Also branched to by LP0 and LP1 resume after + * re-enabling sdram. + */ +ENTRY(tegra_resume) + bl v7_invalidate_l1 + /* Enable coresight */ + mov32 r0, 0xC5ACCE55 + mcr p14, 0, r0, c7, c12, 6 + + cpu_id r0 + cmp r0, #0 @ CPU0? + bne cpu_resume @ no + +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + beq 1f @ Yes + /* Clear the flow controller flags for this CPU. */ + mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR + ldr r1, [r2] + /* Clear event & intr flag */ + orr r1, r1, \ + #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG + movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps + bic r1, r1, r0 + str r1, [r2] +1: +#endif + +#ifdef CONFIG_HAVE_ARM_SCU + /* enable SCU */ + mov32 r0, TEGRA_ARM_PERIF_BASE + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] +#endif + + /* L2 cache resume & re-enable */ + l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr + + b cpu_resume +ENDPROC(tegra_resume) +#endif + +#ifdef CONFIG_CACHE_L2X0 + .globl l2x0_saved_regs_addr +l2x0_saved_regs_addr: + .long 0 +#endif + + .align L1_CACHE_SHIFT +ENTRY(__tegra_cpu_reset_handler_start) + +/* + * __tegra_cpu_reset_handler: + * + * Common handler for all CPU reset events. + * + * Register usage within the reset handler: + * + * R7 = CPU present (to the OS) mask + * R8 = CPU in LP1 state mask + * R9 = CPU in LP2 state mask + * R10 = CPU number + * R11 = CPU mask + * R12 = pointer to reset handler data + * + * NOTE: This code is copied to IRAM. All code and data accesses + * must be position-independent. + */ + + .align L1_CACHE_SHIFT +ENTRY(__tegra_cpu_reset_handler) + + cpsid aif, 0x13 @ SVC mode, interrupts disabled + mrc p15, 0, r10, c0, c0, 5 @ MPIDR + and r10, r10, #0x3 @ R10 = CPU number + mov r11, #1 + mov r11, r11, lsl r10 @ R11 = CPU mask + adr r12, __tegra_cpu_reset_handler_data + +#ifdef CONFIG_SMP + /* Does the OS know about this CPU? */ + ldr r7, [r12, #RESET_DATA(MASK_PRESENT)] + tst r7, r11 @ if !present + bleq __die @ CPU not present (to OS) +#endif + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + bne 1f + /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ + mov32 r6, TEGRA_PMC_BASE + mov r0, #0 + cmp r10, #0 + strne r0, [r6, #PMC_SCRATCH41] +1: +#endif + + /* Waking up from LP2? */ + ldr r9, [r12, #RESET_DATA(MASK_LP2)] + tst r9, r11 @ if in_lp2 + beq __is_not_lp2 + ldr lr, [r12, #RESET_DATA(STARTUP_LP2)] + cmp lr, #0 + bleq __die @ no LP2 startup handler + bx lr + +__is_not_lp2: + +#ifdef CONFIG_SMP + /* + * Can only be secondary boot (initial or hotplug) but CPU 0 + * cannot be here. + */ + cmp r10, #0 + bleq __die @ CPU0 cannot be here + ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)] + cmp lr, #0 + bleq __die @ no secondary startup handler + bx lr +#endif + +/* + * We don't know why the CPU reset. Just kill it. + * The LR register will contain the address we died at + 4. + */ + +__die: + sub lr, lr, #4 + mov32 r7, TEGRA_PMC_BASE + str lr, [r7, #PMC_SCRATCH41] + + mov32 r7, TEGRA_CLK_RESET_BASE + + /* Are we on Tegra20? */ + mov32 r6, TEGRA_APB_MISC_BASE + ldr r0, [r6, #APB_MISC_GP_HIDREV] + and r0, r0, #0xff00 + cmp r0, #(0x20 << 8) + bne 1f + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + mov32 r0, 0x1111 + mov r1, r0, lsl r10 + str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET +#endif +1: +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + mov32 r6, TEGRA_FLOW_CTRL_BASE + + cmp r10, #0 + moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS + moveq r2, #FLOW_CTRL_CPU0_CSR + movne r1, r10, lsl #3 + addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8) + addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8) + + /* Clear CPU "event" and "interrupt" flags and power gate + it when halting but not before it is in the "WFI" state. */ + ldr r0, [r6, +r2] + orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG + orr r0, r0, #FLOW_CTRL_CSR_ENABLE + str r0, [r6, +r2] + + /* Unconditionally halt this CPU */ + mov r0, #FLOW_CTRL_WAITEVENT + str r0, [r6, +r1] + ldr r0, [r6, +r1] @ memory barrier + + dsb + isb + wfi @ CPU should be power gated here + + /* If the CPU didn't power gate above just kill it's clock. */ + + mov r0, r11, lsl #8 + str r0, [r7, #348] @ CLK_CPU_CMPLX_SET +#endif + + /* If the CPU still isn't dead, just spin here. */ + b . +ENDPROC(__tegra_cpu_reset_handler) + + .align L1_CACHE_SHIFT + .type __tegra_cpu_reset_handler_data, %object + .globl __tegra_cpu_reset_handler_data +__tegra_cpu_reset_handler_data: + .rept TEGRA_RESET_DATA_SIZE + .long 0 + .endr + .align L1_CACHE_SHIFT + +ENTRY(__tegra_cpu_reset_handler_end) diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 3fd89ec..1ac434e 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -75,7 +75,7 @@ void __init tegra_cpu_reset_handler_init(void) #ifdef CONFIG_SMP __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] = - *((u32 *)cpu_present_mask); + *((u32 *)cpu_possible_mask); __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] = virt_to_phys((void *)tegra_secondary_startup); #endif diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index 72ce709..9f6bfaf 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -21,6 +21,8 @@ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/proc-fns.h> +#include <asm/cp15.h> #include "sleep.h" #include "flowctrl.h" @@ -33,9 +35,6 @@ * should never return */ ENTRY(tegra20_hotplug_shutdown) - /* Turn off SMP coherency */ - exit_smp r4, r5 - /* Put this CPU down */ cpu_id r0 bl tegra20_cpu_shutdown @@ -58,6 +57,9 @@ ENDPROC(tegra20_hotplug_shutdown) ENTRY(tegra20_cpu_shutdown) cmp r0, #0 moveq pc, lr @ must not be called for CPU 0 + mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov r12, #CPU_RESETTABLE + str r12, [r1] cpu_to_halt_reg r1, r0 ldr r3, =TEGRA_FLOW_CTRL_VIRT @@ -78,3 +80,198 @@ ENTRY(tegra20_cpu_shutdown) mov pc, lr ENDPROC(tegra20_cpu_shutdown) #endif + +#ifdef CONFIG_PM_SLEEP +/* + * tegra_pen_lock + * + * spinlock implementation with no atomic test-and-set and no coherence + * using Peterson's algorithm on strongly-ordered registers + * used to synchronize a cpu waking up from wfi with entering lp2 on idle + * + * The reference link of Peterson's algorithm: + * http://en.wikipedia.org/wiki/Peterson's_algorithm + * + * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm) + * on cpu 0: + * r2 = flag[0] (in SCRATCH38) + * r3 = flag[1] (in SCRATCH39) + * on cpu1: + * r2 = flag[1] (in SCRATCH39) + * r3 = flag[0] (in SCRATCH38) + * + * must be called with MMU on + * corrupts r0-r3, r12 + */ +ENTRY(tegra_pen_lock) + mov32 r3, TEGRA_PMC_VIRT + cpu_id r0 + add r1, r3, #PMC_SCRATCH37 + cmp r0, #0 + addeq r2, r3, #PMC_SCRATCH38 + addeq r3, r3, #PMC_SCRATCH39 + addne r2, r3, #PMC_SCRATCH39 + addne r3, r3, #PMC_SCRATCH38 + + mov r12, #1 + str r12, [r2] @ flag[cpu] = 1 + dsb + str r12, [r1] @ !turn = cpu +1: dsb + ldr r12, [r3] + cmp r12, #1 @ flag[!cpu] == 1? + ldreq r12, [r1] + cmpeq r12, r0 @ !turn == cpu? + beq 1b @ while !turn == cpu && flag[!cpu] == 1 + + mov pc, lr @ locked +ENDPROC(tegra_pen_lock) + +ENTRY(tegra_pen_unlock) + dsb + mov32 r3, TEGRA_PMC_VIRT + cpu_id r0 + cmp r0, #0 + addeq r2, r3, #PMC_SCRATCH38 + addne r2, r3, #PMC_SCRATCH39 + mov r12, #0 + str r12, [r2] + mov pc, lr +ENDPROC(tegra_pen_unlock) + +/* + * tegra20_cpu_clear_resettable(void) + * + * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when + * it is expected that the secondary CPU will be idle soon. + */ +ENTRY(tegra20_cpu_clear_resettable) + mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov r12, #CPU_NOT_RESETTABLE + str r12, [r1] + mov pc, lr +ENDPROC(tegra20_cpu_clear_resettable) + +/* + * tegra20_cpu_set_resettable_soon(void) + * + * Called to set the "resettable soon" flag in PMC_SCRATCH41 when + * it is expected that the secondary CPU will be idle soon. + */ +ENTRY(tegra20_cpu_set_resettable_soon) + mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov r12, #CPU_RESETTABLE_SOON + str r12, [r1] + mov pc, lr +ENDPROC(tegra20_cpu_set_resettable_soon) + +/* + * tegra20_cpu_is_resettable_soon(void) + * + * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been + * set because it is expected that the secondary CPU will be idle soon. + */ +ENTRY(tegra20_cpu_is_resettable_soon) + mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 + ldr r12, [r1] + cmp r12, #CPU_RESETTABLE_SOON + moveq r0, #1 + movne r0, #0 + mov pc, lr +ENDPROC(tegra20_cpu_is_resettable_soon) + +/* + * tegra20_sleep_cpu_secondary_finish(unsigned long v2p) + * + * Enters WFI on secondary CPU by exiting coherency. + */ +ENTRY(tegra20_sleep_cpu_secondary_finish) + stmfd sp!, {r4-r11, lr} + + mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency + + /* Flush and disable the L1 data cache */ + bl tegra_disable_clean_inv_dcache + + mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41 + mov r3, #CPU_RESETTABLE + str r3, [r0] + + bl cpu_do_idle + + /* + * cpu may be reset while in wfi, which will return through + * tegra_resume to cpu_resume + * or interrupt may wake wfi, which will return here + * cpu state is unchanged - MMU is on, cache is on, coherency + * is off, and the data cache is off + * + * r11 contains the original actlr + */ + + bl tegra_pen_lock + + mov32 r3, TEGRA_PMC_VIRT + add r0, r3, #PMC_SCRATCH41 + mov r3, #CPU_NOT_RESETTABLE + str r3, [r0] + + bl tegra_pen_unlock + + /* Re-enable the data cache */ + mrc p15, 0, r10, c1, c0, 0 + orr r10, r10, #CR_C + mcr p15, 0, r10, c1, c0, 0 + isb + + mcr p15, 0, r11, c1, c0, 1 @ reenable coherency + + /* Invalidate the TLBs & BTAC */ + mov r1, #0 + mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs + mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC + dsb + isb + + /* the cpu was running with coherency disabled, + * caches may be out of date */ + bl v7_flush_kern_cache_louis + + ldmfd sp!, {r4 - r11, pc} +ENDPROC(tegra20_sleep_cpu_secondary_finish) + +/* + * tegra20_tear_down_cpu + * + * Switches the CPU cluster to PLL-P and enters sleep. + */ +ENTRY(tegra20_tear_down_cpu) + bl tegra_switch_cpu_to_pllp + b tegra20_enter_sleep +ENDPROC(tegra20_tear_down_cpu) + +/* + * tegra20_enter_sleep + * + * uses flow controller to enter sleep state + * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 + * executes from SDRAM with target state is LP2 + */ +tegra20_enter_sleep: + mov32 r6, TEGRA_FLOW_CTRL_BASE + + mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT + orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ + cpu_id r1 + cpu_to_halt_reg r1, r1 + str r0, [r6, r1] + dsb + ldr r0, [r6, r1] /* memory barrier */ + +halted: + dsb + wfe /* CPU should be power gated here */ + isb + b halted + +#endif diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S index 562a8e7..63a15bd 100644 --- a/arch/arm/mach-tegra/sleep-tegra30.S +++ b/arch/arm/mach-tegra/sleep-tegra30.S @@ -32,9 +32,6 @@ * Should never return. */ ENTRY(tegra30_hotplug_shutdown) - /* Turn off SMP coherency */ - exit_smp r4, r5 - /* Powergate this CPU */ mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN bl tegra30_cpu_shutdown diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index 26afa7c..364d845 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -34,7 +34,10 @@ #include "flowctrl.h" #include "sleep.h" -#ifdef CONFIG_PM_SLEEP +#define CLK_RESET_CCLK_BURST 0x20 +#define CLK_RESET_CCLK_DIVIDER 0x24 + +#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) /* * tegra_disable_clean_inv_dcache * @@ -60,7 +63,9 @@ ENTRY(tegra_disable_clean_inv_dcache) ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc} ENDPROC(tegra_disable_clean_inv_dcache) +#endif +#ifdef CONFIG_PM_SLEEP /* * tegra_sleep_cpu_finish(unsigned long v2p) * @@ -108,4 +113,20 @@ ENTRY(tegra_shut_off_mmu) mov pc, r0 ENDPROC(tegra_shut_off_mmu) .popsection + +/* + * tegra_switch_cpu_to_pllp + * + * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp + */ +ENTRY(tegra_switch_cpu_to_pllp) + /* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */ + mov32 r5, TEGRA_CLK_RESET_BASE + mov r0, #(2 << 28) @ burst policy = run mode + orr r0, r0, #(4 << 4) @ use PLLP in run mode burst + str r0, [r5, #CLK_RESET_CCLK_BURST] + mov r0, #0 + str r0, [r5, #CLK_RESET_CCLK_DIVIDER] + mov pc, lr +ENDPROC(tegra_switch_cpu_to_pllp) #endif diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 9821ee7..4ffae54 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -25,6 +25,19 @@ + IO_PPSB_VIRT) #define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \ + IO_PPSB_VIRT) +#define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT) + +/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */ +#define PMC_SCRATCH37 0x130 +#define PMC_SCRATCH38 0x134 +#define PMC_SCRATCH39 0x138 +#define PMC_SCRATCH41 0x140 + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +#define CPU_RESETTABLE 2 +#define CPU_RESETTABLE_SOON 1 +#define CPU_NOT_RESETTABLE 0 +#endif #ifdef __ASSEMBLY__ /* returns the offset of the flow controller halt register for a cpu */ @@ -104,8 +117,11 @@ exit_l2_resume: .endm #endif /* CONFIG_CACHE_L2X0 */ #else +void tegra_pen_lock(void); +void tegra_pen_unlock(void); void tegra_resume(void); int tegra_sleep_cpu_finish(unsigned long); +void tegra_disable_clean_inv_dcache(void); #ifdef CONFIG_HOTPLUG_CPU void tegra20_hotplug_init(void); @@ -115,6 +131,17 @@ static inline void tegra20_hotplug_init(void) {} static inline void tegra30_hotplug_init(void) {} #endif +void tegra20_cpu_shutdown(int cpu); +int tegra20_cpu_is_resettable_soon(void); +void tegra20_cpu_clear_resettable(void); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +void tegra20_cpu_set_resettable_soon(void); +#else +static inline void tegra20_cpu_set_resettable_soon(void) {} +#endif + +int tegra20_sleep_cpu_secondary_finish(unsigned long); +void tegra20_tear_down_cpu(void); int tegra30_sleep_cpu_secondary_finish(unsigned long); void tegra30_tear_down_cpu(void); diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c deleted file mode 100644 index 4eb6bc8..0000000 --- a/arch/arm/mach-tegra/tegra20_clocks.c +++ /dev/null @@ -1,1623 +0,0 @@ -/* - * arch/arm/mach-tegra/tegra20_clocks.c - * - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clkdev.h> -#include <linux/clk.h> - -#include "clock.h" -#include "fuse.h" -#include "iomap.h" -#include "tegra2_emc.h" -#include "tegra_cpu_car.h" - -#define RST_DEVICES 0x004 -#define RST_DEVICES_SET 0x300 -#define RST_DEVICES_CLR 0x304 -#define RST_DEVICES_NUM 3 - -#define CLK_OUT_ENB 0x010 -#define CLK_OUT_ENB_SET 0x320 -#define CLK_OUT_ENB_CLR 0x324 -#define CLK_OUT_ENB_NUM 3 - -#define CLK_MASK_ARM 0x44 -#define MISC_CLK_ENB 0x48 - -#define OSC_CTRL 0x50 -#define OSC_CTRL_OSC_FREQ_MASK (3<<30) -#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30) -#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) -#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) -#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) -#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) - -#define OSC_FREQ_DET 0x58 -#define OSC_FREQ_DET_TRIG (1<<31) - -#define OSC_FREQ_DET_STATUS 0x5C -#define OSC_FREQ_DET_BUSY (1<<31) -#define OSC_FREQ_DET_CNT_MASK 0xFFFF - -#define PERIPH_CLK_SOURCE_I2S1 0x100 -#define PERIPH_CLK_SOURCE_EMC 0x19c -#define PERIPH_CLK_SOURCE_OSC 0x1fc -#define PERIPH_CLK_SOURCE_NUM \ - ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4) - -#define PERIPH_CLK_SOURCE_MASK (3<<30) -#define PERIPH_CLK_SOURCE_SHIFT 30 -#define PERIPH_CLK_SOURCE_PWM_MASK (7<<28) -#define PERIPH_CLK_SOURCE_PWM_SHIFT 28 -#define PERIPH_CLK_SOURCE_ENABLE (1<<28) -#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF -#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF -#define PERIPH_CLK_SOURCE_DIV_SHIFT 0 - -#define SDMMC_CLK_INT_FB_SEL (1 << 23) -#define SDMMC_CLK_INT_FB_DLY_SHIFT 16 -#define SDMMC_CLK_INT_FB_DLY_MASK (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT) - -#define PLL_BASE 0x0 -#define PLL_BASE_BYPASS (1<<31) -#define PLL_BASE_ENABLE (1<<30) -#define PLL_BASE_REF_ENABLE (1<<29) -#define PLL_BASE_OVERRIDE (1<<28) -#define PLL_BASE_DIVP_MASK (0x7<<20) -#define PLL_BASE_DIVP_SHIFT 20 -#define PLL_BASE_DIVN_MASK (0x3FF<<8) -#define PLL_BASE_DIVN_SHIFT 8 -#define PLL_BASE_DIVM_MASK (0x1F) -#define PLL_BASE_DIVM_SHIFT 0 - -#define PLL_OUT_RATIO_MASK (0xFF<<8) -#define PLL_OUT_RATIO_SHIFT 8 -#define PLL_OUT_OVERRIDE (1<<2) -#define PLL_OUT_CLKEN (1<<1) -#define PLL_OUT_RESET_DISABLE (1<<0) - -#define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) - -#define PLL_MISC_DCCON_SHIFT 20 -#define PLL_MISC_CPCON_SHIFT 8 -#define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) -#define PLL_MISC_LFCON_SHIFT 4 -#define PLL_MISC_LFCON_MASK (0xF<<PLL_MISC_LFCON_SHIFT) -#define PLL_MISC_VCOCON_SHIFT 0 -#define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) - -#define PLLU_BASE_POST_DIV (1<<20) - -#define PLLD_MISC_CLKENABLE (1<<30) -#define PLLD_MISC_DIV_RST (1<<23) -#define PLLD_MISC_DCCON_SHIFT 12 - -#define PLLE_MISC_READY (1 << 15) - -#define PERIPH_CLK_TO_ENB_REG(c) ((c->u.periph.clk_num / 32) * 4) -#define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->u.periph.clk_num / 32) * 8) -#define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->u.periph.clk_num % 32)) - -#define SUPER_CLK_MUX 0x00 -#define SUPER_STATE_SHIFT 28 -#define SUPER_STATE_MASK (0xF << SUPER_STATE_SHIFT) -#define SUPER_STATE_STANDBY (0x0 << SUPER_STATE_SHIFT) -#define SUPER_STATE_IDLE (0x1 << SUPER_STATE_SHIFT) -#define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT) -#define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT) -#define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT) -#define SUPER_SOURCE_MASK 0xF -#define SUPER_FIQ_SOURCE_SHIFT 12 -#define SUPER_IRQ_SOURCE_SHIFT 8 -#define SUPER_RUN_SOURCE_SHIFT 4 -#define SUPER_IDLE_SOURCE_SHIFT 0 - -#define SUPER_CLK_DIVIDER 0x04 - -#define BUS_CLK_DISABLE (1<<3) -#define BUS_CLK_DIV_MASK 0x3 - -#define PMC_CTRL 0x0 - #define PMC_CTRL_BLINK_ENB (1 << 7) - -#define PMC_DPD_PADS_ORIDE 0x1c - #define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20) - -#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0 -#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff -#define PMC_BLINK_TIMER_ENB (1 << 15) -#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 -#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff - -/* Tegra CPU clock and reset control regs */ -#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c -#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 -#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344 - -#define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) -#define CPU_RESET(cpu) (0x1111ul << (cpu)) - -static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); -static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); - -/* - * Some clocks share a register with other clocks. Any clock op that - * non-atomically modifies a register used by another clock must lock - * clock_register_lock first. - */ -static DEFINE_SPINLOCK(clock_register_lock); - -/* - * Some peripheral clocks share an enable bit, so refcount the enable bits - * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U - */ -static int tegra_periph_clk_enable_refcount[3 * 32]; - -#define clk_writel(value, reg) \ - __raw_writel(value, reg_clk_base + (reg)) -#define clk_readl(reg) \ - __raw_readl(reg_clk_base + (reg)) -#define pmc_writel(value, reg) \ - __raw_writel(value, reg_pmc_base + (reg)) -#define pmc_readl(reg) \ - __raw_readl(reg_pmc_base + (reg)) - -static unsigned long clk_measure_input_freq(void) -{ - u32 clock_autodetect; - clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); - do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); - clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); - if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) { - return 12000000; - } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) { - return 13000000; - } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) { - return 19200000; - } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { - return 26000000; - } else { - pr_err("%s: Unexpected clock autodetect value %d", - __func__, clock_autodetect); - BUG(); - return 0; - } -} - -static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate) -{ - s64 divider_u71 = parent_rate * 2; - divider_u71 += rate - 1; - do_div(divider_u71, rate); - - if (divider_u71 - 2 < 0) - return 0; - - if (divider_u71 - 2 > 255) - return -EINVAL; - - return divider_u71 - 2; -} - -static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) -{ - s64 divider_u16; - - divider_u16 = parent_rate; - divider_u16 += rate - 1; - do_div(divider_u16, rate); - - if (divider_u16 - 1 < 0) - return 0; - - if (divider_u16 - 1 > 0xFFFF) - return -EINVAL; - - return divider_u16 - 1; -} - -static unsigned long tegra_clk_fixed_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return to_clk_tegra(hw)->fixed_rate; -} - -struct clk_ops tegra_clk_32k_ops = { - .recalc_rate = tegra_clk_fixed_recalc_rate, -}; - -/* clk_m functions */ -static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - if (!to_clk_tegra(hw)->fixed_rate) - to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq(); - return to_clk_tegra(hw)->fixed_rate; -} - -static void tegra20_clk_m_init(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 osc_ctrl = clk_readl(OSC_CTRL); - u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK; - - switch (c->fixed_rate) { - case 12000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; - break; - case 13000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ; - break; - case 19200000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ; - break; - case 26000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ; - break; - default: - BUG(); - } - clk_writel(auto_clock_control, OSC_CTRL); -} - -struct clk_ops tegra_clk_m_ops = { - .init = tegra20_clk_m_init, - .recalc_rate = tegra20_clk_m_recalc_rate, -}; - -/* super clock functions */ -/* "super clocks" on tegra have two-stage muxes and a clock skipping - * super divider. We will ignore the clock skipping divider, since we - * can't lower the voltage when using the clock skip, but we can if we - * lower the PLL frequency. - */ -static int tegra20_super_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg + SUPER_CLK_MUX); - BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && - ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); - c->state = ON; - return c->state; -} - -static int tegra20_super_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - clk_writel(0, c->reg + SUPER_CLK_DIVIDER); - return 0; -} - -static void tegra20_super_clk_disable(struct clk_hw *hw) -{ - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - /* oops - don't disable the CPU clock! */ - BUG(); -} - -static u8 tegra20_super_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - int val = clk_readl(c->reg + SUPER_CLK_MUX); - int source; - int shift; - - BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && - ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); - shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? - SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; - source = (val >> shift) & SUPER_SOURCE_MASK; - return source; -} - -static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg + SUPER_CLK_MUX); - int shift; - - BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && - ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); - shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? - SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; - val &= ~(SUPER_SOURCE_MASK << shift); - val |= index << shift; - - clk_writel(val, c->reg); - - return 0; -} - -/* FIX ME: Need to switch parents to change the source PLL rate */ -static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - return prate; -} - -static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return *prate; -} - -static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - return 0; -} - -struct clk_ops tegra_super_ops = { - .is_enabled = tegra20_super_clk_is_enabled, - .enable = tegra20_super_clk_enable, - .disable = tegra20_super_clk_disable, - .set_parent = tegra20_super_clk_set_parent, - .get_parent = tegra20_super_clk_get_parent, - .set_rate = tegra20_super_clk_set_rate, - .round_rate = tegra20_super_clk_round_rate, - .recalc_rate = tegra20_super_clk_recalc_rate, -}; - -static unsigned long tegra20_twd_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -struct clk_ops tegra_twd_ops = { - .recalc_rate = tegra20_twd_clk_recalc_rate, -}; - -static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw) -{ - return 0; -} - -struct clk_ops tegra_cop_ops = { - .get_parent = tegra20_cop_clk_get_parent, -}; - -/* virtual cop clock functions. Used to acquire the fake 'cop' clock to - * reset the COP block (i.e. AVP) */ -void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert) -{ - unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; - - pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert"); - clk_writel(1 << 1, reg); -} - -/* bus clock functions */ -static int tegra20_bus_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - - c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; - return c->state; -} - -static int tegra20_bus_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - u32 val; - - spin_lock_irqsave(&clock_register_lock, flags); - - val = clk_readl(c->reg); - val &= ~(BUS_CLK_DISABLE << c->reg_shift); - clk_writel(val, c->reg); - - spin_unlock_irqrestore(&clock_register_lock, flags); - - return 0; -} - -static void tegra20_bus_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - u32 val; - - spin_lock_irqsave(&clock_register_lock, flags); - - val = clk_readl(c->reg); - val |= BUS_CLK_DISABLE << c->reg_shift; - clk_writel(val, c->reg); - - spin_unlock_irqrestore(&clock_register_lock, flags); -} - -static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - u64 rate = prate; - - c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; - c->mul = 1; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -static int tegra20_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - int ret = -EINVAL; - unsigned long flags; - u32 val; - int i; - - spin_lock_irqsave(&clock_register_lock, flags); - - val = clk_readl(c->reg); - for (i = 1; i <= 4; i++) { - if (rate == parent_rate / i) { - val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); - val |= (i - 1) << c->reg_shift; - clk_writel(val, c->reg); - c->div = i; - c->mul = 1; - ret = 0; - break; - } - } - - spin_unlock_irqrestore(&clock_register_lock, flags); - - return ret; -} - -static long tegra20_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - unsigned long parent_rate = *prate; - s64 divider; - - if (rate >= parent_rate) - return rate; - - divider = parent_rate; - divider += rate - 1; - do_div(divider, rate); - - if (divider < 0) - return divider; - - if (divider > 4) - divider = 4; - do_div(parent_rate, divider); - - return parent_rate; -} - -struct clk_ops tegra_bus_ops = { - .is_enabled = tegra20_bus_clk_is_enabled, - .enable = tegra20_bus_clk_enable, - .disable = tegra20_bus_clk_disable, - .set_rate = tegra20_bus_clk_set_rate, - .round_rate = tegra20_bus_clk_round_rate, - .recalc_rate = tegra20_bus_clk_recalc_rate, -}; - -/* Blink output functions */ -static int tegra20_blink_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = pmc_readl(PMC_CTRL); - c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF; - return c->state; -} - -static unsigned long tegra20_blink_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = prate; - u32 val; - - c->mul = 1; - val = pmc_readl(c->reg); - - if (val & PMC_BLINK_TIMER_ENB) { - unsigned int on_off; - - on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) & - PMC_BLINK_TIMER_DATA_ON_MASK; - val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT; - val &= PMC_BLINK_TIMER_DATA_OFF_MASK; - on_off += val; - /* each tick in the blink timer is 4 32KHz clocks */ - c->div = on_off * 4; - } else { - c->div = 1; - } - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -static int tegra20_blink_clk_enable(struct clk_hw *hw) -{ - u32 val; - - val = pmc_readl(PMC_DPD_PADS_ORIDE); - pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); - - val = pmc_readl(PMC_CTRL); - pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL); - - return 0; -} - -static void tegra20_blink_clk_disable(struct clk_hw *hw) -{ - u32 val; - - val = pmc_readl(PMC_CTRL); - pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL); - - val = pmc_readl(PMC_DPD_PADS_ORIDE); - pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); -} - -static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (rate >= parent_rate) { - c->div = 1; - pmc_writel(0, c->reg); - } else { - unsigned int on_off; - u32 val; - - on_off = DIV_ROUND_UP(parent_rate / 8, rate); - c->div = on_off * 8; - - val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) << - PMC_BLINK_TIMER_DATA_ON_SHIFT; - on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK; - on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT; - val |= on_off; - val |= PMC_BLINK_TIMER_ENB; - pmc_writel(val, c->reg); - } - - return 0; -} - -static long tegra20_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - int div; - int mul; - long round_rate = *prate; - - mul = 1; - - if (rate >= *prate) { - div = 1; - } else { - div = DIV_ROUND_UP(*prate / 8, rate); - div *= 8; - } - - round_rate *= mul; - round_rate += div - 1; - do_div(round_rate, div); - - return round_rate; -} - -struct clk_ops tegra_blink_clk_ops = { - .is_enabled = tegra20_blink_clk_is_enabled, - .enable = tegra20_blink_clk_enable, - .disable = tegra20_blink_clk_disable, - .set_rate = tegra20_blink_clk_set_rate, - .round_rate = tegra20_blink_clk_round_rate, - .recalc_rate = tegra20_blink_clk_recalc_rate, -}; - -/* PLL Functions */ -static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c) -{ - udelay(c->u.pll.lock_delay); - return 0; -} - -static int tegra20_pll_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg + PLL_BASE); - - c->state = (val & PLL_BASE_ENABLE) ? ON : OFF; - return c->state; -} - -static unsigned long tegra20_pll_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg + PLL_BASE); - u64 rate = prate; - - if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { - const struct clk_pll_freq_table *sel; - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == prate && - sel->output_rate == c->u.pll.fixed_rate) { - c->mul = sel->n; - c->div = sel->m * sel->p; - break; - } - } - pr_err("Clock %s has unknown fixed frequency\n", - __clk_get_name(hw->clk)); - BUG(); - } else if (val & PLL_BASE_BYPASS) { - c->mul = 1; - c->div = 1; - } else { - c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; - c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; - if (c->flags & PLLU) - c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2; - else - c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; - } - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -static int tegra20_pll_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - val = clk_readl(c->reg + PLL_BASE); - val &= ~PLL_BASE_BYPASS; - val |= PLL_BASE_ENABLE; - clk_writel(val, c->reg + PLL_BASE); - - tegra20_pll_clk_wait_for_lock(c); - - return 0; -} - -static void tegra20_pll_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - val = clk_readl(c->reg); - val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); - clk_writel(val, c->reg); -} - -static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long input_rate = parent_rate; - const struct clk_pll_freq_table *sel; - u32 val; - - pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); - - if (c->flags & PLL_FIXED) { - int ret = 0; - if (rate != c->u.pll.fixed_rate) { - pr_err("%s: Can not change %s fixed rate %lu to %lu\n", - __func__, __clk_get_name(hw->clk), - c->u.pll.fixed_rate, rate); - ret = -EINVAL; - } - return ret; - } - - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == input_rate && sel->output_rate == rate) { - c->mul = sel->n; - c->div = sel->m * sel->p; - - val = clk_readl(c->reg + PLL_BASE); - if (c->flags & PLL_FIXED) - val |= PLL_BASE_OVERRIDE; - val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | - PLL_BASE_DIVM_MASK); - val |= (sel->m << PLL_BASE_DIVM_SHIFT) | - (sel->n << PLL_BASE_DIVN_SHIFT); - BUG_ON(sel->p < 1 || sel->p > 2); - if (c->flags & PLLU) { - if (sel->p == 1) - val |= PLLU_BASE_POST_DIV; - } else { - if (sel->p == 2) - val |= 1 << PLL_BASE_DIVP_SHIFT; - } - clk_writel(val, c->reg + PLL_BASE); - - if (c->flags & PLL_HAS_CPCON) { - val = clk_readl(c->reg + PLL_MISC(c)); - val &= ~PLL_MISC_CPCON_MASK; - val |= sel->cpcon << PLL_MISC_CPCON_SHIFT; - clk_writel(val, c->reg + PLL_MISC(c)); - } - - if (c->state == ON) - tegra20_pll_clk_enable(hw); - return 0; - } - } - return -EINVAL; -} - -static long tegra20_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - const struct clk_pll_freq_table *sel; - unsigned long input_rate = *prate; - u64 output_rate = *prate; - int mul; - int div; - - if (c->flags & PLL_FIXED) - return c->u.pll.fixed_rate; - - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) - if (sel->input_rate == input_rate && sel->output_rate == rate) { - mul = sel->n; - div = sel->m * sel->p; - break; - } - - if (sel->input_rate == 0) - return -EINVAL; - - output_rate *= mul; - output_rate += div - 1; /* round up */ - do_div(output_rate, div); - - return output_rate; -} - -struct clk_ops tegra_pll_ops = { - .is_enabled = tegra20_pll_clk_is_enabled, - .enable = tegra20_pll_clk_enable, - .disable = tegra20_pll_clk_disable, - .set_rate = tegra20_pll_clk_set_rate, - .recalc_rate = tegra20_pll_clk_recalc_rate, - .round_rate = tegra20_pll_clk_round_rate, -}; - -static void tegra20_pllx_clk_init(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (tegra_sku_id == 7) - c->max_rate = 750000000; -} - -struct clk_ops tegra_pllx_ops = { - .init = tegra20_pllx_clk_init, - .is_enabled = tegra20_pll_clk_is_enabled, - .enable = tegra20_pll_clk_enable, - .disable = tegra20_pll_clk_disable, - .set_rate = tegra20_pll_clk_set_rate, - .recalc_rate = tegra20_pll_clk_recalc_rate, - .round_rate = tegra20_pll_clk_round_rate, -}; - -static int tegra20_plle_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - mdelay(1); - - val = clk_readl(c->reg + PLL_BASE); - if (!(val & PLLE_MISC_READY)) - return -EBUSY; - - val = clk_readl(c->reg + PLL_BASE); - val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS; - clk_writel(val, c->reg + PLL_BASE); - - return 0; -} - -struct clk_ops tegra_plle_ops = { - .is_enabled = tegra20_pll_clk_is_enabled, - .enable = tegra20_plle_clk_enable, - .set_rate = tegra20_pll_clk_set_rate, - .recalc_rate = tegra20_pll_clk_recalc_rate, - .round_rate = tegra20_pll_clk_round_rate, -}; - -/* Clock divider ops */ -static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - - val >>= c->reg_shift; - c->state = (val & PLL_OUT_CLKEN) ? ON : OFF; - if (!(val & PLL_OUT_RESET_DISABLE)) - c->state = OFF; - return c->state; -} - -static unsigned long tegra20_pll_div_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = prate; - u32 val = clk_readl(c->reg); - u32 divu71; - - val >>= c->reg_shift; - - if (c->flags & DIV_U71) { - divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT; - c->div = (divu71 + 2); - c->mul = 2; - } else if (c->flags & DIV_2) { - c->div = 2; - c->mul = 1; - } else { - c->div = 1; - c->mul = 1; - } - - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - - return rate; -} - -static int tegra20_pll_div_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - u32 new_val; - u32 val; - - pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); - - if (c->flags & DIV_U71) { - spin_lock_irqsave(&clock_register_lock, flags); - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - - new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE; - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel(val, c->reg); - spin_unlock_irqrestore(&clock_register_lock, flags); - return 0; - } else if (c->flags & DIV_2) { - BUG_ON(!(c->flags & PLLD)); - spin_lock_irqsave(&clock_register_lock, flags); - val = clk_readl(c->reg); - val &= ~PLLD_MISC_DIV_RST; - clk_writel(val, c->reg); - spin_unlock_irqrestore(&clock_register_lock, flags); - return 0; - } - return -EINVAL; -} - -static void tegra20_pll_div_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - u32 new_val; - u32 val; - - pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); - - if (c->flags & DIV_U71) { - spin_lock_irqsave(&clock_register_lock, flags); - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - - new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE); - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel(val, c->reg); - spin_unlock_irqrestore(&clock_register_lock, flags); - } else if (c->flags & DIV_2) { - BUG_ON(!(c->flags & PLLD)); - spin_lock_irqsave(&clock_register_lock, flags); - val = clk_readl(c->reg); - val |= PLLD_MISC_DIV_RST; - clk_writel(val, c->reg); - spin_unlock_irqrestore(&clock_register_lock, flags); - } -} - -static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - int divider_u71; - u32 new_val; - u32 val; - - pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); - - if (c->flags & DIV_U71) { - divider_u71 = clk_div71_get_divider(parent_rate, rate); - if (divider_u71 >= 0) { - spin_lock_irqsave(&clock_register_lock, flags); - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - if (c->flags & DIV_U71_FIXED) - new_val |= PLL_OUT_OVERRIDE; - new_val &= ~PLL_OUT_RATIO_MASK; - new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT; - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel(val, c->reg); - c->div = divider_u71 + 2; - c->mul = 2; - spin_unlock_irqrestore(&clock_register_lock, flags); - return 0; - } - } else if (c->flags & DIV_2) { - if (parent_rate == rate * 2) - return 0; - } - return -EINVAL; -} - -static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long parent_rate = *prate; - int divider; - - pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider(parent_rate, rate); - if (divider < 0) - return divider; - return DIV_ROUND_UP(parent_rate * 2, divider + 2); - } else if (c->flags & DIV_2) { - return DIV_ROUND_UP(parent_rate, 2); - } - return -EINVAL; -} - -struct clk_ops tegra_pll_div_ops = { - .is_enabled = tegra20_pll_div_clk_is_enabled, - .enable = tegra20_pll_div_clk_enable, - .disable = tegra20_pll_div_clk_disable, - .set_rate = tegra20_pll_div_clk_set_rate, - .round_rate = tegra20_pll_div_clk_round_rate, - .recalc_rate = tegra20_pll_div_clk_recalc_rate, -}; - -/* Periph clk ops */ - -static int tegra20_periph_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - c->state = ON; - - if (!c->u.periph.clk_num) - goto out; - - if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & - PERIPH_CLK_TO_ENB_BIT(c))) - c->state = OFF; - - if (!(c->flags & PERIPH_NO_RESET)) - if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & - PERIPH_CLK_TO_ENB_BIT(c)) - c->state = OFF; - -out: - return c->state; -} - -static int tegra20_periph_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - u32 val; - - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - if (!c->u.periph.clk_num) - return 0; - - tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; - if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1) - return 0; - - spin_lock_irqsave(&clock_register_lock, flags); - - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); - if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); - if (c->flags & PERIPH_EMC_ENB) { - /* The EMC peripheral clock has 2 extra enable bits */ - /* FIXME: Do they need to be disabled? */ - val = clk_readl(c->reg); - val |= 0x3 << 24; - clk_writel(val, c->reg); - } - - spin_unlock_irqrestore(&clock_register_lock, flags); - - return 0; -} - -static void tegra20_periph_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long flags; - - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - if (!c->u.periph.clk_num) - return; - - tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; - - if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0) - return; - - spin_lock_irqsave(&clock_register_lock, flags); - - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); - - spin_unlock_irqrestore(&clock_register_lock, flags); -} - -void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; - - pr_debug("%s %s on clock %s\n", __func__, - assert ? "assert" : "deassert", __clk_get_name(hw->clk)); - - BUG_ON(!c->u.periph.clk_num); - - if (!(c->flags & PERIPH_NO_RESET)) - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - base + PERIPH_CLK_TO_ENB_SET_REG(c)); -} - -static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - u32 mask; - u32 shift; - - pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index); - - if (c->flags & MUX_PWM) { - shift = PERIPH_CLK_SOURCE_PWM_SHIFT; - mask = PERIPH_CLK_SOURCE_PWM_MASK; - } else { - shift = PERIPH_CLK_SOURCE_SHIFT; - mask = PERIPH_CLK_SOURCE_MASK; - } - - val = clk_readl(c->reg); - val &= ~mask; - val |= (index) << shift; - - clk_writel(val, c->reg); - - return 0; -} - -static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - u32 mask; - u32 shift; - - if (c->flags & MUX_PWM) { - shift = PERIPH_CLK_SOURCE_PWM_SHIFT; - mask = PERIPH_CLK_SOURCE_PWM_MASK; - } else { - shift = PERIPH_CLK_SOURCE_SHIFT; - mask = PERIPH_CLK_SOURCE_MASK; - } - - if (c->flags & MUX) - return (val & mask) >> shift; - else - return 0; -} - -static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long rate = prate; - u32 val = clk_readl(c->reg); - - if (c->flags & DIV_U71) { - u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; - c->div = divu71 + 2; - c->mul = 2; - } else if (c->flags & DIV_U16) { - u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; - c->div = divu16 + 1; - c->mul = 1; - } else { - c->div = 1; - c->mul = 1; - return rate; - } - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -static int tegra20_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - int divider; - - val = clk_readl(c->reg); - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider(parent_rate, rate); - - if (divider >= 0) { - val = clk_readl(c->reg); - val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; - val |= divider; - clk_writel(val, c->reg); - c->div = divider + 2; - c->mul = 2; - return 0; - } - } else if (c->flags & DIV_U16) { - divider = clk_div16_get_divider(parent_rate, rate); - if (divider >= 0) { - val = clk_readl(c->reg); - val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; - val |= divider; - clk_writel(val, c->reg); - c->div = divider + 1; - c->mul = 1; - return 0; - } - } else if (parent_rate <= rate) { - c->div = 1; - c->mul = 1; - return 0; - } - - return -EINVAL; -} - -static long tegra20_periph_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); - int divider; - - pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); - - if (prate) - parent_rate = *prate; - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider(parent_rate, rate); - if (divider < 0) - return divider; - - return DIV_ROUND_UP(parent_rate * 2, divider + 2); - } else if (c->flags & DIV_U16) { - divider = clk_div16_get_divider(parent_rate, rate); - if (divider < 0) - return divider; - return DIV_ROUND_UP(parent_rate, divider + 1); - } - return -EINVAL; -} - -struct clk_ops tegra_periph_clk_ops = { - .is_enabled = tegra20_periph_clk_is_enabled, - .enable = tegra20_periph_clk_enable, - .disable = tegra20_periph_clk_disable, - .set_parent = tegra20_periph_clk_set_parent, - .get_parent = tegra20_periph_clk_get_parent, - .set_rate = tegra20_periph_clk_set_rate, - .round_rate = tegra20_periph_clk_round_rate, - .recalc_rate = tegra20_periph_clk_recalc_rate, -}; - -/* External memory controller clock ops */ -static void tegra20_emc_clk_init(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - c->max_rate = __clk_get_rate(hw->clk); -} - -static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - long emc_rate; - long clk_rate; - - /* - * The slowest entry in the EMC clock table that is at least as - * fast as rate. - */ - emc_rate = tegra_emc_round_rate(rate); - if (emc_rate < 0) - return c->max_rate; - - /* - * The fastest rate the PLL will generate that is at most the - * requested rate. - */ - clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL); - - /* - * If this fails, and emc_rate > clk_rate, it's because the maximum - * rate in the EMC tables is larger than the maximum rate of the EMC - * clock. The EMC clock's max rate is the rate it was running when the - * kernel booted. Such a mismatch is probably due to using the wrong - * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25. - */ - WARN_ONCE(emc_rate != clk_rate, - "emc_rate %ld != clk_rate %ld", - emc_rate, clk_rate); - - return emc_rate; -} - -static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret; - - /* - * The Tegra2 memory controller has an interlock with the clock - * block that allows memory shadowed registers to be updated, - * and then transfer them to the main registers at the same - * time as the clock update without glitches. - */ - ret = tegra_emc_set_rate(rate); - if (ret < 0) - return ret; - - ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate); - udelay(1); - - return ret; -} - -struct clk_ops tegra_emc_clk_ops = { - .init = tegra20_emc_clk_init, - .is_enabled = tegra20_periph_clk_is_enabled, - .enable = tegra20_periph_clk_enable, - .disable = tegra20_periph_clk_disable, - .set_parent = tegra20_periph_clk_set_parent, - .get_parent = tegra20_periph_clk_get_parent, - .set_rate = tegra20_emc_clk_set_rate, - .round_rate = tegra20_emc_clk_round_rate, - .recalc_rate = tegra20_periph_clk_recalc_rate, -}; - -/* Clock doubler ops */ -static int tegra20_clk_double_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - c->state = ON; - - if (!c->u.periph.clk_num) - goto out; - - if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & - PERIPH_CLK_TO_ENB_BIT(c))) - c->state = OFF; - -out: - return c->state; -}; - -static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = prate; - - c->mul = 2; - c->div = 1; - - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - - return rate; -} - -static long tegra20_clk_double_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - unsigned long output_rate = *prate; - - do_div(output_rate, 2); - return output_rate; -} - -static int tegra20_clk_double_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - if (rate != 2 * parent_rate) - return -EINVAL; - return 0; -} - -struct clk_ops tegra_clk_double_ops = { - .is_enabled = tegra20_clk_double_is_enabled, - .enable = tegra20_periph_clk_enable, - .disable = tegra20_periph_clk_disable, - .set_rate = tegra20_clk_double_set_rate, - .recalc_rate = tegra20_clk_double_recalc_rate, - .round_rate = tegra20_clk_double_round_rate, -}; - -/* Audio sync clock ops */ -static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - - c->state = (val & (1<<4)) ? OFF : ON; - return c->state; -} - -static int tegra20_audio_sync_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - clk_writel(0, c->reg); - return 0; -} - -static void tegra20_audio_sync_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - clk_writel(1, c->reg); -} - -static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - int source; - - source = val & 0xf; - return source; -} - -static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg); - val &= ~0xf; - val |= index; - - clk_writel(val, c->reg); - - return 0; -} - -struct clk_ops tegra_audio_sync_clk_ops = { - .is_enabled = tegra20_audio_sync_clk_is_enabled, - .enable = tegra20_audio_sync_clk_enable, - .disable = tegra20_audio_sync_clk_disable, - .set_parent = tegra20_audio_sync_clk_set_parent, - .get_parent = tegra20_audio_sync_clk_get_parent, -}; - -/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ - -static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - /* We could un-tristate the cdev1 or cdev2 pingroup here; this is - * currently done in the pinmux code. */ - c->state = ON; - - BUG_ON(!c->u.periph.clk_num); - - if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & - PERIPH_CLK_TO_ENB_BIT(c))) - c->state = OFF; - return c->state; -} - -static int tegra20_cdev_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - BUG_ON(!c->u.periph.clk_num); - - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); - return 0; -} - -static void tegra20_cdev_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - BUG_ON(!c->u.periph.clk_num); - - clk_writel(PERIPH_CLK_TO_ENB_BIT(c), - CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); -} - -static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - return to_clk_tegra(hw)->fixed_rate; -} - -struct clk_ops tegra_cdev_clk_ops = { - .is_enabled = tegra20_cdev_clk_is_enabled, - .enable = tegra20_cdev_clk_enable, - .disable = tegra20_cdev_clk_disable, - .recalc_rate = tegra20_cdev_recalc_rate, -}; - -/* Tegra20 CPU clock and reset control functions */ -static void tegra20_wait_cpu_in_reset(u32 cpu) -{ - unsigned int reg; - - do { - reg = readl(reg_clk_base + - TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); - cpu_relax(); - } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ - - return; -} - -static void tegra20_put_cpu_in_reset(u32 cpu) -{ - writel(CPU_RESET(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); - dmb(); -} - -static void tegra20_cpu_out_of_reset(u32 cpu) -{ - writel(CPU_RESET(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); - wmb(); -} - -static void tegra20_enable_cpu_clock(u32 cpu) -{ - unsigned int reg; - - reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - writel(reg & ~CPU_CLOCK(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - barrier(); - reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); -} - -static void tegra20_disable_cpu_clock(u32 cpu) -{ - unsigned int reg; - - reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - writel(reg | CPU_CLOCK(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); -} - -static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { - .wait_for_reset = tegra20_wait_cpu_in_reset, - .put_in_reset = tegra20_put_cpu_in_reset, - .out_of_reset = tegra20_cpu_out_of_reset, - .enable_clock = tegra20_enable_cpu_clock, - .disable_clock = tegra20_disable_cpu_clock, -}; - -void __init tegra20_cpu_car_ops_init(void) -{ - tegra_cpu_car_ops = &tegra20_cpu_car_ops; -} diff --git a/arch/arm/mach-tegra/tegra20_clocks.h b/arch/arm/mach-tegra/tegra20_clocks.h deleted file mode 100644 index 8bfd31b..0000000 --- a/arch/arm/mach-tegra/tegra20_clocks.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __MACH_TEGRA20_CLOCK_H -#define __MACH_TEGRA20_CLOCK_H - -extern struct clk_ops tegra_clk_32k_ops; -extern struct clk_ops tegra_pll_ops; -extern struct clk_ops tegra_clk_m_ops; -extern struct clk_ops tegra_pll_div_ops; -extern struct clk_ops tegra_pllx_ops; -extern struct clk_ops tegra_plle_ops; -extern struct clk_ops tegra_clk_double_ops; -extern struct clk_ops tegra_cdev_clk_ops; -extern struct clk_ops tegra_audio_sync_clk_ops; -extern struct clk_ops tegra_super_ops; -extern struct clk_ops tegra_cpu_ops; -extern struct clk_ops tegra_twd_ops; -extern struct clk_ops tegra_cop_ops; -extern struct clk_ops tegra_bus_ops; -extern struct clk_ops tegra_blink_clk_ops; -extern struct clk_ops tegra_emc_clk_ops; -extern struct clk_ops tegra_periph_clk_ops; -extern struct clk_ops tegra_clk_shared_bus_ops; - -void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert); -void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert); - -#endif diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c deleted file mode 100644 index a23a073..0000000 --- a/arch/arm/mach-tegra/tegra20_clocks_data.c +++ /dev/null @@ -1,1143 +0,0 @@ -/* - * arch/arm/mach-tegra/tegra2_clocks.c - * - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/clk-private.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clk.h> - -#include "clock.h" -#include "fuse.h" -#include "tegra2_emc.h" -#include "tegra20_clocks.h" -#include "tegra_cpu_car.h" - -/* Clock definitions */ - -#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags, \ - _parent_names, _parents, _parent) \ - static struct clk tegra_##_name = { \ - .hw = &tegra_##_name##_hw.hw, \ - .name = #_name, \ - .rate = _rate, \ - .ops = _ops, \ - .flags = _flags, \ - .parent_names = _parent_names, \ - .parents = _parents, \ - .num_parents = ARRAY_SIZE(_parent_names), \ - .parent = _parent, \ - }; - -static struct clk tegra_clk_32k; -static struct clk_tegra tegra_clk_32k_hw = { - .hw = { - .clk = &tegra_clk_32k, - }, - .fixed_rate = 32768, -}; - -static struct clk tegra_clk_32k = { - .name = "clk_32k", - .rate = 32768, - .ops = &tegra_clk_32k_ops, - .hw = &tegra_clk_32k_hw.hw, - .flags = CLK_IS_ROOT, -}; - -static struct clk tegra_clk_m; -static struct clk_tegra tegra_clk_m_hw = { - .hw = { - .clk = &tegra_clk_m, - }, - .flags = ENABLE_ON_INIT, - .reg = 0x1fc, - .reg_shift = 28, - .max_rate = 26000000, - .fixed_rate = 0, -}; - -static struct clk tegra_clk_m = { - .name = "clk_m", - .ops = &tegra_clk_m_ops, - .hw = &tegra_clk_m_hw.hw, - .flags = CLK_IS_ROOT, -}; - -#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min, \ - _input_max, _cf_min, _cf_max, _vco_min, \ - _vco_max, _freq_table, _lock_delay, _ops, \ - _fixed_rate, _parent) \ - static const char *tegra_##_name##_parent_names[] = { \ - #_parent, \ - }; \ - static struct clk *tegra_##_name##_parents[] = { \ - &tegra_##_parent, \ - }; \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .flags = _flags, \ - .reg = _reg, \ - .max_rate = _max_rate, \ - .u.pll = { \ - .input_min = _input_min, \ - .input_max = _input_max, \ - .cf_min = _cf_min, \ - .cf_max = _cf_max, \ - .vco_min = _vco_min, \ - .vco_max = _vco_max, \ - .freq_table = _freq_table, \ - .lock_delay = _lock_delay, \ - .fixed_rate = _fixed_rate, \ - }, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent = &tegra_##_parent, \ - .parent_names = tegra_##_name##_parent_names, \ - .parents = tegra_##_name##_parents, \ - .num_parents = 1, \ - }; - -#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift, \ - _max_rate, _ops, _parent, _clk_flags) \ - static const char *tegra_##_name##_parent_names[] = { \ - #_parent, \ - }; \ - static struct clk *tegra_##_name##_parents[] = { \ - &tegra_##_parent, \ - }; \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .flags = _flags, \ - .reg = _reg, \ - .max_rate = _max_rate, \ - .reg_shift = _reg_shift, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &tegra_pll_div_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent = &tegra_##_parent, \ - .parent_names = tegra_##_name##_parent_names, \ - .parents = tegra_##_name##_parents, \ - .num_parents = 1, \ - .flags = _clk_flags, \ - }; - - -static struct clk_pll_freq_table tegra_pll_s_freq_table[] = { - {32768, 12000000, 366, 1, 1, 0}, - {32768, 13000000, 397, 1, 1, 0}, - {32768, 19200000, 586, 1, 1, 0}, - {32768, 26000000, 793, 1, 1, 0}, - {0, 0, 0, 0, 0, 0}, -}; - -DEFINE_PLL(pll_s, PLL_ALT_MISC_REG, 0xf0, 26000000, 32768, 32768, 0, - 0, 12000000, 26000000, tegra_pll_s_freq_table, 300, - tegra_pll_ops, 0, clk_32k); - -static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { - { 12000000, 600000000, 600, 12, 1, 8 }, - { 13000000, 600000000, 600, 13, 1, 8 }, - { 19200000, 600000000, 500, 16, 1, 6 }, - { 26000000, 600000000, 600, 26, 1, 8 }, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 600000000, 2000000, 31000000, 1000000, - 6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300, - tegra_pll_ops, 0, clk_m); - -DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 600000000, - tegra_pll_div_ops, pll_c, 0); - -static struct clk_pll_freq_table tegra_pll_m_freq_table[] = { - { 12000000, 666000000, 666, 12, 1, 8}, - { 13000000, 666000000, 666, 13, 1, 8}, - { 19200000, 666000000, 555, 16, 1, 8}, - { 26000000, 666000000, 666, 26, 1, 8}, - { 12000000, 600000000, 600, 12, 1, 8}, - { 13000000, 600000000, 600, 13, 1, 8}, - { 19200000, 600000000, 375, 12, 1, 6}, - { 26000000, 600000000, 600, 26, 1, 8}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_m, PLL_HAS_CPCON, 0x90, 800000000, 2000000, 31000000, 1000000, - 6000000, 20000000, 1200000000, tegra_pll_m_freq_table, 300, - tegra_pll_ops, 0, clk_m); - -DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000, - tegra_pll_div_ops, pll_m, 0); - -static struct clk_pll_freq_table tegra_pll_p_freq_table[] = { - { 12000000, 216000000, 432, 12, 2, 8}, - { 13000000, 216000000, 432, 13, 2, 8}, - { 19200000, 216000000, 90, 4, 2, 1}, - { 26000000, 216000000, 432, 26, 2, 8}, - { 12000000, 432000000, 432, 12, 1, 8}, - { 13000000, 432000000, 432, 13, 1, 8}, - { 19200000, 432000000, 90, 4, 1, 1}, - { 26000000, 432000000, 432, 26, 1, 8}, - { 0, 0, 0, 0, 0, 0 }, -}; - - -DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000, - 2000000, 31000000, 1000000, 6000000, 20000000, 1400000000, - tegra_pll_p_freq_table, 300, tegra_pll_ops, 216000000, clk_m); - -DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 0, - 432000000, tegra_pll_div_ops, pll_p, 0); -DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 16, - 432000000, tegra_pll_div_ops, pll_p, 0); -DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 0, - 432000000, tegra_pll_div_ops, pll_p, 0); -DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 16, - 432000000, tegra_pll_div_ops, pll_p, 0); - -static struct clk_pll_freq_table tegra_pll_a_freq_table[] = { - { 28800000, 56448000, 49, 25, 1, 1}, - { 28800000, 73728000, 64, 25, 1, 1}, - { 28800000, 24000000, 5, 6, 1, 1}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 73728000, 2000000, 31000000, 1000000, - 6000000, 20000000, 1400000000, tegra_pll_a_freq_table, 300, - tegra_pll_ops, 0, pll_p_out1); - -DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 73728000, - tegra_pll_div_ops, pll_a, 0); - -static struct clk_pll_freq_table tegra_pll_d_freq_table[] = { - { 12000000, 216000000, 216, 12, 1, 4}, - { 13000000, 216000000, 216, 13, 1, 4}, - { 19200000, 216000000, 135, 12, 1, 3}, - { 26000000, 216000000, 216, 26, 1, 4}, - - { 12000000, 297000000, 99, 4, 1, 4 }, - { 12000000, 339000000, 113, 4, 1, 4 }, - - { 12000000, 594000000, 594, 12, 1, 8}, - { 13000000, 594000000, 594, 13, 1, 8}, - { 19200000, 594000000, 495, 16, 1, 8}, - { 26000000, 594000000, 594, 26, 1, 8}, - - { 12000000, 616000000, 616, 12, 1, 8}, - - { 12000000, 1000000000, 1000, 12, 1, 12}, - { 13000000, 1000000000, 1000, 13, 1, 12}, - { 19200000, 1000000000, 625, 12, 1, 8}, - { 26000000, 1000000000, 1000, 26, 1, 12}, - - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000, - 1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table, - 1000, tegra_pll_ops, 0, clk_m); - -DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000, - tegra_pll_div_ops, pll_d, CLK_SET_RATE_PARENT); - -static struct clk_pll_freq_table tegra_pll_u_freq_table[] = { - { 12000000, 480000000, 960, 12, 2, 0}, - { 13000000, 480000000, 960, 13, 2, 0}, - { 19200000, 480000000, 200, 4, 2, 0}, - { 26000000, 480000000, 960, 26, 2, 0}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_u, PLLU, 0xc0, 480000000, 2000000, 40000000, 1000000, 6000000, - 48000000, 960000000, tegra_pll_u_freq_table, 1000, - tegra_pll_ops, 0, clk_m); - -static struct clk_pll_freq_table tegra_pll_x_freq_table[] = { - /* 1 GHz */ - { 12000000, 1000000000, 1000, 12, 1, 12}, - { 13000000, 1000000000, 1000, 13, 1, 12}, - { 19200000, 1000000000, 625, 12, 1, 8}, - { 26000000, 1000000000, 1000, 26, 1, 12}, - - /* 912 MHz */ - { 12000000, 912000000, 912, 12, 1, 12}, - { 13000000, 912000000, 912, 13, 1, 12}, - { 19200000, 912000000, 760, 16, 1, 8}, - { 26000000, 912000000, 912, 26, 1, 12}, - - /* 816 MHz */ - { 12000000, 816000000, 816, 12, 1, 12}, - { 13000000, 816000000, 816, 13, 1, 12}, - { 19200000, 816000000, 680, 16, 1, 8}, - { 26000000, 816000000, 816, 26, 1, 12}, - - /* 760 MHz */ - { 12000000, 760000000, 760, 12, 1, 12}, - { 13000000, 760000000, 760, 13, 1, 12}, - { 19200000, 760000000, 950, 24, 1, 8}, - { 26000000, 760000000, 760, 26, 1, 12}, - - /* 750 MHz */ - { 12000000, 750000000, 750, 12, 1, 12}, - { 13000000, 750000000, 750, 13, 1, 12}, - { 19200000, 750000000, 625, 16, 1, 8}, - { 26000000, 750000000, 750, 26, 1, 12}, - - /* 608 MHz */ - { 12000000, 608000000, 608, 12, 1, 12}, - { 13000000, 608000000, 608, 13, 1, 12}, - { 19200000, 608000000, 380, 12, 1, 8}, - { 26000000, 608000000, 608, 26, 1, 12}, - - /* 456 MHz */ - { 12000000, 456000000, 456, 12, 1, 12}, - { 13000000, 456000000, 456, 13, 1, 12}, - { 19200000, 456000000, 380, 16, 1, 8}, - { 26000000, 456000000, 456, 26, 1, 12}, - - /* 312 MHz */ - { 12000000, 312000000, 312, 12, 1, 12}, - { 13000000, 312000000, 312, 13, 1, 12}, - { 19200000, 312000000, 260, 16, 1, 8}, - { 26000000, 312000000, 312, 26, 1, 12}, - - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG, 0xe0, 1000000000, 2000000, - 31000000, 1000000, 6000000, 20000000, 1200000000, - tegra_pll_x_freq_table, 300, tegra_pllx_ops, 0, clk_m); - -static struct clk_pll_freq_table tegra_pll_e_freq_table[] = { - { 12000000, 100000000, 200, 24, 1, 0 }, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 12000000, 12000000, 0, 0, - 0, 0, tegra_pll_e_freq_table, 0, tegra_plle_ops, 0, clk_m); - -static const char *tegra_common_parent_names[] = { - "clk_m", -}; - -static struct clk *tegra_common_parents[] = { - &tegra_clk_m, -}; - -static struct clk tegra_clk_d; -static struct clk_tegra tegra_clk_d_hw = { - .hw = { - .clk = &tegra_clk_d, - }, - .flags = PERIPH_NO_RESET, - .reg = 0x34, - .reg_shift = 12, - .max_rate = 52000000, - .u.periph = { - .clk_num = 90, - }, -}; - -static struct clk tegra_clk_d = { - .name = "clk_d", - .hw = &tegra_clk_d_hw.hw, - .ops = &tegra_clk_double_ops, - .parent = &tegra_clk_m, - .parent_names = tegra_common_parent_names, - .parents = tegra_common_parents, - .num_parents = ARRAY_SIZE(tegra_common_parent_names), -}; - -static struct clk tegra_cdev1; -static struct clk_tegra tegra_cdev1_hw = { - .hw = { - .clk = &tegra_cdev1, - }, - .fixed_rate = 26000000, - .u.periph = { - .clk_num = 94, - }, -}; -static struct clk tegra_cdev1 = { - .name = "cdev1", - .hw = &tegra_cdev1_hw.hw, - .ops = &tegra_cdev_clk_ops, - .flags = CLK_IS_ROOT, -}; - -/* dap_mclk2, belongs to the cdev2 pingroup. */ -static struct clk tegra_cdev2; -static struct clk_tegra tegra_cdev2_hw = { - .hw = { - .clk = &tegra_cdev2, - }, - .fixed_rate = 26000000, - .u.periph = { - .clk_num = 93, - }, -}; -static struct clk tegra_cdev2 = { - .name = "cdev2", - .hw = &tegra_cdev2_hw.hw, - .ops = &tegra_cdev_clk_ops, - .flags = CLK_IS_ROOT, -}; - -/* initialized before peripheral clocks */ -static struct clk_mux_sel mux_audio_sync_clk[8+1]; -static const struct audio_sources { - const char *name; - int value; -} mux_audio_sync_clk_sources[] = { - { .name = "spdif_in", .value = 0 }, - { .name = "i2s1", .value = 1 }, - { .name = "i2s2", .value = 2 }, - { .name = "pll_a_out0", .value = 4 }, -#if 0 /* FIXME: not implemented */ - { .name = "ac97", .value = 3 }, - { .name = "ext_audio_clk2", .value = 5 }, - { .name = "ext_audio_clk1", .value = 6 }, - { .name = "ext_vimclk", .value = 7 }, -#endif - { NULL, 0 } -}; - -static const char *audio_parent_names[] = { - "spdif_in", - "i2s1", - "i2s2", - "dummy", - "pll_a_out0", - "dummy", - "dummy", - "dummy", -}; - -static struct clk *audio_parents[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static struct clk tegra_audio; -static struct clk_tegra tegra_audio_hw = { - .hw = { - .clk = &tegra_audio, - }, - .reg = 0x38, - .max_rate = 73728000, -}; -DEFINE_CLK_TEGRA(audio, 0, &tegra_audio_sync_clk_ops, 0, audio_parent_names, - audio_parents, NULL); - -static const char *audio_2x_parent_names[] = { - "audio", -}; - -static struct clk *audio_2x_parents[] = { - &tegra_audio, -}; - -static struct clk tegra_audio_2x; -static struct clk_tegra tegra_audio_2x_hw = { - .hw = { - .clk = &tegra_audio_2x, - }, - .flags = PERIPH_NO_RESET, - .max_rate = 48000000, - .reg = 0x34, - .reg_shift = 8, - .u.periph = { - .clk_num = 89, - }, -}; -DEFINE_CLK_TEGRA(audio_2x, 0, &tegra_clk_double_ops, 0, audio_2x_parent_names, - audio_2x_parents, &tegra_audio); - -static struct clk_lookup tegra_audio_clk_lookups[] = { - { .con_id = "audio", .clk = &tegra_audio }, - { .con_id = "audio_2x", .clk = &tegra_audio_2x } -}; - -/* This is called after peripheral clocks are initialized, as the - * audio_sync clock depends on some of the peripheral clocks. - */ - -static void init_audio_sync_clock_mux(void) -{ - int i; - struct clk_mux_sel *sel = mux_audio_sync_clk; - const struct audio_sources *src = mux_audio_sync_clk_sources; - struct clk_lookup *lookup; - - for (i = 0; src->name; i++, sel++, src++) { - sel->input = tegra_get_clock_by_name(src->name); - if (!sel->input) - pr_err("%s: could not find clk %s\n", __func__, - src->name); - audio_parents[src->value] = sel->input; - sel->value = src->value; - } - - lookup = tegra_audio_clk_lookups; - for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) { - struct clk *c = lookup->clk; - struct clk_tegra *clk = to_clk_tegra(c->hw); - __clk_init(NULL, c); - INIT_LIST_HEAD(&clk->shared_bus_list); - clk->lookup.con_id = lookup->con_id; - clk->lookup.clk = c; - clkdev_add(&clk->lookup); - tegra_clk_add(c); - } -} - -static const char *mux_cclk[] = { - "clk_m", - "pll_c", - "clk_32k", - "pll_m", - "pll_p", - "pll_p_out4", - "pll_p_out3", - "clk_d", - "pll_x", -}; - - -static struct clk *mux_cclk_p[] = { - &tegra_clk_m, - &tegra_pll_c, - &tegra_clk_32k, - &tegra_pll_m, - &tegra_pll_p, - &tegra_pll_p_out4, - &tegra_pll_p_out3, - &tegra_clk_d, - &tegra_pll_x, -}; - -static const char *mux_sclk[] = { - "clk_m", - "pll_c_out1", - "pll_p_out4", - "pllp_p_out3", - "pll_p_out2", - "clk_d", - "clk_32k", - "pll_m_out1", -}; - -static struct clk *mux_sclk_p[] = { - &tegra_clk_m, - &tegra_pll_c_out1, - &tegra_pll_p_out4, - &tegra_pll_p_out3, - &tegra_pll_p_out2, - &tegra_clk_d, - &tegra_clk_32k, - &tegra_pll_m_out1, -}; - -static struct clk tegra_cclk; -static struct clk_tegra tegra_cclk_hw = { - .hw = { - .clk = &tegra_cclk, - }, - .reg = 0x20, - .max_rate = 1000000000, -}; -DEFINE_CLK_TEGRA(cclk, 0, &tegra_super_ops, 0, mux_cclk, - mux_cclk_p, NULL); - -static const char *mux_twd[] = { - "cclk", -}; - -static struct clk *mux_twd_p[] = { - &tegra_cclk, -}; - -static struct clk tegra_clk_twd; -static struct clk_tegra tegra_clk_twd_hw = { - .hw = { - .clk = &tegra_clk_twd, - }, - .max_rate = 1000000000, - .mul = 1, - .div = 4, -}; - -static struct clk tegra_clk_twd = { - .name = "twd", - .ops = &tegra_twd_ops, - .hw = &tegra_clk_twd_hw.hw, - .parent = &tegra_cclk, - .parent_names = mux_twd, - .parents = mux_twd_p, - .num_parents = ARRAY_SIZE(mux_twd), -}; - -static struct clk tegra_sclk; -static struct clk_tegra tegra_sclk_hw = { - .hw = { - .clk = &tegra_sclk, - }, - .reg = 0x28, - .max_rate = 240000000, - .min_rate = 120000000, -}; -DEFINE_CLK_TEGRA(sclk, 0, &tegra_super_ops, 0, mux_sclk, - mux_sclk_p, NULL); - -static const char *tegra_cop_parent_names[] = { - "tegra_sclk", -}; - -static struct clk *tegra_cop_parents[] = { - &tegra_sclk, -}; - -static struct clk tegra_cop; -static struct clk_tegra tegra_cop_hw = { - .hw = { - .clk = &tegra_cop, - }, - .max_rate = 240000000, - .reset = &tegra2_cop_clk_reset, -}; -DEFINE_CLK_TEGRA(cop, 0, &tegra_cop_ops, CLK_SET_RATE_PARENT, - tegra_cop_parent_names, tegra_cop_parents, &tegra_sclk); - -static const char *tegra_hclk_parent_names[] = { - "tegra_sclk", -}; - -static struct clk *tegra_hclk_parents[] = { - &tegra_sclk, -}; - -static struct clk tegra_hclk; -static struct clk_tegra tegra_hclk_hw = { - .hw = { - .clk = &tegra_hclk, - }, - .flags = DIV_BUS, - .reg = 0x30, - .reg_shift = 4, - .max_rate = 240000000, -}; -DEFINE_CLK_TEGRA(hclk, 0, &tegra_bus_ops, 0, tegra_hclk_parent_names, - tegra_hclk_parents, &tegra_sclk); - -static const char *tegra_pclk_parent_names[] = { - "tegra_hclk", -}; - -static struct clk *tegra_pclk_parents[] = { - &tegra_hclk, -}; - -static struct clk tegra_pclk; -static struct clk_tegra tegra_pclk_hw = { - .hw = { - .clk = &tegra_pclk, - }, - .flags = DIV_BUS, - .reg = 0x30, - .reg_shift = 0, - .max_rate = 120000000, -}; -DEFINE_CLK_TEGRA(pclk, 0, &tegra_bus_ops, 0, tegra_pclk_parent_names, - tegra_pclk_parents, &tegra_hclk); - -static const char *tegra_blink_parent_names[] = { - "clk_32k", -}; - -static struct clk *tegra_blink_parents[] = { - &tegra_clk_32k, -}; - -static struct clk tegra_blink; -static struct clk_tegra tegra_blink_hw = { - .hw = { - .clk = &tegra_blink, - }, - .reg = 0x40, - .max_rate = 32768, -}; -DEFINE_CLK_TEGRA(blink, 0, &tegra_blink_clk_ops, 0, tegra_blink_parent_names, - tegra_blink_parents, &tegra_clk_32k); - -static const char *mux_pllm_pllc_pllp_plla[] = { - "pll_m", - "pll_c", - "pll_p", - "pll_a_out0", -}; - -static struct clk *mux_pllm_pllc_pllp_plla_p[] = { - &tegra_pll_m, - &tegra_pll_c, - &tegra_pll_p, - &tegra_pll_a_out0, -}; - -static const char *mux_pllm_pllc_pllp_clkm[] = { - "pll_m", - "pll_c", - "pll_p", - "clk_m", -}; - -static struct clk *mux_pllm_pllc_pllp_clkm_p[] = { - &tegra_pll_m, - &tegra_pll_c, - &tegra_pll_p, - &tegra_clk_m, -}; - -static const char *mux_pllp_pllc_pllm_clkm[] = { - "pll_p", - "pll_c", - "pll_m", - "clk_m", -}; - -static struct clk *mux_pllp_pllc_pllm_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_pll_m, - &tegra_clk_m, -}; - -static const char *mux_pllaout0_audio2x_pllp_clkm[] = { - "pll_a_out0", - "audio_2x", - "pll_p", - "clk_m", -}; - -static struct clk *mux_pllaout0_audio2x_pllp_clkm_p[] = { - &tegra_pll_a_out0, - &tegra_audio_2x, - &tegra_pll_p, - &tegra_clk_m, -}; - -static const char *mux_pllp_plld_pllc_clkm[] = { - "pllp", - "pll_d_out0", - "pll_c", - "clk_m", -}; - -static struct clk *mux_pllp_plld_pllc_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_d_out0, - &tegra_pll_c, - &tegra_clk_m, -}; - -static const char *mux_pllp_pllc_audio_clkm_clk32[] = { - "pll_p", - "pll_c", - "audio", - "clk_m", - "clk_32k", -}; - -static struct clk *mux_pllp_pllc_audio_clkm_clk32_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_audio, - &tegra_clk_m, - &tegra_clk_32k, -}; - -static const char *mux_pllp_pllc_pllm[] = { - "pll_p", - "pll_c", - "pll_m" -}; - -static struct clk *mux_pllp_pllc_pllm_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_pll_m, -}; - -static const char *mux_clk_m[] = { - "clk_m", -}; - -static struct clk *mux_clk_m_p[] = { - &tegra_clk_m, -}; - -static const char *mux_pllp_out3[] = { - "pll_p_out3", -}; - -static struct clk *mux_pllp_out3_p[] = { - &tegra_pll_p_out3, -}; - -static const char *mux_plld[] = { - "pll_d", -}; - -static struct clk *mux_plld_p[] = { - &tegra_pll_d, -}; - -static const char *mux_clk_32k[] = { - "clk_32k", -}; - -static struct clk *mux_clk_32k_p[] = { - &tegra_clk_32k, -}; - -static const char *mux_pclk[] = { - "pclk", -}; - -static struct clk *mux_pclk_p[] = { - &tegra_pclk, -}; - -static struct clk tegra_emc; -static struct clk_tegra tegra_emc_hw = { - .hw = { - .clk = &tegra_emc, - }, - .reg = 0x19c, - .max_rate = 800000000, - .flags = MUX | DIV_U71 | PERIPH_EMC_ENB, - .reset = &tegra2_periph_clk_reset, - .u.periph = { - .clk_num = 57, - }, -}; -DEFINE_CLK_TEGRA(emc, 0, &tegra_emc_clk_ops, 0, mux_pllm_pllc_pllp_clkm, - mux_pllm_pllc_pllp_clkm_p, NULL); - -#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, \ - _max, _inputs, _flags) \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .lookup = { \ - .dev_id = _dev, \ - .con_id = _con, \ - }, \ - .reg = _reg, \ - .flags = _flags, \ - .max_rate = _max, \ - .u.periph = { \ - .clk_num = _clk_num, \ - }, \ - .reset = tegra2_periph_clk_reset, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &tegra_periph_clk_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent_names = _inputs, \ - .parents = _inputs##_p, \ - .num_parents = ARRAY_SIZE(_inputs), \ - }; - -PERIPH_CLK(apbdma, "tegra-apbdma", NULL, 34, 0, 108000000, mux_pclk, 0); -PERIPH_CLK(rtc, "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET); -PERIPH_CLK(timer, "timer", NULL, 5, 0, 26000000, mux_clk_m, 0); -PERIPH_CLK(i2s1, "tegra20-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(i2s2, "tegra20-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(spdif_out, "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(spdif_in, "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71); -PERIPH_CLK(pwm, "tegra-pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71 | MUX_PWM); -PERIPH_CLK(spi, "spi", NULL, 43, 0x114, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(xio, "xio", NULL, 45, 0x120, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(twc, "twc", NULL, 16, 0x12c, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sbc1, "spi_tegra.0", NULL, 41, 0x134, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sbc2, "spi_tegra.1", NULL, 44, 0x118, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sbc3, "spi_tegra.2", NULL, 46, 0x11c, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sbc4, "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(ide, "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(ndflash, "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(vfir, "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sdmmc1, "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc2, "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc3, "sdhci-tegra.2", NULL, 69, 0x1bc, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc4, "sdhci-tegra.3", NULL, 15, 0x164, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(vcp, "tegra-avp", "vcp", 29, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(bsea, "tegra-avp", "bsea", 62, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(bsev, "tegra-aes", "bsev", 63, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(vde, "tegra-avp", "vde", 61, 0x1c8, 250000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(csite, "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* max rate ??? */ -/* FIXME: what is la? */ -PERIPH_CLK(la, "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(owr, "tegra_w1", NULL, 71, 0x1cc, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(nor, "nor", NULL, 42, 0x1d0, 92000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(mipi, "mipi", NULL, 50, 0x174, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(i2c1, "tegra-i2c.0", "div-clk", 12, 0x124, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(i2c2, "tegra-i2c.1", "div-clk", 54, 0x198, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(i2c3, "tegra-i2c.2", "div-clk", 67, 0x1b8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(dvc, "tegra-i2c.3", "div-clk", 47, 0x128, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(uarta, "tegra-uart.0", NULL, 6, 0x178, 600000000, mux_pllp_pllc_pllm_clkm, MUX); -PERIPH_CLK(uartb, "tegra-uart.1", NULL, 7, 0x17c, 600000000, mux_pllp_pllc_pllm_clkm, MUX); -PERIPH_CLK(uartc, "tegra-uart.2", NULL, 55, 0x1a0, 600000000, mux_pllp_pllc_pllm_clkm, MUX); -PERIPH_CLK(uartd, "tegra-uart.3", NULL, 65, 0x1c0, 600000000, mux_pllp_pllc_pllm_clkm, MUX); -PERIPH_CLK(uarte, "tegra-uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX); -PERIPH_CLK(3d, "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET); /* scales with voltage and process_id */ -PERIPH_CLK(2d, "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(vi, "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(vi_sensor, "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET); /* scales with voltage and process_id */ -PERIPH_CLK(epp, "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(mpe, "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(host1x, "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71); /* scales with voltage and process_id */ -PERIPH_CLK(cve, "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(tvo, "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(hdmi, "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(tvdac, "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(disp1, "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_plld_pllc_clkm, MUX); /* scales with voltage and process_id */ -PERIPH_CLK(disp2, "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_plld_pllc_clkm, MUX); /* scales with voltage and process_id */ -PERIPH_CLK(usbd, "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(usb2, "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(usb3, "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(dsi, "dsi", NULL, 48, 0, 500000000, mux_plld, 0); /* scales with voltage */ -PERIPH_CLK(csi, "tegra_camera", "csi", 52, 0, 72000000, mux_pllp_out3, 0); -PERIPH_CLK(isp, "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0); /* same frequency as VI */ -PERIPH_CLK(csus, "tegra_camera", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET); -PERIPH_CLK(pex, NULL, "pex", 70, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET); -PERIPH_CLK(afi, NULL, "afi", 72, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET); -PERIPH_CLK(pcie_xclk, NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET); - -static struct clk *tegra_list_clks[] = { - &tegra_apbdma, - &tegra_rtc, - &tegra_timer, - &tegra_i2s1, - &tegra_i2s2, - &tegra_spdif_out, - &tegra_spdif_in, - &tegra_pwm, - &tegra_spi, - &tegra_xio, - &tegra_twc, - &tegra_sbc1, - &tegra_sbc2, - &tegra_sbc3, - &tegra_sbc4, - &tegra_ide, - &tegra_ndflash, - &tegra_vfir, - &tegra_sdmmc1, - &tegra_sdmmc2, - &tegra_sdmmc3, - &tegra_sdmmc4, - &tegra_vcp, - &tegra_bsea, - &tegra_bsev, - &tegra_vde, - &tegra_csite, - &tegra_la, - &tegra_owr, - &tegra_nor, - &tegra_mipi, - &tegra_i2c1, - &tegra_i2c2, - &tegra_i2c3, - &tegra_dvc, - &tegra_uarta, - &tegra_uartb, - &tegra_uartc, - &tegra_uartd, - &tegra_uarte, - &tegra_3d, - &tegra_2d, - &tegra_vi, - &tegra_vi_sensor, - &tegra_epp, - &tegra_mpe, - &tegra_host1x, - &tegra_cve, - &tegra_tvo, - &tegra_hdmi, - &tegra_tvdac, - &tegra_disp1, - &tegra_disp2, - &tegra_usbd, - &tegra_usb2, - &tegra_usb3, - &tegra_dsi, - &tegra_csi, - &tegra_isp, - &tegra_csus, - &tegra_pex, - &tegra_afi, - &tegra_pcie_xclk, -}; - -#define CLK_DUPLICATE(_name, _dev, _con) \ - { \ - .name = _name, \ - .lookup = { \ - .dev_id = _dev, \ - .con_id = _con, \ - }, \ - } - -/* Some clocks may be used by different drivers depending on the board - * configuration. List those here to register them twice in the clock lookup - * table under two names. - */ -static struct clk_duplicate tegra_clk_duplicates[] = { - CLK_DUPLICATE("uarta", "serial8250.0", NULL), - CLK_DUPLICATE("uartb", "serial8250.1", NULL), - CLK_DUPLICATE("uartc", "serial8250.2", NULL), - CLK_DUPLICATE("uartd", "serial8250.3", NULL), - CLK_DUPLICATE("uarte", "serial8250.4", NULL), - CLK_DUPLICATE("usbd", "utmip-pad", NULL), - CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), - CLK_DUPLICATE("usbd", "tegra-otg", NULL), - CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"), - CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"), - CLK_DUPLICATE("epp", "tegra_grhost", "epp"), - CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"), - CLK_DUPLICATE("cop", "tegra-avp", "cop"), - CLK_DUPLICATE("vde", "tegra-aes", "vde"), - CLK_DUPLICATE("cclk", NULL, "cpu"), - CLK_DUPLICATE("twd", "smp_twd", NULL), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"), - CLK_DUPLICATE("pll_p", "tegradc.0", "parent"), - CLK_DUPLICATE("pll_p", "tegradc.1", "parent"), - CLK_DUPLICATE("pll_d_out0", "hdmi", "parent"), -}; - -#define CLK(dev, con, ck) \ - { \ - .dev_id = dev, \ - .con_id = con, \ - .clk = ck, \ - } - -static struct clk *tegra_ptr_clks[] = { - &tegra_clk_32k, - &tegra_pll_s, - &tegra_clk_m, - &tegra_pll_m, - &tegra_pll_m_out1, - &tegra_pll_c, - &tegra_pll_c_out1, - &tegra_pll_p, - &tegra_pll_p_out1, - &tegra_pll_p_out2, - &tegra_pll_p_out3, - &tegra_pll_p_out4, - &tegra_pll_a, - &tegra_pll_a_out0, - &tegra_pll_d, - &tegra_pll_d_out0, - &tegra_pll_u, - &tegra_pll_x, - &tegra_pll_e, - &tegra_cclk, - &tegra_clk_twd, - &tegra_sclk, - &tegra_hclk, - &tegra_pclk, - &tegra_clk_d, - &tegra_cdev1, - &tegra_cdev2, - &tegra_blink, - &tegra_cop, - &tegra_emc, -}; - -static void tegra2_init_one_clock(struct clk *c) -{ - struct clk_tegra *clk = to_clk_tegra(c->hw); - int ret; - - ret = __clk_init(NULL, c); - if (ret) - pr_err("clk init failed %s\n", __clk_get_name(c)); - - INIT_LIST_HEAD(&clk->shared_bus_list); - if (!clk->lookup.dev_id && !clk->lookup.con_id) - clk->lookup.con_id = c->name; - clk->lookup.clk = c; - clkdev_add(&clk->lookup); - tegra_clk_add(c); -} - -void __init tegra2_init_clocks(void) -{ - int i; - struct clk *c; - - for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++) - tegra2_init_one_clock(tegra_ptr_clks[i]); - - for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++) - tegra2_init_one_clock(tegra_list_clks[i]); - - for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) { - c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name); - if (!c) { - pr_err("%s: Unknown duplicate clock %s\n", __func__, - tegra_clk_duplicates[i].name); - continue; - } - - tegra_clk_duplicates[i].lookup.clk = c; - clkdev_add(&tegra_clk_duplicates[i].lookup); - } - - init_audio_sync_clock_mux(); - tegra20_cpu_car_ops_init(); -} diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c deleted file mode 100644 index d714777..0000000 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ /dev/null @@ -1,2506 +0,0 @@ -/* - * arch/arm/mach-tegra/tegra30_clocks.c - * - * Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/syscore_ops.h> - -#include <asm/clkdev.h> - -#include <mach/powergate.h> - -#include "clock.h" -#include "fuse.h" -#include "iomap.h" -#include "tegra_cpu_car.h" - -#define USE_PLL_LOCK_BITS 0 - -#define RST_DEVICES_L 0x004 -#define RST_DEVICES_H 0x008 -#define RST_DEVICES_U 0x00C -#define RST_DEVICES_V 0x358 -#define RST_DEVICES_W 0x35C -#define RST_DEVICES_SET_L 0x300 -#define RST_DEVICES_CLR_L 0x304 -#define RST_DEVICES_SET_V 0x430 -#define RST_DEVICES_CLR_V 0x434 -#define RST_DEVICES_NUM 5 - -#define CLK_OUT_ENB_L 0x010 -#define CLK_OUT_ENB_H 0x014 -#define CLK_OUT_ENB_U 0x018 -#define CLK_OUT_ENB_V 0x360 -#define CLK_OUT_ENB_W 0x364 -#define CLK_OUT_ENB_SET_L 0x320 -#define CLK_OUT_ENB_CLR_L 0x324 -#define CLK_OUT_ENB_SET_V 0x440 -#define CLK_OUT_ENB_CLR_V 0x444 -#define CLK_OUT_ENB_NUM 5 - -#define RST_DEVICES_V_SWR_CPULP_RST_DIS (0x1 << 1) -#define CLK_OUT_ENB_V_CLK_ENB_CPULP_EN (0x1 << 1) - -#define PERIPH_CLK_TO_BIT(c) (1 << (c->u.periph.clk_num % 32)) -#define PERIPH_CLK_TO_RST_REG(c) \ - periph_clk_to_reg((c), RST_DEVICES_L, RST_DEVICES_V, 4) -#define PERIPH_CLK_TO_RST_SET_REG(c) \ - periph_clk_to_reg((c), RST_DEVICES_SET_L, RST_DEVICES_SET_V, 8) -#define PERIPH_CLK_TO_RST_CLR_REG(c) \ - periph_clk_to_reg((c), RST_DEVICES_CLR_L, RST_DEVICES_CLR_V, 8) - -#define PERIPH_CLK_TO_ENB_REG(c) \ - periph_clk_to_reg((c), CLK_OUT_ENB_L, CLK_OUT_ENB_V, 4) -#define PERIPH_CLK_TO_ENB_SET_REG(c) \ - periph_clk_to_reg((c), CLK_OUT_ENB_SET_L, CLK_OUT_ENB_SET_V, 8) -#define PERIPH_CLK_TO_ENB_CLR_REG(c) \ - periph_clk_to_reg((c), CLK_OUT_ENB_CLR_L, CLK_OUT_ENB_CLR_V, 8) - -#define CLK_MASK_ARM 0x44 -#define MISC_CLK_ENB 0x48 - -#define OSC_CTRL 0x50 -#define OSC_CTRL_OSC_FREQ_MASK (0xF<<28) -#define OSC_CTRL_OSC_FREQ_13MHZ (0x0<<28) -#define OSC_CTRL_OSC_FREQ_19_2MHZ (0x4<<28) -#define OSC_CTRL_OSC_FREQ_12MHZ (0x8<<28) -#define OSC_CTRL_OSC_FREQ_26MHZ (0xC<<28) -#define OSC_CTRL_OSC_FREQ_16_8MHZ (0x1<<28) -#define OSC_CTRL_OSC_FREQ_38_4MHZ (0x5<<28) -#define OSC_CTRL_OSC_FREQ_48MHZ (0x9<<28) -#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) - -#define OSC_CTRL_PLL_REF_DIV_MASK (3<<26) -#define OSC_CTRL_PLL_REF_DIV_1 (0<<26) -#define OSC_CTRL_PLL_REF_DIV_2 (1<<26) -#define OSC_CTRL_PLL_REF_DIV_4 (2<<26) - -#define OSC_FREQ_DET 0x58 -#define OSC_FREQ_DET_TRIG (1<<31) - -#define OSC_FREQ_DET_STATUS 0x5C -#define OSC_FREQ_DET_BUSY (1<<31) -#define OSC_FREQ_DET_CNT_MASK 0xFFFF - -#define PERIPH_CLK_SOURCE_I2S1 0x100 -#define PERIPH_CLK_SOURCE_EMC 0x19c -#define PERIPH_CLK_SOURCE_OSC 0x1fc -#define PERIPH_CLK_SOURCE_NUM1 \ - ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4) - -#define PERIPH_CLK_SOURCE_G3D2 0x3b0 -#define PERIPH_CLK_SOURCE_SE 0x42c -#define PERIPH_CLK_SOURCE_NUM2 \ - ((PERIPH_CLK_SOURCE_SE - PERIPH_CLK_SOURCE_G3D2) / 4 + 1) - -#define AUDIO_DLY_CLK 0x49c -#define AUDIO_SYNC_CLK_SPDIF 0x4b4 -#define PERIPH_CLK_SOURCE_NUM3 \ - ((AUDIO_SYNC_CLK_SPDIF - AUDIO_DLY_CLK) / 4 + 1) - -#define PERIPH_CLK_SOURCE_NUM (PERIPH_CLK_SOURCE_NUM1 + \ - PERIPH_CLK_SOURCE_NUM2 + \ - PERIPH_CLK_SOURCE_NUM3) - -#define CPU_SOFTRST_CTRL 0x380 - -#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF -#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF -#define PERIPH_CLK_SOURCE_DIV_SHIFT 0 -#define PERIPH_CLK_SOURCE_DIVIDLE_SHIFT 8 -#define PERIPH_CLK_SOURCE_DIVIDLE_VAL 50 -#define PERIPH_CLK_UART_DIV_ENB (1<<24) -#define PERIPH_CLK_VI_SEL_EX_SHIFT 24 -#define PERIPH_CLK_VI_SEL_EX_MASK (0x3<<PERIPH_CLK_VI_SEL_EX_SHIFT) -#define PERIPH_CLK_NAND_DIV_EX_ENB (1<<8) -#define PERIPH_CLK_DTV_POLARITY_INV (1<<25) - -#define AUDIO_SYNC_SOURCE_MASK 0x0F -#define AUDIO_SYNC_DISABLE_BIT 0x10 -#define AUDIO_SYNC_TAP_NIBBLE_SHIFT(c) ((c->reg_shift - 24) * 4) - -#define PLL_BASE 0x0 -#define PLL_BASE_BYPASS (1<<31) -#define PLL_BASE_ENABLE (1<<30) -#define PLL_BASE_REF_ENABLE (1<<29) -#define PLL_BASE_OVERRIDE (1<<28) -#define PLL_BASE_LOCK (1<<27) -#define PLL_BASE_DIVP_MASK (0x7<<20) -#define PLL_BASE_DIVP_SHIFT 20 -#define PLL_BASE_DIVN_MASK (0x3FF<<8) -#define PLL_BASE_DIVN_SHIFT 8 -#define PLL_BASE_DIVM_MASK (0x1F) -#define PLL_BASE_DIVM_SHIFT 0 - -#define PLL_OUT_RATIO_MASK (0xFF<<8) -#define PLL_OUT_RATIO_SHIFT 8 -#define PLL_OUT_OVERRIDE (1<<2) -#define PLL_OUT_CLKEN (1<<1) -#define PLL_OUT_RESET_DISABLE (1<<0) - -#define PLL_MISC(c) \ - (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) -#define PLL_MISC_LOCK_ENABLE(c) \ - (((c)->flags & (PLLU | PLLD)) ? (1<<22) : (1<<18)) - -#define PLL_MISC_DCCON_SHIFT 20 -#define PLL_MISC_CPCON_SHIFT 8 -#define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) -#define PLL_MISC_LFCON_SHIFT 4 -#define PLL_MISC_LFCON_MASK (0xF<<PLL_MISC_LFCON_SHIFT) -#define PLL_MISC_VCOCON_SHIFT 0 -#define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) -#define PLLD_MISC_CLKENABLE (1<<30) - -#define PLLU_BASE_POST_DIV (1<<20) - -#define PLLD_BASE_DSIB_MUX_SHIFT 25 -#define PLLD_BASE_DSIB_MUX_MASK (1<<PLLD_BASE_DSIB_MUX_SHIFT) -#define PLLD_BASE_CSI_CLKENABLE (1<<26) -#define PLLD_MISC_DSI_CLKENABLE (1<<30) -#define PLLD_MISC_DIV_RST (1<<23) -#define PLLD_MISC_DCCON_SHIFT 12 - -#define PLLDU_LFCON_SET_DIVN 600 - -/* FIXME: OUT_OF_TABLE_CPCON per pll */ -#define OUT_OF_TABLE_CPCON 0x8 - -#define SUPER_CLK_MUX 0x00 -#define SUPER_STATE_SHIFT 28 -#define SUPER_STATE_MASK (0xF << SUPER_STATE_SHIFT) -#define SUPER_STATE_STANDBY (0x0 << SUPER_STATE_SHIFT) -#define SUPER_STATE_IDLE (0x1 << SUPER_STATE_SHIFT) -#define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT) -#define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT) -#define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT) -#define SUPER_LP_DIV2_BYPASS (0x1 << 16) -#define SUPER_SOURCE_MASK 0xF -#define SUPER_FIQ_SOURCE_SHIFT 12 -#define SUPER_IRQ_SOURCE_SHIFT 8 -#define SUPER_RUN_SOURCE_SHIFT 4 -#define SUPER_IDLE_SOURCE_SHIFT 0 - -#define SUPER_CLK_DIVIDER 0x04 -#define SUPER_CLOCK_DIV_U71_SHIFT 16 -#define SUPER_CLOCK_DIV_U71_MASK (0xff << SUPER_CLOCK_DIV_U71_SHIFT) -/* guarantees safe cpu backup */ -#define SUPER_CLOCK_DIV_U71_MIN 0x2 - -#define BUS_CLK_DISABLE (1<<3) -#define BUS_CLK_DIV_MASK 0x3 - -#define PMC_CTRL 0x0 - #define PMC_CTRL_BLINK_ENB (1 << 7) - -#define PMC_DPD_PADS_ORIDE 0x1c - #define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20) - -#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0 -#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff -#define PMC_BLINK_TIMER_ENB (1 << 15) -#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 -#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff - -#define PMC_PLLP_WB0_OVERRIDE 0xf8 -#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE (1 << 12) - -#define UTMIP_PLL_CFG2 0x488 -#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6) -#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN (1 << 0) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN (1 << 2) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN (1 << 4) - -#define UTMIP_PLL_CFG1 0x484 -#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) -#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN (1 << 14) -#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN (1 << 12) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN (1 << 16) - -#define PLLE_BASE_CML_ENABLE (1<<31) -#define PLLE_BASE_ENABLE (1<<30) -#define PLLE_BASE_DIVCML_SHIFT 24 -#define PLLE_BASE_DIVCML_MASK (0xf<<PLLE_BASE_DIVCML_SHIFT) -#define PLLE_BASE_DIVP_SHIFT 16 -#define PLLE_BASE_DIVP_MASK (0x3f<<PLLE_BASE_DIVP_SHIFT) -#define PLLE_BASE_DIVN_SHIFT 8 -#define PLLE_BASE_DIVN_MASK (0xFF<<PLLE_BASE_DIVN_SHIFT) -#define PLLE_BASE_DIVM_SHIFT 0 -#define PLLE_BASE_DIVM_MASK (0xFF<<PLLE_BASE_DIVM_SHIFT) -#define PLLE_BASE_DIV_MASK \ - (PLLE_BASE_DIVCML_MASK | PLLE_BASE_DIVP_MASK | \ - PLLE_BASE_DIVN_MASK | PLLE_BASE_DIVM_MASK) -#define PLLE_BASE_DIV(m, n, p, cml) \ - (((cml)<<PLLE_BASE_DIVCML_SHIFT) | ((p)<<PLLE_BASE_DIVP_SHIFT) | \ - ((n)<<PLLE_BASE_DIVN_SHIFT) | ((m)<<PLLE_BASE_DIVM_SHIFT)) - -#define PLLE_MISC_SETUP_BASE_SHIFT 16 -#define PLLE_MISC_SETUP_BASE_MASK (0xFFFF<<PLLE_MISC_SETUP_BASE_SHIFT) -#define PLLE_MISC_READY (1<<15) -#define PLLE_MISC_LOCK (1<<11) -#define PLLE_MISC_LOCK_ENABLE (1<<9) -#define PLLE_MISC_SETUP_EX_SHIFT 2 -#define PLLE_MISC_SETUP_EX_MASK (0x3<<PLLE_MISC_SETUP_EX_SHIFT) -#define PLLE_MISC_SETUP_MASK \ - (PLLE_MISC_SETUP_BASE_MASK | PLLE_MISC_SETUP_EX_MASK) -#define PLLE_MISC_SETUP_VALUE \ - ((0x7<<PLLE_MISC_SETUP_BASE_SHIFT) | (0x0<<PLLE_MISC_SETUP_EX_SHIFT)) - -#define PLLE_SS_CTRL 0x68 -#define PLLE_SS_INCINTRV_SHIFT 24 -#define PLLE_SS_INCINTRV_MASK (0x3f<<PLLE_SS_INCINTRV_SHIFT) -#define PLLE_SS_INC_SHIFT 16 -#define PLLE_SS_INC_MASK (0xff<<PLLE_SS_INC_SHIFT) -#define PLLE_SS_MAX_SHIFT 0 -#define PLLE_SS_MAX_MASK (0x1ff<<PLLE_SS_MAX_SHIFT) -#define PLLE_SS_COEFFICIENTS_MASK \ - (PLLE_SS_INCINTRV_MASK | PLLE_SS_INC_MASK | PLLE_SS_MAX_MASK) -#define PLLE_SS_COEFFICIENTS_12MHZ \ - ((0x18<<PLLE_SS_INCINTRV_SHIFT) | (0x1<<PLLE_SS_INC_SHIFT) | \ - (0x24<<PLLE_SS_MAX_SHIFT)) -#define PLLE_SS_DISABLE ((1<<12) | (1<<11) | (1<<10)) - -#define PLLE_AUX 0x48c -#define PLLE_AUX_PLLP_SEL (1<<2) -#define PLLE_AUX_CML_SATA_ENABLE (1<<1) -#define PLLE_AUX_CML_PCIE_ENABLE (1<<0) - -#define PMC_SATA_PWRGT 0x1ac -#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE (1<<5) -#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1<<4) - -#define ROUND_DIVIDER_UP 0 -#define ROUND_DIVIDER_DOWN 1 - -/* FIXME: recommended safety delay after lock is detected */ -#define PLL_POST_LOCK_DELAY 100 - -/* Tegra CPU clock and reset control regs */ -#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c -#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 -#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344 -#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR 0x34c -#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 - -#define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) -#define CPU_RESET(cpu) (0x1111ul << (cpu)) - -#define CLK_RESET_CCLK_BURST 0x20 -#define CLK_RESET_CCLK_DIVIDER 0x24 -#define CLK_RESET_PLLX_BASE 0xe0 -#define CLK_RESET_PLLX_MISC 0xe4 - -#define CLK_RESET_SOURCE_CSITE 0x1d4 - -#define CLK_RESET_CCLK_BURST_POLICY_SHIFT 28 -#define CLK_RESET_CCLK_RUN_POLICY_SHIFT 4 -#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT 0 -#define CLK_RESET_CCLK_IDLE_POLICY 1 -#define CLK_RESET_CCLK_RUN_POLICY 2 -#define CLK_RESET_CCLK_BURST_POLICY_PLLX 8 - -#ifdef CONFIG_PM_SLEEP -static struct cpu_clk_suspend_context { - u32 pllx_misc; - u32 pllx_base; - - u32 cpu_burst; - u32 clk_csite_src; - u32 cclk_divider; -} tegra30_cpu_clk_sctx; -#endif - -/** -* Structure defining the fields for USB UTMI clocks Parameters. -*/ -struct utmi_clk_param { - /* Oscillator Frequency in KHz */ - u32 osc_frequency; - /* UTMIP PLL Enable Delay Count */ - u8 enable_delay_count; - /* UTMIP PLL Stable count */ - u8 stable_count; - /* UTMIP PLL Active delay count */ - u8 active_delay_count; - /* UTMIP PLL Xtal frequency count */ - u8 xtal_freq_count; -}; - -static const struct utmi_clk_param utmi_parameters[] = { - { - .osc_frequency = 13000000, - .enable_delay_count = 0x02, - .stable_count = 0x33, - .active_delay_count = 0x05, - .xtal_freq_count = 0x7F - }, - { - .osc_frequency = 19200000, - .enable_delay_count = 0x03, - .stable_count = 0x4B, - .active_delay_count = 0x06, - .xtal_freq_count = 0xBB}, - { - .osc_frequency = 12000000, - .enable_delay_count = 0x02, - .stable_count = 0x2F, - .active_delay_count = 0x04, - .xtal_freq_count = 0x76 - }, - { - .osc_frequency = 26000000, - .enable_delay_count = 0x04, - .stable_count = 0x66, - .active_delay_count = 0x09, - .xtal_freq_count = 0xFE - }, - { - .osc_frequency = 16800000, - .enable_delay_count = 0x03, - .stable_count = 0x41, - .active_delay_count = 0x0A, - .xtal_freq_count = 0xA4 - }, -}; - -static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); -static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); -static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE); - -#define MISC_GP_HIDREV 0x804 - -/* - * Some peripheral clocks share an enable bit, so refcount the enable bits - * in registers CLK_ENABLE_L, ... CLK_ENABLE_W - */ -static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32]; - -#define clk_writel(value, reg) \ - __raw_writel(value, reg_clk_base + (reg)) -#define clk_readl(reg) \ - __raw_readl(reg_clk_base + (reg)) -#define pmc_writel(value, reg) \ - __raw_writel(value, reg_pmc_base + (reg)) -#define pmc_readl(reg) \ - __raw_readl(reg_pmc_base + (reg)) -#define chipid_readl() \ - __raw_readl(misc_gp_hidrev_base + MISC_GP_HIDREV) - -#define clk_writel_delay(value, reg) \ - do { \ - __raw_writel((value), reg_clk_base + (reg)); \ - udelay(2); \ - } while (0) - -static inline int clk_set_div(struct clk_tegra *c, u32 n) -{ - struct clk *clk = c->hw.clk; - - return clk_set_rate(clk, - (__clk_get_rate(__clk_get_parent(clk)) + n - 1) / n); -} - -static inline u32 periph_clk_to_reg( - struct clk_tegra *c, u32 reg_L, u32 reg_V, int offs) -{ - u32 reg = c->u.periph.clk_num / 32; - BUG_ON(reg >= RST_DEVICES_NUM); - if (reg < 3) - reg = reg_L + (reg * offs); - else - reg = reg_V + ((reg - 3) * offs); - return reg; -} - -static unsigned long clk_measure_input_freq(void) -{ - u32 clock_autodetect; - clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); - do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); - clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); - if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) { - return 12000000; - } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) { - return 13000000; - } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) { - return 19200000; - } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { - return 26000000; - } else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) { - return 16800000; - } else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) { - return 38400000; - } else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) { - return 48000000; - } else { - pr_err("%s: Unexpected clock autodetect value %d", __func__, - clock_autodetect); - BUG(); - return 0; - } -} - -static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate, - u32 flags, u32 round_mode) -{ - s64 divider_u71 = parent_rate; - if (!rate) - return -EINVAL; - - if (!(flags & DIV_U71_INT)) - divider_u71 *= 2; - if (round_mode == ROUND_DIVIDER_UP) - divider_u71 += rate - 1; - do_div(divider_u71, rate); - if (flags & DIV_U71_INT) - divider_u71 *= 2; - - if (divider_u71 - 2 < 0) - return 0; - - if (divider_u71 - 2 > 255) - return -EINVAL; - - return divider_u71 - 2; -} - -static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) -{ - s64 divider_u16; - - divider_u16 = parent_rate; - if (!rate) - return -EINVAL; - divider_u16 += rate - 1; - do_div(divider_u16, rate); - - if (divider_u16 - 1 < 0) - return 0; - - if (divider_u16 - 1 > 0xFFFF) - return -EINVAL; - - return divider_u16 - 1; -} - -static unsigned long tegra30_clk_fixed_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return to_clk_tegra(hw)->fixed_rate; -} - -struct clk_ops tegra30_clk_32k_ops = { - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -/* clk_m functions */ -static unsigned long tegra30_clk_m_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - if (!to_clk_tegra(hw)->fixed_rate) - to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq(); - return to_clk_tegra(hw)->fixed_rate; -} - -static void tegra30_clk_m_init(struct clk_hw *hw) -{ - u32 osc_ctrl = clk_readl(OSC_CTRL); - u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK; - u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; - - switch (to_clk_tegra(hw)->fixed_rate) { - case 12000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - break; - case 13000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - break; - case 19200000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - break; - case 26000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - break; - case 16800000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_16_8MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); - break; - case 38400000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_38_4MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2); - break; - case 48000000: - auto_clock_control |= OSC_CTRL_OSC_FREQ_48MHZ; - BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4); - break; - default: - pr_err("%s: Unexpected clock rate %ld", __func__, - to_clk_tegra(hw)->fixed_rate); - BUG(); - } - clk_writel(auto_clock_control, OSC_CTRL); -} - -struct clk_ops tegra30_clk_m_ops = { - .init = tegra30_clk_m_init, - .recalc_rate = tegra30_clk_m_recalc_rate, -}; - -static unsigned long tegra30_clk_m_div_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -struct clk_ops tegra_clk_m_div_ops = { - .recalc_rate = tegra30_clk_m_div_recalc_rate, -}; - -/* PLL reference divider functions */ -static unsigned long tegra30_pll_ref_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long rate = parent_rate; - u32 pll_ref_div = clk_readl(OSC_CTRL) & OSC_CTRL_PLL_REF_DIV_MASK; - - switch (pll_ref_div) { - case OSC_CTRL_PLL_REF_DIV_1: - c->div = 1; - break; - case OSC_CTRL_PLL_REF_DIV_2: - c->div = 2; - break; - case OSC_CTRL_PLL_REF_DIV_4: - c->div = 4; - break; - default: - pr_err("%s: Invalid pll ref divider %d", __func__, pll_ref_div); - BUG(); - } - c->mul = 1; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -struct clk_ops tegra_pll_ref_ops = { - .recalc_rate = tegra30_pll_ref_recalc_rate, -}; - -/* super clock functions */ -/* "super clocks" on tegra30 have two-stage muxes, fractional 7.1 divider and - * clock skipping super divider. We will ignore the clock skipping divider, - * since we can't lower the voltage when using the clock skip, but we can if - * we lower the PLL frequency. We will use 7.1 divider for CPU super-clock - * only when its parent is a fixed rate PLL, since we can't change PLL rate - * in this case. - */ -static void tegra30_super_clk_init(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - struct clk_tegra *p = - to_clk_tegra(__clk_get_hw(__clk_get_parent(hw->clk))); - - c->state = ON; - if (c->flags & DIV_U71) { - /* Init safe 7.1 divider value (does not affect PLLX path) */ - clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT, - c->reg + SUPER_CLK_DIVIDER); - c->mul = 2; - c->div = 2; - if (!(p->flags & PLLX)) - c->div += SUPER_CLOCK_DIV_U71_MIN; - } else - clk_writel(0, c->reg + SUPER_CLK_DIVIDER); -} - -static u8 tegra30_super_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - int source; - int shift; - - val = clk_readl(c->reg + SUPER_CLK_MUX); - BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && - ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); - shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? - SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; - source = (val >> shift) & SUPER_SOURCE_MASK; - if (c->flags & DIV_2) - source |= val & SUPER_LP_DIV2_BYPASS; - - return source; -} - -static int tegra30_super_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - struct clk_tegra *p = - to_clk_tegra(__clk_get_hw(clk_get_parent(hw->clk))); - u32 val; - int shift; - - val = clk_readl(c->reg + SUPER_CLK_MUX); - BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && - ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); - shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? - SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; - - /* For LP mode super-clock switch between PLLX direct - and divided-by-2 outputs is allowed only when other - than PLLX clock source is current parent */ - if ((c->flags & DIV_2) && (p->flags & PLLX) && - ((index ^ val) & SUPER_LP_DIV2_BYPASS)) { - if (p->flags & PLLX) - return -EINVAL; - val ^= SUPER_LP_DIV2_BYPASS; - clk_writel_delay(val, c->reg); - } - val &= ~(SUPER_SOURCE_MASK << shift); - val |= (index & SUPER_SOURCE_MASK) << shift; - - /* 7.1 divider for CPU super-clock does not affect - PLLX path */ - if (c->flags & DIV_U71) { - u32 div = 0; - if (!(p->flags & PLLX)) { - div = clk_readl(c->reg + - SUPER_CLK_DIVIDER); - div &= SUPER_CLOCK_DIV_U71_MASK; - div >>= SUPER_CLOCK_DIV_U71_SHIFT; - } - c->div = div + 2; - c->mul = 2; - } - clk_writel_delay(val, c->reg); - - return 0; -} - -/* - * Do not use super clocks "skippers", since dividing using a clock skipper - * does not allow the voltage to be scaled down. Instead adjust the rate of - * the parent clock. This requires that the parent of a super clock have no - * other children, otherwise the rate will change underneath the other - * children. Special case: if fixed rate PLL is CPU super clock parent the - * rate of this PLL can't be changed, and it has many other children. In - * this case use 7.1 fractional divider to adjust the super clock rate. - */ -static int tegra30_super_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - struct clk *parent = __clk_get_parent(hw->clk); - struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent)); - - if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) { - int div = clk_div71_get_divider(parent_rate, - rate, c->flags, ROUND_DIVIDER_DOWN); - div = max(div, SUPER_CLOCK_DIV_U71_MIN); - - clk_writel(div << SUPER_CLOCK_DIV_U71_SHIFT, - c->reg + SUPER_CLK_DIVIDER); - c->div = div + 2; - c->mul = 2; - return 0; - } - return 0; -} - -static unsigned long tegra30_super_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -static long tegra30_super_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - struct clk *parent = __clk_get_parent(hw->clk); - struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent)); - int mul = 2; - int div; - - if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) { - div = clk_div71_get_divider(*prate, - rate, c->flags, ROUND_DIVIDER_DOWN); - div = max(div, SUPER_CLOCK_DIV_U71_MIN) + 2; - rate = *prate * mul; - rate += div - 1; /* round up */ - do_div(rate, c->div); - - return rate; - } - return *prate; -} - -struct clk_ops tegra30_super_ops = { - .init = tegra30_super_clk_init, - .set_parent = tegra30_super_clk_set_parent, - .get_parent = tegra30_super_clk_get_parent, - .recalc_rate = tegra30_super_clk_recalc_rate, - .round_rate = tegra30_super_clk_round_rate, - .set_rate = tegra30_super_clk_set_rate, -}; - -static unsigned long tegra30_twd_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -struct clk_ops tegra30_twd_ops = { - .recalc_rate = tegra30_twd_clk_recalc_rate, -}; - -/* bus clock functions */ -static int tegra30_bus_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - - c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; - return c->state; -} - -static int tegra30_bus_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg); - val &= ~(BUS_CLK_DISABLE << c->reg_shift); - clk_writel(val, c->reg); - - return 0; -} - -static void tegra30_bus_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg); - val |= BUS_CLK_DISABLE << c->reg_shift; - clk_writel(val, c->reg); -} - -static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw, - unsigned long prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - u64 rate = prate; - - c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; - c->mul = 1; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - int ret = -EINVAL; - u32 val; - int i; - - val = clk_readl(c->reg); - for (i = 1; i <= 4; i++) { - if (rate == parent_rate / i) { - val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); - val |= (i - 1) << c->reg_shift; - clk_writel(val, c->reg); - c->div = i; - c->mul = 1; - ret = 0; - break; - } - } - - return ret; -} - -static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - unsigned long parent_rate = *prate; - s64 divider; - - if (rate >= parent_rate) - return parent_rate; - - divider = parent_rate; - divider += rate - 1; - do_div(divider, rate); - - if (divider < 0) - return divider; - - if (divider > 4) - divider = 4; - do_div(parent_rate, divider); - - return parent_rate; -} - -struct clk_ops tegra30_bus_ops = { - .is_enabled = tegra30_bus_clk_is_enabled, - .enable = tegra30_bus_clk_enable, - .disable = tegra30_bus_clk_disable, - .set_rate = tegra30_bus_clk_set_rate, - .round_rate = tegra30_bus_clk_round_rate, - .recalc_rate = tegra30_bus_clk_recalc_rate, -}; - -/* Blink output functions */ -static int tegra30_blink_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = pmc_readl(PMC_CTRL); - c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF; - return c->state; -} - -static int tegra30_blink_clk_enable(struct clk_hw *hw) -{ - u32 val; - - val = pmc_readl(PMC_DPD_PADS_ORIDE); - pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); - - val = pmc_readl(PMC_CTRL); - pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL); - - return 0; -} - -static void tegra30_blink_clk_disable(struct clk_hw *hw) -{ - u32 val; - - val = pmc_readl(PMC_CTRL); - pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL); - - val = pmc_readl(PMC_DPD_PADS_ORIDE); - pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); -} - -static int tegra30_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (rate >= parent_rate) { - c->div = 1; - pmc_writel(0, c->reg); - } else { - unsigned int on_off; - u32 val; - - on_off = DIV_ROUND_UP(parent_rate / 8, rate); - c->div = on_off * 8; - - val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) << - PMC_BLINK_TIMER_DATA_ON_SHIFT; - on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK; - on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT; - val |= on_off; - val |= PMC_BLINK_TIMER_ENB; - pmc_writel(val, c->reg); - } - - return 0; -} - -static unsigned long tegra30_blink_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - u32 val; - u32 mul; - u32 div; - u32 on_off; - - mul = 1; - val = pmc_readl(c->reg); - - if (val & PMC_BLINK_TIMER_ENB) { - on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) & - PMC_BLINK_TIMER_DATA_ON_MASK; - val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT; - val &= PMC_BLINK_TIMER_DATA_OFF_MASK; - on_off += val; - /* each tick in the blink timer is 4 32KHz clocks */ - div = on_off * 4; - } else { - div = 1; - } - - if (mul != 0 && div != 0) { - rate *= mul; - rate += div - 1; /* round up */ - do_div(rate, div); - } - return rate; -} - -static long tegra30_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - int div; - int mul; - long round_rate = *prate; - - mul = 1; - - if (rate >= *prate) { - div = 1; - } else { - div = DIV_ROUND_UP(*prate / 8, rate); - div *= 8; - } - - round_rate *= mul; - round_rate += div - 1; - do_div(round_rate, div); - - return round_rate; -} - -struct clk_ops tegra30_blink_clk_ops = { - .is_enabled = tegra30_blink_clk_is_enabled, - .enable = tegra30_blink_clk_enable, - .disable = tegra30_blink_clk_disable, - .recalc_rate = tegra30_blink_clk_recalc_rate, - .round_rate = tegra30_blink_clk_round_rate, - .set_rate = tegra30_blink_clk_set_rate, -}; - -static void tegra30_utmi_param_configure(struct clk_hw *hw) -{ - unsigned long main_rate = - __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk))); - u32 reg; - int i; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (main_rate == utmi_parameters[i].osc_frequency) - break; - } - - if (i >= ARRAY_SIZE(utmi_parameters)) { - pr_err("%s: Unexpected main rate %lu\n", __func__, main_rate); - return; - } - - reg = clk_readl(UTMIP_PLL_CFG2); - - /* Program UTMIP PLL stable and active counts */ - /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ - reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - reg |= UTMIP_PLL_CFG2_STABLE_COUNT( - utmi_parameters[i].stable_count); - - reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT( - utmi_parameters[i].active_delay_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; - - clk_writel(reg, UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - reg = clk_readl(UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT( - utmi_parameters[i].enable_delay_count); - - reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT( - utmi_parameters[i].xtal_freq_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; - - clk_writel(reg, UTMIP_PLL_CFG1); -} - -/* PLL Functions */ -static int tegra30_pll_clk_wait_for_lock(struct clk_tegra *c, u32 lock_reg, - u32 lock_bit) -{ - int ret = 0; - -#if USE_PLL_LOCK_BITS - int i; - for (i = 0; i < c->u.pll.lock_delay; i++) { - if (clk_readl(lock_reg) & lock_bit) { - udelay(PLL_POST_LOCK_DELAY); - return 0; - } - udelay(2); /* timeout = 2 * lock time */ - } - pr_err("Timed out waiting for lock bit on pll %s", - __clk_get_name(hw->clk)); - ret = -1; -#else - udelay(c->u.pll.lock_delay); -#endif - return ret; -} - -static int tegra30_pll_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg + PLL_BASE); - - c->state = (val & PLL_BASE_ENABLE) ? ON : OFF; - return c->state; -} - -static void tegra30_pll_clk_init(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (c->flags & PLLU) - tegra30_utmi_param_configure(hw); -} - -static int tegra30_pll_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - -#if USE_PLL_LOCK_BITS - val = clk_readl(c->reg + PLL_MISC(c)); - val |= PLL_MISC_LOCK_ENABLE(c); - clk_writel(val, c->reg + PLL_MISC(c)); -#endif - val = clk_readl(c->reg + PLL_BASE); - val &= ~PLL_BASE_BYPASS; - val |= PLL_BASE_ENABLE; - clk_writel(val, c->reg + PLL_BASE); - - if (c->flags & PLLM) { - val = pmc_readl(PMC_PLLP_WB0_OVERRIDE); - val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; - pmc_writel(val, PMC_PLLP_WB0_OVERRIDE); - } - - tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_BASE, PLL_BASE_LOCK); - - return 0; -} - -static void tegra30_pll_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); - - val = clk_readl(c->reg); - val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); - clk_writel(val, c->reg); - - if (c->flags & PLLM) { - val = pmc_readl(PMC_PLLP_WB0_OVERRIDE); - val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; - pmc_writel(val, PMC_PLLP_WB0_OVERRIDE); - } -} - -static int tegra30_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val, p_div, old_base; - unsigned long input_rate; - const struct clk_pll_freq_table *sel; - struct clk_pll_freq_table cfg; - - if (c->flags & PLL_FIXED) { - int ret = 0; - if (rate != c->u.pll.fixed_rate) { - pr_err("%s: Can not change %s fixed rate %lu to %lu\n", - __func__, __clk_get_name(hw->clk), - c->u.pll.fixed_rate, rate); - ret = -EINVAL; - } - return ret; - } - - if (c->flags & PLLM) { - if (rate != __clk_get_rate(hw->clk)) { - pr_err("%s: Can not change memory %s rate in flight\n", - __func__, __clk_get_name(hw->clk)); - return -EINVAL; - } - } - - p_div = 0; - input_rate = parent_rate; - - /* Check if the target rate is tabulated */ - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == input_rate && sel->output_rate == rate) { - if (c->flags & PLLU) { - BUG_ON(sel->p < 1 || sel->p > 2); - if (sel->p == 1) - p_div = PLLU_BASE_POST_DIV; - } else { - BUG_ON(sel->p < 1); - for (val = sel->p; val > 1; val >>= 1) - p_div++; - p_div <<= PLL_BASE_DIVP_SHIFT; - } - break; - } - } - - /* Configure out-of-table rate */ - if (sel->input_rate == 0) { - unsigned long cfreq; - BUG_ON(c->flags & PLLU); - sel = &cfg; - - switch (input_rate) { - case 12000000: - case 26000000: - cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000; - break; - case 13000000: - cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000; - break; - case 16800000: - case 19200000: - cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000; - break; - default: - pr_err("%s: Unexpected reference rate %lu\n", - __func__, input_rate); - BUG(); - } - - /* Raise VCO to guarantee 0.5% accuracy */ - for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq; - cfg.output_rate <<= 1) - p_div++; - - cfg.p = 0x1 << p_div; - cfg.m = input_rate / cfreq; - cfg.n = cfg.output_rate / cfreq; - cfg.cpcon = OUT_OF_TABLE_CPCON; - - if ((cfg.m > (PLL_BASE_DIVM_MASK >> PLL_BASE_DIVM_SHIFT)) || - (cfg.n > (PLL_BASE_DIVN_MASK >> PLL_BASE_DIVN_SHIFT)) || - (p_div > (PLL_BASE_DIVP_MASK >> PLL_BASE_DIVP_SHIFT)) || - (cfg.output_rate > c->u.pll.vco_max)) { - pr_err("%s: Failed to set %s out-of-table rate %lu\n", - __func__, __clk_get_name(hw->clk), rate); - return -EINVAL; - } - p_div <<= PLL_BASE_DIVP_SHIFT; - } - - c->mul = sel->n; - c->div = sel->m * sel->p; - - old_base = val = clk_readl(c->reg + PLL_BASE); - val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK | - ((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK)); - val |= (sel->m << PLL_BASE_DIVM_SHIFT) | - (sel->n << PLL_BASE_DIVN_SHIFT) | p_div; - if (val == old_base) - return 0; - - if (c->state == ON) { - tegra30_pll_clk_disable(hw); - val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); - } - clk_writel(val, c->reg + PLL_BASE); - - if (c->flags & PLL_HAS_CPCON) { - val = clk_readl(c->reg + PLL_MISC(c)); - val &= ~PLL_MISC_CPCON_MASK; - val |= sel->cpcon << PLL_MISC_CPCON_SHIFT; - if (c->flags & (PLLU | PLLD)) { - val &= ~PLL_MISC_LFCON_MASK; - if (sel->n >= PLLDU_LFCON_SET_DIVN) - val |= 0x1 << PLL_MISC_LFCON_SHIFT; - } else if (c->flags & (PLLX | PLLM)) { - val &= ~(0x1 << PLL_MISC_DCCON_SHIFT); - if (rate >= (c->u.pll.vco_max >> 1)) - val |= 0x1 << PLL_MISC_DCCON_SHIFT; - } - clk_writel(val, c->reg + PLL_MISC(c)); - } - - if (c->state == ON) - tegra30_pll_clk_enable(hw); - - c->u.pll.fixed_rate = rate; - - return 0; -} - -static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long input_rate = *prate; - u64 output_rate = *prate; - const struct clk_pll_freq_table *sel; - struct clk_pll_freq_table cfg; - int mul; - int div; - u32 p_div; - u32 val; - - if (c->flags & PLL_FIXED) - return c->u.pll.fixed_rate; - - if (c->flags & PLLM) - return __clk_get_rate(hw->clk); - - p_div = 0; - /* Check if the target rate is tabulated */ - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == input_rate && sel->output_rate == rate) { - if (c->flags & PLLU) { - BUG_ON(sel->p < 1 || sel->p > 2); - if (sel->p == 1) - p_div = PLLU_BASE_POST_DIV; - } else { - BUG_ON(sel->p < 1); - for (val = sel->p; val > 1; val >>= 1) - p_div++; - p_div <<= PLL_BASE_DIVP_SHIFT; - } - break; - } - } - - if (sel->input_rate == 0) { - unsigned long cfreq; - BUG_ON(c->flags & PLLU); - sel = &cfg; - - switch (input_rate) { - case 12000000: - case 26000000: - cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000; - break; - case 13000000: - cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000; - break; - case 16800000: - case 19200000: - cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000; - break; - default: - pr_err("%s: Unexpected reference rate %lu\n", - __func__, input_rate); - BUG(); - } - - /* Raise VCO to guarantee 0.5% accuracy */ - for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq; - cfg.output_rate <<= 1) - p_div++; - - cfg.p = 0x1 << p_div; - cfg.m = input_rate / cfreq; - cfg.n = cfg.output_rate / cfreq; - } - - mul = sel->n; - div = sel->m * sel->p; - - output_rate *= mul; - output_rate += div - 1; /* round up */ - do_div(output_rate, div); - - return output_rate; -} - -static unsigned long tegra30_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - u32 val = clk_readl(c->reg + PLL_BASE); - - if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { - const struct clk_pll_freq_table *sel; - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == parent_rate && - sel->output_rate == c->u.pll.fixed_rate) { - c->mul = sel->n; - c->div = sel->m * sel->p; - break; - } - } - pr_err("Clock %s has unknown fixed frequency\n", - __clk_get_name(hw->clk)); - BUG(); - } else if (val & PLL_BASE_BYPASS) { - c->mul = 1; - c->div = 1; - } else { - c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; - c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; - if (c->flags & PLLU) - c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2; - else - c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >> - PLL_BASE_DIVP_SHIFT)); - } - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -struct clk_ops tegra30_pll_ops = { - .is_enabled = tegra30_pll_clk_is_enabled, - .init = tegra30_pll_clk_init, - .enable = tegra30_pll_clk_enable, - .disable = tegra30_pll_clk_disable, - .recalc_rate = tegra30_pll_recalc_rate, - .round_rate = tegra30_pll_round_rate, - .set_rate = tegra30_pll_clk_set_rate, -}; - -int tegra30_plld_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val, mask, reg; - - switch (p) { - case TEGRA_CLK_PLLD_CSI_OUT_ENB: - mask = PLLD_BASE_CSI_CLKENABLE; - reg = c->reg + PLL_BASE; - break; - case TEGRA_CLK_PLLD_DSI_OUT_ENB: - mask = PLLD_MISC_DSI_CLKENABLE; - reg = c->reg + PLL_MISC(c); - break; - case TEGRA_CLK_PLLD_MIPI_MUX_SEL: - if (!(c->flags & PLL_ALT_MISC_REG)) { - mask = PLLD_BASE_DSIB_MUX_MASK; - reg = c->reg + PLL_BASE; - break; - } - /* fall through - error since PLLD2 does not have MUX_SEL control */ - default: - return -EINVAL; - } - - val = clk_readl(reg); - if (setting) - val |= mask; - else - val &= ~mask; - clk_writel(val, reg); - return 0; -} - -static int tegra30_plle_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg + PLL_BASE); - c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF; - return c->state; -} - -static void tegra30_plle_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg + PLL_BASE); - val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE); - clk_writel(val, c->reg + PLL_BASE); -} - -static void tegra30_plle_training(struct clk_tegra *c) -{ - u32 val; - - /* PLLE is already disabled, and setup cleared; - * create falling edge on PLLE IDDQ input */ - val = pmc_readl(PMC_SATA_PWRGT); - val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE; - pmc_writel(val, PMC_SATA_PWRGT); - - val = pmc_readl(PMC_SATA_PWRGT); - val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL; - pmc_writel(val, PMC_SATA_PWRGT); - - val = pmc_readl(PMC_SATA_PWRGT); - val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE; - pmc_writel(val, PMC_SATA_PWRGT); - - do { - val = clk_readl(c->reg + PLL_MISC(c)); - } while (!(val & PLLE_MISC_READY)); -} - -static int tegra30_plle_configure(struct clk_hw *hw, bool force_training) -{ - struct clk_tegra *c = to_clk_tegra(hw); - struct clk *parent = __clk_get_parent(hw->clk); - const struct clk_pll_freq_table *sel; - u32 val; - - unsigned long rate = c->u.pll.fixed_rate; - unsigned long input_rate = __clk_get_rate(parent); - - for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { - if (sel->input_rate == input_rate && sel->output_rate == rate) - break; - } - - if (sel->input_rate == 0) - return -ENOSYS; - - /* disable PLLE, clear setup fiels */ - tegra30_plle_clk_disable(hw); - - val = clk_readl(c->reg + PLL_MISC(c)); - val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK); - clk_writel(val, c->reg + PLL_MISC(c)); - - /* training */ - val = clk_readl(c->reg + PLL_MISC(c)); - if (force_training || (!(val & PLLE_MISC_READY))) - tegra30_plle_training(c); - - /* configure dividers, setup, disable SS */ - val = clk_readl(c->reg + PLL_BASE); - val &= ~PLLE_BASE_DIV_MASK; - val |= PLLE_BASE_DIV(sel->m, sel->n, sel->p, sel->cpcon); - clk_writel(val, c->reg + PLL_BASE); - c->mul = sel->n; - c->div = sel->m * sel->p; - - val = clk_readl(c->reg + PLL_MISC(c)); - val |= PLLE_MISC_SETUP_VALUE; - val |= PLLE_MISC_LOCK_ENABLE; - clk_writel(val, c->reg + PLL_MISC(c)); - - val = clk_readl(PLLE_SS_CTRL); - val |= PLLE_SS_DISABLE; - clk_writel(val, PLLE_SS_CTRL); - - /* enable and lock PLLE*/ - val = clk_readl(c->reg + PLL_BASE); - val |= (PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE); - clk_writel(val, c->reg + PLL_BASE); - - tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_MISC(c), PLLE_MISC_LOCK); - - return 0; -} - -static int tegra30_plle_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - return tegra30_plle_configure(hw, !c->set); -} - -static unsigned long tegra30_plle_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long rate = parent_rate; - u32 val; - - val = clk_readl(c->reg + PLL_BASE); - c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT; - c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT; - c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -struct clk_ops tegra30_plle_ops = { - .is_enabled = tegra30_plle_clk_is_enabled, - .enable = tegra30_plle_clk_enable, - .disable = tegra30_plle_clk_disable, - .recalc_rate = tegra30_plle_clk_recalc_rate, -}; - -/* Clock divider ops */ -static int tegra30_pll_div_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (c->flags & DIV_U71) { - u32 val = clk_readl(c->reg); - val >>= c->reg_shift; - c->state = (val & PLL_OUT_CLKEN) ? ON : OFF; - if (!(val & PLL_OUT_RESET_DISABLE)) - c->state = OFF; - } else { - c->state = ON; - } - return c->state; -} - -static int tegra30_pll_div_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - u32 new_val; - - pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); - if (c->flags & DIV_U71) { - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - - new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE; - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel_delay(val, c->reg); - return 0; - } else if (c->flags & DIV_2) { - return 0; - } - return -EINVAL; -} - -static void tegra30_pll_div_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - u32 new_val; - - pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); - if (c->flags & DIV_U71) { - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - - new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE); - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel_delay(val, c->reg); - } -} - -static int tegra30_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - u32 new_val; - int divider_u71; - - if (c->flags & DIV_U71) { - divider_u71 = clk_div71_get_divider( - parent_rate, rate, c->flags, ROUND_DIVIDER_UP); - if (divider_u71 >= 0) { - val = clk_readl(c->reg); - new_val = val >> c->reg_shift; - new_val &= 0xFFFF; - if (c->flags & DIV_U71_FIXED) - new_val |= PLL_OUT_OVERRIDE; - new_val &= ~PLL_OUT_RATIO_MASK; - new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT; - - val &= ~(0xFFFF << c->reg_shift); - val |= new_val << c->reg_shift; - clk_writel_delay(val, c->reg); - c->div = divider_u71 + 2; - c->mul = 2; - c->fixed_rate = rate; - return 0; - } - } else if (c->flags & DIV_2) { - c->fixed_rate = rate; - return 0; - } - - return -EINVAL; -} - -static unsigned long tegra30_pll_div_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - if (c->flags & DIV_U71) { - u32 divu71; - u32 val = clk_readl(c->reg); - val >>= c->reg_shift; - - divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT; - c->div = (divu71 + 2); - c->mul = 2; - } else if (c->flags & DIV_2) { - if (c->flags & (PLLD | PLLX)) { - c->div = 2; - c->mul = 1; - } else - BUG(); - } else { - c->div = 1; - c->mul = 1; - } - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -static long tegra30_pll_div_clk_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); - int divider; - - if (prate) - parent_rate = *prate; - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider( - parent_rate, rate, c->flags, ROUND_DIVIDER_UP); - if (divider < 0) - return divider; - return DIV_ROUND_UP(parent_rate * 2, divider + 2); - } else if (c->flags & DIV_2) { - *prate = rate * 2; - return rate; - } - - return -EINVAL; -} - -struct clk_ops tegra30_pll_div_ops = { - .is_enabled = tegra30_pll_div_clk_is_enabled, - .enable = tegra30_pll_div_clk_enable, - .disable = tegra30_pll_div_clk_disable, - .set_rate = tegra30_pll_div_clk_set_rate, - .recalc_rate = tegra30_pll_div_clk_recalc_rate, - .round_rate = tegra30_pll_div_clk_round_rate, -}; - -/* Periph clk ops */ -static inline u32 periph_clk_source_mask(struct clk_tegra *c) -{ - if (c->flags & MUX8) - return 7 << 29; - else if (c->flags & MUX_PWM) - return 3 << 28; - else if (c->flags & MUX_CLK_OUT) - return 3 << (c->u.periph.clk_num + 4); - else if (c->flags & PLLD) - return PLLD_BASE_DSIB_MUX_MASK; - else - return 3 << 30; -} - -static inline u32 periph_clk_source_shift(struct clk_tegra *c) -{ - if (c->flags & MUX8) - return 29; - else if (c->flags & MUX_PWM) - return 28; - else if (c->flags & MUX_CLK_OUT) - return c->u.periph.clk_num + 4; - else if (c->flags & PLLD) - return PLLD_BASE_DSIB_MUX_SHIFT; - else - return 30; -} - -static int tegra30_periph_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - c->state = ON; - if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c))) - c->state = OFF; - if (!(c->flags & PERIPH_NO_RESET)) - if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c)) - c->state = OFF; - return c->state; -} - -static int tegra30_periph_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; - if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1) - return 0; - - clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c)); - if (!(c->flags & PERIPH_NO_RESET) && - !(c->flags & PERIPH_MANUAL_RESET)) { - if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & - PERIPH_CLK_TO_BIT(c)) { - udelay(5); /* reset propagation delay */ - clk_writel(PERIPH_CLK_TO_BIT(c), - PERIPH_CLK_TO_RST_CLR_REG(c)); - } - } - return 0; -} - -static void tegra30_periph_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long val; - - tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; - - if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0) - return; - - /* If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock*/ - if (c->flags & PERIPH_ON_APB) - val = chipid_readl(); - - clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c)); -} - -void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long val; - - if (!(c->flags & PERIPH_NO_RESET)) { - if (assert) { - /* If peripheral is in the APB bus then read the APB - * bus to flush the write operation in apb bus. This - * will avoid the peripheral access after disabling - * clock */ - if (c->flags & PERIPH_ON_APB) - val = chipid_readl(); - - clk_writel(PERIPH_CLK_TO_BIT(c), - PERIPH_CLK_TO_RST_SET_REG(c)); - } else - clk_writel(PERIPH_CLK_TO_BIT(c), - PERIPH_CLK_TO_RST_CLR_REG(c)); - } -} - -static int tegra30_periph_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - if (!(c->flags & MUX)) - return (index == 0) ? 0 : (-EINVAL); - - val = clk_readl(c->reg); - val &= ~periph_clk_source_mask(c); - val |= (index << periph_clk_source_shift(c)); - clk_writel_delay(val, c->reg); - return 0; -} - -static u8 tegra30_periph_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - int source = (val & periph_clk_source_mask(c)) >> - periph_clk_source_shift(c); - - if (!(c->flags & MUX)) - return 0; - - return source; -} - -static int tegra30_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - int divider; - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider( - parent_rate, rate, c->flags, ROUND_DIVIDER_UP); - if (divider >= 0) { - val = clk_readl(c->reg); - val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; - val |= divider; - if (c->flags & DIV_U71_UART) { - if (divider) - val |= PERIPH_CLK_UART_DIV_ENB; - else - val &= ~PERIPH_CLK_UART_DIV_ENB; - } - clk_writel_delay(val, c->reg); - c->div = divider + 2; - c->mul = 2; - return 0; - } - } else if (c->flags & DIV_U16) { - divider = clk_div16_get_divider(parent_rate, rate); - if (divider >= 0) { - val = clk_readl(c->reg); - val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; - val |= divider; - clk_writel_delay(val, c->reg); - c->div = divider + 1; - c->mul = 1; - return 0; - } - } else if (parent_rate <= rate) { - c->div = 1; - c->mul = 1; - return 0; - } - return -EINVAL; -} - -static long tegra30_periph_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); - int divider; - - if (prate) - parent_rate = *prate; - - if (c->flags & DIV_U71) { - divider = clk_div71_get_divider( - parent_rate, rate, c->flags, ROUND_DIVIDER_UP); - if (divider < 0) - return divider; - - return DIV_ROUND_UP(parent_rate * 2, divider + 2); - } else if (c->flags & DIV_U16) { - divider = clk_div16_get_divider(parent_rate, rate); - if (divider < 0) - return divider; - return DIV_ROUND_UP(parent_rate, divider + 1); - } - return -EINVAL; -} - -static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - u32 val = clk_readl(c->reg); - - if (c->flags & DIV_U71) { - u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; - if ((c->flags & DIV_U71_UART) && - (!(val & PERIPH_CLK_UART_DIV_ENB))) { - divu71 = 0; - } - if (c->flags & DIV_U71_IDLE) { - val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK << - PERIPH_CLK_SOURCE_DIVIDLE_SHIFT); - val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL << - PERIPH_CLK_SOURCE_DIVIDLE_SHIFT); - clk_writel(val, c->reg); - } - c->div = divu71 + 2; - c->mul = 2; - } else if (c->flags & DIV_U16) { - u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; - c->div = divu16 + 1; - c->mul = 1; - } else { - c->div = 1; - c->mul = 1; - } - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - return rate; -} - -struct clk_ops tegra30_periph_clk_ops = { - .is_enabled = tegra30_periph_clk_is_enabled, - .enable = tegra30_periph_clk_enable, - .disable = tegra30_periph_clk_disable, - .set_parent = tegra30_periph_clk_set_parent, - .get_parent = tegra30_periph_clk_get_parent, - .set_rate = tegra30_periph_clk_set_rate, - .round_rate = tegra30_periph_clk_round_rate, - .recalc_rate = tegra30_periph_clk_recalc_rate, -}; - -static int tegra30_dsib_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk *d = clk_get_sys(NULL, "pll_d"); - /* The DSIB parent selection bit is in PLLD base register */ - tegra_clk_cfg_ex( - d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, index); - - return 0; -} - -struct clk_ops tegra30_dsib_clk_ops = { - .is_enabled = tegra30_periph_clk_is_enabled, - .enable = &tegra30_periph_clk_enable, - .disable = &tegra30_periph_clk_disable, - .set_parent = &tegra30_dsib_clk_set_parent, - .get_parent = &tegra30_periph_clk_get_parent, - .set_rate = &tegra30_periph_clk_set_rate, - .round_rate = &tegra30_periph_clk_round_rate, - .recalc_rate = &tegra30_periph_clk_recalc_rate, -}; - -/* Periph extended clock configuration ops */ -int tegra30_vi_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (p == TEGRA_CLK_VI_INP_SEL) { - u32 val = clk_readl(c->reg); - val &= ~PERIPH_CLK_VI_SEL_EX_MASK; - val |= (setting << PERIPH_CLK_VI_SEL_EX_SHIFT) & - PERIPH_CLK_VI_SEL_EX_MASK; - clk_writel(val, c->reg); - return 0; - } - return -EINVAL; -} - -int tegra30_nand_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (p == TEGRA_CLK_NAND_PAD_DIV2_ENB) { - u32 val = clk_readl(c->reg); - if (setting) - val |= PERIPH_CLK_NAND_DIV_EX_ENB; - else - val &= ~PERIPH_CLK_NAND_DIV_EX_ENB; - clk_writel(val, c->reg); - return 0; - } - return -EINVAL; -} - -int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - if (p == TEGRA_CLK_DTV_INVERT) { - u32 val = clk_readl(c->reg); - if (setting) - val |= PERIPH_CLK_DTV_POLARITY_INV; - else - val &= ~PERIPH_CLK_DTV_POLARITY_INV; - clk_writel(val, c->reg); - return 0; - } - return -EINVAL; -} - -/* Output clock ops */ - -static DEFINE_SPINLOCK(clk_out_lock); - -static int tegra30_clk_out_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = pmc_readl(c->reg); - - c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF; - c->mul = 1; - c->div = 1; - return c->state; -} - -static int tegra30_clk_out_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - unsigned long flags; - - spin_lock_irqsave(&clk_out_lock, flags); - val = pmc_readl(c->reg); - val |= (0x1 << c->u.periph.clk_num); - pmc_writel(val, c->reg); - spin_unlock_irqrestore(&clk_out_lock, flags); - - return 0; -} - -static void tegra30_clk_out_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - unsigned long flags; - - spin_lock_irqsave(&clk_out_lock, flags); - val = pmc_readl(c->reg); - val &= ~(0x1 << c->u.periph.clk_num); - pmc_writel(val, c->reg); - spin_unlock_irqrestore(&clk_out_lock, flags); -} - -static int tegra30_clk_out_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - unsigned long flags; - - spin_lock_irqsave(&clk_out_lock, flags); - val = pmc_readl(c->reg); - val &= ~periph_clk_source_mask(c); - val |= (index << periph_clk_source_shift(c)); - pmc_writel(val, c->reg); - spin_unlock_irqrestore(&clk_out_lock, flags); - - return 0; -} - -static u8 tegra30_clk_out_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = pmc_readl(c->reg); - int source; - - source = (val & periph_clk_source_mask(c)) >> - periph_clk_source_shift(c); - return source; -} - -struct clk_ops tegra_clk_out_ops = { - .is_enabled = tegra30_clk_out_is_enabled, - .enable = tegra30_clk_out_enable, - .disable = tegra30_clk_out_disable, - .set_parent = tegra30_clk_out_set_parent, - .get_parent = tegra30_clk_out_get_parent, - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -/* Clock doubler ops */ -static int tegra30_clk_double_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - c->state = ON; - if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c))) - c->state = OFF; - return c->state; -}; - -static int tegra30_clk_double_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - if (rate == parent_rate) { - val = clk_readl(c->reg) | (0x1 << c->reg_shift); - clk_writel(val, c->reg); - c->mul = 1; - c->div = 1; - return 0; - } else if (rate == 2 * parent_rate) { - val = clk_readl(c->reg) & (~(0x1 << c->reg_shift)); - clk_writel(val, c->reg); - c->mul = 2; - c->div = 1; - return 0; - } - return -EINVAL; -} - -static unsigned long tegra30_clk_double_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u64 rate = parent_rate; - - u32 val = clk_readl(c->reg); - c->mul = val & (0x1 << c->reg_shift) ? 1 : 2; - c->div = 1; - - if (c->mul != 0 && c->div != 0) { - rate *= c->mul; - rate += c->div - 1; /* round up */ - do_div(rate, c->div); - } - - return rate; -} - -static long tegra30_clk_double_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - unsigned long output_rate = *prate; - - do_div(output_rate, 2); - return output_rate; -} - -struct clk_ops tegra30_clk_double_ops = { - .is_enabled = tegra30_clk_double_is_enabled, - .enable = tegra30_periph_clk_enable, - .disable = tegra30_periph_clk_disable, - .recalc_rate = tegra30_clk_double_recalc_rate, - .round_rate = tegra30_clk_double_round_rate, - .set_rate = tegra30_clk_double_set_rate, -}; - -/* Audio sync clock ops */ -struct clk_ops tegra_sync_source_ops = { - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -static int tegra30_audio_sync_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - c->state = (val & AUDIO_SYNC_DISABLE_BIT) ? OFF : ON; - return c->state; -} - -static int tegra30_audio_sync_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - clk_writel((val & (~AUDIO_SYNC_DISABLE_BIT)), c->reg); - return 0; -} - -static void tegra30_audio_sync_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - clk_writel((val | AUDIO_SYNC_DISABLE_BIT), c->reg); -} - -static int tegra30_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val; - - val = clk_readl(c->reg); - val &= ~AUDIO_SYNC_SOURCE_MASK; - val |= index; - - clk_writel(val, c->reg); - return 0; -} - -static u8 tegra30_audio_sync_clk_get_parent(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - int source; - - source = val & AUDIO_SYNC_SOURCE_MASK; - return source; -} - -struct clk_ops tegra30_audio_sync_clk_ops = { - .is_enabled = tegra30_audio_sync_clk_is_enabled, - .enable = tegra30_audio_sync_clk_enable, - .disable = tegra30_audio_sync_clk_disable, - .set_parent = tegra30_audio_sync_clk_set_parent, - .get_parent = tegra30_audio_sync_clk_get_parent, - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -/* cml0 (pcie), and cml1 (sata) clock ops */ -static int tegra30_cml_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - u32 val = clk_readl(c->reg); - c->state = val & (0x1 << c->u.periph.clk_num) ? ON : OFF; - return c->state; -} - -static int tegra30_cml_clk_enable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - u32 val = clk_readl(c->reg); - val |= (0x1 << c->u.periph.clk_num); - clk_writel(val, c->reg); - - return 0; -} - -static void tegra30_cml_clk_disable(struct clk_hw *hw) -{ - struct clk_tegra *c = to_clk_tegra(hw); - - u32 val = clk_readl(c->reg); - val &= ~(0x1 << c->u.periph.clk_num); - clk_writel(val, c->reg); -} - -struct clk_ops tegra_cml_clk_ops = { - .is_enabled = tegra30_cml_clk_is_enabled, - .enable = tegra30_cml_clk_enable, - .disable = tegra30_cml_clk_disable, - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -struct clk_ops tegra_pciex_clk_ops = { - .recalc_rate = tegra30_clk_fixed_recalc_rate, -}; - -/* Tegra30 CPU clock and reset control functions */ -static void tegra30_wait_cpu_in_reset(u32 cpu) -{ - unsigned int reg; - - do { - reg = readl(reg_clk_base + - TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); - cpu_relax(); - } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ - - return; -} - -static void tegra30_put_cpu_in_reset(u32 cpu) -{ - writel(CPU_RESET(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); - dmb(); -} - -static void tegra30_cpu_out_of_reset(u32 cpu) -{ - writel(CPU_RESET(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); - wmb(); -} - -static void tegra30_enable_cpu_clock(u32 cpu) -{ - unsigned int reg; - - writel(CPU_CLOCK(cpu), - reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); - reg = readl(reg_clk_base + - TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); -} - -static void tegra30_disable_cpu_clock(u32 cpu) -{ - - unsigned int reg; - - reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); - writel(reg | CPU_CLOCK(cpu), - reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); -} - -#ifdef CONFIG_PM_SLEEP -static bool tegra30_cpu_rail_off_ready(void) -{ - unsigned int cpu_rst_status; - int cpu_pwr_status; - - cpu_rst_status = readl(reg_clk_base + - TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); - cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) || - tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) || - tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3); - - if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status) - return false; - - return true; -} - -static void tegra30_cpu_clock_suspend(void) -{ - /* switch coresite to clk_m, save off original source */ - tegra30_cpu_clk_sctx.clk_csite_src = - readl(reg_clk_base + CLK_RESET_SOURCE_CSITE); - writel(3<<30, reg_clk_base + CLK_RESET_SOURCE_CSITE); - - tegra30_cpu_clk_sctx.cpu_burst = - readl(reg_clk_base + CLK_RESET_CCLK_BURST); - tegra30_cpu_clk_sctx.pllx_base = - readl(reg_clk_base + CLK_RESET_PLLX_BASE); - tegra30_cpu_clk_sctx.pllx_misc = - readl(reg_clk_base + CLK_RESET_PLLX_MISC); - tegra30_cpu_clk_sctx.cclk_divider = - readl(reg_clk_base + CLK_RESET_CCLK_DIVIDER); -} - -static void tegra30_cpu_clock_resume(void) -{ - unsigned int reg, policy; - - /* Is CPU complex already running on PLLX? */ - reg = readl(reg_clk_base + CLK_RESET_CCLK_BURST); - policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF; - - if (policy == CLK_RESET_CCLK_IDLE_POLICY) - reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF; - else if (policy == CLK_RESET_CCLK_RUN_POLICY) - reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF; - else - BUG(); - - if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) { - /* restore PLLX settings if CPU is on different PLL */ - writel(tegra30_cpu_clk_sctx.pllx_misc, - reg_clk_base + CLK_RESET_PLLX_MISC); - writel(tegra30_cpu_clk_sctx.pllx_base, - reg_clk_base + CLK_RESET_PLLX_BASE); - - /* wait for PLL stabilization if PLLX was enabled */ - if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30)) - udelay(300); - } - - /* - * Restore original burst policy setting for calls resulting from CPU - * LP2 in idle or system suspend. - */ - writel(tegra30_cpu_clk_sctx.cclk_divider, - reg_clk_base + CLK_RESET_CCLK_DIVIDER); - writel(tegra30_cpu_clk_sctx.cpu_burst, - reg_clk_base + CLK_RESET_CCLK_BURST); - - writel(tegra30_cpu_clk_sctx.clk_csite_src, - reg_clk_base + CLK_RESET_SOURCE_CSITE); -} -#endif - -static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { - .wait_for_reset = tegra30_wait_cpu_in_reset, - .put_in_reset = tegra30_put_cpu_in_reset, - .out_of_reset = tegra30_cpu_out_of_reset, - .enable_clock = tegra30_enable_cpu_clock, - .disable_clock = tegra30_disable_cpu_clock, -#ifdef CONFIG_PM_SLEEP - .rail_off_ready = tegra30_cpu_rail_off_ready, - .suspend = tegra30_cpu_clock_suspend, - .resume = tegra30_cpu_clock_resume, -#endif -}; - -void __init tegra30_cpu_car_ops_init(void) -{ - tegra_cpu_car_ops = &tegra30_cpu_car_ops; -} diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h deleted file mode 100644 index 7a34adb..0000000 --- a/arch/arm/mach-tegra/tegra30_clocks.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __MACH_TEGRA30_CLOCK_H -#define __MACH_TEGRA30_CLOCK_H - -extern struct clk_ops tegra30_clk_32k_ops; -extern struct clk_ops tegra30_clk_m_ops; -extern struct clk_ops tegra_clk_m_div_ops; -extern struct clk_ops tegra_pll_ref_ops; -extern struct clk_ops tegra30_pll_ops; -extern struct clk_ops tegra30_pll_div_ops; -extern struct clk_ops tegra_plld_ops; -extern struct clk_ops tegra30_plle_ops; -extern struct clk_ops tegra_cml_clk_ops; -extern struct clk_ops tegra_pciex_clk_ops; -extern struct clk_ops tegra_sync_source_ops; -extern struct clk_ops tegra30_audio_sync_clk_ops; -extern struct clk_ops tegra30_clk_double_ops; -extern struct clk_ops tegra_clk_out_ops; -extern struct clk_ops tegra30_super_ops; -extern struct clk_ops tegra30_blink_clk_ops; -extern struct clk_ops tegra30_twd_ops; -extern struct clk_ops tegra30_bus_ops; -extern struct clk_ops tegra30_periph_clk_ops; -extern struct clk_ops tegra30_dsib_clk_ops; -extern struct clk_ops tegra_nand_clk_ops; -extern struct clk_ops tegra_vi_clk_ops; -extern struct clk_ops tegra_dtv_clk_ops; -extern struct clk_ops tegra_clk_shared_bus_ops; - -int tegra30_plld_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting); -void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert); -int tegra30_vi_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting); -int tegra30_nand_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting); -int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw, - enum tegra_clk_ex_param p, u32 setting); -#endif diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c deleted file mode 100644 index 6942c7a..0000000 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * arch/arm/mach-tegra/tegra30_clocks.c - * - * Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include <linux/clk-private.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> - -#include "clock.h" -#include "fuse.h" -#include "tegra30_clocks.h" -#include "tegra_cpu_car.h" - -#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags, \ - _parent_names, _parents, _parent) \ - static struct clk tegra_##_name = { \ - .hw = &tegra_##_name##_hw.hw, \ - .name = #_name, \ - .rate = _rate, \ - .ops = _ops, \ - .flags = _flags, \ - .parent_names = _parent_names, \ - .parents = _parents, \ - .num_parents = ARRAY_SIZE(_parent_names), \ - .parent = _parent, \ - }; - -static struct clk tegra_clk_32k; -static struct clk_tegra tegra_clk_32k_hw = { - .hw = { - .clk = &tegra_clk_32k, - }, - .fixed_rate = 32768, -}; -static struct clk tegra_clk_32k = { - .name = "clk_32k", - .hw = &tegra_clk_32k_hw.hw, - .ops = &tegra30_clk_32k_ops, - .flags = CLK_IS_ROOT, -}; - -static struct clk tegra_clk_m; -static struct clk_tegra tegra_clk_m_hw = { - .hw = { - .clk = &tegra_clk_m, - }, - .flags = ENABLE_ON_INIT, - .reg = 0x1fc, - .reg_shift = 28, - .max_rate = 48000000, -}; -static struct clk tegra_clk_m = { - .name = "clk_m", - .hw = &tegra_clk_m_hw.hw, - .ops = &tegra30_clk_m_ops, - .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, -}; - -static const char *clk_m_div_parent_names[] = { - "clk_m", -}; - -static struct clk *clk_m_div_parents[] = { - &tegra_clk_m, -}; - -static struct clk tegra_clk_m_div2; -static struct clk_tegra tegra_clk_m_div2_hw = { - .hw = { - .clk = &tegra_clk_m_div2, - }, - .mul = 1, - .div = 2, - .max_rate = 24000000, -}; -DEFINE_CLK_TEGRA(clk_m_div2, 0, &tegra_clk_m_div_ops, 0, - clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m); - -static struct clk tegra_clk_m_div4; -static struct clk_tegra tegra_clk_m_div4_hw = { - .hw = { - .clk = &tegra_clk_m_div4, - }, - .mul = 1, - .div = 4, - .max_rate = 12000000, -}; -DEFINE_CLK_TEGRA(clk_m_div4, 0, &tegra_clk_m_div_ops, 0, - clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m); - -static struct clk tegra_pll_ref; -static struct clk_tegra tegra_pll_ref_hw = { - .hw = { - .clk = &tegra_pll_ref, - }, - .flags = ENABLE_ON_INIT, - .max_rate = 26000000, -}; -DEFINE_CLK_TEGRA(pll_ref, 0, &tegra_pll_ref_ops, 0, clk_m_div_parent_names, - clk_m_div_parents, &tegra_clk_m); - -#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min, \ - _input_max, _cf_min, _cf_max, _vco_min, \ - _vco_max, _freq_table, _lock_delay, _ops, \ - _fixed_rate, _clk_cfg_ex, _parent) \ - static struct clk tegra_##_name; \ - static const char *_name##_parent_names[] = { \ - #_parent, \ - }; \ - static struct clk *_name##_parents[] = { \ - &tegra_##_parent, \ - }; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .flags = _flags, \ - .reg = _reg, \ - .max_rate = _max_rate, \ - .u.pll = { \ - .input_min = _input_min, \ - .input_max = _input_max, \ - .cf_min = _cf_min, \ - .cf_max = _cf_max, \ - .vco_min = _vco_min, \ - .vco_max = _vco_max, \ - .freq_table = _freq_table, \ - .lock_delay = _lock_delay, \ - .fixed_rate = _fixed_rate, \ - }, \ - .clk_cfg_ex = _clk_cfg_ex, \ - }; \ - DEFINE_CLK_TEGRA(_name, 0, &_ops, CLK_IGNORE_UNUSED, \ - _name##_parent_names, _name##_parents, \ - &tegra_##_parent); - -#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift, \ - _max_rate, _ops, _parent, _clk_flags) \ - static const char *_name##_parent_names[] = { \ - #_parent, \ - }; \ - static struct clk *_name##_parents[] = { \ - &tegra_##_parent, \ - }; \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .flags = _flags, \ - .reg = _reg, \ - .max_rate = _max_rate, \ - .reg_shift = _reg_shift, \ - }; \ - DEFINE_CLK_TEGRA(_name, 0, &tegra30_pll_div_ops, \ - _clk_flags, _name##_parent_names, \ - _name##_parents, &tegra_##_parent); - -static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { - { 12000000, 1040000000, 520, 6, 1, 8}, - { 13000000, 1040000000, 480, 6, 1, 8}, - { 16800000, 1040000000, 495, 8, 1, 8}, /* actual: 1039.5 MHz */ - { 19200000, 1040000000, 325, 6, 1, 6}, - { 26000000, 1040000000, 520, 13, 1, 8}, - - { 12000000, 832000000, 416, 6, 1, 8}, - { 13000000, 832000000, 832, 13, 1, 8}, - { 16800000, 832000000, 396, 8, 1, 8}, /* actual: 831.6 MHz */ - { 19200000, 832000000, 260, 6, 1, 8}, - { 26000000, 832000000, 416, 13, 1, 8}, - - { 12000000, 624000000, 624, 12, 1, 8}, - { 13000000, 624000000, 624, 13, 1, 8}, - { 16800000, 600000000, 520, 14, 1, 8}, - { 19200000, 624000000, 520, 16, 1, 8}, - { 26000000, 624000000, 624, 26, 1, 8}, - - { 12000000, 600000000, 600, 12, 1, 8}, - { 13000000, 600000000, 600, 13, 1, 8}, - { 16800000, 600000000, 500, 14, 1, 8}, - { 19200000, 600000000, 375, 12, 1, 6}, - { 26000000, 600000000, 600, 26, 1, 8}, - - { 12000000, 520000000, 520, 12, 1, 8}, - { 13000000, 520000000, 520, 13, 1, 8}, - { 16800000, 520000000, 495, 16, 1, 8}, /* actual: 519.75 MHz */ - { 19200000, 520000000, 325, 12, 1, 6}, - { 26000000, 520000000, 520, 26, 1, 8}, - - { 12000000, 416000000, 416, 12, 1, 8}, - { 13000000, 416000000, 416, 13, 1, 8}, - { 16800000, 416000000, 396, 16, 1, 8}, /* actual: 415.8 MHz */ - { 19200000, 416000000, 260, 12, 1, 6}, - { 26000000, 416000000, 416, 26, 1, 8}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 1400000000, 2000000, 31000000, 1000000, - 6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300, - tegra30_pll_ops, 0, NULL, pll_ref); - -DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 700000000, - tegra30_pll_div_ops, pll_c, CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_m_freq_table[] = { - { 12000000, 666000000, 666, 12, 1, 8}, - { 13000000, 666000000, 666, 13, 1, 8}, - { 16800000, 666000000, 555, 14, 1, 8}, - { 19200000, 666000000, 555, 16, 1, 8}, - { 26000000, 666000000, 666, 26, 1, 8}, - { 12000000, 600000000, 600, 12, 1, 8}, - { 13000000, 600000000, 600, 13, 1, 8}, - { 16800000, 600000000, 500, 14, 1, 8}, - { 19200000, 600000000, 375, 12, 1, 6}, - { 26000000, 600000000, 600, 26, 1, 8}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_m, PLL_HAS_CPCON | PLLM, 0x90, 800000000, 2000000, 31000000, - 1000000, 6000000, 20000000, 1200000000, tegra_pll_m_freq_table, - 300, tegra30_pll_ops, 0, NULL, pll_ref); - -DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000, - tegra30_pll_div_ops, pll_m, CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_p_freq_table[] = { - { 12000000, 216000000, 432, 12, 2, 8}, - { 13000000, 216000000, 432, 13, 2, 8}, - { 16800000, 216000000, 360, 14, 2, 8}, - { 19200000, 216000000, 360, 16, 2, 8}, - { 26000000, 216000000, 432, 26, 2, 8}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000, - 2000000, 31000000, 1000000, 6000000, 20000000, 1400000000, - tegra_pll_p_freq_table, 300, tegra30_pll_ops, 408000000, NULL, - pll_ref); - -DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, - 0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED); -DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, - 16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED); -DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, - 0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED); -DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, - 16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_a_freq_table[] = { - { 9600000, 564480000, 294, 5, 1, 4}, - { 9600000, 552960000, 288, 5, 1, 4}, - { 9600000, 24000000, 5, 2, 1, 1}, - - { 28800000, 56448000, 49, 25, 1, 1}, - { 28800000, 73728000, 64, 25, 1, 1}, - { 28800000, 24000000, 5, 6, 1, 1}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 700000000, 2000000, 31000000, 1000000, - 6000000, 20000000, 1400000000, tegra_pll_a_freq_table, - 300, tegra30_pll_ops, 0, NULL, pll_p_out1); - -DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 100000000, tegra30_pll_div_ops, - pll_a, CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_d_freq_table[] = { - { 12000000, 216000000, 216, 12, 1, 4}, - { 13000000, 216000000, 216, 13, 1, 4}, - { 16800000, 216000000, 180, 14, 1, 4}, - { 19200000, 216000000, 180, 16, 1, 4}, - { 26000000, 216000000, 216, 26, 1, 4}, - - { 12000000, 594000000, 594, 12, 1, 8}, - { 13000000, 594000000, 594, 13, 1, 8}, - { 16800000, 594000000, 495, 14, 1, 8}, - { 19200000, 594000000, 495, 16, 1, 8}, - { 26000000, 594000000, 594, 26, 1, 8}, - - { 12000000, 1000000000, 1000, 12, 1, 12}, - { 13000000, 1000000000, 1000, 13, 1, 12}, - { 19200000, 1000000000, 625, 12, 1, 8}, - { 26000000, 1000000000, 1000, 26, 1, 12}, - - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000, - 1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table, - 1000, tegra30_pll_ops, 0, tegra30_plld_clk_cfg_ex, pll_ref); - -DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops, - pll_d, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); - -DEFINE_PLL(pll_d2, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD, 0x4b8, 1000000000, - 2000000, 40000000, 1000000, 6000000, 40000000, 1000000000, - tegra_pll_d_freq_table, 1000, tegra30_pll_ops, 0, NULL, - pll_ref); - -DEFINE_PLL_OUT(pll_d2_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops, - pll_d2, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_u_freq_table[] = { - { 12000000, 480000000, 960, 12, 2, 12}, - { 13000000, 480000000, 960, 13, 2, 12}, - { 16800000, 480000000, 400, 7, 2, 5}, - { 19200000, 480000000, 200, 4, 2, 3}, - { 26000000, 480000000, 960, 26, 2, 12}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_u, PLL_HAS_CPCON | PLLU, 0xc0, 480000000, 2000000, 40000000, - 1000000, 6000000, 48000000, 960000000, tegra_pll_u_freq_table, - 1000, tegra30_pll_ops, 0, NULL, pll_ref); - -static struct clk_pll_freq_table tegra_pll_x_freq_table[] = { - /* 1.7 GHz */ - { 12000000, 1700000000, 850, 6, 1, 8}, - { 13000000, 1700000000, 915, 7, 1, 8}, /* actual: 1699.2 MHz */ - { 16800000, 1700000000, 708, 7, 1, 8}, /* actual: 1699.2 MHz */ - { 19200000, 1700000000, 885, 10, 1, 8}, /* actual: 1699.2 MHz */ - { 26000000, 1700000000, 850, 13, 1, 8}, - - /* 1.6 GHz */ - { 12000000, 1600000000, 800, 6, 1, 8}, - { 13000000, 1600000000, 738, 6, 1, 8}, /* actual: 1599.0 MHz */ - { 16800000, 1600000000, 857, 9, 1, 8}, /* actual: 1599.7 MHz */ - { 19200000, 1600000000, 500, 6, 1, 8}, - { 26000000, 1600000000, 800, 13, 1, 8}, - - /* 1.5 GHz */ - { 12000000, 1500000000, 750, 6, 1, 8}, - { 13000000, 1500000000, 923, 8, 1, 8}, /* actual: 1499.8 MHz */ - { 16800000, 1500000000, 625, 7, 1, 8}, - { 19200000, 1500000000, 625, 8, 1, 8}, - { 26000000, 1500000000, 750, 13, 1, 8}, - - /* 1.4 GHz */ - { 12000000, 1400000000, 700, 6, 1, 8}, - { 13000000, 1400000000, 969, 9, 1, 8}, /* actual: 1399.7 MHz */ - { 16800000, 1400000000, 1000, 12, 1, 8}, - { 19200000, 1400000000, 875, 12, 1, 8}, - { 26000000, 1400000000, 700, 13, 1, 8}, - - /* 1.3 GHz */ - { 12000000, 1300000000, 975, 9, 1, 8}, - { 13000000, 1300000000, 1000, 10, 1, 8}, - { 16800000, 1300000000, 928, 12, 1, 8}, /* actual: 1299.2 MHz */ - { 19200000, 1300000000, 812, 12, 1, 8}, /* actual: 1299.2 MHz */ - { 26000000, 1300000000, 650, 13, 1, 8}, - - /* 1.2 GHz */ - { 12000000, 1200000000, 1000, 10, 1, 8}, - { 13000000, 1200000000, 923, 10, 1, 8}, /* actual: 1199.9 MHz */ - { 16800000, 1200000000, 1000, 14, 1, 8}, - { 19200000, 1200000000, 1000, 16, 1, 8}, - { 26000000, 1200000000, 600, 13, 1, 8}, - - /* 1.1 GHz */ - { 12000000, 1100000000, 825, 9, 1, 8}, - { 13000000, 1100000000, 846, 10, 1, 8}, /* actual: 1099.8 MHz */ - { 16800000, 1100000000, 982, 15, 1, 8}, /* actual: 1099.8 MHz */ - { 19200000, 1100000000, 859, 15, 1, 8}, /* actual: 1099.5 MHz */ - { 26000000, 1100000000, 550, 13, 1, 8}, - - /* 1 GHz */ - { 12000000, 1000000000, 1000, 12, 1, 8}, - { 13000000, 1000000000, 1000, 13, 1, 8}, - { 16800000, 1000000000, 833, 14, 1, 8}, /* actual: 999.6 MHz */ - { 19200000, 1000000000, 625, 12, 1, 8}, - { 26000000, 1000000000, 1000, 26, 1, 8}, - - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX, 0xe0, 1700000000, - 2000000, 31000000, 1000000, 6000000, 20000000, 1700000000, - tegra_pll_x_freq_table, 300, tegra30_pll_ops, 0, NULL, pll_ref); - -DEFINE_PLL_OUT(pll_x_out0, DIV_2 | PLLX, 0, 0, 850000000, tegra30_pll_div_ops, - pll_x, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); - -static struct clk_pll_freq_table tegra_pll_e_freq_table[] = { - /* PLLE special case: use cpcon field to store cml divider value */ - { 12000000, 100000000, 150, 1, 18, 11}, - { 216000000, 100000000, 200, 18, 24, 13}, - { 0, 0, 0, 0, 0, 0 }, -}; - -DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 2000000, 216000000, - 12000000, 12000000, 1200000000, 2400000000U, - tegra_pll_e_freq_table, 300, tegra30_plle_ops, 100000000, NULL, - pll_ref); - -static const char *mux_plle[] = { - "pll_e", -}; - -static struct clk *mux_plle_p[] = { - &tegra_pll_e, -}; - -static struct clk tegra_cml0; -static struct clk_tegra tegra_cml0_hw = { - .hw = { - .clk = &tegra_cml0, - }, - .reg = 0x48c, - .fixed_rate = 100000000, - .u.periph = { - .clk_num = 0, - }, -}; -DEFINE_CLK_TEGRA(cml0, 0, &tegra_cml_clk_ops, 0, mux_plle, - mux_plle_p, &tegra_pll_e); - -static struct clk tegra_cml1; -static struct clk_tegra tegra_cml1_hw = { - .hw = { - .clk = &tegra_cml1, - }, - .reg = 0x48c, - .fixed_rate = 100000000, - .u.periph = { - .clk_num = 1, - }, -}; -DEFINE_CLK_TEGRA(cml1, 0, &tegra_cml_clk_ops, 0, mux_plle, - mux_plle_p, &tegra_pll_e); - -static struct clk tegra_pciex; -static struct clk_tegra tegra_pciex_hw = { - .hw = { - .clk = &tegra_pciex, - }, - .reg = 0x48c, - .fixed_rate = 100000000, - .reset = tegra30_periph_clk_reset, - .u.periph = { - .clk_num = 74, - }, -}; -DEFINE_CLK_TEGRA(pciex, 0, &tegra_pciex_clk_ops, 0, mux_plle, - mux_plle_p, &tegra_pll_e); - -#define SYNC_SOURCE(_name) \ - static struct clk tegra_##_name##_sync; \ - static struct clk_tegra tegra_##_name##_sync_hw = { \ - .hw = { \ - .clk = &tegra_##_name##_sync, \ - }, \ - .max_rate = 24000000, \ - .fixed_rate = 24000000, \ - }; \ - static struct clk tegra_##_name##_sync = { \ - .name = #_name "_sync", \ - .hw = &tegra_##_name##_sync_hw.hw, \ - .ops = &tegra_sync_source_ops, \ - .flags = CLK_IS_ROOT, \ - }; - -SYNC_SOURCE(spdif_in); -SYNC_SOURCE(i2s0); -SYNC_SOURCE(i2s1); -SYNC_SOURCE(i2s2); -SYNC_SOURCE(i2s3); -SYNC_SOURCE(i2s4); -SYNC_SOURCE(vimclk); - -static struct clk *tegra_sync_source_list[] = { - &tegra_spdif_in_sync, - &tegra_i2s0_sync, - &tegra_i2s1_sync, - &tegra_i2s2_sync, - &tegra_i2s3_sync, - &tegra_i2s4_sync, - &tegra_vimclk_sync, -}; - -static const char *mux_audio_sync_clk[] = { - "spdif_in_sync", - "i2s0_sync", - "i2s1_sync", - "i2s2_sync", - "i2s3_sync", - "i2s4_sync", - "vimclk_sync", -}; - -#define AUDIO_SYNC_CLK(_name, _index) \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .max_rate = 24000000, \ - .reg = 0x4A0 + (_index) * 4, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &tegra30_audio_sync_clk_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent_names = mux_audio_sync_clk, \ - .parents = tegra_sync_source_list, \ - .num_parents = ARRAY_SIZE(mux_audio_sync_clk), \ - }; - -AUDIO_SYNC_CLK(audio0, 0); -AUDIO_SYNC_CLK(audio1, 1); -AUDIO_SYNC_CLK(audio2, 2); -AUDIO_SYNC_CLK(audio3, 3); -AUDIO_SYNC_CLK(audio4, 4); -AUDIO_SYNC_CLK(audio5, 5); - -static struct clk *tegra_clk_audio_list[] = { - &tegra_audio0, - &tegra_audio1, - &tegra_audio2, - &tegra_audio3, - &tegra_audio4, - &tegra_audio5, /* SPDIF */ -}; - -#define AUDIO_SYNC_2X_CLK(_name, _index) \ - static const char *_name##_parent_names[] = { \ - "tegra_" #_name, \ - }; \ - static struct clk *_name##_parents[] = { \ - &tegra_##_name, \ - }; \ - static struct clk tegra_##_name##_2x; \ - static struct clk_tegra tegra_##_name##_2x_hw = { \ - .hw = { \ - .clk = &tegra_##_name##_2x, \ - }, \ - .flags = PERIPH_NO_RESET, \ - .max_rate = 48000000, \ - .reg = 0x49C, \ - .reg_shift = 24 + (_index), \ - .u.periph = { \ - .clk_num = 113 + (_index), \ - }, \ - }; \ - static struct clk tegra_##_name##_2x = { \ - .name = #_name "_2x", \ - .ops = &tegra30_clk_double_ops, \ - .hw = &tegra_##_name##_2x_hw.hw, \ - .parent_names = _name##_parent_names, \ - .parents = _name##_parents, \ - .parent = &tegra_##_name, \ - .num_parents = 1, \ - }; - -AUDIO_SYNC_2X_CLK(audio0, 0); -AUDIO_SYNC_2X_CLK(audio1, 1); -AUDIO_SYNC_2X_CLK(audio2, 2); -AUDIO_SYNC_2X_CLK(audio3, 3); -AUDIO_SYNC_2X_CLK(audio4, 4); -AUDIO_SYNC_2X_CLK(audio5, 5); /* SPDIF */ - -static struct clk *tegra_clk_audio_2x_list[] = { - &tegra_audio0_2x, - &tegra_audio1_2x, - &tegra_audio2_2x, - &tegra_audio3_2x, - &tegra_audio4_2x, - &tegra_audio5_2x, /* SPDIF */ -}; - -#define MUX_I2S_SPDIF(_id) \ -static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { \ - "pll_a_out0", \ - #_id "_2x", \ - "pll_p", \ - "clk_m", \ -}; \ -static struct clk *mux_pllaout0_##_id##_2x_pllp_clkm_p[] = { \ - &tegra_pll_a_out0, \ - &tegra_##_id##_2x, \ - &tegra_pll_p, \ - &tegra_clk_m, \ -}; - -MUX_I2S_SPDIF(audio0); -MUX_I2S_SPDIF(audio1); -MUX_I2S_SPDIF(audio2); -MUX_I2S_SPDIF(audio3); -MUX_I2S_SPDIF(audio4); -MUX_I2S_SPDIF(audio5); /* SPDIF */ - -static struct clk tegra_extern1; -static struct clk tegra_extern2; -static struct clk tegra_extern3; - -/* External clock outputs (through PMC) */ -#define MUX_EXTERN_OUT(_id) \ -static const char *mux_clkm_clkm2_clkm4_extern##_id[] = { \ - "clk_m", \ - "clk_m_div2", \ - "clk_m_div4", \ - "extern" #_id, \ -}; \ -static struct clk *mux_clkm_clkm2_clkm4_extern##_id##_p[] = { \ - &tegra_clk_m, \ - &tegra_clk_m_div2, \ - &tegra_clk_m_div4, \ - &tegra_extern##_id, \ -}; - -MUX_EXTERN_OUT(1); -MUX_EXTERN_OUT(2); -MUX_EXTERN_OUT(3); - -#define CLK_OUT_CLK(_name, _index) \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .lookup = { \ - .dev_id = #_name, \ - .con_id = "extern" #_index, \ - }, \ - .flags = MUX_CLK_OUT, \ - .fixed_rate = 216000000, \ - .reg = 0x1a8, \ - .u.periph = { \ - .clk_num = (_index - 1) * 8 + 2, \ - }, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &tegra_clk_out_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent_names = mux_clkm_clkm2_clkm4_extern##_index, \ - .parents = mux_clkm_clkm2_clkm4_extern##_index##_p, \ - .num_parents = ARRAY_SIZE(mux_clkm_clkm2_clkm4_extern##_index),\ - }; - -CLK_OUT_CLK(clk_out_1, 1); -CLK_OUT_CLK(clk_out_2, 2); -CLK_OUT_CLK(clk_out_3, 3); - -static struct clk *tegra_clk_out_list[] = { - &tegra_clk_out_1, - &tegra_clk_out_2, - &tegra_clk_out_3, -}; - -static const char *mux_sclk[] = { - "clk_m", - "pll_c_out1", - "pll_p_out4", - "pll_p_out3", - "pll_p_out2", - "dummy", - "clk_32k", - "pll_m_out1", -}; - -static struct clk *mux_sclk_p[] = { - &tegra_clk_m, - &tegra_pll_c_out1, - &tegra_pll_p_out4, - &tegra_pll_p_out3, - &tegra_pll_p_out2, - NULL, - &tegra_clk_32k, - &tegra_pll_m_out1, -}; - -static struct clk tegra_clk_sclk; -static struct clk_tegra tegra_clk_sclk_hw = { - .hw = { - .clk = &tegra_clk_sclk, - }, - .reg = 0x28, - .max_rate = 334000000, - .min_rate = 40000000, -}; - -static struct clk tegra_clk_sclk = { - .name = "sclk", - .ops = &tegra30_super_ops, - .hw = &tegra_clk_sclk_hw.hw, - .parent_names = mux_sclk, - .parents = mux_sclk_p, - .num_parents = ARRAY_SIZE(mux_sclk), -}; - -static const char *tegra_hclk_parent_names[] = { - "tegra_sclk", -}; - -static struct clk *tegra_hclk_parents[] = { - &tegra_clk_sclk, -}; - -static struct clk tegra_hclk; -static struct clk_tegra tegra_hclk_hw = { - .hw = { - .clk = &tegra_hclk, - }, - .flags = DIV_BUS, - .reg = 0x30, - .reg_shift = 4, - .max_rate = 378000000, - .min_rate = 12000000, -}; -DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names, - tegra_hclk_parents, &tegra_clk_sclk); - -static const char *tegra_pclk_parent_names[] = { - "tegra_hclk", -}; - -static struct clk *tegra_pclk_parents[] = { - &tegra_hclk, -}; - -static struct clk tegra_pclk; -static struct clk_tegra tegra_pclk_hw = { - .hw = { - .clk = &tegra_pclk, - }, - .flags = DIV_BUS, - .reg = 0x30, - .reg_shift = 0, - .max_rate = 167000000, - .min_rate = 12000000, -}; -DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names, - tegra_pclk_parents, &tegra_hclk); - -static const char *mux_blink[] = { - "clk_32k", -}; - -static struct clk *mux_blink_p[] = { - &tegra_clk_32k, -}; - -static struct clk tegra_clk_blink; -static struct clk_tegra tegra_clk_blink_hw = { - .hw = { - .clk = &tegra_clk_blink, - }, - .reg = 0x40, - .max_rate = 32768, -}; -static struct clk tegra_clk_blink = { - .name = "blink", - .ops = &tegra30_blink_clk_ops, - .hw = &tegra_clk_blink_hw.hw, - .parent = &tegra_clk_32k, - .parent_names = mux_blink, - .parents = mux_blink_p, - .num_parents = ARRAY_SIZE(mux_blink), -}; - -static const char *mux_pllm_pllc_pllp_plla[] = { - "pll_m", - "pll_c", - "pll_p", - "pll_a_out0", -}; - -static const char *mux_pllp_pllc_pllm_clkm[] = { - "pll_p", - "pll_c", - "pll_m", - "clk_m", -}; - -static const char *mux_pllp_clkm[] = { - "pll_p", - "dummy", - "dummy", - "clk_m", -}; - -static const char *mux_pllp_plld_pllc_clkm[] = { - "pll_p", - "pll_d_out0", - "pll_c", - "clk_m", -}; - -static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = { - "pll_p", - "pll_m", - "pll_d_out0", - "pll_a_out0", - "pll_c", - "pll_d2_out0", - "clk_m", -}; - -static const char *mux_plla_pllc_pllp_clkm[] = { - "pll_a_out0", - "dummy", - "pll_p", - "clk_m" -}; - -static const char *mux_pllp_pllc_clk32_clkm[] = { - "pll_p", - "pll_c", - "clk_32k", - "clk_m", -}; - -static const char *mux_pllp_pllc_clkm_clk32[] = { - "pll_p", - "pll_c", - "clk_m", - "clk_32k", -}; - -static const char *mux_pllp_pllc_pllm[] = { - "pll_p", - "pll_c", - "pll_m", -}; - -static const char *mux_clk_m[] = { - "clk_m", -}; - -static const char *mux_pllp_out3[] = { - "pll_p_out3", -}; - -static const char *mux_plld_out0[] = { - "pll_d_out0", -}; - -static const char *mux_plld_out0_plld2_out0[] = { - "pll_d_out0", - "pll_d2_out0", -}; - -static const char *mux_clk_32k[] = { - "clk_32k", -}; - -static const char *mux_plla_clk32_pllp_clkm_plle[] = { - "pll_a_out0", - "clk_32k", - "pll_p", - "clk_m", - "pll_e", -}; - -static const char *mux_cclk_g[] = { - "clk_m", - "pll_c", - "clk_32k", - "pll_m", - "pll_p", - "pll_p_out4", - "pll_p_out3", - "dummy", - "pll_x", -}; - -static struct clk *mux_pllm_pllc_pllp_plla_p[] = { - &tegra_pll_m, - &tegra_pll_c, - &tegra_pll_p, - &tegra_pll_a_out0, -}; - -static struct clk *mux_pllp_pllc_pllm_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_pll_m, - &tegra_clk_m, -}; - -static struct clk *mux_pllp_clkm_p[] = { - &tegra_pll_p, - NULL, - NULL, - &tegra_clk_m, -}; - -static struct clk *mux_pllp_plld_pllc_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_d_out0, - &tegra_pll_c, - &tegra_clk_m, -}; - -static struct clk *mux_pllp_pllm_plld_plla_pllc_plld2_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_m, - &tegra_pll_d_out0, - &tegra_pll_a_out0, - &tegra_pll_c, - &tegra_pll_d2_out0, - &tegra_clk_m, -}; - -static struct clk *mux_plla_pllc_pllp_clkm_p[] = { - &tegra_pll_a_out0, - NULL, - &tegra_pll_p, - &tegra_clk_m, -}; - -static struct clk *mux_pllp_pllc_clk32_clkm_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_clk_32k, - &tegra_clk_m, -}; - -static struct clk *mux_pllp_pllc_clkm_clk32_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_clk_m, - &tegra_clk_32k, -}; - -static struct clk *mux_pllp_pllc_pllm_p[] = { - &tegra_pll_p, - &tegra_pll_c, - &tegra_pll_m, -}; - -static struct clk *mux_clk_m_p[] = { - &tegra_clk_m, -}; - -static struct clk *mux_pllp_out3_p[] = { - &tegra_pll_p_out3, -}; - -static struct clk *mux_plld_out0_p[] = { - &tegra_pll_d_out0, -}; - -static struct clk *mux_plld_out0_plld2_out0_p[] = { - &tegra_pll_d_out0, - &tegra_pll_d2_out0, -}; - -static struct clk *mux_clk_32k_p[] = { - &tegra_clk_32k, -}; - -static struct clk *mux_plla_clk32_pllp_clkm_plle_p[] = { - &tegra_pll_a_out0, - &tegra_clk_32k, - &tegra_pll_p, - &tegra_clk_m, - &tegra_pll_e, -}; - -static struct clk *mux_cclk_g_p[] = { - &tegra_clk_m, - &tegra_pll_c, - &tegra_clk_32k, - &tegra_pll_m, - &tegra_pll_p, - &tegra_pll_p_out4, - &tegra_pll_p_out3, - NULL, - &tegra_pll_x, -}; - -static struct clk tegra_clk_cclk_g; -static struct clk_tegra tegra_clk_cclk_g_hw = { - .hw = { - .clk = &tegra_clk_cclk_g, - }, - .flags = DIV_U71 | DIV_U71_INT, - .reg = 0x368, - .max_rate = 1700000000, -}; -static struct clk tegra_clk_cclk_g = { - .name = "cclk_g", - .ops = &tegra30_super_ops, - .hw = &tegra_clk_cclk_g_hw.hw, - .parent_names = mux_cclk_g, - .parents = mux_cclk_g_p, - .num_parents = ARRAY_SIZE(mux_cclk_g), -}; - -static const char *mux_twd[] = { - "cclk_g", -}; - -static struct clk *mux_twd_p[] = { - &tegra_clk_cclk_g, -}; - -static struct clk tegra30_clk_twd; -static struct clk_tegra tegra30_clk_twd_hw = { - .hw = { - .clk = &tegra30_clk_twd, - }, - .max_rate = 1400000000, - .mul = 1, - .div = 2, -}; - -static struct clk tegra30_clk_twd = { - .name = "twd", - .ops = &tegra30_twd_ops, - .hw = &tegra30_clk_twd_hw.hw, - .parent = &tegra_clk_cclk_g, - .parent_names = mux_twd, - .parents = mux_twd_p, - .num_parents = ARRAY_SIZE(mux_twd), -}; - -#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, \ - _max, _inputs, _flags) \ - static struct clk tegra_##_name; \ - static struct clk_tegra tegra_##_name##_hw = { \ - .hw = { \ - .clk = &tegra_##_name, \ - }, \ - .lookup = { \ - .dev_id = _dev, \ - .con_id = _con, \ - }, \ - .reg = _reg, \ - .flags = _flags, \ - .max_rate = _max, \ - .u.periph = { \ - .clk_num = _clk_num, \ - }, \ - .reset = &tegra30_periph_clk_reset, \ - }; \ - static struct clk tegra_##_name = { \ - .name = #_name, \ - .ops = &tegra30_periph_clk_ops, \ - .hw = &tegra_##_name##_hw.hw, \ - .parent_names = _inputs, \ - .parents = _inputs##_p, \ - .num_parents = ARRAY_SIZE(_inputs), \ - }; - -PERIPH_CLK(apbdma, "tegra-apbdma", NULL, 34, 0, 26000000, mux_clk_m, 0); -PERIPH_CLK(rtc, "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB); -PERIPH_CLK(kbc, "tegra-kbc", NULL, 36, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB); -PERIPH_CLK(timer, "timer", NULL, 5, 0, 26000000, mux_clk_m, 0); -PERIPH_CLK(kfuse, "kfuse-tegra", NULL, 40, 0, 26000000, mux_clk_m, 0); -PERIPH_CLK(fuse, "fuse-tegra", "fuse", 39, 0, 26000000, mux_clk_m, PERIPH_ON_APB); -PERIPH_CLK(fuse_burn, "fuse-tegra", "fuse_burn", 39, 0, 26000000, mux_clk_m, PERIPH_ON_APB); -PERIPH_CLK(apbif, "tegra30-ahub", "apbif", 107, 0, 26000000, mux_clk_m, 0); -PERIPH_CLK(i2s0, "tegra30-i2s.0", NULL, 30, 0x1d8, 26000000, mux_pllaout0_audio0_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(i2s1, "tegra30-i2s.1", NULL, 11, 0x100, 26000000, mux_pllaout0_audio1_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(i2s2, "tegra30-i2s.2", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(i2s3, "tegra30-i2s.3", NULL, 101, 0x3bc, 26000000, mux_pllaout0_audio3_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(i2s4, "tegra30-i2s.4", NULL, 102, 0x3c0, 26000000, mux_pllaout0_audio4_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(spdif_out, "tegra30-spdif", "spdif_out", 10, 0x108, 100000000, mux_pllaout0_audio5_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(spdif_in, "tegra30-spdif", "spdif_in", 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(pwm, "tegra-pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_clk32_clkm, MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(d_audio, "tegra30-ahub", "d_audio", 106, 0x3d0, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(dam0, "tegra30-dam.0", NULL, 108, 0x3d8, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(dam1, "tegra30-dam.1", NULL, 109, 0x3dc, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(dam2, "tegra30-dam.2", NULL, 110, 0x3e0, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71); -PERIPH_CLK(hda, "tegra30-hda", "hda", 125, 0x428, 108000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(hda2codec_2x, "tegra30-hda", "hda2codec", 111, 0x3e4, 48000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(hda2hdmi, "tegra30-hda", "hda2hdmi", 128, 0, 48000000, mux_clk_m, 0); -PERIPH_CLK(sbc1, "spi_tegra.0", NULL, 41, 0x134, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sbc2, "spi_tegra.1", NULL, 44, 0x118, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sbc3, "spi_tegra.2", NULL, 46, 0x11c, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sbc4, "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sbc5, "spi_tegra.4", NULL, 104, 0x3c8, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sbc6, "spi_tegra.5", NULL, 105, 0x3cc, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sata_oob, "tegra_sata_oob", NULL, 123, 0x420, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sata, "tegra_sata", NULL, 124, 0x424, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(sata_cold, "tegra_sata_cold", NULL, 129, 0, 48000000, mux_clk_m, 0); -PERIPH_CLK(ndflash, "tegra_nand", NULL, 13, 0x160, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(ndspeed, "tegra_nand_speed", NULL, 80, 0x3f8, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(vfir, "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(sdmmc1, "sdhci-tegra.0", NULL, 14, 0x150, 208000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc2, "sdhci-tegra.1", NULL, 9, 0x154, 104000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc3, "sdhci-tegra.2", NULL, 69, 0x1bc, 208000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(sdmmc4, "sdhci-tegra.3", NULL, 15, 0x164, 104000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(vcp, "tegra-avp", "vcp", 29, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(bsea, "tegra-avp", "bsea", 62, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(bsev, "tegra-aes", "bsev", 63, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(vde, "vde", NULL, 61, 0x1c8, 520000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_INT); -PERIPH_CLK(csite, "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* max rate ??? */ -PERIPH_CLK(la, "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); -PERIPH_CLK(owr, "tegra_w1", NULL, 71, 0x1cc, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(nor, "nor", NULL, 42, 0x1d0, 127000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(mipi, "mipi", NULL, 50, 0x174, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); /* scales with voltage */ -PERIPH_CLK(i2c1, "tegra-i2c.0", "div-clk", 12, 0x124, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c2, "tegra-i2c.1", "div-clk", 54, 0x198, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c3, "tegra-i2c.2", "div-clk", 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c4, "tegra-i2c.3", "div-clk", 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c5, "tegra-i2c.4", "div-clk", 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(uarta, "tegra-uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartb, "tegra-uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartc, "tegra-uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartd, "tegra-uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uarte, "tegra-uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(vi, "tegra_camera", "vi", 20, 0x148, 425000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT); -PERIPH_CLK(3d, "3d", NULL, 24, 0x158, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET); -PERIPH_CLK(3d2, "3d2", NULL, 98, 0x3b0, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET); -PERIPH_CLK(2d, "2d", NULL, 21, 0x15c, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE); -PERIPH_CLK(vi_sensor, "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET); -PERIPH_CLK(epp, "epp", NULL, 19, 0x16c, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT); -PERIPH_CLK(mpe, "mpe", NULL, 60, 0x170, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT); -PERIPH_CLK(host1x, "host1x", NULL, 28, 0x180, 260000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT); -PERIPH_CLK(cve, "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(tvo, "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(dtv, "dtv", NULL, 79, 0x1dc, 250000000, mux_clk_m, 0); -PERIPH_CLK(hdmi, "hdmi", NULL, 51, 0x18c, 148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8 | DIV_U71); -PERIPH_CLK(tvdac, "tvdac", NULL, 53, 0x194, 220000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71); /* requires min voltage */ -PERIPH_CLK(disp1, "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8); -PERIPH_CLK(disp2, "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8); -PERIPH_CLK(usbd, "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(usb2, "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(usb3, "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0); /* requires min voltage */ -PERIPH_CLK(dsia, "tegradc.0", "dsia", 48, 0, 500000000, mux_plld_out0, 0); -PERIPH_CLK(csi, "tegra_camera", "csi", 52, 0, 102000000, mux_pllp_out3, 0); -PERIPH_CLK(isp, "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0); /* same frequency as VI */ -PERIPH_CLK(csus, "tegra_camera", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET); -PERIPH_CLK(tsensor, "tegra-tsensor", NULL, 100, 0x3b8, 216000000, mux_pllp_pllc_clkm_clk32, MUX | DIV_U71); -PERIPH_CLK(actmon, "actmon", NULL, 119, 0x3e8, 216000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71); -PERIPH_CLK(extern1, "extern1", NULL, 120, 0x3ec, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | MUX8 | DIV_U71); -PERIPH_CLK(extern2, "extern2", NULL, 121, 0x3f0, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | MUX8 | DIV_U71); -PERIPH_CLK(extern3, "extern3", NULL, 122, 0x3f4, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | MUX8 | DIV_U71); -PERIPH_CLK(i2cslow, "i2cslow", NULL, 81, 0x3fc, 26000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71 | PERIPH_ON_APB); -PERIPH_CLK(pcie, "tegra-pcie", "pcie", 70, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(afi, "tegra-pcie", "afi", 72, 0, 250000000, mux_clk_m, 0); -PERIPH_CLK(se, "se", NULL, 127, 0x42c, 520000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_INT); - -static struct clk tegra_dsib; -static struct clk_tegra tegra_dsib_hw = { - .hw = { - .clk = &tegra_dsib, - }, - .lookup = { - .dev_id = "tegradc.1", - .con_id = "dsib", - }, - .reg = 0xd0, - .flags = MUX | PLLD, - .max_rate = 500000000, - .u.periph = { - .clk_num = 82, - }, - .reset = &tegra30_periph_clk_reset, -}; -static struct clk tegra_dsib = { - .name = "dsib", - .ops = &tegra30_dsib_clk_ops, - .hw = &tegra_dsib_hw.hw, - .parent_names = mux_plld_out0_plld2_out0, - .parents = mux_plld_out0_plld2_out0_p, - .num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0), -}; - -struct clk *tegra_list_clks[] = { - &tegra_apbdma, - &tegra_rtc, - &tegra_kbc, - &tegra_timer, - &tegra_kfuse, - &tegra_fuse, - &tegra_fuse_burn, - &tegra_apbif, - &tegra_i2s0, - &tegra_i2s1, - &tegra_i2s2, - &tegra_i2s3, - &tegra_i2s4, - &tegra_spdif_out, - &tegra_spdif_in, - &tegra_pwm, - &tegra_d_audio, - &tegra_dam0, - &tegra_dam1, - &tegra_dam2, - &tegra_hda, - &tegra_hda2codec_2x, - &tegra_hda2hdmi, - &tegra_sbc1, - &tegra_sbc2, - &tegra_sbc3, - &tegra_sbc4, - &tegra_sbc5, - &tegra_sbc6, - &tegra_sata_oob, - &tegra_sata, - &tegra_sata_cold, - &tegra_ndflash, - &tegra_ndspeed, - &tegra_vfir, - &tegra_sdmmc1, - &tegra_sdmmc2, - &tegra_sdmmc3, - &tegra_sdmmc4, - &tegra_vcp, - &tegra_bsea, - &tegra_bsev, - &tegra_vde, - &tegra_csite, - &tegra_la, - &tegra_owr, - &tegra_nor, - &tegra_mipi, - &tegra_i2c1, - &tegra_i2c2, - &tegra_i2c3, - &tegra_i2c4, - &tegra_i2c5, - &tegra_uarta, - &tegra_uartb, - &tegra_uartc, - &tegra_uartd, - &tegra_uarte, - &tegra_vi, - &tegra_3d, - &tegra_3d2, - &tegra_2d, - &tegra_vi_sensor, - &tegra_epp, - &tegra_mpe, - &tegra_host1x, - &tegra_cve, - &tegra_tvo, - &tegra_dtv, - &tegra_hdmi, - &tegra_tvdac, - &tegra_disp1, - &tegra_disp2, - &tegra_usbd, - &tegra_usb2, - &tegra_usb3, - &tegra_dsia, - &tegra_dsib, - &tegra_csi, - &tegra_isp, - &tegra_csus, - &tegra_tsensor, - &tegra_actmon, - &tegra_extern1, - &tegra_extern2, - &tegra_extern3, - &tegra_i2cslow, - &tegra_pcie, - &tegra_afi, - &tegra_se, -}; - -#define CLK_DUPLICATE(_name, _dev, _con) \ - { \ - .name = _name, \ - .lookup = { \ - .dev_id = _dev, \ - .con_id = _con, \ - }, \ - } - -/* Some clocks may be used by different drivers depending on the board - * configuration. List those here to register them twice in the clock lookup - * table under two names. - */ -struct clk_duplicate tegra_clk_duplicates[] = { - CLK_DUPLICATE("uarta", "serial8250.0", NULL), - CLK_DUPLICATE("uartb", "serial8250.1", NULL), - CLK_DUPLICATE("uartc", "serial8250.2", NULL), - CLK_DUPLICATE("uartd", "serial8250.3", NULL), - CLK_DUPLICATE("uarte", "serial8250.4", NULL), - CLK_DUPLICATE("usbd", "utmip-pad", NULL), - CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), - CLK_DUPLICATE("usbd", "tegra-otg", NULL), - CLK_DUPLICATE("dsib", "tegradc.0", "dsib"), - CLK_DUPLICATE("dsia", "tegradc.1", "dsia"), - CLK_DUPLICATE("bsev", "tegra-avp", "bsev"), - CLK_DUPLICATE("bsev", "nvavp", "bsev"), - CLK_DUPLICATE("vde", "tegra-aes", "vde"), - CLK_DUPLICATE("bsea", "tegra-aes", "bsea"), - CLK_DUPLICATE("bsea", "nvavp", "bsea"), - CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL), - CLK_DUPLICATE("cml0", "tegra_pcie", "cml"), - CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"), - CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL), - CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL), - CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL), - CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL), - CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL), - CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL), - CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL), - CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL), - CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL), - CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL), - CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL), - CLK_DUPLICATE("twd", "smp_twd", NULL), - CLK_DUPLICATE("vcp", "nvavp", "vcp"), - CLK_DUPLICATE("i2s0", NULL, "i2s0"), - CLK_DUPLICATE("i2s1", NULL, "i2s1"), - CLK_DUPLICATE("i2s2", NULL, "i2s2"), - CLK_DUPLICATE("i2s3", NULL, "i2s3"), - CLK_DUPLICATE("i2s4", NULL, "i2s4"), - CLK_DUPLICATE("dam0", NULL, "dam0"), - CLK_DUPLICATE("dam1", NULL, "dam1"), - CLK_DUPLICATE("dam2", NULL, "dam2"), - CLK_DUPLICATE("spdif_in", NULL, "spdif_in"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"), - CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"), - CLK_DUPLICATE("pll_p", "tegradc.0", "parent"), - CLK_DUPLICATE("pll_p", "tegradc.1", "parent"), - CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"), -}; - -struct clk *tegra_ptr_clks[] = { - &tegra_clk_32k, - &tegra_clk_m, - &tegra_clk_m_div2, - &tegra_clk_m_div4, - &tegra_pll_ref, - &tegra_pll_m, - &tegra_pll_m_out1, - &tegra_pll_c, - &tegra_pll_c_out1, - &tegra_pll_p, - &tegra_pll_p_out1, - &tegra_pll_p_out2, - &tegra_pll_p_out3, - &tegra_pll_p_out4, - &tegra_pll_a, - &tegra_pll_a_out0, - &tegra_pll_d, - &tegra_pll_d_out0, - &tegra_pll_d2, - &tegra_pll_d2_out0, - &tegra_pll_u, - &tegra_pll_x, - &tegra_pll_x_out0, - &tegra_pll_e, - &tegra_clk_cclk_g, - &tegra_cml0, - &tegra_cml1, - &tegra_pciex, - &tegra_clk_sclk, - &tegra_hclk, - &tegra_pclk, - &tegra_clk_blink, - &tegra30_clk_twd, -}; - -static void tegra30_init_one_clock(struct clk *c) -{ - struct clk_tegra *clk = to_clk_tegra(c->hw); - __clk_init(NULL, c); - INIT_LIST_HEAD(&clk->shared_bus_list); - if (!clk->lookup.dev_id && !clk->lookup.con_id) - clk->lookup.con_id = c->name; - clk->lookup.clk = c; - clkdev_add(&clk->lookup); - tegra_clk_add(c); -} - -void __init tegra30_init_clocks(void) -{ - int i; - struct clk *c; - - for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++) - tegra30_init_one_clock(tegra_ptr_clks[i]); - - for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++) - tegra30_init_one_clock(tegra_list_clks[i]); - - for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) { - c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name); - if (!c) { - pr_err("%s: Unknown duplicate clock %s\n", __func__, - tegra_clk_duplicates[i].name); - continue; - } - - tegra_clk_duplicates[i].lookup.clk = c; - clkdev_add(&tegra_clk_duplicates[i].lookup); - } - - for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++) - tegra30_init_one_clock(tegra_sync_source_list[i]); - for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++) - tegra30_init_one_clock(tegra_clk_audio_list[i]); - for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++) - tegra30_init_one_clock(tegra_clk_audio_2x_list[i]); - - for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++) - tegra30_init_one_clock(tegra_clk_out_list[i]); - - tegra30_cpu_car_ops_init(); -} diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 4ce77cd..12060ae 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -31,11 +31,11 @@ #include <linux/dma-mapping.h> #include <linux/platform_data/clk-u300.h> #include <linux/platform_data/pinctrl-coh901.h> +#include <linux/irqchip/arm-vic.h> #include <asm/types.h> #include <asm/setup.h> #include <asm/memory.h> -#include <asm/hardware/vic.h> #include <asm/mach/map.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -1779,8 +1779,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board") .map_io = u300_map_io, .nr_irqs = 0, .init_irq = u300_init_irq, - .handle_irq = vic_handle_irq, - .timer = &u300_timer, + .init_time = u300_timer_init, .init_machine = u300_init_machine, .restart = u300_restart, MACHINE_END diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 1da10e2..d9e7320 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -349,7 +349,7 @@ static u32 notrace u300_read_sched_clock(void) /* * This sets up the system timers, clock source and clock event. */ -static void __init u300_timer_init(void) +void __init u300_timer_init(void) { struct clk *clk; unsigned long rate; @@ -413,11 +413,3 @@ static void __init u300_timer_init(void) * used by hrtimers! */ } - -/* - * Very simple system timer that only register the clock event and - * clock source. - */ -struct sys_timer u300_timer = { - .init = u300_timer_init, -}; diff --git a/arch/arm/mach-u300/timer.h b/arch/arm/mach-u300/timer.h index b5e9791..d34287b 100644 --- a/arch/arm/mach-u300/timer.h +++ b/arch/arm/mach-u300/timer.h @@ -1 +1 @@ -extern struct sys_timer u300_timer; +extern void u300_timer_init(void); diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index d453522..0e928d2 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -40,7 +40,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/setup.h> @@ -751,8 +750,7 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .map_io = u8500_map_io, .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ - .timer = &ux500_timer, - .handle_irq = gic_handle_irq, + .init_time = ux500_timer_init, .init_machine = mop500_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -761,8 +759,7 @@ MACHINE_START(U8520, "ST-Ericsson U8520 Platform HREFP520") .atag_offset = 0x100, .map_io = u8500_map_io, .init_irq = ux500_init_irq, - .timer = &ux500_timer, - .handle_irq = gic_handle_irq, + .init_time = ux500_timer_init, .init_machine = mop500_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -772,8 +769,7 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") .smp = smp_ops(ux500_smp_ops), .map_io = u8500_map_io, .init_irq = ux500_init_irq, - .timer = &ux500_timer, - .handle_irq = gic_handle_irq, + .init_time = ux500_timer_init, .init_machine = hrefv60_init_machine, .init_late = ux500_init_late, MACHINE_END @@ -784,8 +780,7 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") .map_io = u8500_map_io, .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ - .timer = &ux500_timer, - .handle_irq = gic_handle_irq, + .init_time = ux500_timer_init, .init_machine = snowball_init_machine, .init_late = NULL, MACHINE_END diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 5b286e0..218a6b1 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -27,7 +27,6 @@ #include <asm/pmu.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/setup.h> @@ -341,8 +340,7 @@ DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)") .map_io = u8500_map_io, .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ - .timer = &ux500_timer, - .handle_irq = gic_handle_irq, + .init_time = ux500_timer_init, .init_machine = u8500_init_machine, .init_late = NULL, .dt_compat = stericsson_dt_platform_compat, diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 721e7b4..5dd90d3 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -17,9 +17,10 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/arm-gic.h> #include <linux/platform_data/clk-ux500.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <mach/hardware.h> @@ -42,11 +43,6 @@ void __iomem *_PRCMU_BASE; * This feels fragile because it depends on the gpio device getting probed * _before_ any device uses the gpio interrupts. */ -static const struct of_device_id ux500_dt_irq_match[] = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {}, -}; - void __init ux500_init_irq(void) { void __iomem *dist_base; @@ -62,7 +58,7 @@ void __init ux500_init_irq(void) #ifdef CONFIG_OF if (of_have_populated_dt()) - of_irq_init(ux500_dt_irq_match); + irqchip_init(); else #endif gic_init(0, 29, dist_base, cpu_base); diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 6be4c4d..bddce2b 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -28,8 +28,7 @@ extern struct device *ux500_soc_device_init(const char *soc_id); struct amba_device; extern void __init amba_add_devices(struct amba_device *devs[], int num); -struct sys_timer; -extern struct sys_timer ux500_timer; +extern void ux500_timer_init(void); #define __IO_DEV_DESC(x, sz) { \ .virtual = IO_ADDRESS(x), \ diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 3db7782..b8adac9 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -16,9 +16,9 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/io.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> -#include <asm/hardware/gic.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <mach/hardware.h> @@ -91,7 +91,7 @@ static int __cpuinit ux500_boot_secondary(unsigned int cpu, struct task_struct * */ write_pen_release(cpu_logical_map(cpu)); - smp_send_reschedule(cpu); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -155,8 +155,6 @@ static void __init ux500_smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init ux500_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index 875309a..aa2a78a 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -46,7 +46,7 @@ const static struct of_device_id prcmu_timer_of_match[] __initconst = { { }, }; -static void __init ux500_timer_init(void) +void __init ux500_timer_init(void) { void __iomem *mtu_timer_base; void __iomem *prcmu_timer_base; @@ -99,14 +99,3 @@ dt_fail: clksrc_dbx500_prcmu_init(prcmu_timer_base); ux500_twd_init(); } - -static void ux500_timer_reset(void) -{ - nmdk_clkevt_reset(); - nmdk_clksrc_reset(); -} - -struct sys_timer ux500_timer = { - .init = ux500_timer_init, - .resume = ux500_timer_reset, -}; diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 5d59294..a42b890 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -32,6 +32,7 @@ #include <linux/amba/mmci.h> #include <linux/amba/pl022.h> #include <linux/io.h> +#include <linux/irqchip/arm-vic.h> #include <linux/irqchip/versatile-fpga.h> #include <linux/gfp.h> #include <linux/clkdev.h> @@ -40,7 +41,6 @@ #include <asm/irq.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/icst.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -770,7 +770,7 @@ void __init versatile_init(void) /* * Set up timer interrupt, and return the current time in seconds. */ -static void __init versatile_timer_init(void) +void __init versatile_timer_init(void) { u32 val; @@ -797,8 +797,3 @@ static void __init versatile_timer_init(void) sp804_clocksource_init(TIMER3_VA_BASE, "timer3"); sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0"); } - -struct sys_timer versatile_timer = { - .init = versatile_timer_init, -}; - diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h index 683e607..5c1b87d 100644 --- a/arch/arm/mach-versatile/core.h +++ b/arch/arm/mach-versatile/core.h @@ -29,7 +29,7 @@ extern void __init versatile_init(void); extern void __init versatile_init_early(void); extern void __init versatile_init_irq(void); extern void __init versatile_map_io(void); -extern struct sys_timer versatile_timer; +extern void versatile_timer_init(void); extern void versatile_restart(char, const char *); extern unsigned int mmc_status(struct device *dev); #ifdef CONFIG_OF diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c index 98f6549..1caef10 100644 --- a/arch/arm/mach-versatile/versatile_ab.c +++ b/arch/arm/mach-versatile/versatile_ab.c @@ -26,7 +26,6 @@ #include <mach/hardware.h> #include <asm/irq.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -39,8 +38,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, - .timer = &versatile_timer, + .init_time = versatile_timer_init, .init_machine = versatile_init, .restart = versatile_restart, MACHINE_END diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c index ae5ad3c..2558f2e 100644 --- a/arch/arm/mach-versatile/versatile_dt.c +++ b/arch/arm/mach-versatile/versatile_dt.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/of_irq.h> #include <linux/of_platform.h> -#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -46,8 +45,7 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, - .timer = &versatile_timer, + .init_time = versatile_timer_init, .init_machine = versatile_dt_init, .dt_compat = versatile_dt_match, .restart = versatile_restart, diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index 1973833..611d140 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -27,7 +27,6 @@ #include <linux/io.h> #include <mach/hardware.h> -#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h> @@ -107,8 +106,7 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .handle_irq = vic_handle_irq, - .timer = &versatile_timer, + .init_time = versatile_timer_init, .init_machine = versatile_pb_init, .restart = versatile_restart, MACHINE_END diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 60838dd..6f34497 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -10,10 +10,10 @@ #include <linux/amba/clcd.h> #include <linux/clkdev.h> #include <linux/vexpress.h> +#include <linux/irqchip/arm-gic.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> @@ -182,8 +182,6 @@ static void __init ct_ca9x4_init_cpu_map(void) for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init ct_ca9x4_smp_enable(unsigned int max_cpus) diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index c5d70de..dc1ace5 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -16,7 +16,6 @@ #include <linux/vexpress.h> #include <asm/smp_scu.h> -#include <asm/hardware/gic.h> #include <asm/mach/map.h> #include <mach/motherboard.h> @@ -128,8 +127,6 @@ static void __init vexpress_dt_smp_init_cpus(void) for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); - - set_smp_cross_call(gic_raise_softirq); } static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 011661a..915683c 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -7,6 +7,7 @@ #include <linux/io.h> #include <linux/smp.h> #include <linux/init.h> +#include <linux/irqchip.h> #include <linux/of_address.h> #include <linux/of_fdt.h> #include <linux/of_irq.h> @@ -30,7 +31,6 @@ #include <asm/mach/time.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/hardware/gic.h> #include <asm/hardware/timer-sp.h> #include <mach/ct-ca9x4.h> @@ -291,10 +291,6 @@ static void __init v2m_timer_init(void) v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0); } -static struct sys_timer v2m_timer = { - .init = v2m_timer_init, -}; - static void __init v2m_init_early(void) { if (ct_desc->init_early) @@ -376,8 +372,7 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") .map_io = v2m_map_io, .init_early = v2m_init_early, .init_irq = v2m_init_irq, - .timer = &v2m_timer, - .handle_irq = gic_handle_irq, + .init_time = v2m_timer_init, .init_machine = v2m_init, .restart = vexpress_restart, MACHINE_END @@ -434,16 +429,6 @@ void __init v2m_dt_init_early(void) } } -static struct of_device_id vexpress_irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - {} -}; - -static void __init v2m_dt_init_irq(void) -{ - of_irq_init(vexpress_irq_match); -} - static void __init v2m_dt_timer_init(void) { struct device_node *node = NULL; @@ -468,10 +453,6 @@ static void __init v2m_dt_timer_init(void) 24000000); } -static struct sys_timer v2m_dt_timer = { - .init = v2m_dt_timer_init, -}; - static const struct of_device_id v2m_dt_bus_match[] __initconst = { { .compatible = "simple-bus", }, { .compatible = "arm,amba-bus", }, @@ -497,9 +478,8 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .smp = smp_ops(vexpress_smp_ops), .map_io = v2m_dt_map_io, .init_early = v2m_dt_init_early, - .init_irq = v2m_dt_init_irq, - .timer = &v2m_dt_timer, + .init_irq = irqchip_init, + .init_time = v2m_dt_timer_init, .init_machine = v2m_dt_init, - .handle_irq = gic_handle_irq, .restart = vexpress_restart, MACHINE_END diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig index 2ed0b7d..c0b1c60 100644 --- a/arch/arm/mach-vt8500/Kconfig +++ b/arch/arm/mach-vt8500/Kconfig @@ -1,12 +1,34 @@ config ARCH_VT8500 - bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5 - default ARCH_VT8500_SINGLE + bool select ARCH_HAS_CPUFREQ select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP - select CPU_ARM926T select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK + select VT8500_TIMER help Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. + +config ARCH_WM8505 + bool "VIA/Wondermedia 85xx and WM8650" + depends on ARCH_MULTI_V5 + select ARCH_VT8500 + select CPU_ARM926T + help + +config ARCH_WM8750 + bool "WonderMedia WM8750" + depends on ARCH_MULTI_V6 + select ARCH_VT8500 + select CPU_V6 + help + Support for WonderMedia WM8750 System-on-Chip. + +config ARCH_WM8850 + bool "WonderMedia WM8850" + depends on ARCH_MULTI_V7 + select ARCH_VT8500 + select CPU_V7 + help + Support for WonderMedia WM8850 System-on-Chip. diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile index e035251..92ceb24 100644 --- a/arch/arm/mach-vt8500/Makefile +++ b/arch/arm/mach-vt8500/Makefile @@ -1 +1 @@ -obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o +obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h index 6f2b843..77611a6 100644 --- a/arch/arm/mach-vt8500/common.h +++ b/arch/arm/mach-vt8500/common.h @@ -18,7 +18,6 @@ #include <linux/of.h> -void __init vt8500_timer_init(void); int __init vt8500_irq_init(struct device_node *node, struct device_node *parent); diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h deleted file mode 100644 index e6e81fd..0000000 --- a/arch/arm/mach-vt8500/include/mach/uncompress.h +++ /dev/null @@ -1,37 +0,0 @@ -/* arch/arm/mach-vt8500/include/mach/uncompress.h - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * Based on arch/arm/mach-dove/include/mach/uncompress.h - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define UART0_PHYS 0xd8200000 -#define UART0_ADDR(x) *(volatile unsigned char *)(UART0_PHYS + x) - -static void putc(const char c) -{ - while (UART0_ADDR(0x1c) & 0x2) - /* Tx busy, wait and poll */; - - UART0_ADDR(0) = c; -} - -static void flush(void) -{ -} - -/* - * nothing to do - */ -#define arch_decomp_setup() -#define arch_decomp_wdog() diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c index 3c66d48..6141868 100644 --- a/arch/arm/mach-vt8500/vt8500.c +++ b/arch/arm/mach-vt8500/vt8500.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/pm.h> +#include <linux/vt8500_timer.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -175,21 +176,19 @@ static void __init vt8500_init_irq(void) of_irq_init(vt8500_irq_match); }; -static struct sys_timer vt8500_timer = { - .init = vt8500_timer_init, -}; - static const char * const vt8500_dt_compat[] = { "via,vt8500", "wm,wm8650", "wm,wm8505", + "wm,wm8750", + "wm,wm8850", }; DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") .dt_compat = vt8500_dt_compat, .map_io = vt8500_map_io, .init_irq = vt8500_init_irq, - .timer = &vt8500_timer, + .init_time = vt8500_timer_init, .init_machine = vt8500_init, .restart = vt8500_restart, .handle_irq = vt8500_handle_irq, diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c index b4243e4..92f1c97 100644 --- a/arch/arm/mach-w90x900/mach-nuc910evb.c +++ b/arch/arm/mach-w90x900/mach-nuc910evb.c @@ -37,6 +37,6 @@ MACHINE_START(W90P910EVB, "W90P910EVB") .map_io = nuc910evb_map_io, .init_irq = nuc900_init_irq, .init_machine = nuc910evb_init, - .timer = &nuc900_timer, + .init_time = nuc900_timer_init, .restart = nuc9xx_restart, MACHINE_END diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c index 500fe59..26f7189 100644 --- a/arch/arm/mach-w90x900/mach-nuc950evb.c +++ b/arch/arm/mach-w90x900/mach-nuc950evb.c @@ -40,6 +40,6 @@ MACHINE_START(W90P950EVB, "W90P950EVB") .map_io = nuc950evb_map_io, .init_irq = nuc900_init_irq, .init_machine = nuc950evb_init, - .timer = &nuc900_timer, + .init_time = nuc900_timer_init, .restart = nuc9xx_restart, MACHINE_END diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c index cbb3adc..9b4e73f 100644 --- a/arch/arm/mach-w90x900/mach-nuc960evb.c +++ b/arch/arm/mach-w90x900/mach-nuc960evb.c @@ -37,6 +37,6 @@ MACHINE_START(W90N960EVB, "W90N960EVB") .map_io = nuc960evb_map_io, .init_irq = nuc900_init_irq, .init_machine = nuc960evb_init, - .timer = &nuc900_timer, + .init_time = nuc900_timer_init, .restart = nuc9xx_restart, MACHINE_END diff --git a/arch/arm/mach-w90x900/nuc9xx.h b/arch/arm/mach-w90x900/nuc9xx.h index 91acb40..88ef4b2 100644 --- a/arch/arm/mach-w90x900/nuc9xx.h +++ b/arch/arm/mach-w90x900/nuc9xx.h @@ -15,10 +15,9 @@ * */ struct map_desc; -struct sys_timer; /* core initialisation functions */ extern void nuc900_init_irq(void); -extern struct sys_timer nuc900_timer; +extern void nuc900_timer_init(void); extern void nuc9xx_restart(char, const char *); diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index fa27c49..30fbca8 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -91,7 +91,6 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, static struct clock_event_device nuc900_clockevent_device = { .name = "nuc900-timer0", - .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = nuc900_clockevent_setmode, .set_next_event = nuc900_clockevent_setnextevent, @@ -133,15 +132,10 @@ static void __init nuc900_clockevents_init(void) __raw_writel(RESETINT, REG_TISR); setup_irq(IRQ_TIMER0, &nuc900_timer0_irq); - nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, - nuc900_clockevent_device.shift); - nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, - &nuc900_clockevent_device); - nuc900_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, - &nuc900_clockevent_device); nuc900_clockevent_device.cpumask = cpumask_of(0); - clockevents_register_device(&nuc900_clockevent_device); + clockevents_config_and_register(&nuc900_clockevent_device, rate, + 0xf, 0xffffffff); } static void __init nuc900_clocksource_init(void) @@ -167,12 +161,8 @@ static void __init nuc900_clocksource_init(void) TDR_SHIFT, clocksource_mmio_readl_down); } -static void __init nuc900_timer_init(void) +void __init nuc900_timer_init(void) { nuc900_clocksource_init(); nuc900_clockevents_init(); } - -struct sys_timer nuc900_timer = { - .init = nuc900_timer_init, -}; diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index e16d4be..6472a69 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -31,7 +31,6 @@ #include <asm/mach-types.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" @@ -55,19 +54,6 @@ static void __init xilinx_init_machine(void) of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); } -static struct of_device_id irq_match[] __initdata = { - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, - { } -}; - -/** - * xilinx_irq_init() - Interrupt controller initialization for the GIC. - */ -static void __init xilinx_irq_init(void) -{ - of_irq_init(irq_match); -} - #define SCU_PERIPH_PHYS 0xF8F00000 #define SCU_PERIPH_SIZE SZ_8K #define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) @@ -93,13 +79,6 @@ static void __init xilinx_zynq_timer_init(void) xttcpss_timer_init(); } -/* - * Instantiate and initialize the system timer structure - */ -static struct sys_timer xttcpss_sys_timer = { - .init = xilinx_zynq_timer_init, -}; - /** * xilinx_map_io() - Create memory mappings needed for early I/O. */ @@ -117,9 +96,8 @@ static const char *xilinx_dt_match[] = { MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .map_io = xilinx_map_io, - .init_irq = xilinx_irq_init, - .handle_irq = gic_handle_irq, + .init_irq = irqchip_init, .init_machine = xilinx_init_machine, - .timer = &xttcpss_sys_timer, + .init_time = xilinx_zynq_timer_init, .dt_compat = xilinx_dt_match, MACHINE_END diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index cbfbbe4..837a2d5 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -156,14 +156,9 @@ void __init iop_init_time(unsigned long tick_rate) write_tmr0(timer_ctl & ~IOP_TMR_EN); write_tisr(1); setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); - clockevents_calc_mult_shift(&iop_clockevent, - tick_rate, IOP_MIN_RANGE); - iop_clockevent.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &iop_clockevent); - iop_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &iop_clockevent); iop_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&iop_clockevent); + clockevents_config_and_register(&iop_clockevent, tick_rate, + 0xf, 0xfffffffe); /* * Set up free-running clocksource timer 1. diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c index e686fe76..7310bcf 100644 --- a/arch/arm/plat-orion/mpp.c +++ b/arch/arm/plat-orion/mpp.c @@ -49,7 +49,7 @@ void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask, "number (%u)\n", num); continue; } - if (variant_mask & !(*mpp_list & variant_mask)) { + if (variant_mask && !(*mpp_list & variant_mask)) { printk(KERN_WARNING "orion_mpp_conf: requested MPP%u config " "unavailable on this hardware\n", num); diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 0f4fa86..5d5ac0f 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -156,7 +156,6 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) static struct clock_event_device orion_clkevt = { .name = "orion_tick", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, .rating = 300, .set_next_event = orion_clkevt_next_event, .set_mode = orion_clkevt_mode, @@ -221,9 +220,6 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask, * Setup clockevent timer (interrupt-driven). */ setup_irq(irq, &orion_timer_irq); - orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift); - orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt); - orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt); orion_clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&orion_clkevt); + clockevents_config_and_register(&orion_clkevt, tclk, 1, 0xfffffffe); } diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index b69e11d..37703ef 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -194,8 +194,7 @@ extern void s3c24xx_init_uartdevs(char *name, /* timer for 2410/2440 */ -struct sys_timer; -extern struct sys_timer s3c24xx_timer; +extern void s3c24xx_timer_init(void); extern struct syscore_ops s3c2410_pm_syscore_ops; extern struct syscore_ops s3c2412_pm_syscore_ops; diff --git a/arch/arm/plat-samsung/include/plat/s5p-time.h b/arch/arm/plat-samsung/include/plat/s5p-time.h index 3a70aeb..9c96f35 100644 --- a/arch/arm/plat-samsung/include/plat/s5p-time.h +++ b/arch/arm/plat-samsung/include/plat/s5p-time.h @@ -36,5 +36,5 @@ struct s5p_timer_source { extern void __init s5p_set_timer_source(enum s5p_timer_mode event, enum s5p_timer_mode source); -extern struct sys_timer s5p_timer; +extern void s5p_timer_init(void); #endif /* __ASM_PLAT_S5P_TIME_H */ diff --git a/arch/arm/plat-samsung/s5p-irq-eint.c b/arch/arm/plat-samsung/s5p-irq-eint.c index 33bd3f3..faa6516 100644 --- a/arch/arm/plat-samsung/s5p-irq-eint.c +++ b/arch/arm/plat-samsung/s5p-irq-eint.c @@ -15,8 +15,7 @@ #include <linux/io.h> #include <linux/device.h> #include <linux/gpio.h> - -#include <asm/hardware/vic.h> +#include <linux/irqchip/arm-vic.h> #include <plat/regs-irqtype.h> diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c index dfb47d6..103e371 100644 --- a/arch/arm/plat-samsung/s5p-irq.c +++ b/arch/arm/plat-samsung/s5p-irq.c @@ -13,8 +13,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> - -#include <asm/hardware/vic.h> +#include <linux/irqchip/arm-vic.h> #include <mach/map.h> #include <plat/regs-timer.h> diff --git a/arch/arm/plat-samsung/s5p-time.c b/arch/arm/plat-samsung/s5p-time.c index 028b6e8..e92510c 100644 --- a/arch/arm/plat-samsung/s5p-time.c +++ b/arch/arm/plat-samsung/s5p-time.c @@ -274,15 +274,8 @@ static void __init s5p_clockevent_init(void) clock_rate = clk_get_rate(tin_event); clock_count_per_tick = clock_rate / HZ; - clockevents_calc_mult_shift(&time_event_device, - clock_rate, S5PTIMER_MIN_RANGE); - time_event_device.max_delta_ns = - clockevent_delta2ns(-1, &time_event_device); - time_event_device.min_delta_ns = - clockevent_delta2ns(1, &time_event_device); - time_event_device.cpumask = cpumask_of(0); - clockevents_register_device(&time_event_device); + clockevents_config_and_register(&time_event_device, clock_rate, 1, -1); irq_number = timer_source.event_id + IRQ_TIMER0; setup_irq(irq_number, &s5p_clock_event_irq); @@ -393,13 +386,9 @@ static void __init s5p_timer_resources(void) clk_enable(tin_source); } -static void __init s5p_timer_init(void) +void __init s5p_timer_init(void) { s5p_timer_resources(); s5p_clockevent_init(); s5p_clocksource_init(); } - -struct sys_timer s5p_timer = { - .init = s5p_timer_init, -}; diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c index 60552e2..73defd0 100644 --- a/arch/arm/plat-samsung/time.c +++ b/arch/arm/plat-samsung/time.c @@ -27,6 +27,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/syscore_ops.h> #include <asm/mach-types.h> @@ -95,7 +96,7 @@ static inline unsigned long timer_ticks_to_usec(unsigned long ticks) * IRQs are disabled before entering here from do_gettimeofday() */ -static unsigned long s3c2410_gettimeoffset (void) +static u32 s3c2410_gettimeoffset(void) { unsigned long tdone; unsigned long tval; @@ -120,7 +121,7 @@ static unsigned long s3c2410_gettimeoffset (void) tdone += timer_startval; } - return timer_ticks_to_usec(tdone); + return timer_ticks_to_usec(tdone) * 1000; } @@ -271,15 +272,16 @@ static void __init s3c2410_timer_resources(void) clk_enable(tin); } -static void __init s3c2410_timer_init(void) +static struct syscore_ops s3c24xx_syscore_ops = { + .resume = s3c2410_timer_setup, +}; + +void __init s3c24xx_timer_init(void) { + arch_gettimeoffset = s3c2410_gettimeoffset; + s3c2410_timer_resources(); s3c2410_timer_setup(); setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); + register_syscore_ops(&s3c24xx_syscore_ops); } - -struct sys_timer s3c24xx_timer = { - .init = s3c2410_timer_init, - .offset = s3c2410_gettimeoffset, - .resume = s3c2410_timer_setup -}; diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index 03321af..bd5c53c 100644 --- a/arch/arm/plat-spear/time.c +++ b/arch/arm/plat-spear/time.c @@ -186,15 +186,9 @@ static void __init spear_clockevent_init(int irq) tick_rate = clk_get_rate(gpt_clk); tick_rate >>= CTRL_PRESCALER16; - clockevents_calc_mult_shift(&clkevt, tick_rate, SPEAR_MIN_RANGE); - - clkevt.max_delta_ns = clockevent_delta2ns(0xfff0, - &clkevt); - clkevt.min_delta_ns = clockevent_delta2ns(3, &clkevt); - clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt); + clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0); setup_irq(irq, &spear_timer_irq); } diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 04ca493..f2ac155 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -14,10 +14,10 @@ #include <linux/device.h> #include <linux/jiffies.h> #include <linux/smp.h> +#include <linux/irqchip/arm-gic.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> -#include <asm/hardware/gic.h> /* * Write pen_release in a way that is guaranteed to be visible to all @@ -79,7 +79,7 @@ int __cpuinit versatile_boot_secondary(unsigned int cpu, struct task_struct *idl * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c index 2310b24..3126b92 100644 --- a/arch/blackfin/kernel/time.c +++ b/arch/blackfin/kernel/time.c @@ -85,7 +85,7 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *)) /* * Should return useconds since last timer tick */ -u32 arch_gettimeoffset(void) +static u32 blackfin_gettimeoffset(void) { unsigned long offset; unsigned long clocks_per_jiffy; @@ -141,6 +141,10 @@ void read_persistent_clock(struct timespec *ts) void __init time_init(void) { +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET + arch_gettimeoffset = blackfin_gettimeoffset; +#endif + #ifdef CONFIG_RTC_DRV_BFIN /* [#2663] hack to filter junk RTC values that would cause * userspace to have to deal with time values greater than diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index bcffcb6..fce7c54 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -55,9 +55,9 @@ unsigned long get_ns_in_jiffie(void) return ns; } -unsigned long do_slow_gettimeoffset(void) +static u32 cris_v10_gettimeoffset(void) { - unsigned long count; + u32 count; /* The timer interrupt comes from Etrax timer 0. In order to get * better precision, we check the current value. It might have @@ -65,8 +65,8 @@ unsigned long do_slow_gettimeoffset(void) */ count = *R_TIMER0_DATA; - /* Convert timer value to usec */ - return (TIMER0_DIV - count) * ((NSEC_PER_SEC/1000)/HZ)/TIMER0_DIV; + /* Convert timer value to nsec */ + return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV; } /* Excerpt from the Etrax100 HSDD about the built-in watchdog: @@ -191,6 +191,8 @@ static struct irqaction irq2 = { void __init time_init(void) { + arch_gettimeoffset = cris_v10_gettimeoffset; + /* probe for the RTC and read it if it exists * Before the RTC can be probed the loops_per_usec variable needs * to be initialized to make usleep work. A better value for diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c index 277ffc4..fe6acda 100644 --- a/arch/cris/kernel/time.c +++ b/arch/cris/kernel/time.c @@ -39,17 +39,6 @@ extern unsigned long loops_per_jiffy; /* init/main.c */ unsigned long loops_per_usec; - -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -extern unsigned long do_slow_gettimeoffset(void); -static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; - -u32 arch_gettimeoffset(void) -{ - return do_gettimeoffset() * 1000; -} -#endif - int set_rtc_mmss(unsigned long nowtime) { D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime)); diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 84dd040..1a15f81 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -57,7 +57,7 @@ extern void smp_local_timer_interrupt(void); static unsigned long latch; -u32 arch_gettimeoffset(void) +static u32 m32r_gettimeoffset(void) { unsigned long elapsed_time = 0; /* [us] */ @@ -165,6 +165,8 @@ void read_persistent_clock(struct timespec *ts) void __init time_init(void) { + arch_gettimeoffset = m32r_gettimeoffset; + #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index ee01b7a..b819390 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -95,7 +95,7 @@ static void amiga_sched_init(irq_handler_t handler); static void amiga_get_model(char *model); static void amiga_get_hardware_list(struct seq_file *m); /* amiga specific timer functions */ -static unsigned long amiga_gettimeoffset(void); +static u32 amiga_gettimeoffset(void); extern void amiga_mksound(unsigned int count, unsigned int ticks); static void amiga_reset(void); extern void amiga_init_sound(void); @@ -377,7 +377,7 @@ void __init config_amiga(void) mach_init_IRQ = amiga_init_IRQ; mach_get_model = amiga_get_model; mach_get_hardware_list = amiga_get_hardware_list; - mach_gettimeoffset = amiga_gettimeoffset; + arch_gettimeoffset = amiga_gettimeoffset; /* * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI @@ -482,10 +482,10 @@ static void __init amiga_sched_init(irq_handler_t timer_routine) #define TICK_SIZE 10000 /* This is always executed with interrupts disabled. */ -static unsigned long amiga_gettimeoffset(void) +static u32 amiga_gettimeoffset(void) { unsigned short hi, lo, hi2; - unsigned long ticks, offset = 0; + u32 ticks, offset = 0; /* read CIA B timer A current value */ hi = ciab.tahi; @@ -507,7 +507,7 @@ static unsigned long amiga_gettimeoffset(void) ticks = jiffy_ticks - ticks; ticks = (10000 * ticks) / jiffy_ticks; - return ticks + offset; + return (ticks + offset) * 1000; } static void amiga_reset(void) __noreturn; diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index f5565d6..3ea56b9 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -26,7 +26,7 @@ u_long apollo_model; extern void dn_sched_init(irq_handler_t handler); extern void dn_init_IRQ(void); -extern unsigned long dn_gettimeoffset(void); +extern u32 dn_gettimeoffset(void); extern int dn_dummy_hwclk(int, struct rtc_time *); extern int dn_dummy_set_clock_mmss(unsigned long); extern void dn_dummy_reset(void); @@ -151,7 +151,7 @@ void __init config_apollo(void) mach_sched_init=dn_sched_init; /* */ mach_init_IRQ=dn_init_IRQ; - mach_gettimeoffset = dn_gettimeoffset; + arch_gettimeoffset = dn_gettimeoffset; mach_max_dma_address = 0xffffffff; mach_hwclk = dn_dummy_hwclk; /* */ mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ @@ -203,10 +203,9 @@ void dn_sched_init(irq_handler_t timer_routine) pr_err("Couldn't register timer interrupt\n"); } -unsigned long dn_gettimeoffset(void) { - +u32 dn_gettimeoffset(void) +{ return 0xdeadbeef; - } int dn_dummy_hwclk(int op, struct rtc_time *t) { diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index d8eb327..037c11c 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -74,7 +74,7 @@ static void atari_heartbeat(int on); /* atari specific timer functions (in time.c) */ extern void atari_sched_init(irq_handler_t); -extern unsigned long atari_gettimeoffset (void); +extern u32 atari_gettimeoffset(void); extern int atari_mste_hwclk (int, struct rtc_time *); extern int atari_tt_hwclk (int, struct rtc_time *); extern int atari_mste_set_clock_mmss (unsigned long); @@ -204,7 +204,7 @@ void __init config_atari(void) mach_init_IRQ = atari_init_IRQ; mach_get_model = atari_get_model; mach_get_hardware_list = atari_get_hardware_list; - mach_gettimeoffset = atari_gettimeoffset; + arch_gettimeoffset = atari_gettimeoffset; mach_reset = atari_reset; mach_max_dma_address = 0xffffff; #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE) diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index c0cc68a..da8f981 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -42,9 +42,9 @@ atari_sched_init(irq_handler_t timer_routine) #define TICK_SIZE 10000 /* This is always executed with interrupts disabled. */ -unsigned long atari_gettimeoffset (void) +u32 atari_gettimeoffset(void) { - unsigned long ticks, offset = 0; + u32 ticks, offset = 0; /* read MFP timer C current value */ ticks = st_mfp.tim_dt_c; @@ -57,7 +57,7 @@ unsigned long atari_gettimeoffset (void) ticks = INT_TICKS - ticks; ticks = ticks * 10000L / INT_TICKS; - return ticks + offset; + return (ticks + offset) * 1000; } diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index 0bf850a..8943aa4 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -38,7 +38,7 @@ static void bvme6000_get_model(char *model); extern void bvme6000_sched_init(irq_handler_t handler); -extern unsigned long bvme6000_gettimeoffset (void); +extern u32 bvme6000_gettimeoffset(void); extern int bvme6000_hwclk (int, struct rtc_time *); extern int bvme6000_set_clock_mmss (unsigned long); extern void bvme6000_reset (void); @@ -110,7 +110,7 @@ void __init config_bvme6000(void) mach_max_dma_address = 0xffffffff; mach_sched_init = bvme6000_sched_init; mach_init_IRQ = bvme6000_init_IRQ; - mach_gettimeoffset = bvme6000_gettimeoffset; + arch_gettimeoffset = bvme6000_gettimeoffset; mach_hwclk = bvme6000_hwclk; mach_set_clock_mmss = bvme6000_set_clock_mmss; mach_reset = bvme6000_reset; @@ -216,13 +216,13 @@ void bvme6000_sched_init (irq_handler_t timer_routine) * results... */ -unsigned long bvme6000_gettimeoffset (void) +u32 bvme6000_gettimeoffset(void) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; unsigned char msr = rtc->msr & 0xc0; unsigned char t1int, t1op; - unsigned long v = 800000, ov; + u32 v = 800000, ov; rtc->msr = 0; /* Ensure timer registers accessible */ @@ -246,7 +246,7 @@ unsigned long bvme6000_gettimeoffset (void) v += 10000; /* Int pending, + 10ms */ rtc->msr = msr; - return v; + return v * 1000; } /* diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index bf16af1..b7609f7 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -251,7 +251,7 @@ void __init config_hp300(void) mach_sched_init = hp300_sched_init; mach_init_IRQ = hp300_init_IRQ; mach_get_model = hp300_get_model; - mach_gettimeoffset = hp300_gettimeoffset; + arch_gettimeoffset = hp300_gettimeoffset; mach_hwclk = hp300_hwclk; mach_get_ss = hp300_get_ss; mach_reset = hp300_reset; diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index 29a71be..749543b 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -46,7 +46,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id) return vector(irq, NULL); } -unsigned long hp300_gettimeoffset(void) +u32 hp300_gettimeoffset(void) { /* Read current timer 1 value */ unsigned char lsb, msb1, msb2; @@ -59,7 +59,7 @@ unsigned long hp300_gettimeoffset(void) /* A carry happened while we were reading. Read it again */ lsb = in_8(CLOCKBASE + 7); ticks = INTVAL - ((msb2 << 8) | lsb); - return (USECS_PER_JIFFY * ticks) / INTVAL; + return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000; } void __init hp300_sched_init(irq_handler_t vector) diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h index 7b98242..f5583ec 100644 --- a/arch/m68k/hp300/time.h +++ b/arch/m68k/hp300/time.h @@ -1,2 +1,2 @@ extern void hp300_sched_init(irq_handler_t vector); -extern unsigned long hp300_gettimeoffset(void); +extern u32 hp300_gettimeoffset(void); diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h index 825c1c8..953ca21 100644 --- a/arch/m68k/include/asm/machdep.h +++ b/arch/m68k/include/asm/machdep.h @@ -3,6 +3,7 @@ #include <linux/seq_file.h> #include <linux/interrupt.h> +#include <linux/time.h> struct pt_regs; struct mktime; @@ -16,7 +17,6 @@ extern void (*mach_init_IRQ) (void); extern void (*mach_get_model) (char *model); extern void (*mach_get_hardware_list) (struct seq_file *m); /* machine dependent timer functions */ -extern unsigned long (*mach_gettimeoffset)(void); extern int (*mach_hwclk)(int, struct rtc_time*); extern unsigned int (*mach_get_ss)(void); extern int (*mach_get_rtc_pll)(struct rtc_pll_info *); diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index d872ce4..80cfbe5 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -84,7 +84,6 @@ void (*mach_init_IRQ) (void) __initdata = NULL; void (*mach_get_model) (char *model); void (*mach_get_hardware_list) (struct seq_file *m); /* machine dependent timer functions */ -unsigned long (*mach_gettimeoffset) (void); int (*mach_hwclk) (int, struct rtc_time*); EXPORT_SYMBOL(mach_hwclk); int (*mach_set_clock_mmss) (unsigned long); diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 5d0bcaa..bea6bcf 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -80,18 +80,8 @@ void read_persistent_clock(struct timespec *ts) } } -void __init time_init(void) -{ - mach_sched_init(timer_interrupt); -} - #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -u32 arch_gettimeoffset(void) -{ - return mach_gettimeoffset() * 1000; -} - static int __init rtc_init(void) { struct platform_device *pdev; @@ -106,3 +96,8 @@ static int __init rtc_init(void) module_init(rtc_init); #endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ + +void __init time_init(void) +{ + mach_sched_init(timer_interrupt); +} diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index d9f62e0..afb95d5 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -52,7 +52,7 @@ struct mac_booter_data mac_bi_data; static unsigned long mac_orig_videoaddr; /* Mac specific timer functions */ -extern unsigned long mac_gettimeoffset(void); +extern u32 mac_gettimeoffset(void); extern int mac_hwclk(int, struct rtc_time *); extern int mac_set_clock_mmss(unsigned long); extern void iop_preinit(void); @@ -177,7 +177,7 @@ void __init config_mac(void) mach_sched_init = mac_sched_init; mach_init_IRQ = mac_init_IRQ; mach_get_model = mac_get_model; - mach_gettimeoffset = mac_gettimeoffset; + arch_gettimeoffset = mac_gettimeoffset; mach_hwclk = mac_hwclk; mach_set_clock_mmss = mac_set_clock_mmss; mach_reset = mac_reset; diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 2d85662..5d1458b 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -327,7 +327,7 @@ void via_debug_dump(void) * TBI: get time offset between scheduling timer ticks */ -unsigned long mac_gettimeoffset (void) +u32 mac_gettimeoffset(void) { unsigned long ticks, offset = 0; @@ -341,7 +341,7 @@ unsigned long mac_gettimeoffset (void) ticks = MAC_CLOCK_TICK - ticks; ticks = ticks * 10000L / MAC_CLOCK_TICK; - return ticks + offset; + return (ticks + offset) * 1000; } /* diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index a41c091..1c62628 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -37,7 +37,7 @@ static void mvme147_get_model(char *model); extern void mvme147_sched_init(irq_handler_t handler); -extern unsigned long mvme147_gettimeoffset (void); +extern u32 mvme147_gettimeoffset(void); extern int mvme147_hwclk (int, struct rtc_time *); extern int mvme147_set_clock_mmss (unsigned long); extern void mvme147_reset (void); @@ -88,7 +88,7 @@ void __init config_mvme147(void) mach_max_dma_address = 0x01000000; mach_sched_init = mvme147_sched_init; mach_init_IRQ = mvme147_init_IRQ; - mach_gettimeoffset = mvme147_gettimeoffset; + arch_gettimeoffset = mvme147_gettimeoffset; mach_hwclk = mvme147_hwclk; mach_set_clock_mmss = mvme147_set_clock_mmss; mach_reset = mvme147_reset; @@ -127,7 +127,7 @@ void mvme147_sched_init (irq_handler_t timer_routine) /* This is always executed with interrupts disabled. */ /* XXX There are race hazards in this code XXX */ -unsigned long mvme147_gettimeoffset (void) +u32 mvme147_gettimeoffset(void) { volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012; unsigned short n; @@ -137,7 +137,7 @@ unsigned long mvme147_gettimeoffset (void) n = *cp; n -= PCC_TIMER_PRELOAD; - return (unsigned long)n * 25 / 4; + return ((unsigned long)n * 25 / 4) * 1000; } static int bcd2int (unsigned char b) diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index b6d7d8a..080a342 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -43,7 +43,7 @@ static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; static void mvme16x_get_model(char *model); extern void mvme16x_sched_init(irq_handler_t handler); -extern unsigned long mvme16x_gettimeoffset (void); +extern u32 mvme16x_gettimeoffset(void); extern int mvme16x_hwclk (int, struct rtc_time *); extern int mvme16x_set_clock_mmss (unsigned long); extern void mvme16x_reset (void); @@ -289,7 +289,7 @@ void __init config_mvme16x(void) mach_max_dma_address = 0xffffffff; mach_sched_init = mvme16x_sched_init; mach_init_IRQ = mvme16x_init_IRQ; - mach_gettimeoffset = mvme16x_gettimeoffset; + arch_gettimeoffset = mvme16x_gettimeoffset; mach_hwclk = mvme16x_hwclk; mach_set_clock_mmss = mvme16x_set_clock_mmss; mach_reset = mvme16x_reset; @@ -405,9 +405,9 @@ void mvme16x_sched_init (irq_handler_t timer_routine) /* This is always executed with interrupts disabled. */ -unsigned long mvme16x_gettimeoffset (void) +u32 mvme16x_gettimeoffset(void) { - return (*(volatile unsigned long *)0xfff42008); + return (*(volatile u32 *)0xfff42008) * 1000; } int bcd2int (unsigned char b) diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 1adb5b7..658542b 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -40,7 +40,7 @@ extern void q40_init_IRQ(void); static void q40_get_model(char *model); extern void q40_sched_init(irq_handler_t handler); -static unsigned long q40_gettimeoffset(void); +static u32 q40_gettimeoffset(void); static int q40_hwclk(int, struct rtc_time *); static unsigned int q40_get_ss(void); static int q40_set_clock_mmss(unsigned long); @@ -170,7 +170,7 @@ void __init config_q40(void) mach_sched_init = q40_sched_init; mach_init_IRQ = q40_init_IRQ; - mach_gettimeoffset = q40_gettimeoffset; + arch_gettimeoffset = q40_gettimeoffset; mach_hwclk = q40_hwclk; mach_get_ss = q40_get_ss; mach_get_rtc_pll = q40_get_rtc_pll; @@ -204,9 +204,9 @@ int q40_parse_bootinfo(const struct bi_record *rec) } -static unsigned long q40_gettimeoffset(void) +static u32 q40_gettimeoffset(void) { - return 5000 * (ql_ticks != 0); + return 5000 * (ql_ticks != 0) * 1000; } diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c index 2ca25bd0..f59ec58 100644 --- a/arch/m68k/sun3/config.c +++ b/arch/m68k/sun3/config.c @@ -36,7 +36,7 @@ char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; -extern unsigned long sun3_gettimeoffset(void); +extern u32 sun3_gettimeoffset(void); static void sun3_sched_init(irq_handler_t handler); extern void sun3_get_model (char* model); extern int sun3_hwclk(int set, struct rtc_time *t); @@ -141,7 +141,7 @@ void __init config_sun3(void) mach_sched_init = sun3_sched_init; mach_init_IRQ = sun3_init_IRQ; mach_reset = sun3_reboot; - mach_gettimeoffset = sun3_gettimeoffset; + arch_gettimeoffset = sun3_gettimeoffset; mach_get_model = sun3_get_model; mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c index 94fe801..889829e 100644 --- a/arch/m68k/sun3/intersil.c +++ b/arch/m68k/sun3/intersil.c @@ -23,9 +23,9 @@ #define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE) /* does this need to be implemented? */ -unsigned long sun3_gettimeoffset(void) +u32 sun3_gettimeoffset(void) { - return 1; + return 1000; } diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c index dd306c8..0532d64 100644 --- a/arch/m68k/sun3x/config.c +++ b/arch/m68k/sun3x/config.c @@ -48,7 +48,7 @@ void __init config_sun3x(void) mach_sched_init = sun3x_sched_init; mach_init_IRQ = sun3_init_IRQ; - mach_gettimeoffset = sun3x_gettimeoffset; + arch_gettimeoffset = sun3x_gettimeoffset; mach_reset = sun3x_reboot; mach_hwclk = sun3x_hwclk; diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c index 1d0a724..c8eb08a 100644 --- a/arch/m68k/sun3x/time.c +++ b/arch/m68k/sun3x/time.c @@ -71,7 +71,7 @@ int sun3x_hwclk(int set, struct rtc_time *t) return 0; } /* Not much we can do here */ -unsigned long sun3x_gettimeoffset (void) +u32 sun3x_gettimeoffset(void) { return 0L; } diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h index 6909e12..a4f9126 100644 --- a/arch/m68k/sun3x/time.h +++ b/arch/m68k/sun3x/time.h @@ -2,7 +2,7 @@ #define SUN3X_TIME_H extern int sun3x_hwclk(int set, struct rtc_time *t); -unsigned long sun3x_gettimeoffset (void); +u32 sun3x_gettimeoffset(void); void sun3x_sched_init(irq_handler_t vector); struct mostek_dt { diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index d7af29f..ba61192 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig @@ -8,8 +8,10 @@ config BCM47XX_SSB select SSB_DRIVER_EXTIF select SSB_EMBEDDED select SSB_B43_PCI_BRIDGE if PCI + select SSB_DRIVER_PCICORE if PCI select SSB_PCICORE_HOSTMODE if PCI select SSB_DRIVER_GPIO + select GPIOLIB default y help Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support. @@ -25,6 +27,7 @@ config BCM47XX_BCMA select BCMA_HOST_PCI if PCI select BCMA_DRIVER_PCI_HOSTMODE if PCI select BCMA_DRIVER_GPIO + select GPIOLIB default y help Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c index 9f883bf..33b7214 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c +++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c @@ -30,6 +30,7 @@ * measurement, and debugging facilities. */ +#include <linux/compiler.h> #include <linux/irqflags.h> #include <asm/octeon/cvmx.h> #include <asm/octeon/cvmx-l2c.h> @@ -285,22 +286,22 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter) */ static void fault_in(uint64_t addr, int len) { - volatile char *ptr; - volatile char dummy; + char *ptr; + /* * Adjust addr and length so we get all cache lines even for * small ranges spanning two cache lines. */ len += addr & CVMX_CACHE_LINE_MASK; addr &= ~CVMX_CACHE_LINE_MASK; - ptr = (volatile char *)cvmx_phys_to_ptr(addr); + ptr = cvmx_phys_to_ptr(addr); /* * Invalidate L1 cache to make sure all loads result in data * being in L2. */ CVMX_DCACHE_INVALIDATE; while (len > 0) { - dummy += *ptr; + ACCESS_ONCE(*ptr); len -= CVMX_CACHE_LINE_SIZE; ptr += CVMX_CACHE_LINE_SIZE; } diff --git a/arch/mips/include/asm/dsp.h b/arch/mips/include/asm/dsp.h index e9bfc08..7bfad05 100644 --- a/arch/mips/include/asm/dsp.h +++ b/arch/mips/include/asm/dsp.h @@ -16,7 +16,7 @@ #include <asm/mipsregs.h> #define DSP_DEFAULT 0x00000000 -#define DSP_MASK 0x3ff +#define DSP_MASK 0x3f #define __enable_dsp_hazard() \ do { \ diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h index ab84064..33c34adb 100644 --- a/arch/mips/include/asm/inst.h +++ b/arch/mips/include/asm/inst.h @@ -353,6 +353,7 @@ union mips_instruction { struct u_format u_format; struct c_format c_format; struct r_format r_format; + struct p_format p_format; struct f_format f_format; struct ma_format ma_format; struct b_format b_format; diff --git a/arch/mips/include/asm/mach-pnx833x/war.h b/arch/mips/include/asm/mach-pnx833x/war.h index edaa06d..e410df4 100644 --- a/arch/mips/include/asm/mach-pnx833x/war.h +++ b/arch/mips/include/asm/mach-pnx833x/war.h @@ -21,4 +21,4 @@ #define R10000_LLSC_WAR 0 #define MIPS34K_MISSED_ITLB_WAR 0 -#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */ +#endif /* __ASM_MIPS_MACH_PNX833X_WAR_H */ diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index c631910..013d5f7 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -230,6 +230,7 @@ static inline void pud_clear(pud_t *pudp) #else #define pte_pfn(x) ((unsigned long)((x).pte >> _PFN_SHIFT)) #define pfn_pte(pfn, prot) __pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot)) #endif #define __pgd_offset(address) pgd_index(address) diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index a1a0452..77d4fb3 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -3,6 +3,7 @@ include include/uapi/asm-generic/Kbuild.asm header-y += auxvec.h header-y += bitsperlong.h +header-y += break.h header-y += byteorder.h header-y += cachectl.h header-y += errno.h diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/uapi/asm/break.h index 9161e68..9161e68 100644 --- a/arch/mips/include/asm/break.h +++ b/arch/mips/include/uapi/asm/break.h diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 6a2d758..83fa146 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -25,6 +25,12 @@ #define MCOUNT_OFFSET_INSNS 4 #endif +/* Arch override because MIPS doesn't need to run this from stop_machine() */ +void arch_ftrace_update_code(int command) +{ + ftrace_modify_all_code(command); +} + /* * Check if the address is in kernel space * @@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) return 0; } +#ifndef CONFIG_64BIT +static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1, + unsigned int new_code2) +{ + int faulted; + + safe_store_code(new_code1, ip, faulted); + if (unlikely(faulted)) + return -EFAULT; + ip += 4; + safe_store_code(new_code2, ip, faulted); + if (unlikely(faulted)) + return -EFAULT; + flush_icache_range(ip, ip + 8); /* original ip + 12 */ + return 0; +} +#endif + /* * The details about the calling site of mcount on MIPS * @@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod, * needed. */ new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; - +#ifdef CONFIG_64BIT return ftrace_modify_code(ip, new); +#else + /* + * On 32 bit MIPS platforms, gcc adds a stack adjust + * instruction in the delay slot after the branch to + * mcount and expects mcount to restore the sp on return. + * This is based on a legacy API and does nothing but + * waste instructions so it's being removed at runtime. + */ + return ftrace_modify_code_2(ip, new, INSN_NOP); +#endif } int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 4c968e7..1658676 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -46,9 +46,8 @@ PTR_L a5, PT_R9(sp) PTR_L a6, PT_R10(sp) PTR_L a7, PT_R11(sp) - PTR_ADDIU sp, PT_SIZE #else - PTR_ADDIU sp, (PT_SIZE + 8) + PTR_ADDIU sp, PT_SIZE #endif .endm @@ -69,7 +68,9 @@ NESTED(ftrace_caller, PT_SIZE, ra) .globl _mcount _mcount: b ftrace_stub - nop + addiu sp,sp,8 + + /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ lw t1, function_trace_stop bnez t1, ftrace_stub nop diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index eec690a..147cec1 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -705,7 +705,7 @@ static int vpe_run(struct vpe * v) printk(KERN_WARNING "VPE loader: TC %d is already in use.\n", - t->index); + v->tc->index); return -ENOEXEC; } } else { diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index f36acd1..a7935bf 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -408,7 +408,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) #endif /* tell oprofile which irq to use */ - cp0_perfcount_irq = LTQ_PERF_IRQ; + cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ); /* * if the timer irq is not one of the mips irqs we need to diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c index dc81ca8..288f795 100644 --- a/arch/mips/lib/delay.c +++ b/arch/mips/lib/delay.c @@ -21,7 +21,7 @@ void __delay(unsigned long loops) " .set noreorder \n" " .align 3 \n" "1: bnez %0, 1b \n" -#if __SIZEOF_LONG__ == 4 +#if BITS_PER_LONG == 32 " subu %0, 1 \n" #else " dsubu %0, 1 \n" diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index 7657fd2..cacfd31 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -190,9 +190,3 @@ void __iounmap(const volatile void __iomem *addr) EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__iounmap); - -int __virt_addr_valid(const volatile void *kaddr) -{ - return pfn_valid(PFN_DOWN(virt_to_phys(kaddr))); -} -EXPORT_SYMBOL_GPL(__virt_addr_valid); diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index d9be754..7e5fe27 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -192,3 +192,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) return ret; } + +int __virt_addr_valid(const volatile void *kaddr) +{ + return pfn_valid(PFN_DOWN(virt_to_phys(kaddr))); +} +EXPORT_SYMBOL_GPL(__virt_addr_valid); diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index 4e7f49d..c5ce699 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -193,8 +193,11 @@ static void nlm_init_node(void) void __init prom_init(void) { - int i, *argv, *envp; /* passed as 32 bit ptrs */ + int *argv, *envp; /* passed as 32 bit ptrs */ struct psb_info *prom_infop; +#ifdef CONFIG_SMP + int i; +#endif /* truncate to 32 bit and sign extend all args */ argv = (int *)(long)(int)fw_arg1; diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 1552522..6eaa4f2 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -24,7 +24,7 @@ #include <asm/mach-ath79/pci.h> #define AR71XX_PCI_MEM_BASE 0x10000000 -#define AR71XX_PCI_MEM_SIZE 0x08000000 +#define AR71XX_PCI_MEM_SIZE 0x07000000 #define AR71XX_PCI_WIN0_OFFS 0x10000000 #define AR71XX_PCI_WIN1_OFFS 0x11000000 diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 86d77a6..c11c75b 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -21,7 +21,7 @@ #define AR724X_PCI_CTRL_SIZE 0x100 #define AR724X_PCI_MEM_BASE 0x10000000 -#define AR724X_PCI_MEM_SIZE 0x08000000 +#define AR724X_PCI_MEM_SIZE 0x04000000 #define AR724X_PCI_REG_RESET 0x18 #define AR724X_PCI_REG_INT_STATUS 0x4c diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index d22e73e..e514de5 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -439,6 +439,8 @@ ret_from_fork: ret_from_kernel_thread: REST_NVGPRS(r1) bl schedule_tail + li r3,0 + stw r3,0(r1) mtlr r14 mr r3,r15 PPC440EP_ERR42 diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index b310a05..3d990d3 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -664,6 +664,19 @@ resume_kernel: ld r4,TI_FLAGS(r9) andi. r0,r4,_TIF_NEED_RESCHED bne 1b + + /* + * arch_local_irq_restore() from preempt_schedule_irq above may + * enable hard interrupt but we really should disable interrupts + * when we return from the interrupt, and so that we don't get + * interrupted after loading SRR0/1. + */ +#ifdef CONFIG_PPC_BOOK3E + wrteei 0 +#else + ld r10,PACAKMSR(r13) /* Get kernel MSR without EE */ + mtmsrd r10,1 /* Update machine state */ +#endif /* CONFIG_PPC_BOOK3E */ #endif /* CONFIG_PREEMPT */ .globl fast_exc_return_irq diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index c470a40..a7bc752 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -154,12 +154,12 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) static int kgdb_singlestep(struct pt_regs *regs) { struct thread_info *thread_info, *exception_thread_info; - struct thread_info *backup_current_thread_info = \ - (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL); + struct thread_info *backup_current_thread_info; if (user_mode(regs)) return 0; + backup_current_thread_info = (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL); /* * On Book E and perhaps other processors, singlestep is handled on * the critical exception stack. This causes current_thread_info() @@ -185,6 +185,7 @@ static int kgdb_singlestep(struct pt_regs *regs) /* Restore current_thread_info lastly. */ memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info); + kfree(backup_current_thread_info); return 1; } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6f6b1cc..127361e 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -494,10 +494,15 @@ void timer_interrupt(struct pt_regs * regs) set_dec(DECREMENTER_MAX); /* Some implementations of hotplug will get timer interrupts while - * offline, just ignore these + * offline, just ignore these and we also need to set + * decrementers_next_tb as MAX to make sure __check_irq_replay + * don't replay timer interrupt when return, otherwise we'll trap + * here infinitely :( */ - if (!cpu_online(smp_processor_id())) + if (!cpu_online(smp_processor_id())) { + *next_tb = ~(u64)0; return; + } /* Conditionally hard-enable interrupts now that the DEC has been * bumped to its maximum value diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 315f949..f444b94 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -52,7 +52,7 @@ static int power7_marked_instr_event(u64 mmcr1) for (pmc = 0; pmc < 4; pmc++) { psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK << (OPROFILE_MAX_PMC_NUM - pmc) - * OPROFILE_MAX_PMC_NUM); + * OPROFILE_PMSEL_FIELD_WIDTH); psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc) * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL; unit = mmcr1 & (OPROFILE_PM_UNIT_MSK diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 95d0017..890f30e 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -236,6 +236,13 @@ out: static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) { + /* + * We don't support CPU hotplug. Don't unmap after the system + * has already made it to a running state. + */ + if (system_state != SYSTEM_BOOTING) + return 0; + if (sdcasr_mapbase) iounmap(sdcasr_mapbase); if (sdcpwr_mapbase) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index c1d7930..098adbb 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1365,6 +1365,18 @@ static inline void pmdp_invalidate(struct vm_area_struct *vma, __pmd_idte(address, pmdp); } +#define __HAVE_ARCH_PMDP_SET_WRPROTECT +static inline void pmdp_set_wrprotect(struct mm_struct *mm, + unsigned long address, pmd_t *pmdp) +{ + pmd_t pmd = *pmdp; + + if (pmd_write(pmd)) { + __pmd_idte(address, pmdp); + set_pmd_at(mm, address, pmdp, pmd_wrprotect(pmd)); + } +} + static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot) { pmd_t __pmd; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 79795af..225543b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2138,6 +2138,7 @@ config OLPC_XO1_RTC config OLPC_XO1_SCI bool "OLPC XO-1 SCI extras" depends on OLPC && OLPC_XO1_PM + depends on INPUT=y select POWER_SUPPLY select GPIO_CS5535 select MFD_CORE diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index ccce0ed..379814b 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -71,7 +71,7 @@ GCOV_PROFILE := n $(obj)/bzImage: asflags-y := $(SVGA_MODE) quiet_cmd_image = BUILD $@ -cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@ +cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@ $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE $(call if_changed,image) @@ -92,7 +92,7 @@ targets += voffset.h $(obj)/voffset.h: vmlinux FORCE $(call if_changed,voffset) -sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' +sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p' quiet_cmd_zoffset = ZOFFSET $@ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 18e329c..f8fa411 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -256,10 +256,10 @@ static efi_status_t setup_efi_pci(struct boot_params *params) int i; struct setup_data *data; - data = (struct setup_data *)params->hdr.setup_data; + data = (struct setup_data *)(unsigned long)params->hdr.setup_data; while (data && data->next) - data = (struct setup_data *)data->next; + data = (struct setup_data *)(unsigned long)data->next; status = efi_call_phys5(sys_table->boottime->locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, @@ -295,16 +295,18 @@ static efi_status_t setup_efi_pci(struct boot_params *params) if (!pci) continue; +#ifdef CONFIG_X86_64 status = efi_call_phys4(pci->attributes, pci, EfiPciIoAttributeOperationGet, 0, &attributes); - +#else + status = efi_call_phys5(pci->attributes, pci, + EfiPciIoAttributeOperationGet, 0, 0, + &attributes); +#endif if (status != EFI_SUCCESS) continue; - if (!(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)) - continue; - if (!pci->romimage || !pci->romsize) continue; @@ -345,9 +347,9 @@ static efi_status_t setup_efi_pci(struct boot_params *params) memcpy(rom->romdata, pci->romimage, pci->romsize); if (data) - data->next = (uint64_t)rom; + data->next = (unsigned long)rom; else - params->hdr.setup_data = (uint64_t)rom; + params->hdr.setup_data = (unsigned long)rom; data = (struct setup_data *)rom; @@ -432,10 +434,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, * Once we've found a GOP supporting ConOut, * don't bother looking any further. */ + first_gop = gop; if (conout_found) break; - - first_gop = gop; } } diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index aa4aaf1..1e3184f 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -35,11 +35,11 @@ ENTRY(startup_32) #ifdef CONFIG_EFI_STUB jmp preferred_addr - .balign 0x10 /* * We don't need the return address, so set up the stack so - * efi_main() can find its arugments. + * efi_main() can find its arguments. */ +ENTRY(efi_pe_entry) add $0x4, %esp call make_boot_params @@ -50,8 +50,10 @@ ENTRY(startup_32) pushl %eax pushl %esi pushl %ecx + sub $0x4, %esp - .org 0x30,0x90 +ENTRY(efi_stub_entry) + add $0x4, %esp call efi_main cmpl $0, %eax movl %eax, %esi diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 2c4b171..f5d1aaa 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -201,12 +201,12 @@ ENTRY(startup_64) */ #ifdef CONFIG_EFI_STUB /* - * The entry point for the PE/COFF executable is 0x210, so only - * legacy boot loaders will execute this jmp. + * The entry point for the PE/COFF executable is efi_pe_entry, so + * only legacy boot loaders will execute this jmp. */ jmp preferred_addr - .org 0x210 +ENTRY(efi_pe_entry) mov %rcx, %rdi mov %rdx, %rsi pushq %rdi @@ -218,7 +218,7 @@ ENTRY(startup_64) popq %rsi popq %rdi - .org 0x230,0x90 +ENTRY(efi_stub_entry) call efi_main movq %rax,%rsi cmpq $0,%rax diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 8c132a6..944ce59 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -21,6 +21,7 @@ #include <asm/e820.h> #include <asm/page_types.h> #include <asm/setup.h> +#include <asm/bootparam.h> #include "boot.h" #include "voffset.h" #include "zoffset.h" @@ -255,6 +256,9 @@ section_table: # header, from the old boot sector. .section ".header", "a" + .globl sentinel +sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */ + .globl hdr hdr: setup_sects: .byte 0 /* Filled in by build.c */ @@ -279,7 +283,7 @@ _start: # Part 2 of the header, from the old setup.S .ascii "HdrS" # header signature - .word 0x020b # header version number (>= 0x0105) + .word 0x020c # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) .globl realmode_swtch realmode_swtch: .word 0, 0 # default_switch, SETUPSEG @@ -297,13 +301,7 @@ type_of_loader: .byte 0 # 0 means ancient bootloader, newer # flags, unused bits must be zero (RFU) bit within loadflags loadflags: -LOADED_HIGH = 1 # If set, the kernel is loaded high -CAN_USE_HEAP = 0x80 # If set, the loader also has set - # heap_end_ptr to tell how much - # space behind setup.S can be used for - # heap purposes. - # Only the loader knows what is free - .byte LOADED_HIGH + .byte LOADED_HIGH # The kernel is to be loaded high setup_move_size: .word 0x8000 # size to move, when setup is not # loaded at 0x90000. We will move setup @@ -369,7 +367,23 @@ relocatable_kernel: .byte 1 relocatable_kernel: .byte 0 #endif min_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment -pad3: .word 0 + +xloadflags: +#ifdef CONFIG_X86_64 +# define XLF0 XLF_KERNEL_64 /* 64-bit kernel */ +#else +# define XLF0 0 +#endif +#ifdef CONFIG_EFI_STUB +# ifdef CONFIG_X86_64 +# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */ +# else +# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */ +# endif +#else +# define XLF23 0 +#endif + .word XLF0 | XLF23 cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, #added with boot protocol @@ -397,8 +411,13 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr #define INIT_SIZE VO_INIT_SIZE #endif init_size: .long INIT_SIZE # kernel initialization size -handover_offset: .long 0x30 # offset to the handover +handover_offset: +#ifdef CONFIG_EFI_STUB + .long 0x30 # offset to the handover # protocol entry point +#else + .long 0 +#endif # End of setup header ##################################################### diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld index 03c0683..96a6c75 100644 --- a/arch/x86/boot/setup.ld +++ b/arch/x86/boot/setup.ld @@ -13,7 +13,7 @@ SECTIONS .bstext : { *(.bstext) } .bsdata : { *(.bsdata) } - . = 497; + . = 495; .header : { *(.header) } .entrytext : { *(.entrytext) } .inittext : { *(.inittext) } diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 4b8e165..94c5446 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -52,6 +52,10 @@ int is_big_kernel; #define PECOFF_RELOC_RESERVE 0x20 +unsigned long efi_stub_entry; +unsigned long efi_pe_entry; +unsigned long startup_64; + /*----------------------------------------------------------------------*/ static const u32 crctab32[] = { @@ -132,7 +136,7 @@ static void die(const char * str, ...) static void usage(void) { - die("Usage: build setup system [> image]"); + die("Usage: build setup system [zoffset.h] [> image]"); } #ifdef CONFIG_EFI_STUB @@ -206,30 +210,54 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) */ put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); -#ifdef CONFIG_X86_32 /* - * Address of entry point. - * - * The EFI stub entry point is +16 bytes from the start of - * the .text section. + * Address of entry point for PE/COFF executable */ - put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]); -#else - /* - * Address of entry point. startup_32 is at the beginning and - * the 64-bit entry point (startup_64) is always 512 bytes - * after. The EFI stub entry point is 16 bytes after that, as - * the first instruction allows legacy loaders to jump over - * the EFI stub initialisation - */ - put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]); -#endif /* CONFIG_X86_32 */ + put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]); update_pecoff_section_header(".text", text_start, text_sz); } #endif /* CONFIG_EFI_STUB */ + +/* + * Parse zoffset.h and find the entry points. We could just #include zoffset.h + * but that would mean tools/build would have to be rebuilt every time. It's + * not as if parsing it is hard... + */ +#define PARSE_ZOFS(p, sym) do { \ + if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \ + sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \ +} while (0) + +static void parse_zoffset(char *fname) +{ + FILE *file; + char *p; + int c; + + file = fopen(fname, "r"); + if (!file) + die("Unable to open `%s': %m", fname); + c = fread(buf, 1, sizeof(buf) - 1, file); + if (ferror(file)) + die("read-error on `zoffset.h'"); + buf[c] = 0; + + p = (char *)buf; + + while (p && *p) { + PARSE_ZOFS(p, efi_stub_entry); + PARSE_ZOFS(p, efi_pe_entry); + PARSE_ZOFS(p, startup_64); + + p = strchr(p, '\n'); + while (p && (*p == '\r' || *p == '\n')) + p++; + } +} + int main(int argc, char ** argv) { unsigned int i, sz, setup_sectors; @@ -241,7 +269,19 @@ int main(int argc, char ** argv) void *kernel; u32 crc = 0xffffffffUL; - if (argc != 3) + /* Defaults for old kernel */ +#ifdef CONFIG_X86_32 + efi_pe_entry = 0x10; + efi_stub_entry = 0x30; +#else + efi_pe_entry = 0x210; + efi_stub_entry = 0x230; + startup_64 = 0x200; +#endif + + if (argc == 4) + parse_zoffset(argv[3]); + else if (argc != 3) usage(); /* Copy the setup code */ @@ -299,6 +339,11 @@ int main(int argc, char ** argv) #ifdef CONFIG_EFI_STUB update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); + +#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ + efi_stub_entry -= 0x200; +#endif + put_unaligned_le32(efi_stub_entry, &buf[0x264]); #endif crc = partial_crc32(buf, i, crc); diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 6e8fdf5..28677c5 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; +extern unsigned long x86_efi_facility; extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index b47c2a8..062921e 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -16,7 +16,7 @@ extern void uv_system_init(void); extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long start, - unsigned end, + unsigned long end, unsigned int cpu); #else /* X86_UV */ diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index 92862cd..c15ddaf 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -1,6 +1,31 @@ #ifndef _ASM_X86_BOOTPARAM_H #define _ASM_X86_BOOTPARAM_H +/* setup_data types */ +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 +#define SETUP_DTB 2 +#define SETUP_PCI 3 + +/* ram_size flags */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + +/* loadflags */ +#define LOADED_HIGH (1<<0) +#define QUIET_FLAG (1<<5) +#define KEEP_SEGMENTS (1<<6) +#define CAN_USE_HEAP (1<<7) + +/* xloadflags */ +#define XLF_KERNEL_64 (1<<0) +#define XLF_CAN_BE_LOADED_ABOVE_4G (1<<1) +#define XLF_EFI_HANDOVER_32 (1<<2) +#define XLF_EFI_HANDOVER_64 (1<<3) + +#ifndef __ASSEMBLY__ + #include <linux/types.h> #include <linux/screen_info.h> #include <linux/apm_bios.h> @@ -9,12 +34,6 @@ #include <asm/ist.h> #include <video/edid.h> -/* setup data types */ -#define SETUP_NONE 0 -#define SETUP_E820_EXT 1 -#define SETUP_DTB 2 -#define SETUP_PCI 3 - /* extensible setup data list node */ struct setup_data { __u64 next; @@ -28,9 +47,6 @@ struct setup_header { __u16 root_flags; __u32 syssize; __u16 ram_size; -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 __u16 vid_mode; __u16 root_dev; __u16 boot_flag; @@ -42,10 +58,6 @@ struct setup_header { __u16 kernel_version; __u8 type_of_loader; __u8 loadflags; -#define LOADED_HIGH (1<<0) -#define QUIET_FLAG (1<<5) -#define KEEP_SEGMENTS (1<<6) -#define CAN_USE_HEAP (1<<7) __u16 setup_move_size; __u32 code32_start; __u32 ramdisk_image; @@ -58,7 +70,8 @@ struct setup_header { __u32 initrd_addr_max; __u32 kernel_alignment; __u8 relocatable_kernel; - __u8 _pad2[3]; + __u8 min_alignment; + __u16 xloadflags; __u32 cmdline_size; __u32 hardware_subarch; __u64 hardware_subarch_data; @@ -106,7 +119,10 @@ struct boot_params { __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */ struct sys_desc_table sys_desc_table; /* 0x0a0 */ struct olpc_ofw_header olpc_ofw_header; /* 0x0b0 */ - __u8 _pad4[128]; /* 0x0c0 */ + __u32 ext_ramdisk_image; /* 0x0c0 */ + __u32 ext_ramdisk_size; /* 0x0c4 */ + __u32 ext_cmd_line_ptr; /* 0x0c8 */ + __u8 _pad4[116]; /* 0x0cc */ struct edid_info edid_info; /* 0x140 */ struct efi_info efi_info; /* 0x1c0 */ __u32 alt_mem_k; /* 0x1e0 */ @@ -115,7 +131,20 @@ struct boot_params { __u8 eddbuf_entries; /* 0x1e9 */ __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ __u8 kbd_status; /* 0x1eb */ - __u8 _pad6[5]; /* 0x1ec */ + __u8 _pad5[3]; /* 0x1ec */ + /* + * The sentinel is set to a nonzero value (0xff) in header.S. + * + * A bootloader is supposed to only take setup_header and put + * it into a clean boot_params buffer. If it turns out that + * it is clumsy or too generous with the buffer, it most + * probably will pick up the sentinel variable too. The fact + * that this variable then is still 0xff will let kernel + * know that some variables in boot_params are invalid and + * kernel should zero out certain portions of boot_params. + */ + __u8 sentinel; /* 0x1ef */ + __u8 _pad6[1]; /* 0x1f0 */ struct setup_header hdr; /* setup header */ /* 0x1f1 */ __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ @@ -134,6 +163,6 @@ enum { X86_NR_SUBARCHS, }; - +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_BOOTPARAM_H */ diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 07a7a04..cb3c591 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1781,6 +1781,7 @@ first_nmi: * Leave room for the "copied" frame */ subq $(5*8), %rsp + CFI_ADJUST_CFA_OFFSET 5*8 /* Copy the stack frame to the Saved frame */ .rept 5 @@ -1863,10 +1864,8 @@ end_repeat_nmi: nmi_swapgs: SWAPGS_UNSAFE_STACK nmi_restore: - RESTORE_ALL 8 - - /* Pop the extra iret frame */ - addq $(5*8), %rsp + /* Pop the extra iret frame at once */ + RESTORE_ALL 6*8 /* Clear the NMI executing stack variable */ movq $0, 5*8(%rsp) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 8e7f655..c8932c7 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -300,6 +300,12 @@ ENTRY(startup_32_smp) leal -__PAGE_OFFSET(%ecx),%esp default_entry: +#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \ + X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \ + X86_CR0_PG) + movl $(CR0_STATE & ~X86_CR0_PG),%eax + movl %eax,%cr0 + /* * New page tables may be in 4Mbyte page mode and may * be using the global pages. @@ -364,8 +370,7 @@ default_entry: */ movl $pa(initial_page_table), %eax movl %eax,%cr3 /* set the page table pointer.. */ - movl %cr0,%eax - orl $X86_CR0_PG,%eax + movl $CR0_STATE,%eax movl %eax,%cr0 /* ..and set paging (PG) bit */ ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ 1: diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index a7c5661..4929502 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file) unsigned int cpu; struct cpuinfo_x86 *c; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + cpu = iminor(file->f_path.dentry->d_inode); if (cpu >= nr_cpu_ids || !cpu_online(cpu)) return -ENXIO; /* No such CPU */ diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0f5dec5..872079a 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -56,7 +56,7 @@ struct device x86_dma_fallback_dev = { EXPORT_SYMBOL(x86_dma_fallback_dev); /* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES 32768 +#define PREALLOC_DMA_DEBUG_ENTRIES 65536 int dma_set_mask(struct device *dev, u64 mask) { diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 4e8ba39..76fa1e9 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -584,7 +584,7 @@ static void native_machine_emergency_restart(void) break; case BOOT_EFI: - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 00f6c14..8b24289 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -807,15 +807,15 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_EFI if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL32", 4)) { - efi_enabled = 1; - efi_64bit = false; + set_bit(EFI_BOOT, &x86_efi_facility); } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL64", 4)) { - efi_enabled = 1; - efi_64bit = true; + set_bit(EFI_BOOT, &x86_efi_facility); + set_bit(EFI_64BIT, &x86_efi_facility); } - if (efi_enabled && efi_memblock_x86_reserve_range()) - efi_enabled = 0; + + if (efi_enabled(EFI_BOOT)) + efi_memblock_x86_reserve_range(); #endif x86_init.oem.arch_setup(); @@ -888,7 +888,7 @@ void __init setup_arch(char **cmdline_p) finish_e820_parsing(); - if (efi_enabled) + if (efi_enabled(EFI_BOOT)) efi_init(); dmi_scan_machine(); @@ -971,7 +971,7 @@ void __init setup_arch(char **cmdline_p) * The EFI specification says that boot service code won't be called * after ExitBootServices(). This is, in fact, a lie. */ - if (efi_enabled) + if (efi_enabled(EFI_MEMMAP)) efi_reserve_boot_services(); /* preallocate 4k for mptable mpc */ @@ -1114,7 +1114,7 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) - if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) + if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; @@ -1131,14 +1131,14 @@ void __init setup_arch(char **cmdline_p) register_refined_jiffies(CLOCK_TICK_RATE); #ifdef CONFIG_EFI - /* Once setup is done above, disable efi_enabled on mismatched - * firmware/kernel archtectures since there is no support for - * runtime services. + /* Once setup is done above, unmap the EFI memory map on + * mismatched firmware/kernel archtectures since there is no + * support for runtime services. */ - if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + if (efi_enabled(EFI_BOOT) && + IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) { pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); efi_unmap_memmap(); - efi_enabled = 0; } #endif } diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ad443914..77cf009 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -51,9 +51,6 @@ #define EFI_DEBUG 1 -int efi_enabled; -EXPORT_SYMBOL(efi_enabled); - struct efi __read_mostly efi = { .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, @@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; -bool efi_64bit; - static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; static inline bool efi_is_native(void) { - return IS_ENABLED(CONFIG_X86_64) == efi_64bit; + return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); +} + +unsigned long x86_efi_facility; + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, &x86_efi_facility) != 0; } +EXPORT_SYMBOL(efi_enabled); static int __init setup_noefi(char *arg) { - efi_enabled = 0; + clear_bit(EFI_BOOT, &x86_efi_facility); return 0; } early_param("noefi", setup_noefi); @@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void) void __init efi_unmap_memmap(void) { + clear_bit(EFI_MEMMAP, &x86_efi_facility); if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); memmap.map = NULL; @@ -460,7 +467,7 @@ void __init efi_free_boot_services(void) static int __init efi_systab_init(void *phys) { - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { efi_system_table_64_t *systab64; u64 tmp = 0; @@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) void *config_tables, *tablep; int i, sz; - if (efi_64bit) + if (efi_enabled(EFI_64BIT)) sz = sizeof(efi_config_table_64_t); else sz = sizeof(efi_config_table_32_t); @@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) efi_guid_t guid; unsigned long table; - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { u64 table64; guid = ((efi_config_table_64_t *)tablep)->guid; table64 = ((efi_config_table_64_t *)tablep)->table; @@ -684,7 +691,6 @@ void __init efi_init(void) if (boot_params.efi_info.efi_systab_hi || boot_params.efi_info.efi_memmap_hi) { pr_info("Table located above 4GB, disabling EFI.\n"); - efi_enabled = 0; return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; @@ -694,10 +700,10 @@ void __init efi_init(void) ((__u64)boot_params.efi_info.efi_systab_hi<<32)); #endif - if (efi_systab_init(efi_phys.systab)) { - efi_enabled = 0; + if (efi_systab_init(efi_phys.systab)) return; - } + + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* * Show what we know for posterity @@ -715,10 +721,10 @@ void __init efi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { - efi_enabled = 0; + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) return; - } + + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); /* * Note: We currently don't support runtime services on an EFI @@ -727,15 +733,17 @@ void __init efi_init(void) if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); - else if (efi_runtime_init()) { - efi_enabled = 0; - return; + else { + if (efi_runtime_init()) + return; + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); } - if (efi_memmap_init()) { - efi_enabled = 0; + if (efi_memmap_init()) return; - } + + set_bit(EFI_MEMMAP, &x86_efi_facility); + #ifdef CONFIG_X86_32 if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; @@ -941,7 +949,7 @@ void __init efi_enter_virtual_mode(void) * * Call EFI services through wrapper functions. */ - efi.runtime_version = efi_systab.fw_revision; + efi.runtime_version = efi_systab.hdr.revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; @@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr) efi_memory_desc_t *md; void *p; + if (!efi_enabled(EFI_MEMMAP)) + return 0; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { md = p; if ((md->phys_addr <= phys_addr) && diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 95fd505..2b20038 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -38,7 +38,7 @@ #include <asm/cacheflush.h> #include <asm/fixmap.h> -static pgd_t save_pgd __initdata; +static pgd_t *save_pgd __initdata; static unsigned long efi_flags __initdata; static void __init early_code_mapping_set_exec(int executable) @@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable) void __init efi_call_phys_prelog(void) { unsigned long vaddress; + int pgd; + int n_pgds; early_code_mapping_set_exec(1); local_irq_save(efi_flags); - vaddress = (unsigned long)__va(0x0UL); - save_pgd = *pgd_offset_k(0x0UL); - set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); + + n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); + save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); + + for (pgd = 0; pgd < n_pgds; pgd++) { + save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); + vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); + } __flush_tlb_all(); } @@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void) /* * After the lock is released, the original page table is restored. */ - set_pgd(pgd_offset_k(0x0UL), save_pgd); + int pgd; + int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); + for (pgd = 0; pgd < n_pgds; pgd++) + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); + kfree(save_pgd); __flush_tlb_all(); local_irq_restore(efi_flags); early_code_mapping_set_exec(0); diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index b8b3a37..dbbdca5 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, * globally purge translation cache of a virtual address or all TLB's * @cpumask: mask of all cpu's in which the address is to be removed * @mm: mm_struct containing virtual address range - * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) + * @start: start virtual address to be removed from TLB + * @end: end virtual address to be remove from TLB * @cpu: the current cpu * * This is the entry point for initiating any UV global TLB shootdown. @@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, */ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long start, - unsigned end, unsigned int cpu) + unsigned long end, unsigned int cpu) { int locals = 0; int remotes = 0; @@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, record_send_statistics(stat, locals, hubs, remotes, bau_desc); - bau_desc->payload.address = start; + if (!end || (end - start) <= PAGE_SIZE) + bau_desc->payload.address = start; + else + bau_desc->payload.address = TLB_FLUSH_ALL; bau_desc->payload.sending_cpu = cpu; /* * uv_flush_send_and_wait returns 0 if all cpu's were messaged, diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index 5a1847d..79d67bd 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -814,12 +814,14 @@ int main(int argc, char **argv) read_relocs(fp); if (show_absolute_syms) { print_absolute_symbols(); - return 0; + goto out; } if (show_absolute_relocs) { print_absolute_relocs(); - return 0; + goto out; } emit_relocs(as_text, use_real_mode); +out: + fclose(fp); return 0; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3ff2678..bd22f86 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) return acpi_rsdp; #endif - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index b00000e..33c9a44 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0489, 0xe057) }, + { USB_DEVICE(0x13d3, 0x3393) }, + { USB_DEVICE(0x0489, 0xe04e) }, + { USB_DEVICE(0x0489, 0xe056) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -104,10 +109,15 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a1d4ede..7e351e3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ee90e87..f0b269a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o +obj-$(CONFIG_ARCH_TEGRA) += tegra/ # Chip specific obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c index e69991a..792bc57 100644 --- a/drivers/clk/clk-bcm2835.c +++ b/drivers/clk/clk-bcm2835.c @@ -20,6 +20,13 @@ #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/clk/bcm2835.h> +#include <linux/clk-provider.h> +#include <linux/of.h> + +static const __initconst struct of_device_id clk_match[] = { + { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, + { } +}; /* * These are fixed clocks. They're probably not all root clocks and it may @@ -56,4 +63,6 @@ void __init bcm2835_init_clocks(void) ret = clk_register_clkdev(clk, NULL, "20215000.uart"); if (ret) pr_err("uart1_pclk alias not registered\n"); + + of_clk_init(clk_match); } diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile new file mode 100644 index 0000000..2b41b0f --- /dev/null +++ b/drivers/clk/tegra/Makefile @@ -0,0 +1,11 @@ +obj-y += clk.o +obj-y += clk-audio-sync.o +obj-y += clk-divider.o +obj-y += clk-periph.o +obj-y += clk-periph-gate.o +obj-y += clk-pll.o +obj-y += clk-pll-out.o +obj-y += clk-super.o + +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o +obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o diff --git a/drivers/clk/tegra/clk-audio-sync.c b/drivers/clk/tegra/clk-audio-sync.c new file mode 100644 index 0000000..c0f7843 --- /dev/null +++ b/drivers/clk/tegra/clk-audio-sync.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk-provider.h> +#include <linux/slab.h> +#include <linux/err.h> + +#include "clk.h" + +static unsigned long clk_sync_source_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_sync_source *sync = to_clk_sync_source(hw); + + return sync->rate; +} + +static long clk_sync_source_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct tegra_clk_sync_source *sync = to_clk_sync_source(hw); + + if (rate > sync->max_rate) + return -EINVAL; + else + return rate; +} + +static int clk_sync_source_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tegra_clk_sync_source *sync = to_clk_sync_source(hw); + + sync->rate = rate; + return 0; +} + +const struct clk_ops tegra_clk_sync_source_ops = { + .round_rate = clk_sync_source_round_rate, + .set_rate = clk_sync_source_set_rate, + .recalc_rate = clk_sync_source_recalc_rate, +}; + +struct clk *tegra_clk_register_sync_source(const char *name, + unsigned long rate, unsigned long max_rate) +{ + struct tegra_clk_sync_source *sync; + struct clk_init_data init; + struct clk *clk; + + sync = kzalloc(sizeof(*sync), GFP_KERNEL); + if (!sync) { + pr_err("%s: could not allocate sync source clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + sync->rate = rate; + sync->max_rate = max_rate; + + init.ops = &tegra_clk_sync_source_ops; + init.name = name; + init.flags = CLK_IS_ROOT; + init.parent_names = NULL; + init.num_parents = 0; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + sync->hw.init = &init; + + clk = clk_register(NULL, &sync->hw); + if (IS_ERR(clk)) + kfree(sync); + + return clk; +} diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c new file mode 100644 index 0000000..4d75b1f --- /dev/null +++ b/drivers/clk/tegra/clk-divider.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/clk.h> + +#include "clk.h" + +#define pll_out_override(p) (BIT((p->shift - 6))) +#define div_mask(d) ((1 << (d->width)) - 1) +#define get_mul(d) (1 << d->frac_width) +#define get_max_div(d) div_mask(d) + +#define PERIPH_CLK_UART_DIV_ENB BIT(24) + +static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, + unsigned long parent_rate) +{ + s64 divider_ux1 = parent_rate; + u8 flags = divider->flags; + int mul; + + if (!rate) + return 0; + + mul = get_mul(divider); + + if (!(flags & TEGRA_DIVIDER_INT)) + divider_ux1 *= mul; + + if (flags & TEGRA_DIVIDER_ROUND_UP) + divider_ux1 += rate - 1; + + do_div(divider_ux1, rate); + + if (flags & TEGRA_DIVIDER_INT) + divider_ux1 *= mul; + + divider_ux1 -= mul; + + if (divider_ux1 < 0) + return 0; + + if (divider_ux1 > get_max_div(divider)) + return -EINVAL; + + return divider_ux1; +} + +static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + u32 reg; + int div, mul; + u64 rate = parent_rate; + + reg = readl_relaxed(divider->reg) >> divider->shift; + div = reg & div_mask(divider); + + mul = get_mul(divider); + div += mul; + + rate *= mul; + rate += div - 1; + do_div(rate, div); + + return rate; +} + +static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + int div, mul; + unsigned long output_rate = *prate; + + if (!rate) + return output_rate; + + div = get_div(divider, rate, output_rate); + if (div < 0) + return *prate; + + mul = get_mul(divider); + + return DIV_ROUND_UP(output_rate * mul, div + mul); +} + +static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + int div; + unsigned long flags = 0; + u32 val; + + div = get_div(divider, rate, parent_rate); + if (div < 0) + return div; + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + + val = readl_relaxed(divider->reg); + val &= ~(div_mask(divider) << divider->shift); + val |= div << divider->shift; + + if (divider->flags & TEGRA_DIVIDER_UART) { + if (div) + val |= PERIPH_CLK_UART_DIV_ENB; + else + val &= ~PERIPH_CLK_UART_DIV_ENB; + } + + if (divider->flags & TEGRA_DIVIDER_FIXED) + val |= pll_out_override(divider); + + writel_relaxed(val, divider->reg); + + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + + return 0; +} + +const struct clk_ops tegra_clk_frac_div_ops = { + .recalc_rate = clk_frac_div_recalc_rate, + .set_rate = clk_frac_div_set_rate, + .round_rate = clk_frac_div_round_rate, +}; + +struct clk *tegra_clk_register_divider(const char *name, + const char *parent_name, void __iomem *reg, + unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width, + u8 frac_width, spinlock_t *lock) +{ + struct tegra_clk_frac_div *divider; + struct clk *clk; + struct clk_init_data init; + + divider = kzalloc(sizeof(*divider), GFP_KERNEL); + if (!divider) { + pr_err("%s: could not allocate fractional divider clk\n", + __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.ops = &tegra_clk_frac_div_ops; + init.flags = flags; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + + divider->reg = reg; + divider->shift = shift; + divider->width = width; + divider->frac_width = frac_width; + divider->lock = lock; + divider->flags = clk_divider_flags; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + divider->hw.init = &init; + + clk = clk_register(NULL, ÷r->hw); + if (IS_ERR(clk)) + kfree(divider); + + return clk; +} diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c new file mode 100644 index 0000000..6dd5332 --- /dev/null +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/tegra-soc.h> + +#include "clk.h" + +static DEFINE_SPINLOCK(periph_ref_lock); + +/* Macros to assist peripheral gate clock */ +#define read_enb(gate) \ + readl_relaxed(gate->clk_base + (gate->regs->enb_reg)) +#define write_enb_set(val, gate) \ + writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg)) +#define write_enb_clr(val, gate) \ + writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg)) + +#define read_rst(gate) \ + readl_relaxed(gate->clk_base + (gate->regs->rst_reg)) +#define write_rst_set(val, gate) \ + writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg)) +#define write_rst_clr(val, gate) \ + writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg)) + +#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32)) + +/* Peripheral gate clock ops */ +static int clk_periph_is_enabled(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + int state = 1; + + if (!(read_enb(gate) & periph_clk_to_bit(gate))) + state = 0; + + if (!(gate->flags & TEGRA_PERIPH_NO_RESET)) + if (read_rst(gate) & periph_clk_to_bit(gate)) + state = 0; + + return state; +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + gate->enable_refcnt[gate->clk_num]++; + if (gate->enable_refcnt[gate->clk_num] > 1) { + spin_unlock_irqrestore(&periph_ref_lock, flags); + return 0; + } + + write_enb_set(periph_clk_to_bit(gate), gate); + udelay(2); + + if (!(gate->flags & TEGRA_PERIPH_NO_RESET) && + !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) { + if (read_rst(gate) & periph_clk_to_bit(gate)) { + udelay(5); /* reset propogation delay */ + write_rst_clr(periph_clk_to_bit(gate), gate); + } + } + + spin_unlock_irqrestore(&periph_ref_lock, flags); + + return 0; +} + +static void clk_periph_disable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + gate->enable_refcnt[gate->clk_num]--; + if (gate->enable_refcnt[gate->clk_num] > 0) { + spin_unlock_irqrestore(&periph_ref_lock, flags); + return; + } + + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_enb_clr(periph_clk_to_bit(gate), gate); + + spin_unlock_irqrestore(&periph_ref_lock, flags); +} + +void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert) +{ + if (gate->flags & TEGRA_PERIPH_NO_RESET) + return; + + if (assert) { + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_rst_set(periph_clk_to_bit(gate), gate); + } else { + write_rst_clr(periph_clk_to_bit(gate), gate); + } +} + +const struct clk_ops tegra_clk_periph_gate_ops = { + .is_enabled = clk_periph_is_enabled, + .enable = clk_periph_enable, + .disable = clk_periph_disable, +}; + +struct clk *tegra_clk_register_periph_gate(const char *name, + const char *parent_name, u8 gate_flags, void __iomem *clk_base, + unsigned long flags, int clk_num, + struct tegra_clk_periph_regs *pregs, int *enable_refcnt) +{ + struct tegra_clk_periph_gate *gate; + struct clk *clk; + struct clk_init_data init; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + pr_err("%s: could not allocate periph gate clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.flags = flags; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = &tegra_clk_periph_gate_ops; + + gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC; + gate->clk_base = clk_base; + gate->clk_num = clk_num; + gate->flags = gate_flags; + gate->enable_refcnt = enable_refcnt; + gate->regs = pregs; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + gate->hw.init = &init; + + clk = clk_register(NULL, &gate->hw); + if (IS_ERR(clk)) + kfree(gate); + + return clk; +} diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c new file mode 100644 index 0000000..788486e6 --- /dev/null +++ b/drivers/clk/tegra/clk-periph.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/slab.h> +#include <linux/err.h> + +#include "clk.h" + +static u8 clk_periph_get_parent(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *mux_ops = periph->mux_ops; + struct clk_hw *mux_hw = &periph->mux.hw; + + mux_hw->clk = hw->clk; + + return mux_ops->get_parent(mux_hw); +} + +static int clk_periph_set_parent(struct clk_hw *hw, u8 index) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *mux_ops = periph->mux_ops; + struct clk_hw *mux_hw = &periph->mux.hw; + + mux_hw->clk = hw->clk; + + return mux_ops->set_parent(mux_hw, index); +} + +static unsigned long clk_periph_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *div_ops = periph->div_ops; + struct clk_hw *div_hw = &periph->divider.hw; + + div_hw->clk = hw->clk; + + return div_ops->recalc_rate(div_hw, parent_rate); +} + +static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *div_ops = periph->div_ops; + struct clk_hw *div_hw = &periph->divider.hw; + + div_hw->clk = hw->clk; + + return div_ops->round_rate(div_hw, rate, prate); +} + +static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *div_ops = periph->div_ops; + struct clk_hw *div_hw = &periph->divider.hw; + + div_hw->clk = hw->clk; + + return div_ops->set_rate(div_hw, rate, parent_rate); +} + +static int clk_periph_is_enabled(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_hw->clk = hw->clk; + + return gate_ops->is_enabled(gate_hw); +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_hw->clk = hw->clk; + + return gate_ops->enable(gate_hw); +} + +static void clk_periph_disable(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_ops->disable(gate_hw); +} + +void tegra_periph_reset_deassert(struct clk *c) +{ + struct clk_hw *hw = __clk_get_hw(c); + struct tegra_clk_periph *periph = to_clk_periph(hw); + struct tegra_clk_periph_gate *gate; + + if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) { + gate = to_clk_periph_gate(hw); + if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) { + WARN_ON(1); + return; + } + } else { + gate = &periph->gate; + } + + tegra_periph_reset(gate, 0); +} + +void tegra_periph_reset_assert(struct clk *c) +{ + struct clk_hw *hw = __clk_get_hw(c); + struct tegra_clk_periph *periph = to_clk_periph(hw); + struct tegra_clk_periph_gate *gate; + + if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) { + gate = to_clk_periph_gate(hw); + if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) { + WARN_ON(1); + return; + } + } else { + gate = &periph->gate; + } + + tegra_periph_reset(gate, 1); +} + +const struct clk_ops tegra_clk_periph_ops = { + .get_parent = clk_periph_get_parent, + .set_parent = clk_periph_set_parent, + .recalc_rate = clk_periph_recalc_rate, + .round_rate = clk_periph_round_rate, + .set_rate = clk_periph_set_rate, + .is_enabled = clk_periph_is_enabled, + .enable = clk_periph_enable, + .disable = clk_periph_disable, +}; + +const struct clk_ops tegra_clk_periph_nodiv_ops = { + .get_parent = clk_periph_get_parent, + .set_parent = clk_periph_set_parent, + .is_enabled = clk_periph_is_enabled, + .enable = clk_periph_enable, + .disable = clk_periph_disable, +}; + +static struct clk *_tegra_clk_register_periph(const char *name, + const char **parent_names, int num_parents, + struct tegra_clk_periph *periph, + void __iomem *clk_base, u32 offset, bool div) +{ + struct clk *clk; + struct clk_init_data init; + + init.name = name; + init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; + init.flags = div ? 0 : CLK_SET_RATE_PARENT; + init.parent_names = parent_names; + init.num_parents = num_parents; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + periph->hw.init = &init; + periph->magic = TEGRA_CLK_PERIPH_MAGIC; + periph->mux.reg = clk_base + offset; + periph->divider.reg = div ? (clk_base + offset) : NULL; + periph->gate.clk_base = clk_base; + + clk = clk_register(NULL, &periph->hw); + if (IS_ERR(clk)) + return clk; + + periph->mux.hw.clk = clk; + periph->divider.hw.clk = div ? clk : NULL; + periph->gate.hw.clk = clk; + + return clk; +} + +struct clk *tegra_clk_register_periph(const char *name, + const char **parent_names, int num_parents, + struct tegra_clk_periph *periph, void __iomem *clk_base, + u32 offset) +{ + return _tegra_clk_register_periph(name, parent_names, num_parents, + periph, clk_base, offset, true); +} + +struct clk *tegra_clk_register_periph_nodiv(const char *name, + const char **parent_names, int num_parents, + struct tegra_clk_periph *periph, void __iomem *clk_base, + u32 offset) +{ + return _tegra_clk_register_periph(name, parent_names, num_parents, + periph, clk_base, offset, false); +} diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c new file mode 100644 index 0000000..3598987 --- /dev/null +++ b/drivers/clk/tegra/clk-pll-out.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/clk.h> + +#include "clk.h" + +#define pll_out_enb(p) (BIT(p->enb_bit_idx)) +#define pll_out_rst(p) (BIT(p->rst_bit_idx)) + +static int clk_pll_out_is_enabled(struct clk_hw *hw) +{ + struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); + u32 val = readl_relaxed(pll_out->reg); + int state; + + state = (val & pll_out_enb(pll_out)) ? 1 : 0; + if (!(val & (pll_out_rst(pll_out)))) + state = 0; + return state; +} + +static int clk_pll_out_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); + unsigned long flags = 0; + u32 val; + + if (pll_out->lock) + spin_lock_irqsave(pll_out->lock, flags); + + val = readl_relaxed(pll_out->reg); + + val |= (pll_out_enb(pll_out) | pll_out_rst(pll_out)); + + writel_relaxed(val, pll_out->reg); + udelay(2); + + if (pll_out->lock) + spin_unlock_irqrestore(pll_out->lock, flags); + + return 0; +} + +static void clk_pll_out_disable(struct clk_hw *hw) +{ + struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); + unsigned long flags = 0; + u32 val; + + if (pll_out->lock) + spin_lock_irqsave(pll_out->lock, flags); + + val = readl_relaxed(pll_out->reg); + + val &= ~(pll_out_enb(pll_out) | pll_out_rst(pll_out)); + + writel_relaxed(val, pll_out->reg); + udelay(2); + + if (pll_out->lock) + spin_unlock_irqrestore(pll_out->lock, flags); +} + +const struct clk_ops tegra_clk_pll_out_ops = { + .is_enabled = clk_pll_out_is_enabled, + .enable = clk_pll_out_enable, + .disable = clk_pll_out_disable, +}; + +struct clk *tegra_clk_register_pll_out(const char *name, + const char *parent_name, void __iomem *reg, u8 enb_bit_idx, + u8 rst_bit_idx, unsigned long flags, u8 pll_out_flags, + spinlock_t *lock) +{ + struct tegra_clk_pll_out *pll_out; + struct clk *clk; + struct clk_init_data init; + + pll_out = kzalloc(sizeof(*pll_out), GFP_KERNEL); + if (!pll_out) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &tegra_clk_pll_out_ops; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + init.flags = flags; + + pll_out->reg = reg; + pll_out->enb_bit_idx = enb_bit_idx; + pll_out->rst_bit_idx = rst_bit_idx; + pll_out->flags = pll_out_flags; + pll_out->lock = lock; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + pll_out->hw.init = &init; + + clk = clk_register(NULL, &pll_out->hw); + if (IS_ERR(clk)) + kfree(pll_out); + + return clk; +} diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c new file mode 100644 index 0000000..165f247 --- /dev/null +++ b/drivers/clk/tegra/clk-pll.c @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/clk-provider.h> +#include <linux/clk.h> + +#include "clk.h" + +#define PLL_BASE_BYPASS BIT(31) +#define PLL_BASE_ENABLE BIT(30) +#define PLL_BASE_REF_ENABLE BIT(29) +#define PLL_BASE_OVERRIDE BIT(28) + +#define PLL_BASE_DIVP_SHIFT 20 +#define PLL_BASE_DIVP_WIDTH 3 +#define PLL_BASE_DIVN_SHIFT 8 +#define PLL_BASE_DIVN_WIDTH 10 +#define PLL_BASE_DIVM_SHIFT 0 +#define PLL_BASE_DIVM_WIDTH 5 +#define PLLU_POST_DIVP_MASK 0x1 + +#define PLL_MISC_DCCON_SHIFT 20 +#define PLL_MISC_CPCON_SHIFT 8 +#define PLL_MISC_CPCON_WIDTH 4 +#define PLL_MISC_CPCON_MASK ((1 << PLL_MISC_CPCON_WIDTH) - 1) +#define PLL_MISC_LFCON_SHIFT 4 +#define PLL_MISC_LFCON_WIDTH 4 +#define PLL_MISC_LFCON_MASK ((1 << PLL_MISC_LFCON_WIDTH) - 1) +#define PLL_MISC_VCOCON_SHIFT 0 +#define PLL_MISC_VCOCON_WIDTH 4 +#define PLL_MISC_VCOCON_MASK ((1 << PLL_MISC_VCOCON_WIDTH) - 1) + +#define OUT_OF_TABLE_CPCON 8 + +#define PMC_PLLP_WB0_OVERRIDE 0xf8 +#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE BIT(12) +#define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE BIT(11) + +#define PLL_POST_LOCK_DELAY 50 + +#define PLLDU_LFCON_SET_DIVN 600 + +#define PLLE_BASE_DIVCML_SHIFT 24 +#define PLLE_BASE_DIVCML_WIDTH 4 +#define PLLE_BASE_DIVP_SHIFT 16 +#define PLLE_BASE_DIVP_WIDTH 7 +#define PLLE_BASE_DIVN_SHIFT 8 +#define PLLE_BASE_DIVN_WIDTH 8 +#define PLLE_BASE_DIVM_SHIFT 0 +#define PLLE_BASE_DIVM_WIDTH 8 + +#define PLLE_MISC_SETUP_BASE_SHIFT 16 +#define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT) +#define PLLE_MISC_LOCK_ENABLE BIT(9) +#define PLLE_MISC_READY BIT(15) +#define PLLE_MISC_SETUP_EX_SHIFT 2 +#define PLLE_MISC_SETUP_EX_MASK (3 << PLLE_MISC_SETUP_EX_SHIFT) +#define PLLE_MISC_SETUP_MASK (PLLE_MISC_SETUP_BASE_MASK | \ + PLLE_MISC_SETUP_EX_MASK) +#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT) + +#define PLLE_SS_CTRL 0x68 +#define PLLE_SS_DISABLE (7 << 10) + +#define PMC_SATA_PWRGT 0x1ac +#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) +#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) + +#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) +#define pll_readl_base(p) pll_readl(p->params->base_reg, p) +#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) + +#define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset) +#define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p) +#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) + +#define mask(w) ((1 << (w)) - 1) +#define divm_mask(p) mask(p->divm_width) +#define divn_mask(p) mask(p->divn_width) +#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \ + mask(p->divp_width)) + +#define divm_max(p) (divm_mask(p)) +#define divn_max(p) (divn_mask(p)) +#define divp_max(p) (1 << (divp_mask(p))) + +static void clk_pll_enable_lock(struct tegra_clk_pll *pll) +{ + u32 val; + + if (!(pll->flags & TEGRA_PLL_USE_LOCK)) + return; + + val = pll_readl_misc(pll); + val |= BIT(pll->params->lock_enable_bit_idx); + pll_writel_misc(val, pll); +} + +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll, + void __iomem *lock_addr, u32 lock_bit_idx) +{ + int i; + u32 val; + + if (!(pll->flags & TEGRA_PLL_USE_LOCK)) { + udelay(pll->params->lock_delay); + return 0; + } + + for (i = 0; i < pll->params->lock_delay; i++) { + val = readl_relaxed(lock_addr); + if (val & BIT(lock_bit_idx)) { + udelay(PLL_POST_LOCK_DELAY); + return 0; + } + udelay(2); /* timeout = 2 * lock time */ + } + + pr_err("%s: Timed out waiting for pll %s lock\n", __func__, + __clk_get_name(pll->hw.clk)); + + return -1; +} + +static int clk_pll_is_enabled(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val; + + if (pll->flags & TEGRA_PLLM) { + val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); + if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) + return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0; + } + + val = pll_readl_base(pll); + + return val & PLL_BASE_ENABLE ? 1 : 0; +} + +static int _clk_pll_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val; + + clk_pll_enable_lock(pll); + + val = pll_readl_base(pll); + val &= ~PLL_BASE_BYPASS; + val |= PLL_BASE_ENABLE; + pll_writel_base(val, pll); + + if (pll->flags & TEGRA_PLLM) { + val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); + val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; + writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); + } + + clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg, + pll->params->lock_bit_idx); + + return 0; +} + +static void _clk_pll_disable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val; + + val = pll_readl_base(pll); + val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); + pll_writel_base(val, pll); + + if (pll->flags & TEGRA_PLLM) { + val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE); + val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; + writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); + } +} + +static int clk_pll_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long flags = 0; + int ret; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + ret = _clk_pll_enable(hw); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} + +static void clk_pll_disable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long flags = 0; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + _clk_pll_disable(hw); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); +} + +static int _get_table_rate(struct clk_hw *hw, + struct tegra_clk_pll_freq_table *cfg, + unsigned long rate, unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_freq_table *sel; + + for (sel = pll->freq_table; sel->input_rate != 0; sel++) + if (sel->input_rate == parent_rate && + sel->output_rate == rate) + break; + + if (sel->input_rate == 0) + return -EINVAL; + + BUG_ON(sel->p < 1); + + cfg->input_rate = sel->input_rate; + cfg->output_rate = sel->output_rate; + cfg->m = sel->m; + cfg->n = sel->n; + cfg->p = sel->p; + cfg->cpcon = sel->cpcon; + + return 0; +} + +static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, + unsigned long rate, unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long cfreq; + u32 p_div = 0; + + switch (parent_rate) { + case 12000000: + case 26000000: + cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000; + break; + case 13000000: + cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000; + break; + case 16800000: + case 19200000: + cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000; + break; + case 9600000: + case 28800000: + /* + * PLL_P_OUT1 rate is not listed in PLLA table + */ + cfreq = parent_rate/(parent_rate/1000000); + break; + default: + pr_err("%s Unexpected reference rate %lu\n", + __func__, parent_rate); + BUG(); + } + + /* Raise VCO to guarantee 0.5% accuracy */ + for (cfg->output_rate = rate; cfg->output_rate < 200 * cfreq; + cfg->output_rate <<= 1) + p_div++; + + cfg->p = 1 << p_div; + cfg->m = parent_rate / cfreq; + cfg->n = cfg->output_rate / cfreq; + cfg->cpcon = OUT_OF_TABLE_CPCON; + + if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || + cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) { + pr_err("%s: Failed to set %s rate %lu\n", + __func__, __clk_get_name(hw->clk), rate); + return -EINVAL; + } + + return 0; +} + +static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, + unsigned long rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long flags = 0; + u32 divp, val, old_base; + int state; + + divp = __ffs(cfg->p); + + if (pll->flags & TEGRA_PLLU) + divp ^= 1; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + old_base = val = pll_readl_base(pll); + val &= ~((divm_mask(pll) << pll->divm_shift) | + (divn_mask(pll) << pll->divn_shift) | + (divp_mask(pll) << pll->divp_shift)); + val |= ((cfg->m << pll->divm_shift) | + (cfg->n << pll->divn_shift) | + (divp << pll->divp_shift)); + if (val == old_base) { + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + return 0; + } + + state = clk_pll_is_enabled(hw); + + if (state) { + _clk_pll_disable(hw); + val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); + } + pll_writel_base(val, pll); + + if (pll->flags & TEGRA_PLL_HAS_CPCON) { + val = pll_readl_misc(pll); + val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT); + val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT; + if (pll->flags & TEGRA_PLL_SET_LFCON) { + val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT); + if (cfg->n >= PLLDU_LFCON_SET_DIVN) + val |= 0x1 << PLL_MISC_LFCON_SHIFT; + } else if (pll->flags & TEGRA_PLL_SET_DCCON) { + val &= ~(0x1 << PLL_MISC_DCCON_SHIFT); + if (rate >= (pll->params->vco_max >> 1)) + val |= 0x1 << PLL_MISC_DCCON_SHIFT; + } + pll_writel_misc(val, pll); + } + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + if (state) + clk_pll_enable(hw); + + return 0; +} + +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_freq_table cfg; + + if (pll->flags & TEGRA_PLL_FIXED) { + if (rate != pll->fixed_rate) { + pr_err("%s: Can not change %s fixed rate %lu to %lu\n", + __func__, __clk_get_name(hw->clk), + pll->fixed_rate, rate); + return -EINVAL; + } + return 0; + } + + if (_get_table_rate(hw, &cfg, rate, parent_rate) && + _calc_rate(hw, &cfg, rate, parent_rate)) + return -EINVAL; + + return _program_pll(hw, &cfg, rate); +} + +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_freq_table cfg; + u64 output_rate = *prate; + + if (pll->flags & TEGRA_PLL_FIXED) + return pll->fixed_rate; + + /* PLLM is used for memory; we do not change rate */ + if (pll->flags & TEGRA_PLLM) + return __clk_get_rate(hw->clk); + + if (_get_table_rate(hw, &cfg, rate, *prate) && + _calc_rate(hw, &cfg, rate, *prate)) + return -EINVAL; + + output_rate *= cfg.n; + do_div(output_rate, cfg.m * cfg.p); + + return output_rate; +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val = pll_readl_base(pll); + u32 divn = 0, divm = 0, divp = 0; + u64 rate = parent_rate; + + if (val & PLL_BASE_BYPASS) + return parent_rate; + + if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) { + struct tegra_clk_pll_freq_table sel; + if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) { + pr_err("Clock %s has unknown fixed frequency\n", + __clk_get_name(hw->clk)); + BUG(); + } + return pll->fixed_rate; + } + + divp = (val >> pll->divp_shift) & (divp_mask(pll)); + if (pll->flags & TEGRA_PLLU) + divp ^= 1; + + divn = (val >> pll->divn_shift) & (divn_mask(pll)); + divm = (val >> pll->divm_shift) & (divm_mask(pll)); + divm *= (1 << divp); + + rate *= divn; + do_div(rate, divm); + return rate; +} + +static int clk_plle_training(struct tegra_clk_pll *pll) +{ + u32 val; + unsigned long timeout; + + if (!pll->pmc) + return -ENOSYS; + + /* + * PLLE is already disabled, and setup cleared; + * create falling edge on PLLE IDDQ input. + */ + val = readl(pll->pmc + PMC_SATA_PWRGT); + val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE; + writel(val, pll->pmc + PMC_SATA_PWRGT); + + val = readl(pll->pmc + PMC_SATA_PWRGT); + val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL; + writel(val, pll->pmc + PMC_SATA_PWRGT); + + val = readl(pll->pmc + PMC_SATA_PWRGT); + val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE; + writel(val, pll->pmc + PMC_SATA_PWRGT); + + val = pll_readl_misc(pll); + + timeout = jiffies + msecs_to_jiffies(100); + while (1) { + val = pll_readl_misc(pll); + if (val & PLLE_MISC_READY) + break; + if (time_after(jiffies, timeout)) { + pr_err("%s: timeout waiting for PLLE\n", __func__); + return -EBUSY; + } + udelay(300); + } + + return 0; +} + +static int clk_plle_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + struct tegra_clk_pll_freq_table sel; + u32 val; + int err; + + if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate)) + return -EINVAL; + + clk_pll_disable(hw); + + val = pll_readl_misc(pll); + val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK); + pll_writel_misc(val, pll); + + val = pll_readl_misc(pll); + if (!(val & PLLE_MISC_READY)) { + err = clk_plle_training(pll); + if (err) + return err; + } + + if (pll->flags & TEGRA_PLLE_CONFIGURE) { + /* configure dividers */ + val = pll_readl_base(pll); + val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); + val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); + val |= sel.m << pll->divm_shift; + val |= sel.n << pll->divn_shift; + val |= sel.p << pll->divp_shift; + val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; + pll_writel_base(val, pll); + } + + val = pll_readl_misc(pll); + val |= PLLE_MISC_SETUP_VALUE; + val |= PLLE_MISC_LOCK_ENABLE; + pll_writel_misc(val, pll); + + val = readl(pll->clk_base + PLLE_SS_CTRL); + val |= PLLE_SS_DISABLE; + writel(val, pll->clk_base + PLLE_SS_CTRL); + + val |= pll_readl_base(pll); + val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE); + pll_writel_base(val, pll); + + clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg, + pll->params->lock_bit_idx); + return 0; +} + +static unsigned long clk_plle_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val = pll_readl_base(pll); + u32 divn = 0, divm = 0, divp = 0; + u64 rate = parent_rate; + + divp = (val >> pll->divp_shift) & (divp_mask(pll)); + divn = (val >> pll->divn_shift) & (divn_mask(pll)); + divm = (val >> pll->divm_shift) & (divm_mask(pll)); + divm *= divp; + + rate *= divn; + do_div(rate, divm); + return rate; +} + +const struct clk_ops tegra_clk_pll_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, + .set_rate = clk_pll_set_rate, +}; + +const struct clk_ops tegra_clk_plle_ops = { + .recalc_rate = clk_plle_recalc_rate, + .is_enabled = clk_pll_is_enabled, + .disable = clk_pll_disable, + .enable = clk_plle_enable, +}; + +static struct clk *_tegra_clk_register_pll(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + unsigned long fixed_rate, + struct tegra_clk_pll_params *pll_params, u8 pll_flags, + struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock, + const struct clk_ops *ops) +{ + struct tegra_clk_pll *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = ops; + init.flags = flags; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + + pll->clk_base = clk_base; + pll->pmc = pmc; + + pll->freq_table = freq_table; + pll->params = pll_params; + pll->fixed_rate = fixed_rate; + pll->flags = pll_flags; + pll->lock = lock; + + pll->divp_shift = PLL_BASE_DIVP_SHIFT; + pll->divp_width = PLL_BASE_DIVP_WIDTH; + pll->divn_shift = PLL_BASE_DIVN_SHIFT; + pll->divn_width = PLL_BASE_DIVN_WIDTH; + pll->divm_shift = PLL_BASE_DIVM_SHIFT; + pll->divm_width = PLL_BASE_DIVM_WIDTH; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + pll->hw.init = &init; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, unsigned long fixed_rate, + struct tegra_clk_pll_params *pll_params, u8 pll_flags, + struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) +{ + return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, + flags, fixed_rate, pll_params, pll_flags, freq_table, + lock, &tegra_clk_pll_ops); +} + +struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, unsigned long fixed_rate, + struct tegra_clk_pll_params *pll_params, u8 pll_flags, + struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) +{ + return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, + flags, fixed_rate, pll_params, pll_flags, freq_table, + lock, &tegra_clk_plle_ops); +} diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c new file mode 100644 index 0000000..7ad48a8 --- /dev/null +++ b/drivers/clk/tegra/clk-super.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/clk.h> + +#include "clk.h" + +#define SUPER_STATE_IDLE 0 +#define SUPER_STATE_RUN 1 +#define SUPER_STATE_IRQ 2 +#define SUPER_STATE_FIQ 3 + +#define SUPER_STATE_SHIFT 28 +#define SUPER_STATE_MASK ((BIT(SUPER_STATE_IDLE) | BIT(SUPER_STATE_RUN) | \ + BIT(SUPER_STATE_IRQ) | BIT(SUPER_STATE_FIQ)) \ + << SUPER_STATE_SHIFT) + +#define SUPER_LP_DIV2_BYPASS (1 << 16) + +#define super_state(s) (BIT(s) << SUPER_STATE_SHIFT) +#define super_state_to_src_shift(m, s) ((m->width * s)) +#define super_state_to_src_mask(m) (((1 << m->width) - 1)) + +static u8 clk_super_get_parent(struct clk_hw *hw) +{ + struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); + u32 val, state; + u8 source, shift; + + val = readl_relaxed(mux->reg); + + state = val & SUPER_STATE_MASK; + + BUG_ON((state != super_state(SUPER_STATE_RUN)) && + (state != super_state(SUPER_STATE_IDLE))); + shift = (state == super_state(SUPER_STATE_IDLE)) ? + super_state_to_src_shift(mux, SUPER_STATE_IDLE) : + super_state_to_src_shift(mux, SUPER_STATE_RUN); + + source = (val >> shift) & super_state_to_src_mask(mux); + + /* + * If LP_DIV2_BYPASS is not set and PLLX is current parent then + * PLLX/2 is the input source to CCLKLP. + */ + if ((mux->flags & TEGRA_DIVIDER_2) && !(val & SUPER_LP_DIV2_BYPASS) && + (source == mux->pllx_index)) + source = mux->div2_index; + + return source; +} + +static int clk_super_set_parent(struct clk_hw *hw, u8 index) +{ + struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); + u32 val, state; + u8 parent_index, shift; + + val = readl_relaxed(mux->reg); + state = val & SUPER_STATE_MASK; + BUG_ON((state != super_state(SUPER_STATE_RUN)) && + (state != super_state(SUPER_STATE_IDLE))); + shift = (state == super_state(SUPER_STATE_IDLE)) ? + super_state_to_src_shift(mux, SUPER_STATE_IDLE) : + super_state_to_src_shift(mux, SUPER_STATE_RUN); + + /* + * For LP mode super-clock switch between PLLX direct + * and divided-by-2 outputs is allowed only when other + * than PLLX clock source is current parent. + */ + if ((mux->flags & TEGRA_DIVIDER_2) && ((index == mux->div2_index) || + (index == mux->pllx_index))) { + parent_index = clk_super_get_parent(hw); + if ((parent_index == mux->div2_index) || + (parent_index == mux->pllx_index)) + return -EINVAL; + + val ^= SUPER_LP_DIV2_BYPASS; + writel_relaxed(val, mux->reg); + udelay(2); + + if (index == mux->div2_index) + index = mux->pllx_index; + } + val &= ~((super_state_to_src_mask(mux)) << shift); + val |= (index & (super_state_to_src_mask(mux))) << shift; + + writel_relaxed(val, mux->reg); + udelay(2); + return 0; +} + +const struct clk_ops tegra_clk_super_ops = { + .get_parent = clk_super_get_parent, + .set_parent = clk_super_set_parent, +}; + +struct clk *tegra_clk_register_super_mux(const char *name, + const char **parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 clk_super_flags, + u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock) +{ + struct tegra_clk_super_mux *super; + struct clk *clk; + struct clk_init_data init; + + super = kzalloc(sizeof(*super), GFP_KERNEL); + if (!super) { + pr_err("%s: could not allocate super clk\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.ops = &tegra_clk_super_ops; + init.flags = flags; + init.parent_names = parent_names; + init.num_parents = num_parents; + + super->reg = reg; + super->pllx_index = pllx_index; + super->div2_index = div2_index; + super->lock = lock; + super->width = width; + super->flags = clk_super_flags; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + super->hw.init = &init; + + clk = clk_register(NULL, &super->hw); + if (IS_ERR(clk)) + kfree(super); + + return clk; +} diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c new file mode 100644 index 0000000..5d41569 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra20.c @@ -0,0 +1,1349 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk/tegra.h> +#include <linux/delay.h> + +#include "clk.h" + +#define RST_DEVICES_L 0x004 +#define RST_DEVICES_H 0x008 +#define RST_DEVICES_U 0x00c +#define RST_DEVICES_SET_L 0x300 +#define RST_DEVICES_CLR_L 0x304 +#define RST_DEVICES_SET_H 0x308 +#define RST_DEVICES_CLR_H 0x30c +#define RST_DEVICES_SET_U 0x310 +#define RST_DEVICES_CLR_U 0x314 +#define RST_DEVICES_NUM 3 + +#define CLK_OUT_ENB_L 0x010 +#define CLK_OUT_ENB_H 0x014 +#define CLK_OUT_ENB_U 0x018 +#define CLK_OUT_ENB_SET_L 0x320 +#define CLK_OUT_ENB_CLR_L 0x324 +#define CLK_OUT_ENB_SET_H 0x328 +#define CLK_OUT_ENB_CLR_H 0x32c +#define CLK_OUT_ENB_SET_U 0x330 +#define CLK_OUT_ENB_CLR_U 0x334 +#define CLK_OUT_ENB_NUM 3 + +#define OSC_CTRL 0x50 +#define OSC_CTRL_OSC_FREQ_MASK (3<<30) +#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30) +#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) +#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) +#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) +#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) + +#define OSC_CTRL_PLL_REF_DIV_MASK (3<<28) +#define OSC_CTRL_PLL_REF_DIV_1 (0<<28) +#define OSC_CTRL_PLL_REF_DIV_2 (1<<28) +#define OSC_CTRL_PLL_REF_DIV_4 (2<<28) + +#define OSC_FREQ_DET 0x58 +#define OSC_FREQ_DET_TRIG (1<<31) + +#define OSC_FREQ_DET_STATUS 0x5c +#define OSC_FREQ_DET_BUSY (1<<31) +#define OSC_FREQ_DET_CNT_MASK 0xFFFF + +#define PLLS_BASE 0xf0 +#define PLLS_MISC 0xf4 +#define PLLC_BASE 0x80 +#define PLLC_MISC 0x8c +#define PLLM_BASE 0x90 +#define PLLM_MISC 0x9c +#define PLLP_BASE 0xa0 +#define PLLP_MISC 0xac +#define PLLA_BASE 0xb0 +#define PLLA_MISC 0xbc +#define PLLU_BASE 0xc0 +#define PLLU_MISC 0xcc +#define PLLD_BASE 0xd0 +#define PLLD_MISC 0xdc +#define PLLX_BASE 0xe0 +#define PLLX_MISC 0xe4 +#define PLLE_BASE 0xe8 +#define PLLE_MISC 0xec + +#define PLL_BASE_LOCK 27 +#define PLLE_MISC_LOCK 11 + +#define PLL_MISC_LOCK_ENABLE 18 +#define PLLDU_MISC_LOCK_ENABLE 22 +#define PLLE_MISC_LOCK_ENABLE 9 + +#define PLLC_OUT 0x84 +#define PLLM_OUT 0x94 +#define PLLP_OUTA 0xa4 +#define PLLP_OUTB 0xa8 +#define PLLA_OUT 0xb4 + +#define CCLK_BURST_POLICY 0x20 +#define SUPER_CCLK_DIVIDER 0x24 +#define SCLK_BURST_POLICY 0x28 +#define SUPER_SCLK_DIVIDER 0x2c +#define CLK_SYSTEM_RATE 0x30 + +#define CCLK_BURST_POLICY_SHIFT 28 +#define CCLK_RUN_POLICY_SHIFT 4 +#define CCLK_IDLE_POLICY_SHIFT 0 +#define CCLK_IDLE_POLICY 1 +#define CCLK_RUN_POLICY 2 +#define CCLK_BURST_POLICY_PLLX 8 + +#define CLK_SOURCE_I2S1 0x100 +#define CLK_SOURCE_I2S2 0x104 +#define CLK_SOURCE_SPDIF_OUT 0x108 +#define CLK_SOURCE_SPDIF_IN 0x10c +#define CLK_SOURCE_PWM 0x110 +#define CLK_SOURCE_SPI 0x114 +#define CLK_SOURCE_SBC1 0x134 +#define CLK_SOURCE_SBC2 0x118 +#define CLK_SOURCE_SBC3 0x11c +#define CLK_SOURCE_SBC4 0x1b4 +#define CLK_SOURCE_XIO 0x120 +#define CLK_SOURCE_TWC 0x12c +#define CLK_SOURCE_IDE 0x144 +#define CLK_SOURCE_NDFLASH 0x160 +#define CLK_SOURCE_VFIR 0x168 +#define CLK_SOURCE_SDMMC1 0x150 +#define CLK_SOURCE_SDMMC2 0x154 +#define CLK_SOURCE_SDMMC3 0x1bc +#define CLK_SOURCE_SDMMC4 0x164 +#define CLK_SOURCE_CVE 0x140 +#define CLK_SOURCE_TVO 0x188 +#define CLK_SOURCE_TVDAC 0x194 +#define CLK_SOURCE_HDMI 0x18c +#define CLK_SOURCE_DISP1 0x138 +#define CLK_SOURCE_DISP2 0x13c +#define CLK_SOURCE_CSITE 0x1d4 +#define CLK_SOURCE_LA 0x1f8 +#define CLK_SOURCE_OWR 0x1cc +#define CLK_SOURCE_NOR 0x1d0 +#define CLK_SOURCE_MIPI 0x174 +#define CLK_SOURCE_I2C1 0x124 +#define CLK_SOURCE_I2C2 0x198 +#define CLK_SOURCE_I2C3 0x1b8 +#define CLK_SOURCE_DVC 0x128 +#define CLK_SOURCE_UARTA 0x178 +#define CLK_SOURCE_UARTB 0x17c +#define CLK_SOURCE_UARTC 0x1a0 +#define CLK_SOURCE_UARTD 0x1c0 +#define CLK_SOURCE_UARTE 0x1c4 +#define CLK_SOURCE_3D 0x158 +#define CLK_SOURCE_2D 0x15c +#define CLK_SOURCE_MPE 0x170 +#define CLK_SOURCE_EPP 0x16c +#define CLK_SOURCE_HOST1X 0x180 +#define CLK_SOURCE_VDE 0x1c8 +#define CLK_SOURCE_VI 0x148 +#define CLK_SOURCE_VI_SENSOR 0x1a8 +#define CLK_SOURCE_EMC 0x19c + +#define AUDIO_SYNC_CLK 0x38 + +#define PMC_CTRL 0x0 +#define PMC_CTRL_BLINK_ENB 7 +#define PMC_DPD_PADS_ORIDE 0x1c +#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 +#define PMC_BLINK_TIMER 0x40 + +/* Tegra CPU clock and reset control regs */ +#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c +#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 +#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344 + +#define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) +#define CPU_RESET(cpu) (0x1111ul << (cpu)) + +#ifdef CONFIG_PM_SLEEP +static struct cpu_clk_suspend_context { + u32 pllx_misc; + u32 pllx_base; + + u32 cpu_burst; + u32 clk_csite_src; + u32 cclk_divider; +} tegra20_cpu_clk_sctx; +#endif + +static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; + +static void __iomem *clk_base; +static void __iomem *pmc_base; + +static DEFINE_SPINLOCK(pll_div_lock); + +#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ + _regs, _clk_num, periph_clk_enb_refcnt, \ + _gate_flags, _clk_id) + +#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_id) + +#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_id) + +#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ + _mux_shift, _mux_width, _clk_num, _regs, \ + _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_id) + +/* IDs assigned here must be in sync with DT bindings definition + * for Tegra20 clocks . + */ +enum tegra20_clk { + cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, + ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp, + gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma, + kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3, + dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, + usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, + pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, + iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2, + uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, + osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, + pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, + pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_u, + pll_x, audio, pll_ref, twd, clk_max, +}; + +static struct clk *clks[clk_max]; +static struct clk_onecell_data clk_data; + +static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 19200000, 600000000, 500, 16, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { + { 12000000, 666000000, 666, 12, 1, 8}, + { 13000000, 666000000, 666, 13, 1, 8}, + { 19200000, 666000000, 555, 16, 1, 8}, + { 26000000, 666000000, 666, 26, 1, 8}, + { 12000000, 600000000, 600, 12, 1, 8}, + { 13000000, 600000000, 600, 13, 1, 8}, + { 19200000, 600000000, 375, 12, 1, 6}, + { 26000000, 600000000, 600, 26, 1, 8}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { + { 12000000, 216000000, 432, 12, 2, 8}, + { 13000000, 216000000, 432, 13, 2, 8}, + { 19200000, 216000000, 90, 4, 2, 1}, + { 26000000, 216000000, 432, 26, 2, 8}, + { 12000000, 432000000, 432, 12, 1, 8}, + { 13000000, 432000000, 432, 13, 1, 8}, + { 19200000, 432000000, 90, 4, 1, 1}, + { 26000000, 432000000, 432, 26, 1, 8}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { + { 28800000, 56448000, 49, 25, 1, 1}, + { 28800000, 73728000, 64, 25, 1, 1}, + { 28800000, 24000000, 5, 6, 1, 1}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { + { 12000000, 216000000, 216, 12, 1, 4}, + { 13000000, 216000000, 216, 13, 1, 4}, + { 19200000, 216000000, 135, 12, 1, 3}, + { 26000000, 216000000, 216, 26, 1, 4}, + + { 12000000, 594000000, 594, 12, 1, 8}, + { 13000000, 594000000, 594, 13, 1, 8}, + { 19200000, 594000000, 495, 16, 1, 8}, + { 26000000, 594000000, 594, 26, 1, 8}, + + { 12000000, 1000000000, 1000, 12, 1, 12}, + { 13000000, 1000000000, 1000, 13, 1, 12}, + { 19200000, 1000000000, 625, 12, 1, 8}, + { 26000000, 1000000000, 1000, 26, 1, 12}, + + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { + { 12000000, 480000000, 960, 12, 2, 0}, + { 13000000, 480000000, 960, 13, 2, 0}, + { 19200000, 480000000, 200, 4, 2, 0}, + { 26000000, 480000000, 960, 26, 2, 0}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { + /* 1 GHz */ + { 12000000, 1000000000, 1000, 12, 1, 12}, + { 13000000, 1000000000, 1000, 13, 1, 12}, + { 19200000, 1000000000, 625, 12, 1, 8}, + { 26000000, 1000000000, 1000, 26, 1, 12}, + + /* 912 MHz */ + { 12000000, 912000000, 912, 12, 1, 12}, + { 13000000, 912000000, 912, 13, 1, 12}, + { 19200000, 912000000, 760, 16, 1, 8}, + { 26000000, 912000000, 912, 26, 1, 12}, + + /* 816 MHz */ + { 12000000, 816000000, 816, 12, 1, 12}, + { 13000000, 816000000, 816, 13, 1, 12}, + { 19200000, 816000000, 680, 16, 1, 8}, + { 26000000, 816000000, 816, 26, 1, 12}, + + /* 760 MHz */ + { 12000000, 760000000, 760, 12, 1, 12}, + { 13000000, 760000000, 760, 13, 1, 12}, + { 19200000, 760000000, 950, 24, 1, 8}, + { 26000000, 760000000, 760, 26, 1, 12}, + + /* 750 MHz */ + { 12000000, 750000000, 750, 12, 1, 12}, + { 13000000, 750000000, 750, 13, 1, 12}, + { 19200000, 750000000, 625, 16, 1, 8}, + { 26000000, 750000000, 750, 26, 1, 12}, + + /* 608 MHz */ + { 12000000, 608000000, 608, 12, 1, 12}, + { 13000000, 608000000, 608, 13, 1, 12}, + { 19200000, 608000000, 380, 12, 1, 8}, + { 26000000, 608000000, 608, 26, 1, 12}, + + /* 456 MHz */ + { 12000000, 456000000, 456, 12, 1, 12}, + { 13000000, 456000000, 456, 13, 1, 12}, + { 19200000, 456000000, 380, 16, 1, 8}, + { 26000000, 456000000, 456, 26, 1, 12}, + + /* 312 MHz */ + { 12000000, 312000000, 312, 12, 1, 12}, + { 13000000, 312000000, 312, 13, 1, 12}, + { 19200000, 312000000, 260, 16, 1, 8}, + { 26000000, 312000000, 312, 26, 1, 12}, + + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { + { 12000000, 100000000, 200, 24, 1, 0 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +/* PLL parameters */ +static struct tegra_clk_pll_params pll_c_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLC_BASE, + .misc_reg = PLLC_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_m_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1200000000, + .base_reg = PLLM_BASE, + .misc_reg = PLLM_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_p_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLP_BASE, + .misc_reg = PLLP_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_a_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLA_BASE, + .misc_reg = PLLA_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_d_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 40000000, + .vco_max = 1000000000, + .base_reg = PLLD_BASE, + .misc_reg = PLLD_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, +}; + +static struct tegra_clk_pll_params pll_u_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 48000000, + .vco_max = 960000000, + .base_reg = PLLU_BASE, + .misc_reg = PLLU_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, +}; + +static struct tegra_clk_pll_params pll_x_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1200000000, + .base_reg = PLLX_BASE, + .misc_reg = PLLX_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_e_params = { + .input_min = 12000000, + .input_max = 12000000, + .cf_min = 0, + .cf_max = 0, + .vco_min = 0, + .vco_max = 0, + .base_reg = PLLE_BASE, + .misc_reg = PLLE_MISC, + .lock_bit_idx = PLLE_MISC_LOCK, + .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, + .lock_delay = 0, +}; + +/* Peripheral clock registers */ +static struct tegra_clk_periph_regs periph_l_regs = { + .enb_reg = CLK_OUT_ENB_L, + .enb_set_reg = CLK_OUT_ENB_SET_L, + .enb_clr_reg = CLK_OUT_ENB_CLR_L, + .rst_reg = RST_DEVICES_L, + .rst_set_reg = RST_DEVICES_SET_L, + .rst_clr_reg = RST_DEVICES_CLR_L, +}; + +static struct tegra_clk_periph_regs periph_h_regs = { + .enb_reg = CLK_OUT_ENB_H, + .enb_set_reg = CLK_OUT_ENB_SET_H, + .enb_clr_reg = CLK_OUT_ENB_CLR_H, + .rst_reg = RST_DEVICES_H, + .rst_set_reg = RST_DEVICES_SET_H, + .rst_clr_reg = RST_DEVICES_CLR_H, +}; + +static struct tegra_clk_periph_regs periph_u_regs = { + .enb_reg = CLK_OUT_ENB_U, + .enb_set_reg = CLK_OUT_ENB_SET_U, + .enb_clr_reg = CLK_OUT_ENB_CLR_U, + .rst_reg = RST_DEVICES_U, + .rst_set_reg = RST_DEVICES_SET_U, + .rst_clr_reg = RST_DEVICES_CLR_U, +}; + +static unsigned long tegra20_clk_measure_input_freq(void) +{ + u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); + u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK; + u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; + unsigned long input_freq; + + switch (auto_clk_control) { + case OSC_CTRL_OSC_FREQ_12MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 12000000; + break; + case OSC_CTRL_OSC_FREQ_13MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 13000000; + break; + case OSC_CTRL_OSC_FREQ_19_2MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 19200000; + break; + case OSC_CTRL_OSC_FREQ_26MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 26000000; + break; + default: + pr_err("Unexpected clock autodetect value %d", + auto_clk_control); + BUG(); + return 0; + } + + return input_freq; +} + +static unsigned int tegra20_get_pll_ref_div(void) +{ + u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) & + OSC_CTRL_PLL_REF_DIV_MASK; + + switch (pll_ref_div) { + case OSC_CTRL_PLL_REF_DIV_1: + return 1; + case OSC_CTRL_PLL_REF_DIV_2: + return 2; + case OSC_CTRL_PLL_REF_DIV_4: + return 4; + default: + pr_err("Invalied pll ref divider %d\n", pll_ref_div); + BUG(); + } + return 0; +} + +static void tegra20_pll_init(void) +{ + struct clk *clk; + + /* PLLC */ + clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0, + 0, &pll_c_params, TEGRA_PLL_HAS_CPCON, + pll_c_freq_table, NULL); + clk_register_clkdev(clk, "pll_c", NULL); + clks[pll_c] = clk; + + /* PLLC_OUT1 */ + clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", + clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", + clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, + 0, NULL); + clk_register_clkdev(clk, "pll_c_out1", NULL); + clks[pll_c_out1] = clk; + + /* PLLP */ + clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0, + 216000000, &pll_p_params, TEGRA_PLL_FIXED | + TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL); + clk_register_clkdev(clk, "pll_p", NULL); + clks[pll_p] = clk; + + /* PLLP_OUT1 */ + clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", + clk_base + PLLP_OUTA, 0, + TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", + clk_base + PLLP_OUTA, 1, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out1", NULL); + clks[pll_p_out1] = clk; + + /* PLLP_OUT2 */ + clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", + clk_base + PLLP_OUTA, 0, + TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, + 24, 8, 1, &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", + clk_base + PLLP_OUTA, 17, 16, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out2", NULL); + clks[pll_p_out2] = clk; + + /* PLLP_OUT3 */ + clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", + clk_base + PLLP_OUTB, 0, + TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", + clk_base + PLLP_OUTB, 1, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out3", NULL); + clks[pll_p_out3] = clk; + + /* PLLP_OUT4 */ + clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", + clk_base + PLLP_OUTB, 0, + TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, + 24, 8, 1, &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", + clk_base + PLLP_OUTB, 17, 16, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out4", NULL); + clks[pll_p_out4] = clk; + + /* PLLM */ + clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL, + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, + &pll_m_params, TEGRA_PLL_HAS_CPCON, + pll_m_freq_table, NULL); + clk_register_clkdev(clk, "pll_m", NULL); + clks[pll_m] = clk; + + /* PLLM_OUT1 */ + clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", + clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", + clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_m_out1", NULL); + clks[pll_m_out1] = clk; + + /* PLLX */ + clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0, + 0, &pll_x_params, TEGRA_PLL_HAS_CPCON, + pll_x_freq_table, NULL); + clk_register_clkdev(clk, "pll_x", NULL); + clks[pll_x] = clk; + + /* PLLU */ + clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0, + 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON, + pll_u_freq_table, NULL); + clk_register_clkdev(clk, "pll_u", NULL); + clks[pll_u] = clk; + + /* PLLD */ + clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0, + 0, &pll_d_params, TEGRA_PLL_HAS_CPCON, + pll_d_freq_table, NULL); + clk_register_clkdev(clk, "pll_d", NULL); + clks[pll_d] = clk; + + /* PLLD_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d_out0", NULL); + clks[pll_d_out0] = clk; + + /* PLLA */ + clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0, + 0, &pll_a_params, TEGRA_PLL_HAS_CPCON, + pll_a_freq_table, NULL); + clk_register_clkdev(clk, "pll_a", NULL); + clks[pll_a] = clk; + + /* PLLA_OUT0 */ + clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", + clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", + clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_a_out0", NULL); + clks[pll_a_out0] = clk; + + /* PLLE */ + clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL, + 0, 100000000, &pll_e_params, + 0, pll_e_freq_table, NULL); + clk_register_clkdev(clk, "pll_e", NULL); + clks[pll_e] = clk; +} + +static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", + "pll_p_cclk", "pll_p_out4_cclk", + "pll_p_out3_cclk", "clk_d", "pll_x" }; +static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", + "pll_p_out3", "pll_p_out2", "clk_d", + "clk_32k", "pll_m_out1" }; + +static void tegra20_super_clk_init(void) +{ + struct clk *clk; + + /* + * DIV_U71 dividers for CCLK, these dividers are used only + * if parent clock is fixed rate. + */ + + /* + * Clock input to cclk divided from pll_p using + * U71 divider of cclk. + */ + clk = tegra_clk_register_divider("pll_p_cclk", "pll_p", + clk_base + SUPER_CCLK_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_cclk", NULL); + + /* + * Clock input to cclk divided from pll_p_out3 using + * U71 divider of cclk. + */ + clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3", + clk_base + SUPER_CCLK_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out3_cclk", NULL); + + /* + * Clock input to cclk divided from pll_p_out4 using + * U71 divider of cclk. + */ + clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4", + clk_base + SUPER_CCLK_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out4_cclk", NULL); + + /* CCLK */ + clk = tegra_clk_register_super_mux("cclk", cclk_parents, + ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, + clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL); + clk_register_clkdev(clk, "cclk", NULL); + clks[cclk] = clk; + + /* SCLK */ + clk = tegra_clk_register_super_mux("sclk", sclk_parents, + ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT, + clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); + clk_register_clkdev(clk, "sclk", NULL); + clks[sclk] = clk; + + /* HCLK */ + clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, + clk_base + CLK_SYSTEM_RATE, 4, 2, 0, NULL); + clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT, + clk_base + CLK_SYSTEM_RATE, 7, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "hclk", NULL); + clks[hclk] = clk; + + /* PCLK */ + clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, + clk_base + CLK_SYSTEM_RATE, 0, 2, 0, NULL); + clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT, + clk_base + CLK_SYSTEM_RATE, 3, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "pclk", NULL); + clks[pclk] = clk; + + /* twd */ + clk = clk_register_fixed_factor(NULL, "twd", "cclk", 0, 1, 4); + clk_register_clkdev(clk, "twd", NULL); + clks[twd] = clk; +} + +static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused", + "pll_a_out0", "unused", "unused", + "unused"}; + +static void __init tegra20_audio_clk_init(void) +{ + struct clk *clk; + + /* audio */ + clk = clk_register_mux(NULL, "audio_mux", audio_parents, + ARRAY_SIZE(audio_parents), 0, + clk_base + AUDIO_SYNC_CLK, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio", "audio_mux", 0, + clk_base + AUDIO_SYNC_CLK, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio", NULL); + clks[audio] = clk; + + /* audio_2x */ + clk = clk_register_fixed_factor(NULL, "audio_doubler", "audio", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_periph_gate("audio_2x", "audio_doubler", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 89, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio_2x", NULL); + clks[audio_2x] = clk; + +} + +static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p", + "clk_m"}; +static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p", + "clk_m"}; +static const char *spdif_out_parents[] = {"pll_a_out0", "audio_2x", "pll_p", + "clk_m"}; +static const char *spdif_in_parents[] = {"pll_p", "pll_c", "pll_m"}; +static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m", + "clk_32k"}; +static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"}; +static const char *mux_pllmcpa[] = {"pll_m", "pll_c", "pll_c", "pll_a"}; +static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c", + "clk_m"}; +static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"}; + +static struct tegra_periph_init_data tegra_periph_clk_list[] = { + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra20-i2s.0", i2s1_parents, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra20-i2s.1", i2s2_parents, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra20-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), + TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), + TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), + TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), + TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), + TEGRA_INIT_DATA_MUX("spi", NULL, "spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, &periph_h_regs, TEGRA_PERIPH_ON_APB, spi), + TEGRA_INIT_DATA_MUX("xio", NULL, "xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, &periph_h_regs, 0, xio), + TEGRA_INIT_DATA_MUX("twc", NULL, "twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, &periph_l_regs, TEGRA_PERIPH_ON_APB, twc), + TEGRA_INIT_DATA_MUX("ide", NULL, "ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, &periph_l_regs, 0, ide), + TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_l_regs, 0, ndflash), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), + TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, 0, csite), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, 0, la), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), + TEGRA_INIT_DATA_MUX("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), + TEGRA_INIT_DATA_MUX("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), + TEGRA_INIT_DATA_MUX("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), + TEGRA_INIT_DATA_MUX("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, &periph_h_regs, 0, mpe), + TEGRA_INIT_DATA_MUX("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), + TEGRA_INIT_DATA_MUX("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d), + TEGRA_INIT_DATA_MUX("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr2d), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), + TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, &periph_h_regs, 0, cve), + TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, &periph_h_regs, 0, tvo), + TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, &periph_h_regs, 0, tvdac), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), + TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1), + TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2), + TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3), + TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, &periph_h_regs, TEGRA_PERIPH_ON_APB, dvc), + TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), + TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm), +}; + +static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { + TEGRA_INIT_DATA_NODIV("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, &periph_l_regs, TEGRA_PERIPH_ON_APB, uarta), + TEGRA_INIT_DATA_NODIV("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, uartb), + TEGRA_INIT_DATA_NODIV("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, &periph_h_regs, TEGRA_PERIPH_ON_APB, uartc), + TEGRA_INIT_DATA_NODIV("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, &periph_u_regs, TEGRA_PERIPH_ON_APB, uartd), + TEGRA_INIT_DATA_NODIV("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, &periph_u_regs, TEGRA_PERIPH_ON_APB, uarte), + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, &periph_l_regs, 0, disp1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, &periph_l_regs, 0, disp2), +}; + +static void __init tegra20_periph_clk_init(void) +{ + struct tegra_periph_init_data *data; + struct clk *clk; + int i; + + /* apbdma */ + clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, + 0, 34, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-apbdma"); + clks[apbdma] = clk; + + /* rtc */ + clk = tegra_clk_register_periph_gate("rtc", "clk_32k", + TEGRA_PERIPH_NO_RESET, + clk_base, 0, 4, &periph_l_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "rtc-tegra"); + clks[rtc] = clk; + + /* timer */ + clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, + 0, 5, &periph_l_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "timer"); + clks[timer] = clk; + + /* kbc */ + clk = tegra_clk_register_periph_gate("kbc", "clk_32k", + TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, + clk_base, 0, 36, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-kbc"); + clks[kbc] = clk; + + /* csus */ + clk = tegra_clk_register_periph_gate("csus", "clk_m", + TEGRA_PERIPH_NO_RESET, + clk_base, 0, 92, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "csus", "tengra_camera"); + clks[csus] = clk; + + /* vcp */ + clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, + clk_base, 0, 29, &periph_l_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "vcp", "tegra-avp"); + clks[vcp] = clk; + + /* bsea */ + clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, + clk_base, 0, 62, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "bsea", "tegra-avp"); + clks[bsea] = clk; + + /* bsev */ + clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, + clk_base, 0, 63, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "bsev", "tegra-aes"); + clks[bsev] = clk; + + /* emc */ + clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, + ARRAY_SIZE(mux_pllmcp_clkm), 0, + clk_base + CLK_SOURCE_EMC, + 30, 2, 0, NULL); + clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, + 57, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "emc", NULL); + clks[emc] = clk; + + /* usbd */ + clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, + 22, &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); + clks[usbd] = clk; + + /* usb2 */ + clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, + 58, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-ehci.1"); + clks[usb2] = clk; + + /* usb3 */ + clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, + 59, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-ehci.2"); + clks[usb3] = clk; + + /* dsi */ + clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0, + 48, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "dsi"); + clks[dsi] = clk; + + /* csi */ + clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, + 0, 52, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "csi", "tegra_camera"); + clks[csi] = clk; + + /* isp */ + clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, + &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "isp", "tegra_camera"); + clks[isp] = clk; + + /* pex */ + clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70, + &periph_u_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "pex", NULL); + clks[pex] = clk; + + /* afi */ + clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, + &periph_u_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "afi", NULL); + clks[afi] = clk; + + /* pcie_xclk */ + clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base, + 0, 74, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "pcie_xclk", NULL); + clks[pcie_xclk] = clk; + + /* cdev1 */ + clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT, + 26000000); + clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0, + clk_base, 0, 94, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "cdev1", NULL); + clks[cdev1] = clk; + + /* cdev2 */ + clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT, + 26000000); + clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0, + clk_base, 0, 93, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "cdev2", NULL); + clks[cdev2] = clk; + + for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { + data = &tegra_periph_clk_list[i]; + clk = tegra_clk_register_periph(data->name, data->parent_names, + data->num_parents, &data->periph, + clk_base, data->offset); + clk_register_clkdev(clk, data->con_id, data->dev_id); + clks[data->clk_id] = clk; + } + + for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { + data = &tegra_periph_nodiv_clk_list[i]; + clk = tegra_clk_register_periph_nodiv(data->name, + data->parent_names, + data->num_parents, &data->periph, + clk_base, data->offset); + clk_register_clkdev(clk, data->con_id, data->dev_id); + clks[data->clk_id] = clk; + } +} + + +static void __init tegra20_fixed_clk_init(void) +{ + struct clk *clk; + + /* clk_32k */ + clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, + 32768); + clk_register_clkdev(clk, "clk_32k", NULL); + clks[clk_32k] = clk; +} + +static void __init tegra20_pmc_clk_init(void) +{ + struct clk *clk; + + /* blink */ + writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); + clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, + pmc_base + PMC_DPD_PADS_ORIDE, + PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); + clk = clk_register_gate(NULL, "blink", "blink_override", 0, + pmc_base + PMC_CTRL, + PMC_CTRL_BLINK_ENB, 0, NULL); + clk_register_clkdev(clk, "blink", NULL); + clks[blink] = clk; +} + +static void __init tegra20_osc_clk_init(void) +{ + struct clk *clk; + unsigned long input_freq; + unsigned int pll_ref_div; + + input_freq = tegra20_clk_measure_input_freq(); + + /* clk_m */ + clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT | + CLK_IGNORE_UNUSED, input_freq); + clk_register_clkdev(clk, "clk_m", NULL); + clks[clk_m] = clk; + + /* pll_ref */ + pll_ref_div = tegra20_get_pll_ref_div(); + clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", + CLK_SET_RATE_PARENT, 1, pll_ref_div); + clk_register_clkdev(clk, "pll_ref", NULL); + clks[pll_ref] = clk; +} + +/* Tegra20 CPU clock and reset control functions */ +static void tegra20_wait_cpu_in_reset(u32 cpu) +{ + unsigned int reg; + + do { + reg = readl(clk_base + + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + cpu_relax(); + } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ + + return; +} + +static void tegra20_put_cpu_in_reset(u32 cpu) +{ + writel(CPU_RESET(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + dmb(); +} + +static void tegra20_cpu_out_of_reset(u32 cpu) +{ + writel(CPU_RESET(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); + wmb(); +} + +static void tegra20_enable_cpu_clock(u32 cpu) +{ + unsigned int reg; + + reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + writel(reg & ~CPU_CLOCK(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + barrier(); + reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); +} + +static void tegra20_disable_cpu_clock(u32 cpu) +{ + unsigned int reg; + + reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + writel(reg | CPU_CLOCK(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); +} + +#ifdef CONFIG_PM_SLEEP +static bool tegra20_cpu_rail_off_ready(void) +{ + unsigned int cpu_rst_status; + + cpu_rst_status = readl(clk_base + + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + + return !!(cpu_rst_status & 0x2); +} + +static void tegra20_cpu_clock_suspend(void) +{ + /* switch coresite to clk_m, save off original source */ + tegra20_cpu_clk_sctx.clk_csite_src = + readl(clk_base + CLK_SOURCE_CSITE); + writel(3<<30, clk_base + CLK_SOURCE_CSITE); + + tegra20_cpu_clk_sctx.cpu_burst = + readl(clk_base + CCLK_BURST_POLICY); + tegra20_cpu_clk_sctx.pllx_base = + readl(clk_base + PLLX_BASE); + tegra20_cpu_clk_sctx.pllx_misc = + readl(clk_base + PLLX_MISC); + tegra20_cpu_clk_sctx.cclk_divider = + readl(clk_base + SUPER_CCLK_DIVIDER); +} + +static void tegra20_cpu_clock_resume(void) +{ + unsigned int reg, policy; + + /* Is CPU complex already running on PLLX? */ + reg = readl(clk_base + CCLK_BURST_POLICY); + policy = (reg >> CCLK_BURST_POLICY_SHIFT) & 0xF; + + if (policy == CCLK_IDLE_POLICY) + reg = (reg >> CCLK_IDLE_POLICY_SHIFT) & 0xF; + else if (policy == CCLK_RUN_POLICY) + reg = (reg >> CCLK_RUN_POLICY_SHIFT) & 0xF; + else + BUG(); + + if (reg != CCLK_BURST_POLICY_PLLX) { + /* restore PLLX settings if CPU is on different PLL */ + writel(tegra20_cpu_clk_sctx.pllx_misc, + clk_base + PLLX_MISC); + writel(tegra20_cpu_clk_sctx.pllx_base, + clk_base + PLLX_BASE); + + /* wait for PLL stabilization if PLLX was enabled */ + if (tegra20_cpu_clk_sctx.pllx_base & (1 << 30)) + udelay(300); + } + + /* + * Restore original burst policy setting for calls resulting from CPU + * LP2 in idle or system suspend. + */ + writel(tegra20_cpu_clk_sctx.cclk_divider, + clk_base + SUPER_CCLK_DIVIDER); + writel(tegra20_cpu_clk_sctx.cpu_burst, + clk_base + CCLK_BURST_POLICY); + + writel(tegra20_cpu_clk_sctx.clk_csite_src, + clk_base + CLK_SOURCE_CSITE); +} +#endif + +static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { + .wait_for_reset = tegra20_wait_cpu_in_reset, + .put_in_reset = tegra20_put_cpu_in_reset, + .out_of_reset = tegra20_cpu_out_of_reset, + .enable_clock = tegra20_enable_cpu_clock, + .disable_clock = tegra20_disable_cpu_clock, +#ifdef CONFIG_PM_SLEEP + .rail_off_ready = tegra20_cpu_rail_off_ready, + .suspend = tegra20_cpu_clock_suspend, + .resume = tegra20_cpu_clock_resume, +#endif +}; + +static __initdata struct tegra_clk_init_table init_table[] = { + {pll_p, clk_max, 216000000, 1}, + {pll_p_out1, clk_max, 28800000, 1}, + {pll_p_out2, clk_max, 48000000, 1}, + {pll_p_out3, clk_max, 72000000, 1}, + {pll_p_out4, clk_max, 24000000, 1}, + {pll_c, clk_max, 600000000, 1}, + {pll_c_out1, clk_max, 120000000, 1}, + {sclk, pll_c_out1, 0, 1}, + {hclk, clk_max, 0, 1}, + {pclk, clk_max, 60000000, 1}, + {csite, clk_max, 0, 1}, + {emc, clk_max, 0, 1}, + {cclk, clk_max, 0, 1}, + {uarta, pll_p, 0, 1}, + {uartd, pll_p, 0, 1}, + {usbd, clk_max, 12000000, 0}, + {usb2, clk_max, 12000000, 0}, + {usb3, clk_max, 12000000, 0}, + {pll_a, clk_max, 56448000, 1}, + {pll_a_out0, clk_max, 11289600, 1}, + {cdev1, clk_max, 0, 1}, + {blink, clk_max, 32768, 1}, + {i2s1, pll_a_out0, 11289600, 0}, + {i2s2, pll_a_out0, 11289600, 0}, + {sdmmc1, pll_p, 48000000, 0}, + {sdmmc3, pll_p, 48000000, 0}, + {sdmmc4, pll_p, 48000000, 0}, + {spi, pll_p, 20000000, 0}, + {sbc1, pll_p, 100000000, 0}, + {sbc2, pll_p, 100000000, 0}, + {sbc3, pll_p, 100000000, 0}, + {sbc4, pll_p, 100000000, 0}, + {host1x, pll_c, 150000000, 0}, + {disp1, pll_p, 600000000, 0}, + {disp2, pll_p, 600000000, 0}, + {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ +}; + +/* + * Some clocks may be used by different drivers depending on the board + * configuration. List those here to register them twice in the clock lookup + * table under two names. + */ +static struct tegra_clk_duplicate tegra_clk_duplicates[] = { + TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL), + TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), + TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), + TEGRA_CLK_DUPLICATE(cclk, NULL, "cpu"), + TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL), + TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */ +}; + +static const struct of_device_id pmc_match[] __initconst = { + { .compatible = "nvidia,tegra20-pmc" }, + {}, +}; + +void __init tegra20_clock_init(struct device_node *np) +{ + int i; + struct device_node *node; + + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("Can't map CAR registers\n"); + BUG(); + } + + node = of_find_matching_node(NULL, pmc_match); + if (!node) { + pr_err("Failed to find pmc node\n"); + BUG(); + } + + pmc_base = of_iomap(node, 0); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + BUG(); + } + + tegra20_osc_clk_init(); + tegra20_pmc_clk_init(); + tegra20_fixed_clk_init(); + tegra20_pll_init(); + tegra20_super_clk_init(); + tegra20_periph_clk_init(); + tegra20_audio_clk_init(); + + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + if (IS_ERR(clks[i])) { + pr_err("Tegra20 clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + BUG(); + } + if (!clks[i]) + clks[i] = ERR_PTR(-EINVAL); + } + + tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + tegra_init_from_table(init_table, clks, clk_max); + + tegra_cpu_car_ops = &tegra20_cpu_car_ops; +} diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c new file mode 100644 index 0000000..a163812 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra30.c @@ -0,0 +1,1987 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk/tegra.h> + +#include <mach/powergate.h> + +#include "clk.h" + +#define RST_DEVICES_L 0x004 +#define RST_DEVICES_H 0x008 +#define RST_DEVICES_U 0x00c +#define RST_DEVICES_V 0x358 +#define RST_DEVICES_W 0x35c +#define RST_DEVICES_SET_L 0x300 +#define RST_DEVICES_CLR_L 0x304 +#define RST_DEVICES_SET_H 0x308 +#define RST_DEVICES_CLR_H 0x30c +#define RST_DEVICES_SET_U 0x310 +#define RST_DEVICES_CLR_U 0x314 +#define RST_DEVICES_SET_V 0x430 +#define RST_DEVICES_CLR_V 0x434 +#define RST_DEVICES_SET_W 0x438 +#define RST_DEVICES_CLR_W 0x43c +#define RST_DEVICES_NUM 5 + +#define CLK_OUT_ENB_L 0x010 +#define CLK_OUT_ENB_H 0x014 +#define CLK_OUT_ENB_U 0x018 +#define CLK_OUT_ENB_V 0x360 +#define CLK_OUT_ENB_W 0x364 +#define CLK_OUT_ENB_SET_L 0x320 +#define CLK_OUT_ENB_CLR_L 0x324 +#define CLK_OUT_ENB_SET_H 0x328 +#define CLK_OUT_ENB_CLR_H 0x32c +#define CLK_OUT_ENB_SET_U 0x330 +#define CLK_OUT_ENB_CLR_U 0x334 +#define CLK_OUT_ENB_SET_V 0x440 +#define CLK_OUT_ENB_CLR_V 0x444 +#define CLK_OUT_ENB_SET_W 0x448 +#define CLK_OUT_ENB_CLR_W 0x44c +#define CLK_OUT_ENB_NUM 5 + +#define OSC_CTRL 0x50 +#define OSC_CTRL_OSC_FREQ_MASK (0xF<<28) +#define OSC_CTRL_OSC_FREQ_13MHZ (0X0<<28) +#define OSC_CTRL_OSC_FREQ_19_2MHZ (0X4<<28) +#define OSC_CTRL_OSC_FREQ_12MHZ (0X8<<28) +#define OSC_CTRL_OSC_FREQ_26MHZ (0XC<<28) +#define OSC_CTRL_OSC_FREQ_16_8MHZ (0X1<<28) +#define OSC_CTRL_OSC_FREQ_38_4MHZ (0X5<<28) +#define OSC_CTRL_OSC_FREQ_48MHZ (0X9<<28) +#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) + +#define OSC_CTRL_PLL_REF_DIV_MASK (3<<26) +#define OSC_CTRL_PLL_REF_DIV_1 (0<<26) +#define OSC_CTRL_PLL_REF_DIV_2 (1<<26) +#define OSC_CTRL_PLL_REF_DIV_4 (2<<26) + +#define OSC_FREQ_DET 0x58 +#define OSC_FREQ_DET_TRIG BIT(31) + +#define OSC_FREQ_DET_STATUS 0x5c +#define OSC_FREQ_DET_BUSY BIT(31) +#define OSC_FREQ_DET_CNT_MASK 0xffff + +#define CCLKG_BURST_POLICY 0x368 +#define SUPER_CCLKG_DIVIDER 0x36c +#define CCLKLP_BURST_POLICY 0x370 +#define SUPER_CCLKLP_DIVIDER 0x374 +#define SCLK_BURST_POLICY 0x028 +#define SUPER_SCLK_DIVIDER 0x02c + +#define SYSTEM_CLK_RATE 0x030 + +#define PLLC_BASE 0x80 +#define PLLC_MISC 0x8c +#define PLLM_BASE 0x90 +#define PLLM_MISC 0x9c +#define PLLP_BASE 0xa0 +#define PLLP_MISC 0xac +#define PLLX_BASE 0xe0 +#define PLLX_MISC 0xe4 +#define PLLD_BASE 0xd0 +#define PLLD_MISC 0xdc +#define PLLD2_BASE 0x4b8 +#define PLLD2_MISC 0x4bc +#define PLLE_BASE 0xe8 +#define PLLE_MISC 0xec +#define PLLA_BASE 0xb0 +#define PLLA_MISC 0xbc +#define PLLU_BASE 0xc0 +#define PLLU_MISC 0xcc + +#define PLL_MISC_LOCK_ENABLE 18 +#define PLLDU_MISC_LOCK_ENABLE 22 +#define PLLE_MISC_LOCK_ENABLE 9 + +#define PLL_BASE_LOCK 27 +#define PLLE_MISC_LOCK 11 + +#define PLLE_AUX 0x48c +#define PLLC_OUT 0x84 +#define PLLM_OUT 0x94 +#define PLLP_OUTA 0xa4 +#define PLLP_OUTB 0xa8 +#define PLLA_OUT 0xb4 + +#define AUDIO_SYNC_CLK_I2S0 0x4a0 +#define AUDIO_SYNC_CLK_I2S1 0x4a4 +#define AUDIO_SYNC_CLK_I2S2 0x4a8 +#define AUDIO_SYNC_CLK_I2S3 0x4ac +#define AUDIO_SYNC_CLK_I2S4 0x4b0 +#define AUDIO_SYNC_CLK_SPDIF 0x4b4 + +#define PMC_CLK_OUT_CNTRL 0x1a8 + +#define CLK_SOURCE_I2S0 0x1d8 +#define CLK_SOURCE_I2S1 0x100 +#define CLK_SOURCE_I2S2 0x104 +#define CLK_SOURCE_I2S3 0x3bc +#define CLK_SOURCE_I2S4 0x3c0 +#define CLK_SOURCE_SPDIF_OUT 0x108 +#define CLK_SOURCE_SPDIF_IN 0x10c +#define CLK_SOURCE_PWM 0x110 +#define CLK_SOURCE_D_AUDIO 0x3d0 +#define CLK_SOURCE_DAM0 0x3d8 +#define CLK_SOURCE_DAM1 0x3dc +#define CLK_SOURCE_DAM2 0x3e0 +#define CLK_SOURCE_HDA 0x428 +#define CLK_SOURCE_HDA2CODEC_2X 0x3e4 +#define CLK_SOURCE_SBC1 0x134 +#define CLK_SOURCE_SBC2 0x118 +#define CLK_SOURCE_SBC3 0x11c +#define CLK_SOURCE_SBC4 0x1b4 +#define CLK_SOURCE_SBC5 0x3c8 +#define CLK_SOURCE_SBC6 0x3cc +#define CLK_SOURCE_SATA_OOB 0x420 +#define CLK_SOURCE_SATA 0x424 +#define CLK_SOURCE_NDFLASH 0x160 +#define CLK_SOURCE_NDSPEED 0x3f8 +#define CLK_SOURCE_VFIR 0x168 +#define CLK_SOURCE_SDMMC1 0x150 +#define CLK_SOURCE_SDMMC2 0x154 +#define CLK_SOURCE_SDMMC3 0x1bc +#define CLK_SOURCE_SDMMC4 0x164 +#define CLK_SOURCE_VDE 0x1c8 +#define CLK_SOURCE_CSITE 0x1d4 +#define CLK_SOURCE_LA 0x1f8 +#define CLK_SOURCE_OWR 0x1cc +#define CLK_SOURCE_NOR 0x1d0 +#define CLK_SOURCE_MIPI 0x174 +#define CLK_SOURCE_I2C1 0x124 +#define CLK_SOURCE_I2C2 0x198 +#define CLK_SOURCE_I2C3 0x1b8 +#define CLK_SOURCE_I2C4 0x3c4 +#define CLK_SOURCE_I2C5 0x128 +#define CLK_SOURCE_UARTA 0x178 +#define CLK_SOURCE_UARTB 0x17c +#define CLK_SOURCE_UARTC 0x1a0 +#define CLK_SOURCE_UARTD 0x1c0 +#define CLK_SOURCE_UARTE 0x1c4 +#define CLK_SOURCE_VI 0x148 +#define CLK_SOURCE_VI_SENSOR 0x1a8 +#define CLK_SOURCE_3D 0x158 +#define CLK_SOURCE_3D2 0x3b0 +#define CLK_SOURCE_2D 0x15c +#define CLK_SOURCE_EPP 0x16c +#define CLK_SOURCE_MPE 0x170 +#define CLK_SOURCE_HOST1X 0x180 +#define CLK_SOURCE_CVE 0x140 +#define CLK_SOURCE_TVO 0x188 +#define CLK_SOURCE_DTV 0x1dc +#define CLK_SOURCE_HDMI 0x18c +#define CLK_SOURCE_TVDAC 0x194 +#define CLK_SOURCE_DISP1 0x138 +#define CLK_SOURCE_DISP2 0x13c +#define CLK_SOURCE_DSIB 0xd0 +#define CLK_SOURCE_TSENSOR 0x3b8 +#define CLK_SOURCE_ACTMON 0x3e8 +#define CLK_SOURCE_EXTERN1 0x3ec +#define CLK_SOURCE_EXTERN2 0x3f0 +#define CLK_SOURCE_EXTERN3 0x3f4 +#define CLK_SOURCE_I2CSLOW 0x3fc +#define CLK_SOURCE_SE 0x42c +#define CLK_SOURCE_MSELECT 0x3b4 +#define CLK_SOURCE_EMC 0x19c + +#define AUDIO_SYNC_DOUBLER 0x49c + +#define PMC_CTRL 0 +#define PMC_CTRL_BLINK_ENB 7 + +#define PMC_DPD_PADS_ORIDE 0x1c +#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 +#define PMC_BLINK_TIMER 0x40 + +#define UTMIP_PLL_CFG2 0x488 +#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) +#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) + +#define UTMIP_PLL_CFG1 0x484 +#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) +#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) +#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) + +/* Tegra CPU clock and reset control regs */ +#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c +#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 +#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344 +#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR 0x34c +#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 + +#define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) +#define CPU_RESET(cpu) (0x1111ul << (cpu)) + +#define CLK_RESET_CCLK_BURST 0x20 +#define CLK_RESET_CCLK_DIVIDER 0x24 +#define CLK_RESET_PLLX_BASE 0xe0 +#define CLK_RESET_PLLX_MISC 0xe4 + +#define CLK_RESET_SOURCE_CSITE 0x1d4 + +#define CLK_RESET_CCLK_BURST_POLICY_SHIFT 28 +#define CLK_RESET_CCLK_RUN_POLICY_SHIFT 4 +#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT 0 +#define CLK_RESET_CCLK_IDLE_POLICY 1 +#define CLK_RESET_CCLK_RUN_POLICY 2 +#define CLK_RESET_CCLK_BURST_POLICY_PLLX 8 + +#ifdef CONFIG_PM_SLEEP +static struct cpu_clk_suspend_context { + u32 pllx_misc; + u32 pllx_base; + + u32 cpu_burst; + u32 clk_csite_src; + u32 cclk_divider; +} tegra30_cpu_clk_sctx; +#endif + +static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; + +static void __iomem *clk_base; +static void __iomem *pmc_base; +static unsigned long input_freq; + +static DEFINE_SPINLOCK(clk_doubler_lock); +static DEFINE_SPINLOCK(clk_out_lock); +static DEFINE_SPINLOCK(pll_div_lock); +static DEFINE_SPINLOCK(cml_lock); +static DEFINE_SPINLOCK(pll_d_lock); + +#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 8, 1, 0, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id) + +#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, \ + _regs, _clk_num, periph_clk_enb_refcnt, \ + _gate_flags, _clk_id) + +#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 29, 3, 0, 0, 8, 1, 0, _regs, _clk_num, \ + periph_clk_enb_refcnt, _gate_flags, _clk_id) + +#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ + _clk_num, _regs, _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_id) + +#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ + _clk_num, _regs, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + 30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs, \ + _clk_num, periph_clk_enb_refcnt, 0, _clk_id) + +#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ + _mux_shift, _mux_width, _clk_num, _regs, \ + _gate_flags, _clk_id) \ + TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ + _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ + _clk_num, periph_clk_enb_refcnt, _gate_flags, \ + _clk_id) + +/* + * IDs assigned here must be in sync with DT bindings definition + * for Tegra30 clocks. + */ +enum tegra30_clk { + cpu, rtc = 4, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, ndflash, + sdmmc1, sdmmc4, pwm = 17, i2s2, epp, gr2d = 21, usbd, isp, gr3d, + disp2 = 26, disp1, host1x, vcp, i2s0, cop_cache, mc, ahbdma, apbdma, + kbc = 36, statmon, pmc, kfuse = 40, sbc1, nor, sbc2 = 44, sbc3 = 46, + i2c5, dsia, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, + usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, + pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2c_slow, + dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92, + cdev1, cdev2, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4, + i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x, + atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x, + spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda, se, + hda2hdmi, sata_cold, uartb = 160, vfir, spdif_out, spdif_in, vi, + vi_sensor, fuse, fuse_burn, cve, tvo, clk_32k, clk_m, clk_m_div2, + clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_m, pll_m_out1, pll_p, + pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_a, pll_a_out0, + pll_d, pll_d_out0, pll_d2, pll_d2_out0, pll_u, pll_x, pll_x_out0, pll_e, + spdif_in_sync, i2s0_sync, i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, + vimclk_sync, audio0, audio1, audio2, audio3, audio4, spdif, clk_out_1, + clk_out_2, clk_out_3, sclk, blink, cclk_g, cclk_lp, twd, cml0, cml1, + i2cslow, hclk, pclk, clk_out_1_mux = 300, clk_max +}; + +static struct clk *clks[clk_max]; +static struct clk_onecell_data clk_data; + +/* + * Structure defining the fields for USB UTMI clocks Parameters. + */ +struct utmi_clk_param { + /* Oscillator Frequency in KHz */ + u32 osc_frequency; + /* UTMIP PLL Enable Delay Count */ + u8 enable_delay_count; + /* UTMIP PLL Stable count */ + u8 stable_count; + /* UTMIP PLL Active delay count */ + u8 active_delay_count; + /* UTMIP PLL Xtal frequency count */ + u8 xtal_freq_count; +}; + +static const struct utmi_clk_param utmi_parameters[] = { +/* OSC_FREQUENCY, ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT */ + {13000000, 0x02, 0x33, 0x05, 0x7F}, + {19200000, 0x03, 0x4B, 0x06, 0xBB}, + {12000000, 0x02, 0x2F, 0x04, 0x76}, + {26000000, 0x04, 0x66, 0x09, 0xFE}, + {16800000, 0x03, 0x41, 0x0A, 0xA4}, +}; + +static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { + { 12000000, 1040000000, 520, 6, 1, 8}, + { 13000000, 1040000000, 480, 6, 1, 8}, + { 16800000, 1040000000, 495, 8, 1, 8}, /* actual: 1039.5 MHz */ + { 19200000, 1040000000, 325, 6, 1, 6}, + { 26000000, 1040000000, 520, 13, 1, 8}, + + { 12000000, 832000000, 416, 6, 1, 8}, + { 13000000, 832000000, 832, 13, 1, 8}, + { 16800000, 832000000, 396, 8, 1, 8}, /* actual: 831.6 MHz */ + { 19200000, 832000000, 260, 6, 1, 8}, + { 26000000, 832000000, 416, 13, 1, 8}, + + { 12000000, 624000000, 624, 12, 1, 8}, + { 13000000, 624000000, 624, 13, 1, 8}, + { 16800000, 600000000, 520, 14, 1, 8}, + { 19200000, 624000000, 520, 16, 1, 8}, + { 26000000, 624000000, 624, 26, 1, 8}, + + { 12000000, 600000000, 600, 12, 1, 8}, + { 13000000, 600000000, 600, 13, 1, 8}, + { 16800000, 600000000, 500, 14, 1, 8}, + { 19200000, 600000000, 375, 12, 1, 6}, + { 26000000, 600000000, 600, 26, 1, 8}, + + { 12000000, 520000000, 520, 12, 1, 8}, + { 13000000, 520000000, 520, 13, 1, 8}, + { 16800000, 520000000, 495, 16, 1, 8}, /* actual: 519.75 MHz */ + { 19200000, 520000000, 325, 12, 1, 6}, + { 26000000, 520000000, 520, 26, 1, 8}, + + { 12000000, 416000000, 416, 12, 1, 8}, + { 13000000, 416000000, 416, 13, 1, 8}, + { 16800000, 416000000, 396, 16, 1, 8}, /* actual: 415.8 MHz */ + { 19200000, 416000000, 260, 12, 1, 6}, + { 26000000, 416000000, 416, 26, 1, 8}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { + { 12000000, 666000000, 666, 12, 1, 8}, + { 13000000, 666000000, 666, 13, 1, 8}, + { 16800000, 666000000, 555, 14, 1, 8}, + { 19200000, 666000000, 555, 16, 1, 8}, + { 26000000, 666000000, 666, 26, 1, 8}, + { 12000000, 600000000, 600, 12, 1, 8}, + { 13000000, 600000000, 600, 13, 1, 8}, + { 16800000, 600000000, 500, 14, 1, 8}, + { 19200000, 600000000, 375, 12, 1, 6}, + { 26000000, 600000000, 600, 26, 1, 8}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { + { 12000000, 216000000, 432, 12, 2, 8}, + { 13000000, 216000000, 432, 13, 2, 8}, + { 16800000, 216000000, 360, 14, 2, 8}, + { 19200000, 216000000, 360, 16, 2, 8}, + { 26000000, 216000000, 432, 26, 2, 8}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { + { 9600000, 564480000, 294, 5, 1, 4}, + { 9600000, 552960000, 288, 5, 1, 4}, + { 9600000, 24000000, 5, 2, 1, 1}, + + { 28800000, 56448000, 49, 25, 1, 1}, + { 28800000, 73728000, 64, 25, 1, 1}, + { 28800000, 24000000, 5, 6, 1, 1}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { + { 12000000, 216000000, 216, 12, 1, 4}, + { 13000000, 216000000, 216, 13, 1, 4}, + { 16800000, 216000000, 180, 14, 1, 4}, + { 19200000, 216000000, 180, 16, 1, 4}, + { 26000000, 216000000, 216, 26, 1, 4}, + + { 12000000, 594000000, 594, 12, 1, 8}, + { 13000000, 594000000, 594, 13, 1, 8}, + { 16800000, 594000000, 495, 14, 1, 8}, + { 19200000, 594000000, 495, 16, 1, 8}, + { 26000000, 594000000, 594, 26, 1, 8}, + + { 12000000, 1000000000, 1000, 12, 1, 12}, + { 13000000, 1000000000, 1000, 13, 1, 12}, + { 19200000, 1000000000, 625, 12, 1, 8}, + { 26000000, 1000000000, 1000, 26, 1, 12}, + + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { + { 12000000, 480000000, 960, 12, 2, 12}, + { 13000000, 480000000, 960, 13, 2, 12}, + { 16800000, 480000000, 400, 7, 2, 5}, + { 19200000, 480000000, 200, 4, 2, 3}, + { 26000000, 480000000, 960, 26, 2, 12}, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { + /* 1.7 GHz */ + { 12000000, 1700000000, 850, 6, 1, 8}, + { 13000000, 1700000000, 915, 7, 1, 8}, /* actual: 1699.2 MHz */ + { 16800000, 1700000000, 708, 7, 1, 8}, /* actual: 1699.2 MHz */ + { 19200000, 1700000000, 885, 10, 1, 8}, /* actual: 1699.2 MHz */ + { 26000000, 1700000000, 850, 13, 1, 8}, + + /* 1.6 GHz */ + { 12000000, 1600000000, 800, 6, 1, 8}, + { 13000000, 1600000000, 738, 6, 1, 8}, /* actual: 1599.0 MHz */ + { 16800000, 1600000000, 857, 9, 1, 8}, /* actual: 1599.7 MHz */ + { 19200000, 1600000000, 500, 6, 1, 8}, + { 26000000, 1600000000, 800, 13, 1, 8}, + + /* 1.5 GHz */ + { 12000000, 1500000000, 750, 6, 1, 8}, + { 13000000, 1500000000, 923, 8, 1, 8}, /* actual: 1499.8 MHz */ + { 16800000, 1500000000, 625, 7, 1, 8}, + { 19200000, 1500000000, 625, 8, 1, 8}, + { 26000000, 1500000000, 750, 13, 1, 8}, + + /* 1.4 GHz */ + { 12000000, 1400000000, 700, 6, 1, 8}, + { 13000000, 1400000000, 969, 9, 1, 8}, /* actual: 1399.7 MHz */ + { 16800000, 1400000000, 1000, 12, 1, 8}, + { 19200000, 1400000000, 875, 12, 1, 8}, + { 26000000, 1400000000, 700, 13, 1, 8}, + + /* 1.3 GHz */ + { 12000000, 1300000000, 975, 9, 1, 8}, + { 13000000, 1300000000, 1000, 10, 1, 8}, + { 16800000, 1300000000, 928, 12, 1, 8}, /* actual: 1299.2 MHz */ + { 19200000, 1300000000, 812, 12, 1, 8}, /* actual: 1299.2 MHz */ + { 26000000, 1300000000, 650, 13, 1, 8}, + + /* 1.2 GHz */ + { 12000000, 1200000000, 1000, 10, 1, 8}, + { 13000000, 1200000000, 923, 10, 1, 8}, /* actual: 1199.9 MHz */ + { 16800000, 1200000000, 1000, 14, 1, 8}, + { 19200000, 1200000000, 1000, 16, 1, 8}, + { 26000000, 1200000000, 600, 13, 1, 8}, + + /* 1.1 GHz */ + { 12000000, 1100000000, 825, 9, 1, 8}, + { 13000000, 1100000000, 846, 10, 1, 8}, /* actual: 1099.8 MHz */ + { 16800000, 1100000000, 982, 15, 1, 8}, /* actual: 1099.8 MHz */ + { 19200000, 1100000000, 859, 15, 1, 8}, /* actual: 1099.5 MHz */ + { 26000000, 1100000000, 550, 13, 1, 8}, + + /* 1 GHz */ + { 12000000, 1000000000, 1000, 12, 1, 8}, + { 13000000, 1000000000, 1000, 13, 1, 8}, + { 16800000, 1000000000, 833, 14, 1, 8}, /* actual: 999.6 MHz */ + { 19200000, 1000000000, 625, 12, 1, 8}, + { 26000000, 1000000000, 1000, 26, 1, 8}, + + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { + /* PLLE special case: use cpcon field to store cml divider value */ + { 12000000, 100000000, 150, 1, 18, 11}, + { 216000000, 100000000, 200, 18, 24, 13}, + { 0, 0, 0, 0, 0, 0 }, +}; + +/* PLL parameters */ +static struct tegra_clk_pll_params pll_c_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLC_BASE, + .misc_reg = PLLC_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_m_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1200000000, + .base_reg = PLLM_BASE, + .misc_reg = PLLM_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_p_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLP_BASE, + .misc_reg = PLLP_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_a_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1400000000, + .base_reg = PLLA_BASE, + .misc_reg = PLLA_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_d_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 40000000, + .vco_max = 1000000000, + .base_reg = PLLD_BASE, + .misc_reg = PLLD_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, +}; + +static struct tegra_clk_pll_params pll_d2_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 40000000, + .vco_max = 1000000000, + .base_reg = PLLD2_BASE, + .misc_reg = PLLD2_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, +}; + +static struct tegra_clk_pll_params pll_u_params = { + .input_min = 2000000, + .input_max = 40000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 48000000, + .vco_max = 960000000, + .base_reg = PLLU_BASE, + .misc_reg = PLLU_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, + .lock_delay = 1000, +}; + +static struct tegra_clk_pll_params pll_x_params = { + .input_min = 2000000, + .input_max = 31000000, + .cf_min = 1000000, + .cf_max = 6000000, + .vco_min = 20000000, + .vco_max = 1700000000, + .base_reg = PLLX_BASE, + .misc_reg = PLLX_MISC, + .lock_bit_idx = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +static struct tegra_clk_pll_params pll_e_params = { + .input_min = 12000000, + .input_max = 216000000, + .cf_min = 12000000, + .cf_max = 12000000, + .vco_min = 1200000000, + .vco_max = 2400000000U, + .base_reg = PLLE_BASE, + .misc_reg = PLLE_MISC, + .lock_bit_idx = PLLE_MISC_LOCK, + .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, + .lock_delay = 300, +}; + +/* Peripheral clock registers */ +static struct tegra_clk_periph_regs periph_l_regs = { + .enb_reg = CLK_OUT_ENB_L, + .enb_set_reg = CLK_OUT_ENB_SET_L, + .enb_clr_reg = CLK_OUT_ENB_CLR_L, + .rst_reg = RST_DEVICES_L, + .rst_set_reg = RST_DEVICES_SET_L, + .rst_clr_reg = RST_DEVICES_CLR_L, +}; + +static struct tegra_clk_periph_regs periph_h_regs = { + .enb_reg = CLK_OUT_ENB_H, + .enb_set_reg = CLK_OUT_ENB_SET_H, + .enb_clr_reg = CLK_OUT_ENB_CLR_H, + .rst_reg = RST_DEVICES_H, + .rst_set_reg = RST_DEVICES_SET_H, + .rst_clr_reg = RST_DEVICES_CLR_H, +}; + +static struct tegra_clk_periph_regs periph_u_regs = { + .enb_reg = CLK_OUT_ENB_U, + .enb_set_reg = CLK_OUT_ENB_SET_U, + .enb_clr_reg = CLK_OUT_ENB_CLR_U, + .rst_reg = RST_DEVICES_U, + .rst_set_reg = RST_DEVICES_SET_U, + .rst_clr_reg = RST_DEVICES_CLR_U, +}; + +static struct tegra_clk_periph_regs periph_v_regs = { + .enb_reg = CLK_OUT_ENB_V, + .enb_set_reg = CLK_OUT_ENB_SET_V, + .enb_clr_reg = CLK_OUT_ENB_CLR_V, + .rst_reg = RST_DEVICES_V, + .rst_set_reg = RST_DEVICES_SET_V, + .rst_clr_reg = RST_DEVICES_CLR_V, +}; + +static struct tegra_clk_periph_regs periph_w_regs = { + .enb_reg = CLK_OUT_ENB_W, + .enb_set_reg = CLK_OUT_ENB_SET_W, + .enb_clr_reg = CLK_OUT_ENB_CLR_W, + .rst_reg = RST_DEVICES_W, + .rst_set_reg = RST_DEVICES_SET_W, + .rst_clr_reg = RST_DEVICES_CLR_W, +}; + +static void tegra30_clk_measure_input_freq(void) +{ + u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); + u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK; + u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; + + switch (auto_clk_control) { + case OSC_CTRL_OSC_FREQ_12MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 12000000; + break; + case OSC_CTRL_OSC_FREQ_13MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 13000000; + break; + case OSC_CTRL_OSC_FREQ_19_2MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 19200000; + break; + case OSC_CTRL_OSC_FREQ_26MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 26000000; + break; + case OSC_CTRL_OSC_FREQ_16_8MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); + input_freq = 16800000; + break; + case OSC_CTRL_OSC_FREQ_38_4MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2); + input_freq = 38400000; + break; + case OSC_CTRL_OSC_FREQ_48MHZ: + BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4); + input_freq = 48000000; + break; + default: + pr_err("Unexpected auto clock control value %d", + auto_clk_control); + BUG(); + return; + } +} + +static unsigned int tegra30_get_pll_ref_div(void) +{ + u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) & + OSC_CTRL_PLL_REF_DIV_MASK; + + switch (pll_ref_div) { + case OSC_CTRL_PLL_REF_DIV_1: + return 1; + case OSC_CTRL_PLL_REF_DIV_2: + return 2; + case OSC_CTRL_PLL_REF_DIV_4: + return 4; + default: + pr_err("Invalid pll ref divider %d", pll_ref_div); + BUG(); + } + return 0; +} + +static void tegra30_utmi_param_configure(void) +{ + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (input_freq == utmi_parameters[i].osc_frequency) + break; + } + + if (i >= ARRAY_SIZE(utmi_parameters)) { + pr_err("%s: Unexpected input rate %lu\n", __func__, input_freq); + return; + } + + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL stable and active counts */ + reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + reg |= UTMIP_PLL_CFG2_STABLE_COUNT( + utmi_parameters[i].stable_count); + + reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + + reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT( + utmi_parameters[i].active_delay_count); + + /* Remove power downs from UTMIP PLL control bits */ + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; + + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL delay and oscillator frequency counts */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + + reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT( + utmi_parameters[i].enable_delay_count); + + reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT( + utmi_parameters[i].xtal_freq_count); + + /* Remove power downs from UTMIP PLL control bits */ + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; + + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); +} + +static const char *pll_e_parents[] = {"pll_ref", "pll_p"}; + +static void __init tegra30_pll_init(void) +{ + struct clk *clk; + + /* PLLC */ + clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0, + 0, &pll_c_params, + TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + pll_c_freq_table, NULL); + clk_register_clkdev(clk, "pll_c", NULL); + clks[pll_c] = clk; + + /* PLLC_OUT1 */ + clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", + clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", + clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, + 0, NULL); + clk_register_clkdev(clk, "pll_c_out1", NULL); + clks[pll_c_out1] = clk; + + /* PLLP */ + clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc_base, 0, + 408000000, &pll_p_params, + TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_USE_LOCK, pll_p_freq_table, NULL); + clk_register_clkdev(clk, "pll_p", NULL); + clks[pll_p] = clk; + + /* PLLP_OUT1 */ + clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", + clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | + TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, + &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", + clk_base + PLLP_OUTA, 1, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out1", NULL); + clks[pll_p_out1] = clk; + + /* PLLP_OUT2 */ + clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", + clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | + TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, + &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", + clk_base + PLLP_OUTA, 17, 16, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out2", NULL); + clks[pll_p_out2] = clk; + + /* PLLP_OUT3 */ + clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", + clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | + TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, + &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", + clk_base + PLLP_OUTB, 1, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out3", NULL); + clks[pll_p_out3] = clk; + + /* PLLP_OUT4 */ + clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", + clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | + TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, + &pll_div_lock); + clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", + clk_base + PLLP_OUTB, 17, 16, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, + &pll_div_lock); + clk_register_clkdev(clk, "pll_p_out4", NULL); + clks[pll_p_out4] = clk; + + /* PLLM */ + clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base, + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, + &pll_m_params, TEGRA_PLLM | TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, + pll_m_freq_table, NULL); + clk_register_clkdev(clk, "pll_m", NULL); + clks[pll_m] = clk; + + /* PLLM_OUT1 */ + clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", + clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", + clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_m_out1", NULL); + clks[pll_m_out1] = clk; + + /* PLLX */ + clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, pmc_base, 0, + 0, &pll_x_params, TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, + pll_x_freq_table, NULL); + clk_register_clkdev(clk, "pll_x", NULL); + clks[pll_x] = clk; + + /* PLLX_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_x_out0", NULL); + clks[pll_x_out0] = clk; + + /* PLLU */ + clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0, + 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, + pll_u_freq_table, + NULL); + clk_register_clkdev(clk, "pll_u", NULL); + clks[pll_u] = clk; + + tegra30_utmi_param_configure(); + + /* PLLD */ + clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0, + 0, &pll_d_params, TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, + pll_d_freq_table, &pll_d_lock); + clk_register_clkdev(clk, "pll_d", NULL); + clks[pll_d] = clk; + + /* PLLD_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d_out0", NULL); + clks[pll_d_out0] = clk; + + /* PLLD2 */ + clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0, + 0, &pll_d2_params, TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, + pll_d_freq_table, NULL); + clk_register_clkdev(clk, "pll_d2", NULL); + clks[pll_d2] = clk; + + /* PLLD2_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d2_out0", NULL); + clks[pll_d2_out0] = clk; + + /* PLLA */ + clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc_base, + 0, 0, &pll_a_params, TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL); + clk_register_clkdev(clk, "pll_a", NULL); + clks[pll_a] = clk; + + /* PLLA_OUT0 */ + clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", + clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", + clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_a_out0", NULL); + clks[pll_a_out0] = clk; + + /* PLLE */ + clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents, + ARRAY_SIZE(pll_e_parents), 0, + clk_base + PLLE_AUX, 2, 1, 0, NULL); + clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base, + CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params, + TEGRA_PLLE_CONFIGURE, pll_e_freq_table, NULL); + clk_register_clkdev(clk, "pll_e", NULL); + clks[pll_e] = clk; +} + +static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", + "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",}; +static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern1", }; +static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern2", }; +static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", + "clk_m_div4", "extern3", }; + +static void __init tegra30_audio_clk_init(void) +{ + struct clk *clk; + + /* spdif_in_sync */ + clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, + 24000000); + clk_register_clkdev(clk, "spdif_in_sync", NULL); + clks[spdif_in_sync] = clk; + + /* i2s0_sync */ + clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); + clk_register_clkdev(clk, "i2s0_sync", NULL); + clks[i2s0_sync] = clk; + + /* i2s1_sync */ + clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); + clk_register_clkdev(clk, "i2s1_sync", NULL); + clks[i2s1_sync] = clk; + + /* i2s2_sync */ + clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); + clk_register_clkdev(clk, "i2s2_sync", NULL); + clks[i2s2_sync] = clk; + + /* i2s3_sync */ + clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); + clk_register_clkdev(clk, "i2s3_sync", NULL); + clks[i2s3_sync] = clk; + + /* i2s4_sync */ + clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); + clk_register_clkdev(clk, "i2s4_sync", NULL); + clks[i2s4_sync] = clk; + + /* vimclk_sync */ + clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); + clk_register_clkdev(clk, "vimclk_sync", NULL); + clks[vimclk_sync] = clk; + + /* audio0 */ + clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, + clk_base + AUDIO_SYNC_CLK_I2S0, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio0", NULL); + clks[audio0] = clk; + + /* audio1 */ + clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, + clk_base + AUDIO_SYNC_CLK_I2S1, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio1", NULL); + clks[audio1] = clk; + + /* audio2 */ + clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, + clk_base + AUDIO_SYNC_CLK_I2S2, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio2", NULL); + clks[audio2] = clk; + + /* audio3 */ + clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, + clk_base + AUDIO_SYNC_CLK_I2S3, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio3", NULL); + clks[audio3] = clk; + + /* audio4 */ + clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, + clk_base + AUDIO_SYNC_CLK_I2S4, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "audio4", NULL); + clks[audio4] = clk; + + /* spdif */ + clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk), 0, + clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL); + clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, + clk_base + AUDIO_SYNC_CLK_SPDIF, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "spdif", NULL); + clks[spdif] = clk; + + /* audio0_2x */ + clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("audio0_div", "audio0_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 113, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio0_2x", NULL); + clks[audio0_2x] = clk; + + /* audio1_2x */ + clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("audio1_div", "audio1_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 114, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio1_2x", NULL); + clks[audio1_2x] = clk; + + /* audio2_2x */ + clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("audio2_div", "audio2_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 115, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio2_2x", NULL); + clks[audio2_2x] = clk; + + /* audio3_2x */ + clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("audio3_div", "audio3_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 116, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio3_2x", NULL); + clks[audio3_2x] = clk; + + /* audio4_2x */ + clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("audio4_div", "audio4_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 117, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "audio4_2x", NULL); + clks[audio4_2x] = clk; + + /* spdif_2x */ + clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif", + CLK_SET_RATE_PARENT, 2, 1); + clk = tegra_clk_register_divider("spdif_div", "spdif_doubler", + clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, 0, + &clk_doubler_lock); + clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", + TEGRA_PERIPH_NO_RESET, clk_base, + CLK_SET_RATE_PARENT, 118, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "spdif_2x", NULL); + clks[spdif_2x] = clk; +} + +static void __init tegra30_pmc_clk_init(void) +{ + struct clk *clk; + + /* clk_out_1 */ + clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, + ARRAY_SIZE(clk_out1_parents), 0, + pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, + &clk_out_lock); + clks[clk_out_1_mux] = clk; + clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, + pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, + &clk_out_lock); + clk_register_clkdev(clk, "extern1", "clk_out_1"); + clks[clk_out_1] = clk; + + /* clk_out_2 */ + clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, + ARRAY_SIZE(clk_out1_parents), 0, + pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, + &clk_out_lock); + clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, + pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, + &clk_out_lock); + clk_register_clkdev(clk, "extern2", "clk_out_2"); + clks[clk_out_2] = clk; + + /* clk_out_3 */ + clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, + ARRAY_SIZE(clk_out1_parents), 0, + pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, + &clk_out_lock); + clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, + pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, + &clk_out_lock); + clk_register_clkdev(clk, "extern3", "clk_out_3"); + clks[clk_out_3] = clk; + + /* blink */ + writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); + clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, + pmc_base + PMC_DPD_PADS_ORIDE, + PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); + clk = clk_register_gate(NULL, "blink", "blink_override", 0, + pmc_base + PMC_CTRL, + PMC_CTRL_BLINK_ENB, 0, NULL); + clk_register_clkdev(clk, "blink", NULL); + clks[blink] = clk; + +} + +const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", + "pll_p_cclkg", "pll_p_out4_cclkg", + "pll_p_out3_cclkg", "unused", "pll_x" }; +const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", + "pll_p_cclklp", "pll_p_out4_cclklp", + "pll_p_out3_cclklp", "unused", "pll_x", + "pll_x_out0" }; +const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", + "pll_p_out3", "pll_p_out2", "unused", + "clk_32k", "pll_m_out1" }; + +static void __init tegra30_super_clk_init(void) +{ + struct clk *clk; + + /* + * Clock input to cclk_g divided from pll_p using + * U71 divider of cclk_g. + */ + clk = tegra_clk_register_divider("pll_p_cclkg", "pll_p", + clk_base + SUPER_CCLKG_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_cclkg", NULL); + + /* + * Clock input to cclk_g divided from pll_p_out3 using + * U71 divider of cclk_g. + */ + clk = tegra_clk_register_divider("pll_p_out3_cclkg", "pll_p_out3", + clk_base + SUPER_CCLKG_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out3_cclkg", NULL); + + /* + * Clock input to cclk_g divided from pll_p_out4 using + * U71 divider of cclk_g. + */ + clk = tegra_clk_register_divider("pll_p_out4_cclkg", "pll_p_out4", + clk_base + SUPER_CCLKG_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out4_cclkg", NULL); + + /* CCLKG */ + clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, + ARRAY_SIZE(cclk_g_parents), + CLK_SET_RATE_PARENT, + clk_base + CCLKG_BURST_POLICY, + 0, 4, 0, 0, NULL); + clk_register_clkdev(clk, "cclk_g", NULL); + clks[cclk_g] = clk; + + /* + * Clock input to cclk_lp divided from pll_p using + * U71 divider of cclk_lp. + */ + clk = tegra_clk_register_divider("pll_p_cclklp", "pll_p", + clk_base + SUPER_CCLKLP_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_cclklp", NULL); + + /* + * Clock input to cclk_lp divided from pll_p_out3 using + * U71 divider of cclk_lp. + */ + clk = tegra_clk_register_divider("pll_p_out3_cclklp", "pll_p_out3", + clk_base + SUPER_CCLKG_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out3_cclklp", NULL); + + /* + * Clock input to cclk_lp divided from pll_p_out4 using + * U71 divider of cclk_lp. + */ + clk = tegra_clk_register_divider("pll_p_out4_cclklp", "pll_p_out4", + clk_base + SUPER_CCLKLP_DIVIDER, 0, + TEGRA_DIVIDER_INT, 16, 8, 1, NULL); + clk_register_clkdev(clk, "pll_p_out4_cclklp", NULL); + + /* CCLKLP */ + clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, + ARRAY_SIZE(cclk_lp_parents), + CLK_SET_RATE_PARENT, + clk_base + CCLKLP_BURST_POLICY, + TEGRA_DIVIDER_2, 4, 8, 9, + NULL); + clk_register_clkdev(clk, "cclk_lp", NULL); + clks[cclk_lp] = clk; + + /* SCLK */ + clk = tegra_clk_register_super_mux("sclk", sclk_parents, + ARRAY_SIZE(sclk_parents), + CLK_SET_RATE_PARENT, + clk_base + SCLK_BURST_POLICY, + 0, 4, 0, 0, NULL); + clk_register_clkdev(clk, "sclk", NULL); + clks[sclk] = clk; + + /* HCLK */ + clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, + clk_base + SYSTEM_CLK_RATE, 4, 2, 0, NULL); + clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT, + clk_base + SYSTEM_CLK_RATE, 7, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "hclk", NULL); + clks[hclk] = clk; + + /* PCLK */ + clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, + clk_base + SYSTEM_CLK_RATE, 0, 2, 0, NULL); + clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT, + clk_base + SYSTEM_CLK_RATE, 3, + CLK_GATE_SET_TO_DISABLE, NULL); + clk_register_clkdev(clk, "pclk", NULL); + clks[pclk] = clk; + + /* twd */ + clk = clk_register_fixed_factor(NULL, "twd", "cclk_g", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "twd", NULL); + clks[twd] = clk; +} + +static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p", + "clk_m" }; +static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" }; +static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" }; +static const char *i2s0_parents[] = { "pll_a_out0", "audio0_2x", "pll_p", + "clk_m" }; +static const char *i2s1_parents[] = { "pll_a_out0", "audio1_2x", "pll_p", + "clk_m" }; +static const char *i2s2_parents[] = { "pll_a_out0", "audio2_2x", "pll_p", + "clk_m" }; +static const char *i2s3_parents[] = { "pll_a_out0", "audio3_2x", "pll_p", + "clk_m" }; +static const char *i2s4_parents[] = { "pll_a_out0", "audio4_2x", "pll_p", + "clk_m" }; +static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p", + "clk_m" }; +static const char *spdif_in_parents[] = { "pll_p", "pll_c", "pll_m" }; +static const char *mux_pllpc_clk32k_clkm[] = { "pll_p", "pll_c", "clk_32k", + "clk_m" }; +static const char *mux_pllpc_clkm_clk32k[] = { "pll_p", "pll_c", "clk_m", + "clk_32k" }; +static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" }; +static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c", + "clk_m" }; +static const char *mux_pllp_clkm[] = { "pll_p", "unused", "unused", "clk_m" }; +static const char *mux_pllpmdacd2_clkm[] = { "pll_p", "pll_m", "pll_d_out0", + "pll_a_out0", "pll_c", + "pll_d2_out0", "clk_m" }; +static const char *mux_plla_clk32k_pllp_clkm_plle[] = { "pll_a_out0", + "clk_32k", "pll_p", + "clk_m", "pll_e" }; +static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0", + "pll_d2_out0" }; + +static struct tegra_periph_init_data tegra_periph_clk_list[] = { + TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", i2s0_parents, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0), + TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", i2s1_parents, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), + TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", i2s2_parents, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), + TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", i2s3_parents, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3), + TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", i2s4_parents, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4), + TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), + TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), + TEGRA_INIT_DATA_MUX("d_audio", "d_audio", "tegra30-ahub", mux_pllacp_clkm, CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, 0, d_audio), + TEGRA_INIT_DATA_MUX("dam0", NULL, "tegra30-dam.0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, &periph_v_regs, 0, dam0), + TEGRA_INIT_DATA_MUX("dam1", NULL, "tegra30-dam.1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, &periph_v_regs, 0, dam1), + TEGRA_INIT_DATA_MUX("dam2", NULL, "tegra30-dam.2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, &periph_v_regs, 0, dam2), + TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, 0, hda), + TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllpcm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, 0, hda2codec_2x), + TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), + TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), + TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), + TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), + TEGRA_INIT_DATA_MUX("sbc5", NULL, "spi_tegra.4", mux_pllpcm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5), + TEGRA_INIT_DATA_MUX("sbc6", NULL, "spi_tegra.5", mux_pllpcm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6), + TEGRA_INIT_DATA_MUX("sata_oob", NULL, "tegra_sata_oob", mux_pllpcm_clkm, CLK_SOURCE_SATA_OOB, 123, &periph_v_regs, TEGRA_PERIPH_ON_APB, sata_oob), + TEGRA_INIT_DATA_MUX("sata", NULL, "tegra_sata", mux_pllpcm_clkm, CLK_SOURCE_SATA, 124, &periph_v_regs, TEGRA_PERIPH_ON_APB, sata), + TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_l_regs, TEGRA_PERIPH_ON_APB, ndflash), + TEGRA_INIT_DATA_MUX("ndspeed", NULL, "tegra_nand_speed", mux_pllpcm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), + TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), + TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite), + TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la), + TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), + TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), + TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllpc_clkm_clk32k, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor), + TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllpc_clk32k_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow), + TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), + TEGRA_INIT_DATA_INT("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), + TEGRA_INIT_DATA_INT("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), + TEGRA_INIT_DATA_INT("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, &periph_h_regs, 0, mpe), + TEGRA_INIT_DATA_INT("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), + TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d), + TEGRA_INIT_DATA_INT("3d2", NULL, "3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, &periph_v_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d2), + TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr2d), + TEGRA_INIT_DATA_INT("se", NULL, "se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, 0, se), + TEGRA_INIT_DATA_MUX("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect), + TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), + TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), + TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), + TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), + TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), + TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, &periph_h_regs, 0, cve), + TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, &periph_h_regs, 0, tvo), + TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, &periph_h_regs, 0, tvdac), + TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllpc_clk32k_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon), + TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), + TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1), + TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2), + TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3), + TEGRA_INIT_DATA_DIV16("i2c4", "div-clk", "tegra-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2c4), + TEGRA_INIT_DATA_DIV16("i2c5", "div-clk", "tegra-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c5), + TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta), + TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb), + TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc), + TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd), + TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 66, &periph_u_regs, uarte), + TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), + TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1), + TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2), + TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32k_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3), + TEGRA_INIT_DATA("pwm", NULL, "pwm", mux_pllpc_clk32k_clkm, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, 0, pwm), +}; + +static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { + TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, &periph_l_regs, 0, disp1), + TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpmdacd2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, &periph_l_regs, 0, disp2), + TEGRA_INIT_DATA_NODIV("dsib", NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB, 25, 1, 82, &periph_u_regs, 0, dsib), +}; + +static void __init tegra30_periph_clk_init(void) +{ + struct tegra_periph_init_data *data; + struct clk *clk; + int i; + + /* apbdma */ + clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34, + &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-apbdma"); + clks[apbdma] = clk; + + /* rtc */ + clk = tegra_clk_register_periph_gate("rtc", "clk_32k", + TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, + clk_base, 0, 4, &periph_l_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "rtc-tegra"); + clks[rtc] = clk; + + /* timer */ + clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0, + 5, &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "timer"); + clks[timer] = clk; + + /* kbc */ + clk = tegra_clk_register_periph_gate("kbc", "clk_32k", + TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, + clk_base, 0, 36, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-kbc"); + clks[kbc] = clk; + + /* csus */ + clk = tegra_clk_register_periph_gate("csus", "clk_m", + TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, + clk_base, 0, 92, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "csus", "tengra_camera"); + clks[csus] = clk; + + /* vcp */ + clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29, + &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "vcp", "tegra-avp"); + clks[vcp] = clk; + + /* bsea */ + clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0, + 62, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "bsea", "tegra-avp"); + clks[bsea] = clk; + + /* bsev */ + clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0, + 63, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "bsev", "tegra-aes"); + clks[bsev] = clk; + + /* usbd */ + clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, + 22, &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); + clks[usbd] = clk; + + /* usb2 */ + clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, + 58, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-ehci.1"); + clks[usb2] = clk; + + /* usb3 */ + clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, + 59, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra-ehci.2"); + clks[usb3] = clk; + + /* dsia */ + clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base, + 0, 48, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "dsia", "tegradc.0"); + clks[dsia] = clk; + + /* csi */ + clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, + 0, 52, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "csi", "tegra_camera"); + clks[csi] = clk; + + /* isp */ + clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, + &periph_l_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "isp", "tegra_camera"); + clks[isp] = clk; + + /* pcie */ + clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0, + 70, &periph_u_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "pcie", "tegra-pcie"); + clks[pcie] = clk; + + /* afi */ + clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, + &periph_u_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "afi", "tegra-pcie"); + clks[afi] = clk; + + /* kfuse */ + clk = tegra_clk_register_periph_gate("kfuse", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 40, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "kfuse-tegra"); + clks[kfuse] = clk; + + /* fuse */ + clk = tegra_clk_register_periph_gate("fuse", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 39, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "fuse", "fuse-tegra"); + clks[fuse] = clk; + + /* fuse_burn */ + clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 39, &periph_h_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "fuse_burn", "fuse-tegra"); + clks[fuse_burn] = clk; + + /* apbif */ + clk = tegra_clk_register_periph_gate("apbif", "clk_m", 0, + clk_base, 0, 107, &periph_v_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "apbif", "tegra30-ahub"); + clks[apbif] = clk; + + /* hda2hdmi */ + clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 128, &periph_w_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda"); + clks[hda2hdmi] = clk; + + /* sata_cold */ + clk = tegra_clk_register_periph_gate("sata_cold", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 129, &periph_w_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "tegra_sata_cold"); + clks[sata_cold] = clk; + + /* dtv */ + clk = tegra_clk_register_periph_gate("dtv", "clk_m", + TEGRA_PERIPH_ON_APB, + clk_base, 0, 79, &periph_u_regs, + periph_clk_enb_refcnt); + clk_register_clkdev(clk, NULL, "dtv"); + clks[dtv] = clk; + + /* emc */ + clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, + ARRAY_SIZE(mux_pllmcp_clkm), 0, + clk_base + CLK_SOURCE_EMC, + 30, 2, 0, NULL); + clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, + 57, &periph_h_regs, periph_clk_enb_refcnt); + clk_register_clkdev(clk, "emc", NULL); + clks[emc] = clk; + + for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { + data = &tegra_periph_clk_list[i]; + clk = tegra_clk_register_periph(data->name, data->parent_names, + data->num_parents, &data->periph, + clk_base, data->offset); + clk_register_clkdev(clk, data->con_id, data->dev_id); + clks[data->clk_id] = clk; + } + + for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { + data = &tegra_periph_nodiv_clk_list[i]; + clk = tegra_clk_register_periph_nodiv(data->name, + data->parent_names, + data->num_parents, &data->periph, + clk_base, data->offset); + clk_register_clkdev(clk, data->con_id, data->dev_id); + clks[data->clk_id] = clk; + } +} + +static void __init tegra30_fixed_clk_init(void) +{ + struct clk *clk; + + /* clk_32k */ + clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, + 32768); + clk_register_clkdev(clk, "clk_32k", NULL); + clks[clk_32k] = clk; + + /* clk_m_div2 */ + clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "clk_m_div2", NULL); + clks[clk_m_div2] = clk; + + /* clk_m_div4 */ + clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", + CLK_SET_RATE_PARENT, 1, 4); + clk_register_clkdev(clk, "clk_m_div4", NULL); + clks[clk_m_div4] = clk; + + /* cml0 */ + clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX, + 0, 0, &cml_lock); + clk_register_clkdev(clk, "cml0", NULL); + clks[cml0] = clk; + + /* cml1 */ + clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX, + 1, 0, &cml_lock); + clk_register_clkdev(clk, "cml1", NULL); + clks[cml1] = clk; + + /* pciex */ + clk = clk_register_fixed_rate(NULL, "pciex", "pll_e", 0, 100000000); + clk_register_clkdev(clk, "pciex", NULL); + clks[pciex] = clk; +} + +static void __init tegra30_osc_clk_init(void) +{ + struct clk *clk; + unsigned int pll_ref_div; + + tegra30_clk_measure_input_freq(); + + /* clk_m */ + clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, + input_freq); + clk_register_clkdev(clk, "clk_m", NULL); + clks[clk_m] = clk; + + /* pll_ref */ + pll_ref_div = tegra30_get_pll_ref_div(); + clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", + CLK_SET_RATE_PARENT, 1, pll_ref_div); + clk_register_clkdev(clk, "pll_ref", NULL); + clks[pll_ref] = clk; +} + +/* Tegra30 CPU clock and reset control functions */ +static void tegra30_wait_cpu_in_reset(u32 cpu) +{ + unsigned int reg; + + do { + reg = readl(clk_base + + TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); + cpu_relax(); + } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ + + return; +} + +static void tegra30_put_cpu_in_reset(u32 cpu) +{ + writel(CPU_RESET(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + dmb(); +} + +static void tegra30_cpu_out_of_reset(u32 cpu) +{ + writel(CPU_RESET(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); + wmb(); +} + + +static void tegra30_enable_cpu_clock(u32 cpu) +{ + unsigned int reg; + + writel(CPU_CLOCK(cpu), + clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); + reg = readl(clk_base + + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR); +} + +static void tegra30_disable_cpu_clock(u32 cpu) +{ + + unsigned int reg; + + reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + writel(reg | CPU_CLOCK(cpu), + clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); +} + +#ifdef CONFIG_PM_SLEEP +static bool tegra30_cpu_rail_off_ready(void) +{ + unsigned int cpu_rst_status; + int cpu_pwr_status; + + cpu_rst_status = readl(clk_base + + TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); + cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) || + tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) || + tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3); + + if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status) + return false; + + return true; +} + +static void tegra30_cpu_clock_suspend(void) +{ + /* switch coresite to clk_m, save off original source */ + tegra30_cpu_clk_sctx.clk_csite_src = + readl(clk_base + CLK_RESET_SOURCE_CSITE); + writel(3<<30, clk_base + CLK_RESET_SOURCE_CSITE); + + tegra30_cpu_clk_sctx.cpu_burst = + readl(clk_base + CLK_RESET_CCLK_BURST); + tegra30_cpu_clk_sctx.pllx_base = + readl(clk_base + CLK_RESET_PLLX_BASE); + tegra30_cpu_clk_sctx.pllx_misc = + readl(clk_base + CLK_RESET_PLLX_MISC); + tegra30_cpu_clk_sctx.cclk_divider = + readl(clk_base + CLK_RESET_CCLK_DIVIDER); +} + +static void tegra30_cpu_clock_resume(void) +{ + unsigned int reg, policy; + + /* Is CPU complex already running on PLLX? */ + reg = readl(clk_base + CLK_RESET_CCLK_BURST); + policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF; + + if (policy == CLK_RESET_CCLK_IDLE_POLICY) + reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF; + else if (policy == CLK_RESET_CCLK_RUN_POLICY) + reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF; + else + BUG(); + + if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) { + /* restore PLLX settings if CPU is on different PLL */ + writel(tegra30_cpu_clk_sctx.pllx_misc, + clk_base + CLK_RESET_PLLX_MISC); + writel(tegra30_cpu_clk_sctx.pllx_base, + clk_base + CLK_RESET_PLLX_BASE); + + /* wait for PLL stabilization if PLLX was enabled */ + if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30)) + udelay(300); + } + + /* + * Restore original burst policy setting for calls resulting from CPU + * LP2 in idle or system suspend. + */ + writel(tegra30_cpu_clk_sctx.cclk_divider, + clk_base + CLK_RESET_CCLK_DIVIDER); + writel(tegra30_cpu_clk_sctx.cpu_burst, + clk_base + CLK_RESET_CCLK_BURST); + + writel(tegra30_cpu_clk_sctx.clk_csite_src, + clk_base + CLK_RESET_SOURCE_CSITE); +} +#endif + +static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { + .wait_for_reset = tegra30_wait_cpu_in_reset, + .put_in_reset = tegra30_put_cpu_in_reset, + .out_of_reset = tegra30_cpu_out_of_reset, + .enable_clock = tegra30_enable_cpu_clock, + .disable_clock = tegra30_disable_cpu_clock, +#ifdef CONFIG_PM_SLEEP + .rail_off_ready = tegra30_cpu_rail_off_ready, + .suspend = tegra30_cpu_clock_suspend, + .resume = tegra30_cpu_clock_resume, +#endif +}; + +static __initdata struct tegra_clk_init_table init_table[] = { + {uarta, pll_p, 408000000, 1}, + {pll_a, clk_max, 564480000, 1}, + {pll_a_out0, clk_max, 11289600, 1}, + {extern1, pll_a_out0, 0, 1}, + {clk_out_1_mux, extern1, 0, 0}, + {clk_out_1, clk_max, 0, 1}, + {blink, clk_max, 0, 1}, + {i2s0, pll_a_out0, 11289600, 0}, + {i2s1, pll_a_out0, 11289600, 0}, + {i2s2, pll_a_out0, 11289600, 0}, + {i2s3, pll_a_out0, 11289600, 0}, + {i2s4, pll_a_out0, 11289600, 0}, + {sdmmc1, pll_p, 48000000, 0}, + {sdmmc2, pll_p, 48000000, 0}, + {sdmmc3, pll_p, 48000000, 0}, + {pll_m, clk_max, 0, 1}, + {pclk, clk_max, 0, 1}, + {csite, clk_max, 0, 1}, + {emc, clk_max, 0, 1}, + {mselect, clk_max, 0, 1}, + {sbc1, pll_p, 100000000, 0}, + {sbc2, pll_p, 100000000, 0}, + {sbc3, pll_p, 100000000, 0}, + {sbc4, pll_p, 100000000, 0}, + {sbc5, pll_p, 100000000, 0}, + {sbc6, pll_p, 100000000, 0}, + {host1x, pll_c, 150000000, 0}, + {disp1, pll_p, 600000000, 0}, + {disp2, pll_p, 600000000, 0}, + {twd, clk_max, 0, 1}, + {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ +}; + +/* + * Some clocks may be used by different drivers depending on the board + * configuration. List those here to register them twice in the clock lookup + * table under two names. + */ +static struct tegra_clk_duplicate tegra_clk_duplicates[] = { + TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL), + TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), + TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), + TEGRA_CLK_DUPLICATE(bsev, "tegra-avp", "bsev"), + TEGRA_CLK_DUPLICATE(bsev, "nvavp", "bsev"), + TEGRA_CLK_DUPLICATE(vde, "tegra-aes", "vde"), + TEGRA_CLK_DUPLICATE(bsea, "tegra-aes", "bsea"), + TEGRA_CLK_DUPLICATE(bsea, "nvavp", "bsea"), + TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL), + TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"), + TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"), + TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL), + TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"), + TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */ +}; + +static const struct of_device_id pmc_match[] __initconst = { + { .compatible = "nvidia,tegra30-pmc" }, + {}, +}; + +void __init tegra30_clock_init(struct device_node *np) +{ + struct device_node *node; + int i; + + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("ioremap tegra30 CAR failed\n"); + return; + } + + node = of_find_matching_node(NULL, pmc_match); + if (!node) { + pr_err("Failed to find pmc node\n"); + BUG(); + } + + pmc_base = of_iomap(node, 0); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + BUG(); + } + + tegra30_osc_clk_init(); + tegra30_fixed_clk_init(); + tegra30_pll_init(); + tegra30_super_clk_init(); + tegra30_periph_clk_init(); + tegra30_audio_clk_init(); + tegra30_pmc_clk_init(); + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + if (IS_ERR(clks[i])) { + pr_err("Tegra30 clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + BUG(); + } + if (!clks[i]) + clks[i] = ERR_PTR(-EINVAL); + } + + tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + tegra_init_from_table(init_table, clks, clk_max); + + tegra_cpu_car_ops = &tegra30_cpu_car_ops; +} diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c new file mode 100644 index 0000000..a603b9a --- /dev/null +++ b/drivers/clk/tegra/clk.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/clk/tegra.h> + +#include "clk.h" + +/* Global data of Tegra CPU CAR ops */ +struct tegra_cpu_car_ops *tegra_cpu_car_ops; + +void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, + struct clk *clks[], int clk_max) +{ + struct clk *clk; + + for (; dup_list->clk_id < clk_max; dup_list++) { + clk = clks[dup_list->clk_id]; + dup_list->lookup.clk = clk; + clkdev_add(&dup_list->lookup); + } +} + +void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, + struct clk *clks[], int clk_max) +{ + struct clk *clk; + + for (; tbl->clk_id < clk_max; tbl++) { + clk = clks[tbl->clk_id]; + if (IS_ERR_OR_NULL(clk)) + return; + + if (tbl->parent_id < clk_max) { + struct clk *parent = clks[tbl->parent_id]; + if (clk_set_parent(clk, parent)) { + pr_err("%s: Failed to set parent %s of %s\n", + __func__, __clk_get_name(parent), + __clk_get_name(clk)); + WARN_ON(1); + } + } + + if (tbl->rate) + if (clk_set_rate(clk, tbl->rate)) { + pr_err("%s: Failed to set rate %lu of %s\n", + __func__, tbl->rate, + __clk_get_name(clk)); + WARN_ON(1); + } + + if (tbl->state) + if (clk_prepare_enable(clk)) { + pr_err("%s: Failed to enable %s\n", __func__, + __clk_get_name(clk)); + WARN_ON(1); + } + } +} + +static const struct of_device_id tegra_dt_clk_match[] = { + { .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init }, + { .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init }, + { } +}; + +void __init tegra_clocks_init(void) +{ + of_clk_init(tegra_dt_clk_match); +} diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h new file mode 100644 index 0000000..0744731 --- /dev/null +++ b/drivers/clk/tegra/clk.h @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __TEGRA_CLK_H +#define __TEGRA_CLK_H + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> + +/** + * struct tegra_clk_sync_source - external clock source from codec + * + * @hw: handle between common and hardware-specific interfaces + * @rate: input frequency from source + * @max_rate: max rate allowed + */ +struct tegra_clk_sync_source { + struct clk_hw hw; + unsigned long rate; + unsigned long max_rate; +}; + +#define to_clk_sync_source(_hw) \ + container_of(_hw, struct tegra_clk_sync_source, hw) + +extern const struct clk_ops tegra_clk_sync_source_ops; +struct clk *tegra_clk_register_sync_source(const char *name, + unsigned long fixed_rate, unsigned long max_rate); + +/** + * struct tegra_clk_frac_div - fractional divider clock + * + * @hw: handle between common and hardware-specific interfaces + * @reg: register containing divider + * @flags: hardware-specific flags + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @frac_width: width of the fractional bit field + * @lock: register lock + * + * Flags: + * TEGRA_DIVIDER_ROUND_UP - This flags indicates to round up the divider value. + * TEGRA_DIVIDER_FIXED - Fixed rate PLL dividers has addition override bit, this + * flag indicates that this divider is for fixed rate PLL. + * TEGRA_DIVIDER_INT - Some modules can not cope with the duty cycle when + * fraction bit is set. This flags indicates to calculate divider for which + * fracton bit will be zero. + * TEGRA_DIVIDER_UART - UART module divider has additional enable bit which is + * set when divider value is not 0. This flags indicates that the divider + * is for UART module. + */ +struct tegra_clk_frac_div { + struct clk_hw hw; + void __iomem *reg; + u8 flags; + u8 shift; + u8 width; + u8 frac_width; + spinlock_t *lock; +}; + +#define to_clk_frac_div(_hw) container_of(_hw, struct tegra_clk_frac_div, hw) + +#define TEGRA_DIVIDER_ROUND_UP BIT(0) +#define TEGRA_DIVIDER_FIXED BIT(1) +#define TEGRA_DIVIDER_INT BIT(2) +#define TEGRA_DIVIDER_UART BIT(3) + +extern const struct clk_ops tegra_clk_frac_div_ops; +struct clk *tegra_clk_register_divider(const char *name, + const char *parent_name, void __iomem *reg, + unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width, + u8 frac_width, spinlock_t *lock); + +/* + * Tegra PLL: + * + * In general, there are 3 requirements for each PLL + * that SW needs to be comply with. + * (1) Input frequency range (REF). + * (2) Comparison frequency range (CF). CF = REF/DIVM. + * (3) VCO frequency range (VCO). VCO = CF * DIVN. + * + * The final PLL output frequency (FO) = VCO >> DIVP. + */ + +/** + * struct tegra_clk_pll_freq_table - PLL frequecy table + * + * @input_rate: input rate from source + * @output_rate: output rate from PLL for the input rate + * @n: feedback divider + * @m: input divider + * @p: post divider + * @cpcon: charge pump current + */ +struct tegra_clk_pll_freq_table { + unsigned long input_rate; + unsigned long output_rate; + u16 n; + u16 m; + u8 p; + u8 cpcon; +}; + +/** + * struct clk_pll_params - PLL parameters + * + * @input_min: Minimum input frequency + * @input_max: Maximum input frequency + * @cf_min: Minimum comparison frequency + * @cf_max: Maximum comparison frequency + * @vco_min: Minimum VCO frequency + * @vco_max: Maximum VCO frequency + * @base_reg: PLL base reg offset + * @misc_reg: PLL misc reg offset + * @lock_reg: PLL lock reg offset + * @lock_bit_idx: Bit index for PLL lock status + * @lock_enable_bit_idx: Bit index to enable PLL lock + * @lock_delay: Delay in us if PLL lock is not used + */ +struct tegra_clk_pll_params { + unsigned long input_min; + unsigned long input_max; + unsigned long cf_min; + unsigned long cf_max; + unsigned long vco_min; + unsigned long vco_max; + + u32 base_reg; + u32 misc_reg; + u32 lock_reg; + u32 lock_bit_idx; + u32 lock_enable_bit_idx; + int lock_delay; +}; + +/** + * struct tegra_clk_pll - Tegra PLL clock + * + * @hw: handle between common and hardware-specifix interfaces + * @clk_base: address of CAR controller + * @pmc: address of PMC, required to read override bits + * @freq_table: array of frequencies supported by PLL + * @params: PLL parameters + * @flags: PLL flags + * @fixed_rate: PLL rate if it is fixed + * @lock: register lock + * @divn_shift: shift to the feedback divider bit field + * @divn_width: width of the feedback divider bit field + * @divm_shift: shift to the input divider bit field + * @divm_width: width of the input divider bit field + * @divp_shift: shift to the post divider bit field + * @divp_width: width of the post divider bit field + * + * Flags: + * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for + * PLL locking. If not set it will use lock_delay value to wait. + * TEGRA_PLL_HAS_CPCON - This flag indicates that CPCON value needs + * to be programmed to change output frequency of the PLL. + * TEGRA_PLL_SET_LFCON - This flag indicates that LFCON value needs + * to be programmed to change output frequency of the PLL. + * TEGRA_PLL_SET_DCCON - This flag indicates that DCCON value needs + * to be programmed to change output frequency of the PLL. + * TEGRA_PLLU - PLLU has inverted post divider. This flags indicated + * that it is PLLU and invert post divider value. + * TEGRA_PLLM - PLLM has additional override settings in PMC. This + * flag indicates that it is PLLM and use override settings. + * TEGRA_PLL_FIXED - We are not supposed to change output frequency + * of some plls. + * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling. + */ +struct tegra_clk_pll { + struct clk_hw hw; + void __iomem *clk_base; + void __iomem *pmc; + u8 flags; + unsigned long fixed_rate; + spinlock_t *lock; + u8 divn_shift; + u8 divn_width; + u8 divm_shift; + u8 divm_width; + u8 divp_shift; + u8 divp_width; + struct tegra_clk_pll_freq_table *freq_table; + struct tegra_clk_pll_params *params; +}; + +#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw) + +#define TEGRA_PLL_USE_LOCK BIT(0) +#define TEGRA_PLL_HAS_CPCON BIT(1) +#define TEGRA_PLL_SET_LFCON BIT(2) +#define TEGRA_PLL_SET_DCCON BIT(3) +#define TEGRA_PLLU BIT(4) +#define TEGRA_PLLM BIT(5) +#define TEGRA_PLL_FIXED BIT(6) +#define TEGRA_PLLE_CONFIGURE BIT(7) + +extern const struct clk_ops tegra_clk_pll_ops; +extern const struct clk_ops tegra_clk_plle_ops; +struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, unsigned long fixed_rate, + struct tegra_clk_pll_params *pll_params, u8 pll_flags, + struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); +struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, unsigned long fixed_rate, + struct tegra_clk_pll_params *pll_params, u8 pll_flags, + struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); + +/** + * struct tegra_clk_pll_out - PLL divider down clock + * + * @hw: handle between common and hardware-specific interfaces + * @reg: register containing the PLL divider + * @enb_bit_idx: bit to enable/disable PLL divider + * @rst_bit_idx: bit to reset PLL divider + * @lock: register lock + * @flags: hardware-specific flags + */ +struct tegra_clk_pll_out { + struct clk_hw hw; + void __iomem *reg; + u8 enb_bit_idx; + u8 rst_bit_idx; + spinlock_t *lock; + u8 flags; +}; + +#define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw) + +extern const struct clk_ops tegra_clk_pll_out_ops; +struct clk *tegra_clk_register_pll_out(const char *name, + const char *parent_name, void __iomem *reg, u8 enb_bit_idx, + u8 rst_bit_idx, unsigned long flags, u8 pll_div_flags, + spinlock_t *lock); + +/** + * struct tegra_clk_periph_regs - Registers controlling peripheral clock + * + * @enb_reg: read the enable status + * @enb_set_reg: write 1 to enable clock + * @enb_clr_reg: write 1 to disable clock + * @rst_reg: read the reset status + * @rst_set_reg: write 1 to assert the reset of peripheral + * @rst_clr_reg: write 1 to deassert the reset of peripheral + */ +struct tegra_clk_periph_regs { + u32 enb_reg; + u32 enb_set_reg; + u32 enb_clr_reg; + u32 rst_reg; + u32 rst_set_reg; + u32 rst_clr_reg; +}; + +/** + * struct tegra_clk_periph_gate - peripheral gate clock + * + * @magic: magic number to validate type + * @hw: handle between common and hardware-specific interfaces + * @clk_base: address of CAR controller + * @regs: Registers to control the peripheral + * @flags: hardware-specific flags + * @clk_num: Clock number + * @enable_refcnt: array to maintain reference count of the clock + * + * Flags: + * TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed + * for this module. + * TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module + * after clock enable and driver for the module is responsible for + * doing reset. + * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the + * bus to flush the write operation in apb bus. This flag indicates + * that this peripheral is in apb bus. + */ +struct tegra_clk_periph_gate { + u32 magic; + struct clk_hw hw; + void __iomem *clk_base; + u8 flags; + int clk_num; + int *enable_refcnt; + struct tegra_clk_periph_regs *regs; +}; + +#define to_clk_periph_gate(_hw) \ + container_of(_hw, struct tegra_clk_periph_gate, hw) + +#define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309 + +#define TEGRA_PERIPH_NO_RESET BIT(0) +#define TEGRA_PERIPH_MANUAL_RESET BIT(1) +#define TEGRA_PERIPH_ON_APB BIT(2) + +void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); +extern const struct clk_ops tegra_clk_periph_gate_ops; +struct clk *tegra_clk_register_periph_gate(const char *name, + const char *parent_name, u8 gate_flags, void __iomem *clk_base, + unsigned long flags, int clk_num, + struct tegra_clk_periph_regs *pregs, int *enable_refcnt); + +/** + * struct clk-periph - peripheral clock + * + * @magic: magic number to validate type + * @hw: handle between common and hardware-specific interfaces + * @mux: mux clock + * @divider: divider clock + * @gate: gate clock + * @mux_ops: mux clock ops + * @div_ops: divider clock ops + * @gate_ops: gate clock ops + */ +struct tegra_clk_periph { + u32 magic; + struct clk_hw hw; + struct clk_mux mux; + struct tegra_clk_frac_div divider; + struct tegra_clk_periph_gate gate; + + const struct clk_ops *mux_ops; + const struct clk_ops *div_ops; + const struct clk_ops *gate_ops; +}; + +#define to_clk_periph(_hw) container_of(_hw, struct tegra_clk_periph, hw) + +#define TEGRA_CLK_PERIPH_MAGIC 0x18221223 + +extern const struct clk_ops tegra_clk_periph_ops; +struct clk *tegra_clk_register_periph(const char *name, + const char **parent_names, int num_parents, + struct tegra_clk_periph *periph, void __iomem *clk_base, + u32 offset); +struct clk *tegra_clk_register_periph_nodiv(const char *name, + const char **parent_names, int num_parents, + struct tegra_clk_periph *periph, void __iomem *clk_base, + u32 offset); + +#define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \ + _div_shift, _div_width, _div_frac_width, \ + _div_flags, _clk_num, _enb_refcnt, _regs, \ + _gate_flags) \ + { \ + .mux = { \ + .flags = _mux_flags, \ + .shift = _mux_shift, \ + .width = _mux_width, \ + }, \ + .divider = { \ + .flags = _div_flags, \ + .shift = _div_shift, \ + .width = _div_width, \ + .frac_width = _div_frac_width, \ + }, \ + .gate = { \ + .flags = _gate_flags, \ + .clk_num = _clk_num, \ + .enable_refcnt = _enb_refcnt, \ + .regs = _regs, \ + }, \ + .mux_ops = &clk_mux_ops, \ + .div_ops = &tegra_clk_frac_div_ops, \ + .gate_ops = &tegra_clk_periph_gate_ops, \ + } + +struct tegra_periph_init_data { + const char *name; + int clk_id; + const char **parent_names; + int num_parents; + struct tegra_clk_periph periph; + u32 offset; + const char *con_id; + const char *dev_id; +}; + +#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \ + _mux_shift, _mux_width, _mux_flags, _div_shift, \ + _div_width, _div_frac_width, _div_flags, _regs, \ + _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ + { \ + .name = _name, \ + .clk_id = _clk_id, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \ + _mux_flags, _div_shift, \ + _div_width, _div_frac_width, \ + _div_flags, _clk_num, \ + _enb_refcnt, _regs, \ + _gate_flags), \ + .offset = _offset, \ + .con_id = _con_id, \ + .dev_id = _dev_id, \ + } + +/** + * struct clk_super_mux - super clock + * + * @hw: handle between common and hardware-specific interfaces + * @reg: register controlling multiplexer + * @width: width of the multiplexer bit field + * @flags: hardware-specific flags + * @div2_index: bit controlling divide-by-2 + * @pllx_index: PLLX index in the parent list + * @lock: register lock + * + * Flags: + * TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates + * that this is LP cluster clock. + */ +struct tegra_clk_super_mux { + struct clk_hw hw; + void __iomem *reg; + u8 width; + u8 flags; + u8 div2_index; + u8 pllx_index; + spinlock_t *lock; +}; + +#define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw) + +#define TEGRA_DIVIDER_2 BIT(0) + +extern const struct clk_ops tegra_clk_super_ops; +struct clk *tegra_clk_register_super_mux(const char *name, + const char **parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 clk_super_flags, + u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock); + +/** + * struct clk_init_tabel - clock initialization table + * @clk_id: clock id as mentioned in device tree bindings + * @parent_id: parent clock id as mentioned in device tree bindings + * @rate: rate to set + * @state: enable/disable + */ +struct tegra_clk_init_table { + unsigned int clk_id; + unsigned int parent_id; + unsigned long rate; + int state; +}; + +/** + * struct clk_duplicate - duplicate clocks + * @clk_id: clock id as mentioned in device tree bindings + * @lookup: duplicate lookup entry for the clock + */ +struct tegra_clk_duplicate { + int clk_id; + struct clk_lookup lookup; +}; + +#define TEGRA_CLK_DUPLICATE(_clk_id, _dev, _con) \ + { \ + .clk_id = _clk_id, \ + .lookup = { \ + .dev_id = _dev, \ + .con_id = _con, \ + }, \ + } + +void tegra_init_from_table(struct tegra_clk_init_table *tbl, + struct clk *clks[], int clk_max); + +void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, + struct clk *clks[], int clk_max); + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +void tegra20_clock_init(struct device_node *np); +#else +static inline void tegra20_clock_init(struct device_node *np) {} +#endif /* CONFIG_ARCH_TEGRA_2x_SOC */ + +#ifdef CONFIG_ARCH_TEGRA_3x_SOC +void tegra30_clock_init(struct device_node *np); +#else +static inline void tegra30_clock_init(struct device_node *np) {} +#endif /* CONFIG_ARCH_TEGRA_3x_SOC */ + +#endif /* TEGRA_CLK_H */ diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 7fdcbd3..7d978c1 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -1,3 +1,6 @@ +config CLKSRC_OF + bool + config CLKSRC_I8253 bool @@ -25,6 +28,9 @@ config ARMADA_370_XP_TIMER config SUNXI_TIMER bool +config VT8500_TIMER + bool + config CLKSRC_NOMADIK_MTU bool depends on (ARCH_NOMADIK || ARCH_U8500) diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index f93453d..596c45c 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o @@ -16,5 +17,7 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o +obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o +obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index bc19f12..7f796d8f 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -101,7 +101,7 @@ static struct of_device_id bcm2835_time_match[] __initconst = { {} }; -static void __init bcm2835_time_init(void) +void __init bcm2835_timer_init(void) { struct device_node *node; void __iomem *base; @@ -155,7 +155,3 @@ static void __init bcm2835_time_init(void) pr_info("bcm2835: system timer (irq = %d)\n", irq); } - -struct sys_timer bcm2835_timer = { - .init = bcm2835_time_init, -}; diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c new file mode 100644 index 0000000..bdabdaa --- /dev/null +++ b/drivers/clocksource/clksrc-of.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/init.h> +#include <linux/of.h> + +extern struct of_device_id __clksrc_of_table[]; + +static const struct of_device_id __clksrc_of_table_sentinel + __used __section(__clksrc_of_table_end); + +void __init clocksource_of_init(void) +{ + struct device_node *np; + const struct of_device_id *match; + void (*init_func)(void); + + for_each_matching_node_and_match(np, __clksrc_of_table, &match) { + init_func = match->data; + init_func(); + } +} diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index d927938..ea21048 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -100,7 +100,6 @@ static struct clock_event_device cs5535_clockevent = { .set_mode = mfgpt_set_mode, .set_next_event = mfgpt_next_event, .rating = 250, - .shift = 32 }; static irqreturn_t mfgpt_tick(int irq, void *dev_id) @@ -169,17 +168,11 @@ static int __init cs5535_mfgpt_init(void) cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, val); /* Set up the clock event */ - cs5535_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, - cs5535_clockevent.shift); - cs5535_clockevent.min_delta_ns = clockevent_delta2ns(0xF, - &cs5535_clockevent); - cs5535_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, - &cs5535_clockevent); - printk(KERN_INFO DRV_NAME ": Registering MFGPT timer as a clock event, using IRQ %d\n", timer_irq); - clockevents_register_device(&cs5535_clockevent); + clockevents_config_and_register(&cs5535_clockevent, MFGPT_HZ, + 0xF, 0xFFFE); return 0; diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index f7dba5b..ab09ed3 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -107,7 +107,7 @@ static const struct of_device_id osctimer_ids[] __initconst = { {}, }; -static void __init timer_init(void) +void __init dw_apb_timer_init(void) { struct device_node *event_timer, *source_timer; @@ -125,7 +125,3 @@ static void __init timer_init(void) init_sched_clock(); } - -struct sys_timer dw_apb_timer = { - .init = timer_init, -}; diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index 8914c3c..025afc6 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -134,12 +134,32 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, } } +void nmdk_clksrc_reset(void) +{ + /* Disable */ + writel(0, mtu_base + MTU_CR(0)); + + /* ClockSource: configure load and background-load, and fire it up */ + writel(nmdk_cycle, mtu_base + MTU_LR(0)); + writel(nmdk_cycle, mtu_base + MTU_BGLR(0)); + + writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA, + mtu_base + MTU_CR(0)); +} + +static void nmdk_clkevt_resume(struct clock_event_device *cedev) +{ + nmdk_clkevt_reset(); + nmdk_clksrc_reset(); +} + static struct clock_event_device nmdk_clkevt = { .name = "mtu_1", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 200, .set_mode = nmdk_clkevt_mode, .set_next_event = nmdk_clkevt_next, + .resume = nmdk_clkevt_resume, }; /* @@ -161,19 +181,6 @@ static struct irqaction nmdk_timer_irq = { .dev_id = &nmdk_clkevt, }; -void nmdk_clksrc_reset(void) -{ - /* Disable */ - writel(0, mtu_base + MTU_CR(0)); - - /* ClockSource: configure load and background-load, and fire it up */ - writel(nmdk_cycle, mtu_base + MTU_LR(0)); - writel(nmdk_cycle, mtu_base + MTU_BGLR(0)); - - writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA, - mtu_base + MTU_CR(0)); -} - void __init nmdk_timer_init(void __iomem *base, int irq) { unsigned long rate; diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 3cd1bd3..0ce85e2 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c @@ -74,7 +74,6 @@ static int sunxi_clkevt_next_event(unsigned long evt, static struct clock_event_device sunxi_clockevent = { .name = "sunxi_tick", - .shift = 32, .rating = 300, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = sunxi_clkevt_mode, @@ -104,7 +103,7 @@ static struct of_device_id sunxi_timer_dt_ids[] = { { } }; -static void __init sunxi_timer_init(void) +void __init sunxi_timer_init(void) { struct device_node *node; unsigned long rate = 0; @@ -154,18 +153,8 @@ static void __init sunxi_timer_init(void) val = readl(timer_base + TIMER_CTL_REG); writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG); - sunxi_clockevent.mult = div_sc(rate / TIMER_SCAL, - NSEC_PER_SEC, - sunxi_clockevent.shift); - sunxi_clockevent.max_delta_ns = clockevent_delta2ns(0xff, - &sunxi_clockevent); - sunxi_clockevent.min_delta_ns = clockevent_delta2ns(0x1, - &sunxi_clockevent); sunxi_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&sunxi_clockevent); + clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL, + 0x1, 0xff); } - -struct sys_timer sunxi_timer = { - .init = sunxi_timer_init, -}; diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 32cb929..8a61872 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -157,7 +157,6 @@ static struct tc_clkevt_device clkevt = { .name = "tc_clkevt", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, /* Should be lower than at91rm9200's system timer */ .rating = 125, .set_next_event = tc_next_event, @@ -196,13 +195,9 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) timer_clock = clk32k_divisor_idx; - clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift); - clkevt.clkevt.max_delta_ns - = clockevent_delta2ns(0xffff, &clkevt.clkevt); - clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1; clkevt.clkevt.cpumask = cpumask_of(0); - clockevents_register_device(&clkevt.clkevt); + clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff); setup_irq(irq, &tc_irqaction); } diff --git a/arch/arm/mach-tegra/timer.c b/drivers/clocksource/tegra20_timer.c index e4863f3..0bde03f 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -1,6 +1,4 @@ /* - * arch/arch/mach-tegra/timer.c - * * Copyright (C) 2010 Google, Inc. * * Author: @@ -33,8 +31,6 @@ #include <asm/smp_twd.h> #include <asm/sched_clock.h> -#include "board.h" - #define RTC_SECONDS 0x08 #define RTC_SHADOW_SECONDS 0x0c #define RTC_MILLISECONDS 0x10 @@ -168,7 +164,7 @@ static const struct of_device_id rtc_match[] __initconst = { {} }; -static void __init tegra_init_timer(void) +static void __init tegra20_init_timer(void) { struct device_node *np; struct clk *clk; @@ -183,7 +179,7 @@ static void __init tegra_init_timer(void) timer_reg_base = of_iomap(np, 0); if (!timer_reg_base) { - pr_err("Can't map timer registers"); + pr_err("Can't map timer registers\n"); BUG(); } @@ -259,23 +255,16 @@ static void __init tegra_init_timer(void) BUG(); } - clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5); - tegra_clockevent.max_delta_ns = - clockevent_delta2ns(0x1fffffff, &tegra_clockevent); - tegra_clockevent.min_delta_ns = - clockevent_delta2ns(0x1, &tegra_clockevent); tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq; - clockevents_register_device(&tegra_clockevent); + clockevents_config_and_register(&tegra_clockevent, 1000000, + 0x1, 0x1fffffff); #ifdef CONFIG_HAVE_ARM_TWD twd_local_timer_of_register(); #endif register_persistent_clock(NULL, tegra_read_persistent_clock); } - -struct sys_timer tegra_sys_timer = { - .init = tegra_init_timer, -}; +CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer); #ifdef CONFIG_PM static u32 usec_config; diff --git a/arch/arm/mach-vt8500/timer.c b/drivers/clocksource/vt8500_timer.c index 3dd21a4..ed66cf0 100644 --- a/arch/arm/mach-vt8500/timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -168,17 +168,12 @@ void __init vt8500_timer_init(void) pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", __func__, clocksource.name); - clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); - - /* copy-pasted from mach-msm; no idea */ - clockevent.max_delta_ns = - clockevent_delta2ns(0xf0000000, &clockevent); - clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); clockevent.cpumask = cpumask_of(0); if (setup_irq(timer_irq, &irq)) pr_err("%s: setup_irq failed for %s\n", __func__, clockevent.name); - clockevents_register_device(&clockevent); + clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, + 4, 0xf0000000); } diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c4cc27e..071e2c3 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -39,4 +39,10 @@ config CPU_IDLE_CALXEDA help Select this to enable cpuidle on Calxeda processors. +config CPU_IDLE_KIRKWOOD + bool "CPU Idle Driver for Kirkwood processors" + depends on ARCH_KIRKWOOD + help + Select this to enable cpuidle on Kirkwood processors. + endif diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 03ee874..24c6e7d 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -6,3 +6,4 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o +obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/drivers/cpuidle/cpuidle-kirkwood.c index f730467..670aa1e 100644 --- a/arch/arm/mach-kirkwood/cpuidle.c +++ b/drivers/cpuidle/cpuidle-kirkwood.c @@ -14,6 +14,7 @@ */ #include <linux/kernel.h> +#include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/cpuidle.h> @@ -21,16 +22,17 @@ #include <linux/export.h> #include <asm/proc-fns.h> #include <asm/cpuidle.h> -#include <mach/kirkwood.h> #define KIRKWOOD_MAX_STATES 2 +static void __iomem *ddr_operation_base; + /* Actual code that puts the SoC in different idle states */ static int kirkwood_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, + struct cpuidle_driver *drv, int index) { - writel(0x7, DDR_OPERATION_BASE); + writel(0x7, ddr_operation_base); cpu_do_idle(); return index; @@ -51,13 +53,22 @@ static struct cpuidle_driver kirkwood_idle_driver = { }, .state_count = KIRKWOOD_MAX_STATES, }; +static struct cpuidle_device *device; static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); /* Initialize CPU idle by registering the idle states */ -static int kirkwood_init_cpuidle(void) +static int kirkwood_cpuidle_probe(struct platform_device *pdev) { - struct cpuidle_device *device; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) + return -EINVAL; + + ddr_operation_base = devm_request_and_ioremap(&pdev->dev, res); + if (!ddr_operation_base) + return -EADDRNOTAVAIL; device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); device->state_count = KIRKWOOD_MAX_STATES; @@ -70,4 +81,26 @@ static int kirkwood_init_cpuidle(void) return 0; } -device_initcall(kirkwood_init_cpuidle); +int kirkwood_cpuidle_remove(struct platform_device *pdev) +{ + cpuidle_unregister_device(device); + cpuidle_unregister_driver(&kirkwood_idle_driver); + + return 0; +} + +static struct platform_driver kirkwood_cpuidle_driver = { + .probe = kirkwood_cpuidle_probe, + .remove = kirkwood_cpuidle_remove, + .driver = { + .name = "kirkwood_cpuidle", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(kirkwood_cpuidle_driver); + +MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); +MODULE_DESCRIPTION("Kirkwood cpu idle driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:kirkwood-cpuidle"); diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 3cad856..2a02c11 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -31,8 +31,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> +#include <linux/clk/tegra.h> -#include <mach/clk.h> #include "dmaengine.h" #define TEGRA_APBDMA_GENERAL 0x0 diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 281f566..d1e9eb1 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -340,7 +340,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* * Alocate and fill the csrow/channels structs */ - mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); + mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL); if (!mci->csrows) goto error; for (row = 0; row < tot_csrows; row++) { @@ -351,7 +351,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, csr->csrow_idx = row; csr->mci = mci; csr->nr_channels = tot_channels; - csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, + csr->channels = kcalloc(tot_channels, sizeof(*csr->channels), GFP_KERNEL); if (!csr->channels) goto error; @@ -369,7 +369,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* * Allocate and fill the dimm structs */ - mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); + mci->dimms = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL); if (!mci->dimms) goto error; diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index dc6e905..0056c4d 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -256,7 +256,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; - if (edac_pci_dev->show) + if (edac_pci_dev->store) return edac_pci_dev->store(edac_pci_dev->value, buffer, count); return -EIO; } diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index fd3ae62..982f1f5 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -471,7 +471,7 @@ void __init dmi_scan_machine(void) char __iomem *p, *q; int rc; - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto error; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 7b1c374..f5596db 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -674,7 +674,7 @@ static int efi_status_to_err(efi_status_t status) err = -EACCES; break; case EFI_NOT_FOUND: - err = -ENOENT; + err = -EIO; break; default: err = -EINVAL; @@ -793,6 +793,7 @@ static ssize_t efivarfs_file_write(struct file *file, spin_unlock(&efivars->lock); efivar_unregister(var); drop_nlink(inode); + d_delete(file->f_dentry); dput(file->f_dentry); } else { @@ -994,7 +995,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) list_del(&var->list); spin_unlock(&efivars->lock); efivar_unregister(var); - drop_nlink(dir); + drop_nlink(dentry->d_inode); dput(dentry); return 0; } @@ -1782,7 +1783,7 @@ efivars_init(void) printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, EFIVARS_DATE); - if (!efi_enabled) + if (!efi_enabled(EFI_RUNTIME_SERVICES)) return 0; /* For now we'll register the efi directory at /sys/firmware/efi */ @@ -1822,7 +1823,7 @@ err_put: static void __exit efivars_exit(void) { - if (efi_enabled) { + if (efi_enabled(EFI_RUNTIME_SERVICES)) { unregister_efivars(&__efivars); kobject_put(efi_kobj); } diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index 4da4eb9..2224f1d 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep) /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will * only use ACPI for this */ - if (!efi_enabled) + if (!efi_enabled(EFI_BOOT)) find_ibft_in_mem(); if (ibft_addr) { diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 1d1f1e5..046bcda 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF config DRM_EXYNOS_FIMD bool "Exynos DRM FIMD" - depends on DRM_EXYNOS && !FB_S3C + depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM help Choose this option if you want to use Exynos FIMD for DRM. @@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D config DRM_EXYNOS_IPP bool "Exynos DRM IPP" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM help Choose this option if you want to use IPP feature for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index ab37437..4c5b685 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -18,7 +18,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" -#define MAX_EDID 256 #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ drm_connector) @@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) to_exynos_connector(connector); struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_display_ops *display_ops = manager->display_ops; - unsigned int count; + struct edid *edid = NULL; + unsigned int count = 0; + int ret; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) * because lcd panel has only one mode. */ if (display_ops->get_edid) { - int ret; - void *edid; - - edid = kzalloc(MAX_EDID, GFP_KERNEL); - if (!edid) { - DRM_ERROR("failed to allocate edid\n"); - return 0; + edid = display_ops->get_edid(manager->dev, connector); + if (IS_ERR_OR_NULL(edid)) { + ret = PTR_ERR(edid); + edid = NULL; + DRM_ERROR("Panel operation get_edid failed %d\n", ret); + goto out; } - ret = display_ops->get_edid(manager->dev, connector, - edid, MAX_EDID); - if (ret < 0) { - DRM_ERROR("failed to get edid data.\n"); - kfree(edid); - edid = NULL; - return 0; + count = drm_add_edid_modes(connector, edid); + if (count < 0) { + DRM_ERROR("Add edid modes failed %d\n", count); + goto out; } drm_mode_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - kfree(edid); } else { struct exynos_drm_panel_info *panel; struct drm_display_mode *mode = drm_mode_create(connector->dev); @@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) count = 1; } +out: + kfree(edid); return count; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 9df9771..ba0a3aa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -19,6 +19,7 @@ struct exynos_drm_dmabuf_attachment { struct sg_table sgt; enum dma_data_direction dir; + bool is_mapped; }; static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, @@ -72,17 +73,10 @@ static struct sg_table * DRM_DEBUG_PRIME("%s\n", __FILE__); - if (WARN_ON(dir == DMA_NONE)) - return ERR_PTR(-EINVAL); - /* just return current sgt if already requested. */ - if (exynos_attach->dir == dir) + if (exynos_attach->dir == dir && exynos_attach->is_mapped) return &exynos_attach->sgt; - /* reattaching is not allowed. */ - if (WARN_ON(exynos_attach->dir != DMA_NONE)) - return ERR_PTR(-EBUSY); - buf = gem_obj->buffer; if (!buf) { DRM_ERROR("buffer is null.\n"); @@ -107,13 +101,17 @@ static struct sg_table * wr = sg_next(wr); } - nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); - if (!nents) { - DRM_ERROR("failed to map sgl with iommu.\n"); - sgt = ERR_PTR(-EIO); - goto err_unlock; + if (dir != DMA_NONE) { + nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); + if (!nents) { + DRM_ERROR("failed to map sgl with iommu.\n"); + sg_free_table(sgt); + sgt = ERR_PTR(-EIO); + goto err_unlock; + } } + exynos_attach->is_mapped = true; exynos_attach->dir = dir; attach->priv = exynos_attach; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index b9e51bc..4606fac7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -148,8 +148,8 @@ struct exynos_drm_overlay { struct exynos_drm_display_ops { enum exynos_drm_output_type type; bool (*is_connected)(struct device *dev); - int (*get_edid)(struct device *dev, struct drm_connector *connector, - u8 *edid, int len); + struct edid *(*get_edid)(struct device *dev, + struct drm_connector *connector); void *(*get_panel)(struct device *dev); int (*check_timing)(struct device *dev, void *timing); int (*power_on)(struct device *dev, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 36c3905..9a4c08e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -324,7 +324,7 @@ out: g2d_userptr = NULL; } -dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, +static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, unsigned long userptr, unsigned long size, struct drm_file *filp, diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 850e995..2864453 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev) return false; } -static int drm_hdmi_get_edid(struct device *dev, - struct drm_connector *connector, u8 *edid, int len) +static struct edid *drm_hdmi_get_edid(struct device *dev, + struct drm_connector *connector) { struct drm_hdmi_context *ctx = to_context(dev); DRM_DEBUG_KMS("%s\n", __FILE__); if (hdmi_ops && hdmi_ops->get_edid) - return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, - len); + return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector); - return 0; + return NULL; } static int drm_hdmi_check_timing(struct device *dev, void *timing) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 784a7e9..d80516f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context { struct exynos_hdmi_ops { /* display */ bool (*is_connected)(void *ctx); - int (*get_edid)(void *ctx, struct drm_connector *connector, - u8 *edid, int len); + struct edid *(*get_edid)(void *ctx, + struct drm_connector *connector); int (*check_timing)(void *ctx, void *timing); int (*power_on)(void *ctx, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 0bda964..1a55635 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, } } -void ipp_handle_cmd_work(struct device *dev, +static void ipp_handle_cmd_work(struct device *dev, struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_cmd_work *cmd_work, struct drm_exynos_ipp_cmd_node *c_node) diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index e9e83ef..f976e29 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev) return 0; } -struct rot_limit_table rot_limit_tbl = { +static struct rot_limit_table rot_limit_tbl = { .ycbcr420_2p = { .min_w = 32, .min_h = 32, @@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = { }, }; -struct platform_device_id rotator_driver_ids[] = { +static struct platform_device_id rotator_driver_ids[] = { { .name = "exynos-rot", .driver_data = (unsigned long)&rot_limit_tbl, diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index d0ca3c4..13ccbd4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev) return ctx->connected ? true : false; } -static int vidi_get_edid(struct device *dev, struct drm_connector *connector, - u8 *edid, int len) +static struct edid *vidi_get_edid(struct device *dev, + struct drm_connector *connector) { struct vidi_context *ctx = get_vidi_context(dev); + struct edid *edid; + int edid_len; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, */ if (!ctx->raw_edid) { DRM_DEBUG_KMS("raw_edid is null.\n"); - return -EFAULT; + return ERR_PTR(-EFAULT); } - memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) - * EDID_LENGTH, len)); + edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; + edid = kzalloc(edid_len, GFP_KERNEL); + if (!edid) { + DRM_DEBUG_KMS("failed to allocate edid\n"); + return ERR_PTR(-ENOMEM); + } - return 0; + memcpy(edid, ctx->raw_edid, edid_len); + return edid; } static void *vidi_get_panel(struct device *dev) @@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, struct exynos_drm_manager *manager; struct exynos_drm_display_ops *display_ops; struct drm_exynos_vidi_connection *vidi = data; - struct edid *raw_edid; int edid_len; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, } if (vidi->connection) { - if (!vidi->edid) { - DRM_DEBUG_KMS("edid data is null.\n"); + struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid; + if (!drm_edid_is_valid(raw_edid)) { + DRM_DEBUG_KMS("edid data is invalid.\n"); return -EINVAL; } - raw_edid = (struct edid *)(uint32_t)vidi->edid; edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); if (!ctx->raw_edid) { diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 41ff79d..fbab3c4 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -34,7 +34,6 @@ #include <linux/regulator/consumer.h> #include <linux/io.h> #include <linux/of_gpio.h> -#include <plat/gpio-cfg.h> #include <drm/exynos_drm.h> @@ -98,8 +97,7 @@ struct hdmi_context { void __iomem *regs; void *parent_ctx; - int external_irq; - int internal_irq; + int irq; struct i2c_client *ddc_port; struct i2c_client *hdmiphy_port; @@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx) return hdata->hpd; } -static int hdmi_get_edid(void *ctx, struct drm_connector *connector, - u8 *edid, int len) +static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) { struct edid *raw_edid; struct hdmi_context *hdata = ctx; @@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); if (!hdata->ddc_port) - return -ENODEV; + return ERR_PTR(-ENODEV); raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); - if (raw_edid) { - hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); - memcpy(edid, raw_edid, min((1 + raw_edid->extensions) - * EDID_LENGTH, len)); - DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", - (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), - raw_edid->width_cm, raw_edid->height_cm); - kfree(raw_edid); - } else { - return -ENODEV; - } + if (!raw_edid) + return ERR_PTR(-ENODEV); - return 0; + hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); + DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", + (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), + raw_edid->width_cm, raw_edid->height_cm); + + return raw_edid; } static int hdmi_v13_check_timing(struct fb_videomode *check_timing) @@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) /* resetting HDMI core */ hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); } static void hdmi_conf_init(struct hdmi_context *hdata) { struct hdmi_infoframe infoframe; - /* disable HPD interrupts */ + /* disable HPD interrupts from HDMI IP block, use GPIO instead */ hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); @@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); if (val & HDMI_PHY_STATUS_READY) break; - mdelay(1); + usleep_range(1000, 2000); } /* steady state not achieved */ if (tries == 0) { @@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); if (val & HDMI_PHY_STATUS_READY) break; - mdelay(1); + usleep_range(1000, 2000); } /* steady state not achieved */ if (tries == 0) { @@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) /* reset hdmiphy */ hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); - mdelay(10); + usleep_range(10000, 12000); } static void hdmiphy_poweron(struct hdmi_context *hdata) @@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) return; } - mdelay(10); + usleep_range(10000, 12000); /* operation mode */ operation[0] = 0x1f; @@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + mutex_lock(&hdata->hdmi_mutex); + if (!hdata->powered) { + mutex_unlock(&hdata->hdmi_mutex); + return; + } + mutex_unlock(&hdata->hdmi_mutex); + hdmi_conf_apply(hdata); } @@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = { .dpms = hdmi_dpms, }; -static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) +static irqreturn_t hdmi_irq_thread(int irq, void *arg) { struct exynos_drm_hdmi_context *ctx = arg; struct hdmi_context *hdata = ctx->ctx; @@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) return IRQ_HANDLED; } -static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) -{ - struct exynos_drm_hdmi_context *ctx = arg; - struct hdmi_context *hdata = ctx->ctx; - u32 intc_flag; - - intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); - /* clearing flags for HPD plug/unplug */ - if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - DRM_DEBUG_KMS("unplugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_UNPLUG); - } - if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - DRM_DEBUG_KMS("plugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_PLUG); - } - - if (ctx->drm_dev) - drm_helper_hpd_irq_event(ctx->drm_dev); - - return IRQ_HANDLED; -} - static int hdmi_resources_init(struct hdmi_context *hdata) { struct device *dev = hdata->dev; @@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev) hdata->hdmiphy_port = hdmi_hdmiphy; - hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); - if (hdata->external_irq < 0) { - DRM_ERROR("failed to get GPIO external irq\n"); - ret = hdata->external_irq; - goto err_hdmiphy; - } - - hdata->internal_irq = platform_get_irq(pdev, 0); - if (hdata->internal_irq < 0) { - DRM_ERROR("failed to get platform internal irq\n"); - ret = hdata->internal_irq; + hdata->irq = gpio_to_irq(hdata->hpd_gpio); + if (hdata->irq < 0) { + DRM_ERROR("failed to get GPIO irq\n"); + ret = hdata->irq; goto err_hdmiphy; } hdata->hpd = gpio_get_value(hdata->hpd_gpio); - ret = request_threaded_irq(hdata->external_irq, NULL, - hdmi_external_irq_thread, IRQF_TRIGGER_RISING | + ret = request_threaded_irq(hdata->irq, NULL, + hdmi_irq_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "hdmi_external", drm_hdmi_ctx); + "hdmi", drm_hdmi_ctx); if (ret) { - DRM_ERROR("failed to register hdmi external interrupt\n"); + DRM_ERROR("failed to register hdmi interrupt\n"); goto err_hdmiphy; } - ret = request_threaded_irq(hdata->internal_irq, NULL, - hdmi_internal_irq_thread, IRQF_ONESHOT, - "hdmi_internal", drm_hdmi_ctx); - if (ret) { - DRM_ERROR("failed to register hdmi internal interrupt\n"); - goto err_free_irq; - } - /* Attach HDMI Driver to common hdmi. */ exynos_hdmi_drv_attach(drm_hdmi_ctx); @@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev) return 0; -err_free_irq: - free_irq(hdata->external_irq, drm_hdmi_ctx); err_hdmiphy: i2c_del_driver(&hdmiphy_driver); err_ddc: @@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev) pm_runtime_disable(dev); - free_irq(hdata->internal_irq, hdata); - free_irq(hdata->external_irq, hdata); + free_irq(hdata->irq, hdata); /* hdmiphy i2c driver */ @@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - disable_irq(hdata->internal_irq); - disable_irq(hdata->external_irq); + disable_irq(hdata->irq); hdata->hpd = false; if (ctx->drm_dev) @@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev) hdata->hpd = gpio_get_value(hdata->hpd_gpio); - enable_irq(hdata->external_irq); - enable_irq(hdata->internal_irq); + enable_irq(hdata->irq); if (!pm_runtime_suspended(dev)) { DRM_DEBUG_KMS("%s : Already resumed\n", __func__); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index c187ea3..c414584 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx) /* waiting until VP_SRESET_PROCESSING is 0 */ if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) break; - mdelay(10); + usleep_range(10000, 12000); } WARN(tries == 0, "failed to reset Video Processor\n"); } @@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win) DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); + mutex_lock(&mixer_ctx->mixer_mutex); + if (!mixer_ctx->powered) { + mutex_unlock(&mixer_ctx->mixer_mutex); + return; + } + mutex_unlock(&mixer_ctx->mixer_mutex); + if (win > 1 && mixer_ctx->vp_enabled) vp_video_buffer(mixer_ctx, win); else diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7944d3015..9d4a2c2 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -30,6 +30,7 @@ #include <linux/debugfs.h> #include <linux/slab.h> #include <linux/export.h> +#include <generated/utsrelease.h> #include <drm/drmP.h> #include "intel_drv.h" #include "intel_ringbuffer.h" @@ -690,6 +691,7 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, error->time.tv_usec); + seq_printf(m, "Kernel: " UTS_RELEASE); seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b401788..59afb7e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -533,6 +533,7 @@ #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) +# define ASYNC_FLIP_PERF_DISABLE (1 << 14) #define GEN6_GT_MODE 0x20d0 #define GEN6_GT_MODE_HI (1 << 9) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ae253e0..42ff97d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring) struct drm_i915_private *dev_priv = dev->dev_private; int ret = init_ring_common(ring); - if (INTEL_INFO(dev)->gen > 3) { + if (INTEL_INFO(dev)->gen > 3) I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); - if (IS_GEN7(dev)) - I915_WRITE(GFX_MODE_GEN7, - _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | - _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); - } + + /* We need to disable the AsyncFlip performance optimisations in order + * to use MI_WAIT_FOR_EVENT within the CS. It should already be + * programmed to '1' on all products. + */ + if (INTEL_INFO(dev)->gen >= 6) + I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); + + /* Required for the hardware to program scanline values for waiting */ + if (INTEL_INFO(dev)->gen == 6) + I915_WRITE(GFX_MODE, + _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); + + if (IS_GEN7(dev)) + I915_WRITE(GFX_MODE_GEN7, + _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | + _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); if (INTEL_INFO(dev)->gen >= 5) { ret = init_pipe_control(ring); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 59acabb..835992d 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev) int cayman_dma_resume(struct radeon_device *rdev) { struct radeon_ring *ring; - u32 rb_cntl, dma_cntl; + u32 rb_cntl, dma_cntl, ib_cntl; u32 rb_bufsz; u32 reg_offset, wb_offset; int i, r; @@ -1265,7 +1265,11 @@ int cayman_dma_resume(struct radeon_device *rdev) WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); /* enable DMA IBs */ - WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE); + ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL + reg_offset, ib_cntl); dma_cntl = RREG32(DMA_CNTL + reg_offset); dma_cntl &= ~CTXEMPTY_INT_ENABLE; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3cb9d60..bc2540b 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2313,7 +2313,7 @@ void r600_dma_stop(struct radeon_device *rdev) int r600_dma_resume(struct radeon_device *rdev) { struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; - u32 rb_cntl, dma_cntl; + u32 rb_cntl, dma_cntl, ib_cntl; u32 rb_bufsz; int r; @@ -2353,7 +2353,11 @@ int r600_dma_resume(struct radeon_device *rdev) WREG32(DMA_RB_BASE, ring->gpu_addr >> 8); /* enable DMA IBs */ - WREG32(DMA_IB_CNTL, DMA_IB_ENABLE); + ib_cntl = DMA_IB_ENABLE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL, ib_cntl); dma_cntl = RREG32(DMA_CNTL); dma_cntl &= ~CTXEMPTY_INT_ENABLE; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 469661f..5407459 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -286,6 +286,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { kfree(p->chunks[p->chunk_ib_idx].kpage[0]); kfree(p->chunks[p->chunk_ib_idx].kpage[1]); + p->chunks[p->chunk_ib_idx].kpage[0] = NULL; + p->chunks[p->chunk_ib_idx].kpage[1] = NULL; return -ENOMEM; } } diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index ad6df62..0d67674 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, y = 0; } - if (ASIC_IS_AVIVO(rdev)) { + /* fixed on DCE6 and newer */ + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { int i = 0; struct drm_crtc *crtc_p; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index edfc54e..0d6562b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; - if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + if (efi_enabled(EFI_BOOT) && + rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) return false; /* first check CRTCs */ diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1da2386..ff3def7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1122,7 +1122,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, if (ret) { kfree(radeon_fb); drm_gem_object_unreference_unlocked(obj); - return NULL; + return ERR_PTR(ret); } return &radeon_fb->base; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 656b2e3..56813f9 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -12,8 +12,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> - -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include "drm.h" #include "dc.h" diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 3a503c9..d980dc7 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -11,7 +11,6 @@ #include <linux/of_address.h> #include <linux/of_platform.h> -#include <mach/clk.h> #include <linux/dma-mapping.h> #include <asm/dma-iommu.h> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index e060c7e..92ad276 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -14,8 +14,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> - -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include "hdmi.h" #include "drm.h" diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 4dfa605..34e2547 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -306,6 +306,9 @@ #define USB_VENDOR_ID_EZKEY 0x0518 #define USB_DEVICE_ID_BTC_8193 0x0002 +#define USB_VENDOR_ID_FORMOSA 0x147a +#define USB_DEVICE_ID_FORMOSA_IR_RECEIVER 0xe03e + #define USB_VENDOR_ID_FREESCALE 0x15A2 #define USB_DEVICE_ID_FREESCALE_MX28 0x004F diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 12e4fdc..e766b56 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -540,13 +540,24 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, { struct i2c_client *client = hid->driver_data; int report_id = buf[0]; + int ret; if (report_type == HID_INPUT_REPORT) return -EINVAL; - return i2c_hid_set_report(client, + if (report_id) { + buf++; + count--; + } + + ret = i2c_hid_set_report(client, report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, report_id, buf, count); + + if (report_id && ret >= 0) + ret++; /* add report_id to the number of transfered bytes */ + + return ret; } static int i2c_hid_parse(struct hid_device *hid) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index ac9e352..e0e6abf 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7b38877..c7aca35 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -29,11 +29,10 @@ #include <linux/of_i2c.h> #include <linux/of_device.h> #include <linux/module.h> +#include <linux/clk/tegra.h> #include <asm/unaligned.h> -#include <mach/clk.h> - #define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000)) #define BYTES_PER_FIFO_WORD 4 diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index c76f968..54ac1dc 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -30,7 +30,7 @@ #include <linux/clk.h> #include <linux/slab.h> #include <linux/input/tegra_kbc.h> -#include <mach/clk.h> +#include <linux/clk/tegra.h> #define KBC_MAX_DEBOUNCE_CNT 0x3ffu diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 81837b0..faf10ba 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -975,6 +975,38 @@ static void __init free_iommu_all(void) } /* + * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) + * Workaround: + * BIOS should disable L2B micellaneous clock gating by setting + * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b + */ +static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) +{ + u32 value; + + if ((boot_cpu_data.x86 != 0x15) || + (boot_cpu_data.x86_model < 0x10) || + (boot_cpu_data.x86_model > 0x1f)) + return; + + pci_write_config_dword(iommu->dev, 0xf0, 0x90); + pci_read_config_dword(iommu->dev, 0xf4, &value); + + if (value & BIT(2)) + return; + + /* Select NB indirect register 0x90 and enable writing */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); + + pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); + pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", + dev_name(&iommu->dev->dev)); + + /* Clear the enable writing bit */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90); +} + +/* * This function clues the initialization function for one IOMMU * together and also allocates the command buffer and programs the * hardware. It does NOT enable the IOMMU. This is done afterwards. @@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu) iommu->stored_l2[i] = iommu_read_l2(iommu, i); } + amd_iommu_erratum_746_workaround(iommu); + return pci_enable_device(iommu->dev); } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b9d0911..eca2801 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4234,6 +4234,21 @@ static struct iommu_ops intel_iommu_ops = { .pgsize_bitmap = INTEL_IOMMU_PGSIZES, }; +static void quirk_iommu_g4x_gfx(struct pci_dev *dev) +{ + /* G4x/GM45 integrated gfx dmar support is totally busted. */ + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx); + static void quirk_iommu_rwbf(struct pci_dev *dev) { /* @@ -4242,12 +4257,6 @@ static void quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; - - /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ - if (dev->revision == 0x07) { - printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); - dmar_map_gfx = 0; - } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 62ca575..a350969 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -1,3 +1,30 @@ +config IRQCHIP + def_bool y + depends on OF_IRQ + +config ARM_GIC + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + +config GIC_NON_BANKED + bool + +config ARM_VIC + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + +config ARM_VIC_NR + int + default 4 if ARCH_S5PV210 + default 3 if ARCH_S5PC100 + default 2 + depends on ARM_VIC + help + The maximum number of VICs available in the system, for + power management. + config VERSATILE_FPGA_IRQ bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index bf4609a..0fb8655 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -1,4 +1,8 @@ +obj-$(CONFIG_IRQCHIP) += irqchip.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o -obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o +obj-$(CONFIG_ARM_GIC) += irq-gic.o +obj-$(CONFIG_ARM_VIC) += irq-vic.o +obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o diff --git a/arch/arm/common/gic.c b/drivers/irqchip/irq-gic.c index 36ae03a..69d9a39 100644 --- a/arch/arm/common/gic.c +++ b/drivers/irqchip/irq-gic.c @@ -38,12 +38,14 @@ #include <linux/interrupt.h> #include <linux/percpu.h> #include <linux/slab.h> +#include <linux/irqchip/arm-gic.h> #include <asm/irq.h> #include <asm/exception.h> #include <asm/smp_plat.h> #include <asm/mach/irq.h> -#include <asm/hardware/gic.h> + +#include "irqchip.h" union gic_base { void __iomem *common_base; @@ -276,7 +278,7 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) #define gic_set_wake NULL #endif -asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) +static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; @@ -617,6 +619,27 @@ static void __init gic_pm_init(struct gic_chip_data *gic) } #endif +#ifdef CONFIG_SMP +void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) +{ + int cpu; + unsigned long map = 0; + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + map |= 1 << cpu_logical_map(cpu); + + /* + * Ensure that stores to Normal memory are visible to the + * other CPUs before issuing the IPI. + */ + dsb(); + + /* this always happens on GIC0 */ + writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); +} +#endif + static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { @@ -743,6 +766,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, if (WARN_ON(!gic->domain)) return; +#ifdef CONFIG_SMP + set_smp_cross_call(gic_raise_softirq); +#endif + + set_handle_irq(gic_handle_irq); + gic_chip.flags |= gic_arch_extn.flags; gic_dist_init(gic); gic_cpu_init(gic); @@ -756,27 +785,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr) gic_cpu_init(&gic_data[gic_nr]); } -#ifdef CONFIG_SMP -void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) -{ - int cpu; - unsigned long map = 0; - - /* Convert our logical CPU mask into a physical one. */ - for_each_cpu(cpu, mask) - map |= gic_cpu_map[cpu]; - - /* - * Ensure that stores to Normal memory are visible to the - * other CPUs before issuing the IPI. - */ - dsb(); - - /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); -} -#endif - #ifdef CONFIG_OF static int gic_cnt __initdata = 0; @@ -808,4 +816,9 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) gic_cnt++; return 0; } +IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); +IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); +IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); + #endif diff --git a/arch/arm/common/vic.c b/drivers/irqchip/irq-vic.c index 8f324b9..3cf97aa 100644 --- a/arch/arm/common/vic.c +++ b/drivers/irqchip/irq-vic.c @@ -30,10 +30,29 @@ #include <linux/syscore_ops.h> #include <linux/device.h> #include <linux/amba/bus.h> +#include <linux/irqchip/arm-vic.h> #include <asm/exception.h> #include <asm/mach/irq.h> -#include <asm/hardware/vic.h> + +#include "irqchip.h" + +#define VIC_IRQ_STATUS 0x00 +#define VIC_FIQ_STATUS 0x04 +#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ +#define VIC_INT_SOFT 0x18 +#define VIC_INT_SOFT_CLEAR 0x1c +#define VIC_PROTECT 0x20 +#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ +#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ + +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ +#define VIC_ITCR 0x300 /* VIC test control register */ + +#define VIC_VECT_CNTL_ENABLE (1 << 5) + +#define VIC_PL192_VECT_ADDR 0xF00 /** * struct vic_device - VIC PM device @@ -66,6 +85,8 @@ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; static int vic_id; +static void vic_handle_irq(struct pt_regs *regs); + /** * vic_init2 - common initialisation code * @base: Base of the VIC. @@ -182,6 +203,40 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq, return 0; } +/* + * Handle each interrupt in a single VIC. Returns non-zero if we've + * handled at least one interrupt. This reads the status register + * before handling each interrupt, which is necessary given that + * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. + */ +static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) +{ + u32 stat, irq; + int handled = 0; + + while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { + irq = ffs(stat) - 1; + handle_IRQ(irq_find_mapping(vic->domain, irq), regs); + handled = 1; + } + + return handled; +} + +/* + * Keep iterating over all registered VIC's until there are no pending + * interrupts. + */ +static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ + int i, handled; + + do { + for (i = 0, handled = 0; i < vic_id; ++i) + handled |= handle_one_vic(&vic_devices[i], regs); + } while (handled); +} + static struct irq_domain_ops vic_irqdomain_ops = { .map = vic_irqdomain_map, .xlate = irq_domain_xlate_onetwocell, @@ -218,6 +273,7 @@ static void __init vic_register(void __iomem *base, unsigned int irq, v->valid_sources = valid_sources; v->resume_sources = resume_sources; v->irq = irq; + set_handle_irq(vic_handle_irq); vic_id++; v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, &vic_irqdomain_ops, v); @@ -427,38 +483,7 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) return 0; } +IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init); +IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init); +IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init); #endif /* CONFIG OF */ - -/* - * Handle each interrupt in a single VIC. Returns non-zero if we've - * handled at least one interrupt. This reads the status register - * before handling each interrupt, which is necessary given that - * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. - */ -static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) -{ - u32 stat, irq; - int handled = 0; - - while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { - irq = ffs(stat) - 1; - handle_IRQ(irq_find_mapping(vic->domain, irq), regs); - handled = 1; - } - - return handled; -} - -/* - * Keep iterating over all registered VIC's until there are no pending - * interrupts. - */ -asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) -{ - int i, handled; - - do { - for (i = 0, handled = 0; i < vic_id; ++i) - handled |= handle_one_vic(&vic_devices[i], regs); - } while (handled); -} diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c new file mode 100644 index 0000000..f496afc --- /dev/null +++ b/drivers/irqchip/irqchip.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/init.h> +#include <linux/of_irq.h> + +#include "irqchip.h" + +/* + * This special of_device_id is the sentinel at the end of the + * of_device_id[] array of all irqchips. It is automatically placed at + * the end of the array by the linker, thanks to being part of a + * special section. + */ +static const struct of_device_id +irqchip_of_match_end __used __section(__irqchip_of_end); + +extern struct of_device_id __irqchip_begin[]; + +void __init irqchip_init(void) +{ + of_irq_init(__irqchip_begin); +} diff --git a/drivers/irqchip/irqchip.h b/drivers/irqchip/irqchip.h new file mode 100644 index 0000000..e445ba2 --- /dev/null +++ b/drivers/irqchip/irqchip.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _IRQCHIP_H +#define _IRQCHIP_H + +/* + * This macro must be used by the different irqchip drivers to declare + * the association between their DT compatible string and their + * initialization function. + * + * @name: name that must be unique accross all IRQCHIP_DECLARE of the + * same file. + * @compstr: compatible string of the irqchip driver + * @fn: initialization function + */ +#define IRQCHIP_DECLARE(name,compstr,fn) \ + static const struct of_device_id irqchip_of_match_##name \ + __used __section(__irqchip_of_table) \ + = { .compatible = compstr, .data = fn } + +#endif diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 80e1d2f..8527743 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c @@ -25,6 +25,8 @@ #include <linux/of_irq.h> #include <linux/spinlock.h> +#include "irqchip.h" + static DEFINE_SPINLOCK(lock); /* spear300 shared irq registers offsets and masks */ @@ -300,6 +302,7 @@ int __init spear300_shirq_of_init(struct device_node *np, return shirq_init(spear300_shirq_blocks, ARRAY_SIZE(spear300_shirq_blocks), np); } +IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init); int __init spear310_shirq_of_init(struct device_node *np, struct device_node *parent) @@ -307,6 +310,7 @@ int __init spear310_shirq_of_init(struct device_node *np, return shirq_init(spear310_shirq_blocks, ARRAY_SIZE(spear310_shirq_blocks), np); } +IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init); int __init spear320_shirq_of_init(struct device_node *np, struct device_node *parent) @@ -314,3 +318,4 @@ int __init spear320_shirq_of_init(struct device_node *np, return shirq_init(spear320_shirq_blocks, ARRAY_SIZE(spear320_shirq_blocks), np); } +IRQCHIP_DECLARE(spear320_shirq, "st,spear320-shirq", spear320_shirq_of_init); diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 68452b7..03a0a01 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, CAPIMSG_CONTROL(data)); l -= 12; + if (l <= 0) + return; dbgline = kmalloc(3 * l, GFP_ATOMIC); if (!dbgline) return; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 3d8984e..9e58dbd 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) } /* - * validate_rebuild_devices + * validate_raid_redundancy * @rs * - * Determine if the devices specified for rebuild can result in a valid - * usable array that is capable of rebuilding the given devices. + * Determine if there are enough devices in the array that haven't + * failed (or are being rebuilt) to form a usable array. * * Returns: 0 on success, -EINVAL on failure. */ -static int validate_rebuild_devices(struct raid_set *rs) +static int validate_raid_redundancy(struct raid_set *rs) { unsigned i, rebuild_cnt = 0; unsigned rebuilds_per_group, copies, d; - if (!(rs->print_flags & DMPF_REBUILD)) - return 0; - for (i = 0; i < rs->md.raid_disks; i++) - if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) + if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || + !rs->dev[i].rdev.sb_page) rebuild_cnt++; switch (rs->raid_type->level) { @@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs) * A A B B C * C D D E E */ - rebuilds_per_group = 0; for (i = 0; i < rs->md.raid_disks * copies; i++) { + if (!(i % copies)) + rebuilds_per_group = 0; d = i % rs->md.raid_disks; - if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && + if ((!rs->dev[d].rdev.sb_page || + !test_bit(In_sync, &rs->dev[d].rdev.flags)) && (++rebuilds_per_group >= copies)) goto too_many; - if (!((i + 1) % copies)) - rebuilds_per_group = 0; } break; default: - DMERR("The rebuild parameter is not supported for %s", - rs->raid_type->name); - rs->ti->error = "Rebuild not supported for this RAID type"; - return -EINVAL; + if (rebuild_cnt) + return -EINVAL; } return 0; too_many: - rs->ti->error = "Too many rebuild devices specified"; return -EINVAL; } @@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, } rs->md.dev_sectors = sectors_per_dev; - if (validate_rebuild_devices(rs)) - return -EINVAL; - /* Assume there are no metadata devices until the drives are parsed */ rs->md.persistent = 0; rs->md.external = 1; @@ -995,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) { int ret; - unsigned redundancy = 0; struct raid_dev *dev; struct md_rdev *rdev, *tmp, *freshest; struct mddev *mddev = &rs->md; - switch (rs->raid_type->level) { - case 1: - redundancy = rs->md.raid_disks - 1; - break; - case 4: - case 5: - case 6: - redundancy = rs->raid_type->parity_devs; - break; - case 10: - redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; - break; - default: - ti->error = "Unknown RAID type"; - return -EINVAL; - } - freshest = NULL; rdev_for_each_safe(rdev, tmp, mddev) { /* @@ -1045,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) break; default: dev = container_of(rdev, struct raid_dev, rdev); - if (redundancy--) { - if (dev->meta_dev) - dm_put_device(ti, dev->meta_dev); - - dev->meta_dev = NULL; - rdev->meta_bdev = NULL; + if (dev->meta_dev) + dm_put_device(ti, dev->meta_dev); - if (rdev->sb_page) - put_page(rdev->sb_page); + dev->meta_dev = NULL; + rdev->meta_bdev = NULL; - rdev->sb_page = NULL; + if (rdev->sb_page) + put_page(rdev->sb_page); - rdev->sb_loaded = 0; + rdev->sb_page = NULL; - /* - * We might be able to salvage the data device - * even though the meta device has failed. For - * now, we behave as though '- -' had been - * set for this device in the table. - */ - if (dev->data_dev) - dm_put_device(ti, dev->data_dev); + rdev->sb_loaded = 0; - dev->data_dev = NULL; - rdev->bdev = NULL; + /* + * We might be able to salvage the data device + * even though the meta device has failed. For + * now, we behave as though '- -' had been + * set for this device in the table. + */ + if (dev->data_dev) + dm_put_device(ti, dev->data_dev); - list_del(&rdev->same_set); + dev->data_dev = NULL; + rdev->bdev = NULL; - continue; - } - ti->error = "Failed to load superblock"; - return ret; + list_del(&rdev->same_set); } } if (!freshest) return 0; + if (validate_raid_redundancy(rs)) { + rs->ti->error = "Insufficient redundancy to activate array"; + return -EINVAL; + } + /* * Validation of the freshest device provides the source of * validation for the remaining devices. @@ -1432,7 +1405,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 4, 0}, + .version = {1, 4, 1}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr, diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 675ae52..5409607 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2746,19 +2746,9 @@ static int thin_iterate_devices(struct dm_target *ti, return 0; } -/* - * A thin device always inherits its queue limits from its pool. - */ -static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) -{ - struct thin_c *tc = ti->private; - - *limits = bdev_get_queue(tc->pool_dev->bdev)->limits; -} - static struct target_type thin_target = { .name = "thin", - .version = {1, 6, 0}, + .version = {1, 7, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, @@ -2767,7 +2757,6 @@ static struct target_type thin_target = { .postsuspend = thin_postsuspend, .status = thin_status, .iterate_devices = thin_iterate_devices, - .io_hints = thin_io_hints, }; /*----------------------------------------------------------------*/ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index c72e4d5..314a0e2 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1188,6 +1188,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, { struct dm_target *ti; sector_t len; + unsigned num_requests; do { ti = dm_table_find_target(ci->map, ci->sector); @@ -1200,7 +1201,8 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, * reconfiguration might also have changed that since the * check was performed. */ - if (!get_num_requests || !get_num_requests(ti)) + num_requests = get_num_requests ? get_num_requests(ti) : 0; + if (!num_requests) return -EOPNOTSUPP; if (is_split_required && !is_split_required(ti)) @@ -1208,7 +1210,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, else len = min(ci->sector_count, max_io_len(ci->sector, ti)); - __issue_target_requests(ci, ti, ti->num_discard_requests, len); + __issue_target_requests(ci, ti, num_requests, len); ci->sector += len; } while (ci->sector_count -= len); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 47ad4e2..ff553ba 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -237,6 +237,7 @@ config MFD_TPS65910 depends on I2C=y && GPIOLIB select MFD_CORE select REGMAP_I2C + select REGMAP_IRQ select IRQ_DOMAIN help if you say yes here you get support for the TPS65910 series of diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index e1650ba..4778bb1 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -19,6 +19,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/regulator/ab8500.h> #include <linux/of.h> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bc8a3ed..222c03a 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -239,7 +239,12 @@ static int arizona_runtime_resume(struct device *dev) return ret; } - regcache_sync(arizona->regmap); + ret = regcache_sync(arizona->regmap); + if (ret != 0) { + dev_err(arizona->dev, "Failed to restore register cache\n"); + regulator_disable(arizona->dcvdd); + return ret; + } return 0; } diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 74713bf..2bec5f0 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -176,14 +176,7 @@ int arizona_irq_init(struct arizona *arizona) aod = &wm5102_aod; irq = &wm5102_irq; - switch (arizona->rev) { - case 0: - case 1: - ctrlif_error = false; - break; - default: - break; - } + ctrlif_error = false; break; #endif #ifdef CONFIG_MFD_WM5110 @@ -191,14 +184,7 @@ int arizona_irq_init(struct arizona *arizona) aod = &wm5110_aod; irq = &wm5110_irq; - switch (arizona->rev) { - case 0: - case 1: - ctrlif_error = false; - break; - default: - break; - } + ctrlif_error = false; break; #endif default: diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index ac74a4d..885e567 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -27,6 +27,66 @@ #include <linux/of_device.h> #endif +/* I2C safe register check */ +static inline bool i2c_safe_reg(unsigned char reg) +{ + switch (reg) { + case DA9052_STATUS_A_REG: + case DA9052_STATUS_B_REG: + case DA9052_STATUS_C_REG: + case DA9052_STATUS_D_REG: + case DA9052_ADC_RES_L_REG: + case DA9052_ADC_RES_H_REG: + case DA9052_VDD_RES_REG: + case DA9052_ICHG_AV_REG: + case DA9052_TBAT_RES_REG: + case DA9052_ADCIN4_RES_REG: + case DA9052_ADCIN5_RES_REG: + case DA9052_ADCIN6_RES_REG: + case DA9052_TJUNC_RES_REG: + case DA9052_TSI_X_MSB_REG: + case DA9052_TSI_Y_MSB_REG: + case DA9052_TSI_LSB_REG: + case DA9052_TSI_Z_MSB_REG: + return true; + default: + return false; + } +} + +/* + * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC + * gets lockup up or fails to respond following a system reset. + * This fix is to follow any read or write with a dummy read to a safe + * register. + */ +int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) +{ + int val; + + switch (da9052->chip_id) { + case DA9052: + case DA9053_AA: + case DA9053_BA: + case DA9053_BB: + /* A dummy read to a safe register address. */ + if (!i2c_safe_reg(reg)) + return regmap_read(da9052->regmap, + DA9052_PARK_REGISTER, + &val); + break; + default: + /* + * For other chips parking of I2C register + * to a safe place is not required. + */ + break; + } + + return 0; +} +EXPORT_SYMBOL(da9052_i2c_fix); + static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) { int reg_val, ret; @@ -83,6 +143,7 @@ static int da9052_i2c_probe(struct i2c_client *client, da9052->dev = &client->dev; da9052->chip_irq = client->irq; + da9052->fix_io = da9052_i2c_fix; i2c_set_clientdata(client, da9052); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dc8826d..6fbe1c9 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -26,13 +26,13 @@ #include <linux/fs.h> #include <linux/platform_device.h> #include <linux/uaccess.h> +#include <linux/irqchip/arm-gic.h> #include <linux/mfd/core.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/mfd/abx500/ab8500.h> #include <linux/regulator/db8500-prcmu.h> #include <linux/regulator/machine.h> #include <linux/cpufreq.h> -#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/db8500-regs.h> @@ -2524,7 +2524,7 @@ static bool read_mailbox_0(void) for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { if (ev & prcmu_irq_bit[n]) - generic_handle_irq(IRQ_PRCMU_BASE + n); + generic_handle_irq(irq_find_mapping(db8500_irq_domain, n)); } r = true; break; @@ -2737,13 +2737,14 @@ static int db8500_irq_map(struct irq_domain *d, unsigned int virq, } static struct irq_domain_ops db8500_irq_ops = { - .map = db8500_irq_map, - .xlate = irq_domain_xlate_twocell, + .map = db8500_irq_map, + .xlate = irq_domain_xlate_twocell, }; static int db8500_irq_init(struct device_node *np) { - int irq_base = -1; + int irq_base = 0; + int i; /* In the device tree case, just take some IRQs */ if (!np) @@ -2758,6 +2759,10 @@ static int db8500_irq_init(struct device_node *np) return -ENOSYS; } + /* All wakeups will be used, so create mappings for all */ + for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) + irq_create_mapping(db8500_irq_domain, i); + return 0; } diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index f6878f8..4d73963 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -93,15 +93,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, if (max77686 == NULL) return -ENOMEM; - max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); - if (IS_ERR(max77686->regmap)) { - ret = PTR_ERR(max77686->regmap); - dev_err(max77686->dev, "Failed to allocate register map: %d\n", - ret); - kfree(max77686); - return ret; - } - i2c_set_clientdata(i2c, max77686); max77686->dev = &i2c->dev; max77686->i2c = i2c; @@ -111,6 +102,15 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->irq_gpio = pdata->irq_gpio; max77686->irq = i2c->irq; + max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); + if (IS_ERR(max77686->regmap)) { + ret = PTR_ERR(max77686->regmap); + dev_err(max77686->dev, "Failed to allocate register map: %d\n", + ret); + kfree(max77686); + return ret; + } + if (regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data) < 0) { dev_err(max77686->dev, diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index cc5155e..9e60fed 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -114,35 +114,37 @@ static int max77693_i2c_probe(struct i2c_client *i2c, u8 reg_data; int ret = 0; + if (!pdata) { + dev_err(&i2c->dev, "No platform data found.\n"); + return -EINVAL; + } + max77693 = devm_kzalloc(&i2c->dev, sizeof(struct max77693_dev), GFP_KERNEL); if (max77693 == NULL) return -ENOMEM; - max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); - if (IS_ERR(max77693->regmap)) { - ret = PTR_ERR(max77693->regmap); - dev_err(max77693->dev,"failed to allocate register map: %d\n", - ret); - goto err_regmap; - } - i2c_set_clientdata(i2c, max77693); max77693->dev = &i2c->dev; max77693->i2c = i2c; max77693->irq = i2c->irq; max77693->type = id->driver_data; - if (!pdata) - goto err_regmap; + max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); + if (IS_ERR(max77693->regmap)) { + ret = PTR_ERR(max77693->regmap); + dev_err(max77693->dev, "failed to allocate register map: %d\n", + ret); + return ret; + } max77693->wakeup = pdata->wakeup; - if (max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_PMIC_ID2, ®_data) < 0) { + ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, + ®_data); + if (ret < 0) { dev_err(max77693->dev, "device not found on this channel\n"); - ret = -ENODEV; - goto err_regmap; + return ret; } else dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); @@ -163,7 +165,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max77693->regmap_muic); dev_err(max77693->dev, "failed to allocate register map: %d\n", ret); - goto err_regmap; + goto err_regmap_muic; } ret = max77693_irq_init(max77693); @@ -184,9 +186,9 @@ static int max77693_i2c_probe(struct i2c_client *i2c, err_mfd: max77693_irq_exit(max77693); err_irq: +err_regmap_muic: i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); -err_regmap: return ret; } diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 64803f1..d115673 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -208,6 +208,8 @@ static int pcf50633_probe(struct i2c_client *client, if (!pcf) return -ENOMEM; + i2c_set_clientdata(client, pcf); + pcf->dev = &client->dev; pcf->pdata = pdata; mutex_init(&pcf->lock); @@ -219,9 +221,6 @@ static int pcf50633_probe(struct i2c_client *client, return ret; } - i2c_set_clientdata(client, pcf); - pcf->dev = &client->dev; - version = pcf50633_reg_read(pcf, 0); variant = pcf50633_reg_read(pcf, 1); if (version < 0 || variant < 0) { diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 89f046c..3d3b4ad 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) BPP_LDO_POWB, BPP_LDO_SUSPEND); } +static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + u8 mask, val; + + mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; + if (voltage == OUTPUT_3V3) + val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; + else if (voltage == OUTPUT_1V8) + val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; + else + return -EINVAL; + + return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); +} + static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) { unsigned int card_exist; @@ -163,6 +178,18 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) return card_exist; } +static int rtl8411_conv_clk_and_div_n(int input, int dir) +{ + int output; + + if (dir == CLK_TO_DIV_N) + output = input * 4 / 5 - 2; + else + output = (input + 2) * 5 / 4; + + return output; +} + static const struct pcr_ops rtl8411_pcr_ops = { .extra_init_hw = rtl8411_extra_init_hw, .optimize_phy = NULL, @@ -172,7 +199,9 @@ static const struct pcr_ops rtl8411_pcr_ops = { .disable_auto_blink = rtl8411_disable_auto_blink, .card_power_on = rtl8411_card_power_on, .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 283a4f1..98fe0f3 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) return rtsx_pci_send_cmd(pcr, 100); } +static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + int err; + + if (voltage == OUTPUT_3V3) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); + if (err < 0) + return err; + } else if (voltage == OUTPUT_1V8) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); + if (err < 0) + return err; + } else { + return -EINVAL; + } + + return 0; +} + static const struct pcr_ops rts5209_pcr_ops = { .extra_init_hw = rts5209_extra_init_hw, .optimize_phy = rts5209_optimize_phy, @@ -153,7 +172,9 @@ static const struct pcr_ops rts5209_pcr_ops = { .disable_auto_blink = rts5209_disable_auto_blink, .card_power_on = rts5209_card_power_on, .card_power_off = rts5209_card_power_off, + .switch_output_voltage = rts5209_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index b9dbab2..29d889c 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) return rtsx_pci_send_cmd(pcr, 100); } +static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + int err; + + if (voltage == OUTPUT_3V3) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); + if (err < 0) + return err; + } else if (voltage == OUTPUT_1V8) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); + if (err < 0) + return err; + } else { + return -EINVAL; + } + + return 0; +} + static const struct pcr_ops rts5229_pcr_ops = { .extra_init_hw = rts5229_extra_init_hw, .optimize_phy = rts5229_optimize_phy, @@ -123,7 +142,9 @@ static const struct pcr_ops rts5229_pcr_ops = { .disable_auto_blink = rts5229_disable_auto_blink, .card_power_on = rts5229_card_power_on, .card_power_off = rts5229_card_power_off, + .switch_output_voltage = rts5229_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 7a7b0bd..9fc5700 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -630,7 +630,10 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, if (clk == pcr->cur_clock) return 0; - N = (u8)(clk - 2); + if (pcr->ops->conv_clk_and_div_n) + N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); + else + N = (u8)(clk - 2); if ((clk <= 2) || (N > max_N)) return -EINVAL; @@ -641,7 +644,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, /* Make sure that the SSC clock div_n is equal or greater than min_N */ div = CLK_DIV_1; while ((N < min_N) && (div < max_div)) { - N = (N + 2) * 2 - 2; + if (pcr->ops->conv_clk_and_div_n) { + int dbl_clk = pcr->ops->conv_clk_and_div_n(N, + DIV_N_TO_CLK) * 2; + N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, + CLK_TO_DIV_N); + } else { + N = (N + 2) * 2 - 2; + } div++; } dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div); @@ -703,6 +713,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) } EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); +int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + if (pcr->ops->switch_output_voltage) + return pcr->ops->switch_output_voltage(pcr, voltage); + + return 0; +} +EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage); + unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr) { unsigned int val; @@ -767,10 +786,10 @@ static void rtsx_pci_card_detect(struct work_struct *work) spin_unlock_irqrestore(&pcr->lock, flags); - if (card_detect & SD_EXIST) + if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) pcr->slots[RTSX_SD_CARD].card_event( pcr->slots[RTSX_SD_CARD].p_dev); - if (card_detect & MS_EXIST) + if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event) pcr->slots[RTSX_MS_CARD].card_event( pcr->slots[RTSX_MS_CARD].p_dev); } diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index a06d66b..ecc092c 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -219,25 +219,18 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq) } static struct irq_domain_ops tc3589x_irq_ops = { - .map = tc3589x_irq_map, + .map = tc3589x_irq_map, .unmap = tc3589x_irq_unmap, - .xlate = irq_domain_xlate_twocell, + .xlate = irq_domain_xlate_twocell, }; static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) { int base = tc3589x->irq_base; - if (base) { - tc3589x->domain = irq_domain_add_legacy( - NULL, TC3589x_NR_INTERNAL_IRQS, base, - 0, &tc3589x_irq_ops, tc3589x); - } - else { - tc3589x->domain = irq_domain_add_linear( - np, TC3589x_NR_INTERNAL_IRQS, - &tc3589x_irq_ops, tc3589x); - } + tc3589x->domain = irq_domain_add_simple( + np, TC3589x_NR_INTERNAL_IRQS, base, + &tc3589x_irq_ops, tc3589x); if (!tc3589x->domain) { dev_err(tc3589x->dev, "Failed to create irqdomain\n"); diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 4dae241..dd362c1 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -159,7 +159,7 @@ out: static int twl4030_write_script(u8 address, struct twl4030_ins *script, int len) { - int err; + int err = -EINVAL; for (; len; len--, address++, script++) { if (len == 1) { diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c index fae15d8..3c1723aa 100644 --- a/drivers/mfd/vexpress-config.c +++ b/drivers/mfd/vexpress-config.c @@ -67,6 +67,7 @@ struct vexpress_config_bridge *vexpress_config_bridge_register( return bridge; } +EXPORT_SYMBOL(vexpress_config_bridge_register); void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) { @@ -83,6 +84,7 @@ void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) while (!list_empty(&__bridge.transactions)) cpu_relax(); } +EXPORT_SYMBOL(vexpress_config_bridge_unregister); struct vexpress_config_func { @@ -142,6 +144,7 @@ struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, return func; } +EXPORT_SYMBOL(__vexpress_config_func_get); void vexpress_config_func_put(struct vexpress_config_func *func) { @@ -149,7 +152,7 @@ void vexpress_config_func_put(struct vexpress_config_func *func) of_node_put(func->bridge->node); kfree(func); } - +EXPORT_SYMBOL(vexpress_config_func_put); struct vexpress_config_trans { struct vexpress_config_func *func; @@ -229,6 +232,7 @@ void vexpress_config_complete(struct vexpress_config_bridge *bridge, complete(&trans->completion); } +EXPORT_SYMBOL(vexpress_config_complete); int vexpress_config_wait(struct vexpress_config_trans *trans) { @@ -236,7 +240,7 @@ int vexpress_config_wait(struct vexpress_config_trans *trans) return trans->status; } - +EXPORT_SYMBOL(vexpress_config_wait); int vexpress_config_read(struct vexpress_config_func *func, int offset, u32 *data) diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 088872a..1133a64 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -1882,7 +1882,7 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) } } -#define WM5102_MAX_REGISTER 0x1a8fff +#define WM5102_MAX_REGISTER 0x1a9800 const struct regmap_config wm5102_spi_regmap = { .reg_bits = 32, diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 571915d..f74b5ad 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1060,26 +1060,6 @@ static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host) return 0; } -static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage) -{ - struct rtsx_pcr *pcr = host->pcr; - int err; - - if (voltage == SD_IO_3V3) { - err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); - if (err < 0) - return err; - } else if (voltage == SD_IO_1V8) { - err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); - if (err < 0) - return err; - } else { - return -EINVAL; - } - - return 0; -} - static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); @@ -1098,11 +1078,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) rtsx_pci_start_run(pcr); if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) - voltage = SD_IO_3V3; + voltage = OUTPUT_3V3; else - voltage = SD_IO_1V8; + voltage = OUTPUT_1V8; - if (voltage == SD_IO_1V8) { + if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); if (err < 0) @@ -1113,11 +1093,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) goto out; } - err = sd_change_bank_voltage(host, voltage); + err = rtsx_pci_switch_output_voltage(pcr, voltage); if (err < 0) goto out; - if (voltage == SD_IO_1V8) { + if (voltage == OUTPUT_1V8) { err = sd_wait_voltage_stable_2(host); if (err < 0) goto out; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 5233b8f..58607f1 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -960,7 +960,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: @@ -973,7 +973,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 7d17485..5c314a9 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) stats->rx_errors++; break; case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; priv->can.can_stats.bus_error++; stats->rx_errors++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f898c63..300581b 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -746,12 +746,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index 66df936..ffd8de2 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link) netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", cardname, dev->base_addr, dev->irq, dev->dev_addr); netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", - 8 << config & Ram_size, + 8 << (config & Ram_size), ram_split[(config & Ram_split) >> Ram_split_shift], config & Autoselect ? "autoselect " : ""); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 78ea90c..bdb0869 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1283,14 +1283,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + + if (err) + return err; + if (enable) + + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -2223,7 +2235,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2248,7 +2260,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -2284,9 +2296,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) if (!tp->setlpicnt) { if (current_link_up == 1 && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2302,11 +2314,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || tg3_flag(tp, 57765_CLASS)) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2450,7 +2462,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2471,7 +2483,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_CTRL1000, phy9_orig); @@ -2572,10 +2584,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2584,14 +2596,14 @@ out: } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2600,7 +2612,7 @@ out: } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -4009,7 +4021,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -4042,7 +4054,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) MII_TG3_DSP_CH34TP2_HIBW01); } - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } @@ -6950,6 +6962,9 @@ static void tg3_poll_controller(struct net_device *dev) int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } @@ -16367,6 +16382,7 @@ static int tg3_init_one(struct pci_dev *pdev, tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index b407043..f7f0290 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -548,6 +548,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) return -1; } + /* All frames should fit into a single buffer */ + if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) + return -1; + /* Check if packet has checksum already */ if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && !(ext_status & RXDESC_IP_PAYLOAD_MASK)) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f0718e1..c306df7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1994,9 +1994,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { const struct port_info *pi = netdev_priv(dev); struct adapter *adap = pi->adapter; - - return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq, - c->rx_coalesce_usecs, c->rx_max_coalesced_frames); + struct sge_rspq *q; + int i; + int r = 0; + + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) { + q = &adap->sge.ethrxq[i].rspq; + r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs, + c->rx_max_coalesced_frames); + if (r) { + dev_err(&dev->dev, "failed to set coalesce %d\n", r); + break; + } + } + return r; } static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile index f3a632b..687c83d 100644 --- a/drivers/net/ethernet/intel/ixgbe/Makefile +++ b/drivers/net/ethernet/intel/ixgbe/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o -ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\ +ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o @@ -40,4 +40,5 @@ ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o +ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c index 50aa546..3504686 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c @@ -24,9 +24,6 @@ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ - -#ifdef CONFIG_DEBUG_FS - #include <linux/debugfs.h> #include <linux/module.h> @@ -277,5 +274,3 @@ void ixgbe_dbg_exit(void) { debugfs_remove_recursive(ixgbe_dbg_root); } - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 1a751c9..bb9256a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -660,11 +660,11 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG; + tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG; break; case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG; + tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 2b799f4..6771b69 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -630,10 +630,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - ethh = (struct ethhdr *)skb->data; - tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); - tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { + /* Copy dst mac address to wqe. This allows loopback in eSwitch, + * so that VFs and PF can communicate with each other + */ + ethh = (struct ethhdr *)skb->data; + tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); + tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index e1bafff..a6542d7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1790,15 +1790,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index bc165f4..695667d 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 6098fd4a..69e321a 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1963,10 +1963,12 @@ unwind: while (--i >= 0) { nf = &pbuf->frag_array[i+1]; pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + nf->dma = 0ULL; } nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + nf->dma = 0ULL; out_err: return -ENOMEM; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index ed96f30..1170232 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1826,8 +1826,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) if (opts2 & RxVlanTag) __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); - - desc->opts2 = 0; } static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) @@ -6064,8 +6062,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget !(status & (RxRWT | RxFOVF)) && (dev->features & NETIF_F_RXALL)) goto process_pkt; - - rtl8169_mark_to_asic(desc, rx_buf_sz); } else { struct sk_buff *skb; dma_addr_t addr; @@ -6086,16 +6082,14 @@ process_pkt: if (unlikely(rtl8169_fragmented_frame(status))) { dev->stats.rx_dropped++; dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; + goto release_descriptor; } skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); if (!skb) { dev->stats.rx_dropped++; - continue; + goto release_descriptor; } rtl8169_rx_csum(skb, status); @@ -6111,13 +6105,10 @@ process_pkt: tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } +release_descriptor: + desc->opts2 = 0; + wmb(); + rtl8169_mark_to_asic(desc, rx_buf_sz); } count = cur_rx - tp->cur_rx; diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 5fd6f46..e6fe0d8 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -84,7 +84,7 @@ struct hv_netvsc_packet { }; struct netvsc_device_info { - unsigned char mac_adr[6]; + unsigned char mac_adr[ETH_ALEN]; bool link_state; /* 0 - link up, 1 - link down */ int ring_size; }; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f825a62..8264f0e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -349,7 +349,7 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p) struct net_device_context *ndevctx = netdev_priv(ndev); struct hv_device *hdev = ndevctx->device_ctx; struct sockaddr *addr = p; - char save_adr[14]; + char save_adr[ETH_ALEN]; unsigned char save_aatype; int err; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 81f8f9e..fcbf680 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb_orphan(skb); + /* Before queueing this packet to netif_rx(), + * make sure dst is refcounted. + */ + skb_dst_force(skb); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 68a43fe..d3fb97d 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -822,7 +822,10 @@ static int macvlan_changelink(struct net_device *dev, static size_t macvlan_get_size(const struct net_device *dev) { - return nla_total_size(4); + return (0 + + nla_total_size(4) /* IFLA_MACVLAN_MODE */ + + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ + ); } static int macvlan_fill_info(struct sk_buff *skb, diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index d5199cb..b5ddd50 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -36,8 +36,9 @@ MODULE_LICENSE("GPL"); /* IP101A/G - IP1001 */ #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ +#define IP1001_RXPHASE_SEL (1<<0) /* Add delay on RX_CLK */ +#define IP1001_TXPHASE_SEL (1<<1) /* Add delay on TX_CLK */ #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ -#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */ #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ @@ -138,19 +139,24 @@ static int ip1001_config_init(struct phy_device *phydev) if (c < 0) return c; - /* INTR pin used: speed/link/duplex will cause an interrupt */ - c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); - if (c < 0) - return c; + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { - /* Additional delay (2ns) used to adjust RX clock phase - * at RGMII interface */ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); if (c < 0) return c; - c |= IP1001_PHASE_SEL_MASK; + c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + c |= IP1001_RXPHASE_SEL; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + c |= IP1001_TXPHASE_SEL; + c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); if (c < 0) return c; @@ -167,6 +173,11 @@ static int ip101a_g_config_init(struct phy_device *phydev) if (c < 0) return c; + /* INTR pin used: speed/link/duplex will cause an interrupt */ + c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); + if (c < 0) + return c; + /* Enable Auto Power Saving mode */ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); c |= IP101A_G_APS_ON; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5d2a3f2..22dec9c 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -353,15 +353,6 @@ static int m88e1111_config_init(struct phy_device *phydev) int err; int temp; - /* Enable Fiber/Copper auto selection */ - temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); - temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; - phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); - - temp = phy_read(phydev, MII_BMCR); - temp |= BMCR_RESET; - phy_write(phydev, MII_BMCR, temp); - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || diff --git a/drivers/net/tun.c b/drivers/net/tun.c index af372d0..cc09b67 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -109,11 +109,11 @@ struct tap_filter { unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; }; -/* 1024 is probably a high enough limit: modern hypervisors seem to support on - * the order of 100-200 CPUs so this leaves us some breathing space if we want - * to match a queue per guest CPU. - */ -#define MAX_TAP_QUEUES 1024 +/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for + * the netdevice to be fit in one page. So we can make sure the success of + * memory allocation. TODO: increase the limit. */ +#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES +#define MAX_TAP_FLOWS 4096 #define TUN_FLOW_EXPIRE (3 * HZ) @@ -185,6 +185,8 @@ struct tun_struct { unsigned long ageing_time; unsigned int numdisabled; struct list_head disabled; + void *security; + u32 flow_count; }; static inline u32 tun_hashfn(u32 rxhash) @@ -218,6 +220,7 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, e->queue_index = queue_index; e->tun = tun; hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; } return e; } @@ -228,6 +231,7 @@ static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) e->rxhash, e->queue_index); hlist_del_rcu(&e->hash_link); kfree_rcu(e, rcu); + --tun->flow_count; } static void tun_flow_flush(struct tun_struct *tun) @@ -317,7 +321,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash, e->updated = jiffies; } else { spin_lock_bh(&tun->lock); - if (!tun_flow_find(head, rxhash)) + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) tun_flow_create(tun, head, rxhash, queue_index); if (!timer_pending(&tun->flow_gc_timer)) @@ -490,6 +495,10 @@ static int tun_attach(struct tun_struct *tun, struct file *file) struct tun_file *tfile = file->private_data; int err; + err = security_tun_dev_attach(tfile->socket.sk, tun->security); + if (err < 0) + goto out; + err = -EINVAL; if (rtnl_dereference(tfile->tun)) goto out; @@ -1373,6 +1382,7 @@ static void tun_free_netdev(struct net_device *dev) BUG_ON(!(list_empty(&tun->disabled))); tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); free_netdev(dev); } @@ -1562,7 +1572,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (tun_not_capable(tun)) return -EPERM; - err = security_tun_dev_attach(tfile->socket.sk); + err = security_tun_dev_open(tun->security); if (err < 0) return err; @@ -1577,6 +1587,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else { char *name; unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -1600,8 +1612,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) name = ifr->ifr_name; dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, - tun_setup, - MAX_TAP_QUEUES, MAX_TAP_QUEUES); + tun_setup, queues, queues); + if (!dev) return -ENOMEM; @@ -1619,7 +1631,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) spin_lock_init(&tun->lock); - security_tun_dev_post_create(&tfile->sk); + err = security_tun_dev_alloc_security(&tun->security); + if (err < 0) + goto err_free_dev; tun_net_init(dev); @@ -1789,10 +1803,14 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { tun = tfile->detached; - if (!tun) + if (!tun) { ret = -EINVAL; - else - ret = tun_attach(tun, file); + goto unlock; + } + ret = security_tun_dev_attach_queue(tun->security); + if (ret < 0) + goto unlock; + ret = tun_attach(tun, file); } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { tun = rtnl_dereference(tfile->tun); if (!tun || !(tun->flags & TUN_TAP_MQ)) @@ -1802,6 +1820,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) } else ret = -EINVAL; +unlock: rtnl_unlock(); return ret; } diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 42f51c7..248d2dc 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -374,6 +374,21 @@ static const struct driver_info cdc_mbim_info = { .tx_fixup = cdc_mbim_tx_fixup, }; +/* MBIM and NCM devices should not need a ZLP after NTBs with + * dwNtbOutMaxSize length. This driver_info is for the exceptional + * devices requiring it anyway, allowing them to be supported without + * forcing the performance penalty on all the sane devices. + */ +static const struct driver_info cdc_mbim_info_zlp = { + .description = "CDC MBIM", + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, + .bind = cdc_mbim_bind, + .unbind = cdc_mbim_unbind, + .manage_power = cdc_mbim_manage_power, + .rx_fixup = cdc_mbim_rx_fixup, + .tx_fixup = cdc_mbim_tx_fixup, +}; + static const struct usb_device_id mbim_devs[] = { /* This duplicate NCM entry is intentional. MBIM devices can * be disguised as NCM by default, and this is necessary to @@ -385,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = { { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info, }, + /* Sierra Wireless MC7710 need ZLPs */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&cdc_mbim_info_zlp, + }, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info, }, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 71b6e92..9197b2c 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -435,6 +435,13 @@ advance: len -= temp; } + /* some buggy devices have an IAD but no CDC Union */ + if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) { + ctx->control = intf; + ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1); + dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n"); + } + /* check if we got everything */ if ((ctx->control == NULL) || (ctx->data == NULL) || ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf)))) @@ -497,7 +504,8 @@ advance: error2: usb_set_intfdata(ctx->control, NULL); usb_set_intfdata(ctx->data, NULL); - usb_driver_release_interface(driver, ctx->data); + if (ctx->data != ctx->control) + usb_driver_release_interface(driver, ctx->data); error: cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); dev->data[0] = 0; @@ -1155,6 +1163,20 @@ static const struct driver_info wwan_info = { .tx_fixup = cdc_ncm_tx_fixup, }; +/* Same as wwan_info, but with FLAG_NOARP */ +static const struct driver_info wwan_noarp_info = { + .description = "Mobile Broadband Network Device (NO ARP)", + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET + | FLAG_WWAN | FLAG_NOARP, + .bind = cdc_ncm_bind, + .unbind = cdc_ncm_unbind, + .check_connect = cdc_ncm_check_connect, + .manage_power = usbnet_manage_power, + .status = cdc_ncm_status, + .rx_fixup = cdc_ncm_rx_fixup, + .tx_fixup = cdc_ncm_tx_fixup, +}; + static const struct usb_device_id cdc_devs[] = { /* Ericsson MBM devices like F5521gw */ { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO @@ -1194,6 +1216,13 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long)&wwan_info, }, + /* Infineon(now Intel) HSPA Modem platform */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_noarp_info, + }, + /* Generic CDC-NCM devices */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 3f554c1..d7e9944 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -45,6 +45,12 @@ #define DM_MCAST_ADDR 0x16 /* 8 bytes */ #define DM_GPR_CTRL 0x1e #define DM_GPR_DATA 0x1f +#define DM_CHIP_ID 0x2c +#define DM_MODE_CTRL 0x91 /* only on dm9620 */ + +/* chip id values */ +#define ID_DM9601 0 +#define ID_DM9620 1 #define DM_MAX_MCAST 64 #define DM_MCAST_SIZE 8 @@ -53,7 +59,6 @@ #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ #define DM_TIMEOUT 1000 - static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) { int err; @@ -84,32 +89,23 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) { - return usbnet_write_cmd(dev, DM_WRITE_REGS, + return usbnet_write_cmd(dev, DM_WRITE_REG, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, reg, NULL, 0); } -static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, - u16 length, void *data) +static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) { usbnet_write_cmd_async(dev, DM_WRITE_REGS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, reg, data, length); -} - -static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) -{ - netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); - - dm_write_async_helper(dev, reg, 0, length, data); + 0, reg, data, length); } static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) { - netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n", - reg, value); - - dm_write_async_helper(dev, reg, value, 0, NULL); + usbnet_write_cmd_async(dev, DM_WRITE_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, reg, NULL, 0); } static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) @@ -358,7 +354,7 @@ static const struct net_device_ops dm9601_netdev_ops = { static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) { int ret; - u8 mac[ETH_ALEN]; + u8 mac[ETH_ALEN], id; ret = usbnet_get_endpoints(dev, intf); if (ret) @@ -399,6 +395,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) __dm9601_set_mac_address(dev); } + if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) { + netdev_err(dev->net, "Error reading chip ID\n"); + ret = -ENODEV; + goto out; + } + + /* put dm9620 devices in dm9601 mode */ + if (id == ID_DM9620) { + u8 mode; + + if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) { + netdev_err(dev->net, "Error reading MODE_CTRL\n"); + ret = -ENODEV; + goto out; + } + dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f); + } + /* power up phy */ dm_write_reg(dev, DM_GPR_CTRL, 1); dm_write_reg(dev, DM_GPR_DATA, 0); @@ -581,6 +595,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x9620), /* DM9620 USB to Fast Ethernet Adapter */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6a1ca50..575a583 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -433,6 +433,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ + {QMI_FIXED_INTF(0x19d2, 0x0265, 4)}, /* ONDA MT8205 4G LTE */ {QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */ {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ @@ -459,6 +460,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ + {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 3d4bf01..f34b2eb 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1448,6 +1448,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_WWAN) != 0) strcpy(net->name, "wwan%d"); + /* devices that cannot do ARP */ + if ((dev->driver_info->flags & FLAG_NOARP) != 0) + net->flags |= IFF_NOARP; + /* maybe the remote can't receive an Ethernet MTU */ if (net->mtu > (dev->hard_mtu - net->hard_header_len)) net->mtu = dev->hard_mtu - net->hard_header_len; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index a6fcf15..35c00c5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -26,6 +26,7 @@ #include <linux/scatterlist.h> #include <linux/if_vlan.h> #include <linux/slab.h> +#include <linux/cpu.h> static int napi_weight = 128; module_param(napi_weight, int, 0444); @@ -123,6 +124,12 @@ struct virtnet_info { /* Does the affinity hint is set for virtqueues? */ bool affinity_hint_set; + + /* Per-cpu variable to show the mapping from CPU to virtqueue */ + int __percpu *vq_index; + + /* CPU hot plug notifier */ + struct notifier_block nb; }; struct skb_vnet_hdr { @@ -1013,32 +1020,75 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) return 0; } -static void virtnet_set_affinity(struct virtnet_info *vi, bool set) +static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu) { int i; + int cpu; + + if (vi->affinity_hint_set) { + for (i = 0; i < vi->max_queue_pairs; i++) { + virtqueue_set_affinity(vi->rq[i].vq, -1); + virtqueue_set_affinity(vi->sq[i].vq, -1); + } + + vi->affinity_hint_set = false; + } + + i = 0; + for_each_online_cpu(cpu) { + if (cpu == hcpu) { + *per_cpu_ptr(vi->vq_index, cpu) = -1; + } else { + *per_cpu_ptr(vi->vq_index, cpu) = + ++i % vi->curr_queue_pairs; + } + } +} + +static void virtnet_set_affinity(struct virtnet_info *vi) +{ + int i; + int cpu; /* In multiqueue mode, when the number of cpu is equal to the number of * queue pairs, we let the queue pairs to be private to one cpu by * setting the affinity hint to eliminate the contention. */ - if ((vi->curr_queue_pairs == 1 || - vi->max_queue_pairs != num_online_cpus()) && set) { - if (vi->affinity_hint_set) - set = false; - else - return; + if (vi->curr_queue_pairs == 1 || + vi->max_queue_pairs != num_online_cpus()) { + virtnet_clean_affinity(vi, -1); + return; } - for (i = 0; i < vi->max_queue_pairs; i++) { - int cpu = set ? i : -1; + i = 0; + for_each_online_cpu(cpu) { virtqueue_set_affinity(vi->rq[i].vq, cpu); virtqueue_set_affinity(vi->sq[i].vq, cpu); + *per_cpu_ptr(vi->vq_index, cpu) = i; + i++; } - if (set) - vi->affinity_hint_set = true; - else - vi->affinity_hint_set = false; + vi->affinity_hint_set = true; +} + +static int virtnet_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + + switch(action & ~CPU_TASKS_FROZEN) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: + case CPU_DEAD: + virtnet_set_affinity(vi); + break; + case CPU_DOWN_PREPARE: + virtnet_clean_affinity(vi, (long)hcpu); + break; + default: + break; + } + return NOTIFY_OK; } static void virtnet_get_ringparam(struct net_device *dev, @@ -1082,13 +1132,15 @@ static int virtnet_set_channels(struct net_device *dev, if (queue_pairs > vi->max_queue_pairs) return -EINVAL; + get_online_cpus(); err = virtnet_set_queues(vi, queue_pairs); if (!err) { netif_set_real_num_tx_queues(dev, queue_pairs); netif_set_real_num_rx_queues(dev, queue_pairs); - virtnet_set_affinity(vi, true); + virtnet_set_affinity(vi); } + put_online_cpus(); return err; } @@ -1127,12 +1179,19 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu) /* To avoid contending a lock hold by a vcpu who would exit to host, select the * txq based on the processor id. - * TODO: handle cpu hotplug. */ static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb) { - int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : - smp_processor_id(); + int txq; + struct virtnet_info *vi = netdev_priv(dev); + + if (skb_rx_queue_recorded(skb)) { + txq = skb_get_rx_queue(skb); + } else { + txq = *__this_cpu_ptr(vi->vq_index); + if (txq == -1) + txq = 0; + } while (unlikely(txq >= dev->real_num_tx_queues)) txq -= dev->real_num_tx_queues; @@ -1248,7 +1307,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi) { struct virtio_device *vdev = vi->vdev; - virtnet_set_affinity(vi, false); + virtnet_clean_affinity(vi, -1); vdev->config->del_vqs(vdev); @@ -1371,7 +1430,10 @@ static int init_vqs(struct virtnet_info *vi) if (ret) goto err_free; - virtnet_set_affinity(vi, true); + get_online_cpus(); + virtnet_set_affinity(vi); + put_online_cpus(); + return 0; err_free: @@ -1453,6 +1515,10 @@ static int virtnet_probe(struct virtio_device *vdev) if (vi->stats == NULL) goto free; + vi->vq_index = alloc_percpu(int); + if (vi->vq_index == NULL) + goto free_stats; + mutex_init(&vi->config_lock); vi->config_enable = true; INIT_WORK(&vi->config_work, virtnet_config_changed_work); @@ -1476,7 +1542,7 @@ static int virtnet_probe(struct virtio_device *vdev) /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ err = init_vqs(vi); if (err) - goto free_stats; + goto free_index; netif_set_real_num_tx_queues(dev, 1); netif_set_real_num_rx_queues(dev, 1); @@ -1499,6 +1565,13 @@ static int virtnet_probe(struct virtio_device *vdev) } } + vi->nb.notifier_call = &virtnet_cpu_callback; + err = register_hotcpu_notifier(&vi->nb); + if (err) { + pr_debug("virtio_net: registering cpu notifier failed\n"); + goto free_recv_bufs; + } + /* Assume link up if device can't report link status, otherwise get link status from config. */ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { @@ -1520,6 +1593,8 @@ free_recv_bufs: free_vqs: cancel_delayed_work_sync(&vi->refill); virtnet_del_vqs(vi); +free_index: + free_percpu(vi->vq_index); free_stats: free_percpu(vi->stats); free: @@ -1543,6 +1618,8 @@ static void virtnet_remove(struct virtio_device *vdev) { struct virtnet_info *vi = vdev->priv; + unregister_hotcpu_notifier(&vi->nb); + /* Prevent config work handler from accessing the device. */ mutex_lock(&vi->config_lock); vi->config_enable = false; @@ -1554,6 +1631,7 @@ static void virtnet_remove(struct virtio_device *vdev) flush_work(&vi->config_work); + free_percpu(vi->vq_index); free_percpu(vi->stats); free_netdev(vi->dev); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 8b0d8dc..56317b0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -976,6 +976,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, AR_PHY_CL_TAB_1, AR_PHY_CL_TAB_2 }; + ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); + if (rtt) { if (!ar9003_hw_rtt_restore(ah, chan)) run_rtt_cal = true; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ce19c09..3afc24b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -586,32 +586,19 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, ath9k_hw_synth_delay(ah, chan, synthDelay); } -static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { - switch (rx) { - case 0x5: + if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5) REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); - case 0x3: - case 0x1: - case 0x2: - case 0x7: - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); - break; - default: - break; - } + + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) - REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); - else - REG_WRITE(ah, AR_SELFGEN_MASK, tx); + tx = 3; - if (tx == 0x5) { - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - } + REG_WRITE(ah, AR_SELFGEN_MASK, tx); } /* diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 86e26a1..42794c5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -317,7 +317,6 @@ struct ath_rx { u32 *rxlink; u32 num_pkts; unsigned int rxfilter; - spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; struct ath_buf *rx_bufptr; @@ -328,7 +327,6 @@ struct ath_rx { int ath_startrecv(struct ath_softc *sc); bool ath_stoprecv(struct ath_softc *sc); -void ath_flushrecv(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc); int ath_rx_init(struct ath_softc *sc, int nbufs); void ath_rx_cleanup(struct ath_softc *sc); @@ -646,7 +644,6 @@ void ath_ant_comb_update(struct ath_softc *sc); enum sc_op_flags { SC_OP_INVALID, SC_OP_BEACONS, - SC_OP_RXFLUSH, SC_OP_ANI_RUN, SC_OP_PRIM_STA_VIF, SC_OP_HW_RESET, diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 531fffd..2ca355e 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; + bf->bf_mpdu = NULL; } skb = ieee80211_beacon_get(hw, vif); @@ -359,7 +360,6 @@ void ath9k_beacon_tasklet(unsigned long data) return; bf = ath9k_beacon_generate(sc->hw, vif); - WARN_ON(!bf); if (sc->beacon.bmisscnt != 0) { ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 13ff9ed..e585fc8 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -861,7 +861,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, RXS_ERR("RX-LENGTH-ERR", rx_len_err); RXS_ERR("RX-OOM-ERR", rx_oom_err); RXS_ERR("RX-RATE-ERR", rx_rate_err); - RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 375c3b4..6df2ab6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -216,7 +216,6 @@ struct ath_tx_stats { * @rx_oom_err: No. of frames dropped due to OOM issues. * @rx_rate_err: No. of frames dropped due to rate errors. * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. - * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. * @rx_beacons: No. of beacons received. * @rx_frags: No. of rx-fragements received. */ @@ -235,7 +234,6 @@ struct ath_rx_stats { u32 rx_oom_err; u32 rx_rate_err; u32 rx_too_many_frags_err; - u32 rx_drop_rxflush; u32 rx_beacons; u32 rx_frags; }; diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 4a9570d..aac4a40 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); + } else { + kfree_skb(skb); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7f1a8e9..9d26fc5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1066,6 +1066,7 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); int ar9003_paprd_init_table(struct ath_hw *ah); bool ar9003_paprd_is_done(struct ath_hw *ah); bool ar9003_is_paprd_enabled(struct ath_hw *ah); +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); /* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index be30a9a..dd91f8f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc) ath_start_ani(sc); } -static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) +static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hw *ah = sc->sc_ah; bool ret = true; @@ -202,14 +202,6 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) if (!ath_drain_all_txq(sc, retry_tx)) ret = false; - if (!flush) { - if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ath_rx_tasklet(sc, 1, true); - ath_rx_tasklet(sc, 1, false); - } else { - ath_flushrecv(sc); - } - return ret; } @@ -262,11 +254,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_cal_data *caldata = NULL; bool fastcc = true; - bool flush = false; int r; __ath_cancel_work(sc); + tasklet_disable(&sc->intr_tq); spin_lock_bh(&sc->sc_pcu_lock); if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { @@ -276,11 +268,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, if (!hchan) { fastcc = false; - flush = true; hchan = ah->curchan; } - if (!ath_prepare_reset(sc, retry_tx, flush)) + if (!ath_prepare_reset(sc, retry_tx)) fastcc = false; ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", @@ -302,6 +293,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, out: spin_unlock_bh(&sc->sc_pcu_lock); + tasklet_enable(&sc->intr_tq); + return r; } @@ -804,7 +797,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_hw_cfg_gpio_input(ah, ah->led_pin); } - ath_prepare_reset(sc, false, true); + ath_prepare_reset(sc, false); if (sc->rx.frag) { dev_kfree_skb_any(sc->rx.frag); @@ -1833,6 +1826,9 @@ static u32 fill_chainmask(u32 cap, u32 new) static bool validate_antenna_mask(struct ath_hw *ah, u32 val) { + if (AR_SREV_9300_20_OR_LATER(ah)) + return true; + switch (val & 0x7) { case 0x1: case 0x3: diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d4df98a..90752f2 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -254,8 +254,6 @@ rx_init_fail: static void ath_edma_start_recv(struct ath_softc *sc) { - spin_lock_bh(&sc->rx.rxbuflock); - ath9k_hw_rxena(sc->sc_ah); ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, @@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc) ath_opmode_init(sc); ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); - - spin_unlock_bh(&sc->rx.rxbuflock); } static void ath_edma_stop_recv(struct ath_softc *sc) @@ -285,8 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) int error = 0; spin_lock_init(&sc->sc_pcu_lock); - spin_lock_init(&sc->rx.rxbuflock); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + sc->sc_ah->caps.rx_status_len; @@ -447,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc) return 0; } - spin_lock_bh(&sc->rx.rxbuflock); if (list_empty(&sc->rx.rxbuf)) goto start_recv; @@ -468,26 +461,31 @@ start_recv: ath_opmode_init(sc); ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); - spin_unlock_bh(&sc->rx.rxbuflock); - return 0; } +static void ath_flushrecv(struct ath_softc *sc) +{ + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_rx_tasklet(sc, 1, true); + ath_rx_tasklet(sc, 1, false); +} + bool ath_stoprecv(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; bool stopped, reset = false; - spin_lock_bh(&sc->rx.rxbuflock); ath9k_hw_abortpcurecv(ah); ath9k_hw_setrxfilter(ah, 0); stopped = ath9k_hw_stopdmarecv(ah, &reset); + ath_flushrecv(sc); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ath_edma_stop_recv(sc); else sc->rx.rxlink = NULL; - spin_unlock_bh(&sc->rx.rxbuflock); if (!(ah->ah_flags & AH_UNPLUGGED) && unlikely(!stopped)) { @@ -499,15 +497,6 @@ bool ath_stoprecv(struct ath_softc *sc) return stopped && !reset; } -void ath_flushrecv(struct ath_softc *sc) -{ - set_bit(SC_OP_RXFLUSH, &sc->sc_flags); - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ath_rx_tasklet(sc, 1, true); - ath_rx_tasklet(sc, 1, false); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); -} - static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) { /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ @@ -744,6 +733,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, return NULL; } + list_del(&bf->list); if (!bf->bf_mpdu) return bf; @@ -1059,16 +1049,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) dma_type = DMA_FROM_DEVICE; qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; - spin_lock_bh(&sc->rx.rxbuflock); tsf = ath9k_hw_gettsf64(ah); tsf_lower = tsf & 0xffffffff; do { bool decrypt_error = false; - /* If handling rx interrupt and flush is in progress => exit */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) - break; memset(&rs, 0, sizeof(rs)); if (edma) @@ -1111,15 +1097,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath_debug_stat_rx(sc, &rs); - /* - * If we're asked to flush receive queue, directly - * chain it back at the queue without processing it. - */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { - RX_STAT_INC(rx_drop_rxflush); - goto requeue_drop_frag; - } - memset(rxs, 0, sizeof(struct ieee80211_rx_status)); rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; @@ -1254,19 +1231,18 @@ requeue_drop_frag: sc->rx.frag = NULL; } requeue: + list_add_tail(&bf->list, &sc->rx.rxbuf); + if (flush) + continue; + if (edma) { - list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); } else { - list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); - if (!flush) - ath9k_hw_rxena(ah); + ath9k_hw_rxena(ah); } } while (1); - spin_unlock_bh(&sc->rx.rxbuflock); - if (!(ah->imask & ATH9K_INT_RXEOL)) { ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); ath9k_hw_set_interrupts(ah); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 1fbd8ec..0f71d1d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1407,9 +1407,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) #endif t->ms = ms; t->periodic = (bool) periodic; - t->set = true; - - atomic_inc(&t->wl->callbacks); + if (!t->set) { + t->set = true; + atomic_inc(&t->wl->callbacks); + } ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); } diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7e16d10..90b8970 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) memset(&il->staging, 0, sizeof(il->staging)); - if (!il->vif) { + switch (il->iw_mode) { + case NL80211_IFTYPE_UNSPECIFIED: il->staging.dev_type = RXON_DEV_TYPE_ESS; - } else if (il->vif->type == NL80211_IFTYPE_STATION) { + break; + case NL80211_IFTYPE_STATION: il->staging.dev_type = RXON_DEV_TYPE_ESS; il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { + break; + case NL80211_IFTYPE_ADHOC: il->staging.dev_type = RXON_DEV_TYPE_IBSS; il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - } else { + break; + default: IL_ERR("Unsupported interface type %d\n", il->vif->type); return; } @@ -4550,8 +4554,7 @@ out: EXPORT_SYMBOL(il_mac_add_interface); static void -il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, - bool mode_change) +il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) { lockdep_assert_held(&il->mutex); @@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, il_force_scan_end(il); } - if (!mode_change) - il_set_mode(il); - + il_set_mode(il); } void @@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) WARN_ON(il->vif != vif); il->vif = NULL; - - il_teardown_interface(il, vif, false); + il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; + il_teardown_interface(il, vif); memset(il->bssid, 0, ETH_ALEN); D_MAC80211("leave\n"); @@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } /* success */ - il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - err = il_set_mode(il); - WARN_ON(err); - /* - * We've switched internally, but submitting to the - * device may have failed for some reason. Mask this - * error, because otherwise mac80211 will not switch - * (and set the interface type back) and we'll be - * out of sync with it. - */ + il->iw_mode = newtype; + il_teardown_interface(il, vif); err = 0; out: diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index a790599..31534f7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -1079,6 +1079,8 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, { u16 status = le16_to_cpu(tx_resp->status.status); + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_tx_status_to_mac80211(status); iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index efe525b..cdb11b3 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1459,7 +1459,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, struct cfg80211_ssid req_ssid; int ret, auth_type = 0; struct cfg80211_bss *bss = NULL; - u8 is_scanning_required = 0, config_bands = 0; + u8 is_scanning_required = 0; memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); @@ -1478,19 +1478,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, /* disconnect before try to associate */ mwifiex_deauthenticate(priv, NULL); - if (channel) { - if (mode == NL80211_IFTYPE_STATION) { - if (channel->band == IEEE80211_BAND_2GHZ) - config_bands = BAND_B | BAND_G | BAND_GN; - else - config_bands = BAND_A | BAND_AN; - - if (!((config_bands | priv->adapter->fw_bands) & - ~priv->adapter->fw_bands)) - priv->adapter->config_bands = config_bands; - } - } - /* As this is new association, clear locally stored * keys and security related flags */ priv->sec_info.wpa_enabled = false; @@ -1707,7 +1694,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, if (cfg80211_get_chandef_type(¶ms->chandef) != NL80211_CHAN_NO_HT) - config_bands |= BAND_GN; + config_bands |= BAND_G | BAND_GN; } else { if (cfg80211_get_chandef_type(¶ms->chandef) == NL80211_CHAN_NO_HT) diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 13fbc4e..b879e13 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -161,7 +161,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) if (pdev) { card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || card->adapter) { + if (!card || !card->adapter) { pr_err("Card or adapter structure is not valid\n"); return 0; } diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 60e88b5..f542bb8 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -283,6 +283,20 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, if (ret) goto done; + if (bss_desc) { + u8 config_bands = 0; + + if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) + == HostCmd_SCAN_RADIO_TYPE_BG) + config_bands = BAND_B | BAND_G | BAND_GN; + else + config_bands = BAND_A | BAND_AN; + + if (!((config_bands | adapter->fw_bands) & + ~adapter->fw_bands)) + adapter->config_bands = config_bands; + } + ret = mwifiex_check_network_compatibility(priv, bss_desc); if (ret) goto done; diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index 21b1bbb..b80bc46 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig @@ -57,12 +57,12 @@ config RTL8192CU config RTLWIFI tristate - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE default m config RTLWIFI_DEBUG bool "Additional debugging output" - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE default y config RTL8192C_COMMON diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c31aeb0..efaecef 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -181,7 +181,6 @@ config PINCTRL_COH901 config PINCTRL_SAMSUNG bool - depends on OF && GPIOLIB select PINMUX select PINCONF diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index 69aba36..428ea96 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c @@ -588,7 +588,7 @@ static int dove_pinctrl_probe(struct platform_device *pdev) { const struct of_device_id *match = of_match_device(dove_pinctrl_of_match, &pdev->dev); - pdev->dev.platform_data = match->data; + pdev->dev.platform_data = (void *)match->data; /* * General MPP Configuration Register is part of pdma registers. diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c index f12084e..cdd483d 100644 --- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c +++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c @@ -66,9 +66,9 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = { MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)), MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))), MPP_MODE(6, - MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1, 1)), - MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1, 1)), - MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0, 0))), + MPP_VAR_FUNCTION(0x1, "sysrst", "out", V(1, 1, 1, 1, 1, 1)), + MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1)), + MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0))), MPP_MODE(7, MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)), MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)), @@ -458,7 +458,7 @@ static int kirkwood_pinctrl_probe(struct platform_device *pdev) { const struct of_device_id *match = of_match_device(kirkwood_pinctrl_of_match, &pdev->dev); - pdev->dev.platform_data = match->data; + pdev->dev.platform_data = (void *)match->data; return mvebu_pinctrl_probe(pdev); } diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c index de05b64..1427299 100644 --- a/drivers/pinctrl/pinctrl-exynos5440.c +++ b/drivers/pinctrl/pinctrl-exynos5440.c @@ -599,7 +599,7 @@ static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offse } /* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */ -static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, +static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, struct device_node *cfg_np, unsigned int **pin_list, unsigned int *npins) { @@ -630,7 +630,7 @@ static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, * Parse the information about all the available pin groups and pin functions * from device node of the pin-controller. */ -static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev, +static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev, struct exynos5440_pinctrl_priv_data *priv) { struct device *dev = &pdev->dev; @@ -723,7 +723,7 @@ static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev, } /* register the pinctrl interface with the pinctrl subsystem */ -static int __init exynos5440_pinctrl_register(struct platform_device *pdev, +static int exynos5440_pinctrl_register(struct platform_device *pdev, struct exynos5440_pinctrl_priv_data *priv) { struct device *dev = &pdev->dev; @@ -798,7 +798,7 @@ static int __init exynos5440_pinctrl_register(struct platform_device *pdev, } /* register the gpiolib interface with the gpiolib subsystem */ -static int __init exynos5440_gpiolib_register(struct platform_device *pdev, +static int exynos5440_gpiolib_register(struct platform_device *pdev, struct exynos5440_pinctrl_priv_data *priv) { struct gpio_chip *gc; @@ -831,7 +831,7 @@ static int __init exynos5440_gpiolib_register(struct platform_device *pdev, } /* unregister the gpiolib interface with the gpiolib subsystem */ -static int __init exynos5440_gpiolib_unregister(struct platform_device *pdev, +static int exynos5440_gpiolib_unregister(struct platform_device *pdev, struct exynos5440_pinctrl_priv_data *priv) { int ret = gpiochip_remove(priv->gc); diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c index dd227d2..23af9f1 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/pinctrl-mxs.c @@ -146,7 +146,7 @@ free: static void mxs_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - int i; + u32 i; for (i = 0; i < num_maps; i++) { if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) @@ -203,7 +203,7 @@ static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector, void __iomem *reg; u8 bank, shift; u16 pin; - int i; + u32 i; for (i = 0; i < g->npins; i++) { bank = PINID_TO_BANK(g->pins[i]); @@ -256,7 +256,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev, void __iomem *reg; u8 ma, vol, pull, bank, shift; u16 pin; - int i; + u32 i; ma = CONFIG_TO_MA(config); vol = CONFIG_TO_VOL(config); @@ -345,8 +345,7 @@ static int mxs_pinctrl_parse_group(struct platform_device *pdev, const char *propname = "fsl,pinmux-ids"; char *group; int length = strlen(np->name) + SUFFIX_LEN; - int i; - u32 val; + u32 val, i; group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); if (!group) diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 1bb16ff..5767b18 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -676,7 +676,7 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) } EXPORT_SYMBOL(nmk_gpio_set_mode); -static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) +static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) { int i; u16 reg; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index f6a360b..5c32e88 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -30,7 +30,6 @@ #define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) #define PCS_OFF_DISABLED ~0U -#define PCS_MAX_GPIO_VALUES 2 /** * struct pcs_pingroup - pingroups for a function @@ -78,16 +77,6 @@ struct pcs_function { }; /** - * struct pcs_gpio_range - pinctrl gpio range - * @range: subrange of the GPIO number space - * @gpio_func: gpio function value in the pinmux register - */ -struct pcs_gpio_range { - struct pinctrl_gpio_range range; - int gpio_func; -}; - -/** * struct pcs_data - wrapper for data needed by pinctrl framework * @pa: pindesc array * @cur: index to current element @@ -414,26 +403,9 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, } static int pcs_request_gpio(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, unsigned pin) + struct pinctrl_gpio_range *range, unsigned offset) { - struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); - struct pcs_gpio_range *gpio = NULL; - int end, mux_bytes; - unsigned data; - - gpio = container_of(range, struct pcs_gpio_range, range); - end = range->pin_base + range->npins - 1; - if (pin < range->pin_base || pin > end) { - dev_err(pctldev->dev, - "pin %d isn't in the range of %d to %d\n", - pin, range->pin_base, end); - return -EINVAL; - } - mux_bytes = pcs->width / BITS_PER_BYTE; - data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask; - data |= gpio->gpio_func; - pcs->write(data, pcs->base + pin * mux_bytes); - return 0; + return -ENOTSUPP; } static struct pinmux_ops pcs_pinmux_ops = { @@ -907,49 +879,6 @@ static void pcs_free_resources(struct pcs_device *pcs) static struct of_device_id pcs_of_match[]; -static int pcs_add_gpio_range(struct device_node *node, struct pcs_device *pcs) -{ - struct pcs_gpio_range *gpio; - struct device_node *child; - struct resource r; - const char name[] = "pinctrl-single"; - u32 gpiores[PCS_MAX_GPIO_VALUES]; - int ret, i = 0, mux_bytes = 0; - - for_each_child_of_node(node, child) { - ret = of_address_to_resource(child, 0, &r); - if (ret < 0) - continue; - memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES); - ret = of_property_read_u32_array(child, "pinctrl-single,gpio", - gpiores, PCS_MAX_GPIO_VALUES); - if (ret < 0) - continue; - gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL); - if (!gpio) { - dev_err(pcs->dev, "failed to allocate pcs gpio\n"); - return -ENOMEM; - } - gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name), - GFP_KERNEL); - if (!gpio->range.name) { - dev_err(pcs->dev, "failed to allocate range name\n"); - return -ENOMEM; - } - memcpy((char *)gpio->range.name, name, sizeof(name)); - - gpio->range.id = i++; - gpio->range.base = gpiores[0]; - gpio->gpio_func = gpiores[1]; - mux_bytes = pcs->width / BITS_PER_BYTE; - gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; - gpio->range.npins = (r.end - r.start) / mux_bytes + 1; - - pinctrl_add_gpio_range(pcs->pctl, &gpio->range); - } - return 0; -} - static int pcs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1046,10 +975,6 @@ static int pcs_probe(struct platform_device *pdev) goto free; } - ret = pcs_add_gpio_range(np, pcs); - if (ret < 0) - goto free; - dev_info(pcs->dev, "%i pins at pa %p size %u\n", pcs->desc.npins, pcs->base, pcs->size); diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 7481146..97c2be1 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c @@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) { if (force) pr_warn("module loaded by force\n"); /* first ensure that we are running on IBM HW */ - else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table)) + else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table)) return -ENODEV; /* Get the address for the Extended BIOS Data Area */ diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index 71623a2..d1f03005 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,6 +26,7 @@ #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/ctype.h> +#include <linux/efi.h> #include <acpi/video.h> /* @@ -1544,6 +1545,9 @@ static int __init samsung_init(void) struct samsung_laptop *samsung; int ret; + if (efi_enabled(EFI_BOOT)) + return -ENODEV; + quirks = &samsung_unknown; if (!force && !dmi_check_system(samsung_dmi_table)) return -ENODEV; diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index 261f3d2..89bd2fa 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -14,6 +14,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/slab.h> +#include <linux/module.h> #include "dbx500-prcmu.h" diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c index b15d711..9019d0e 100644 --- a/drivers/regulator/tps80031-regulator.c +++ b/drivers/regulator/tps80031-regulator.c @@ -728,7 +728,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev) } } rdev = regulator_register(&ri->rinfo->desc, &config); - if (IS_ERR_OR_NULL(rdev)) { + if (IS_ERR(rdev)) { dev_err(&pdev->dev, "register regulator failed %s\n", ri->rinfo->desc.name); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 923a9da..20354b4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1023,7 +1023,7 @@ config RTC_DRV_TX4939 config RTC_DRV_MV tristate "Marvell SoC RTC" - depends on ARCH_KIRKWOOD || ARCH_DOVE + depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU help If you say yes here you will get support for the in-chip RTC that can be found in some of Marvell's SoC devices, such as diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index d73fdcf..2839baa 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -633,7 +633,7 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; pci_set_drvdata(pdev, pci_info); - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) orom = isci_get_efi_var(pdev); if (!orom) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 448a8cc..e5dce91 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -34,7 +34,7 @@ #include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi-tegra.h> -#include <mach/clk.h> +#include <linux/clk/tegra.h> #define SPI_COMMAND 0x000 #define SPI_GO BIT(30) @@ -525,7 +525,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) goto exit_free_master; } - tsd->clk = devm_clk_get(&pdev->dev, "spi"); + tsd->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tsd->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tsd->clk); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 651167f..e255e7a 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -35,7 +35,7 @@ #include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi-tegra.h> -#include <mach/clk.h> +#include <linux/clk/tegra.h> #define SLINK_COMMAND 0x000 #define SLINK_BIT_LENGTH(x) (((x) & 0x1f) << 0) @@ -1191,7 +1191,7 @@ static int tegra_slink_probe(struct platform_device *pdev) goto exit_free_master; } - tspi->clk = devm_clk_get(&pdev->dev, "slink"); + tspi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); diff --git a/drivers/staging/nvec/TODO b/drivers/staging/nvec/TODO index f950ab8..e5ae42a 100644 --- a/drivers/staging/nvec/TODO +++ b/drivers/staging/nvec/TODO @@ -1,9 +1,5 @@ ToDo list (incomplete, unordered) - add compile as module support - - fix clk usage - should not be using clk_get_sys(), but clk_get(&pdev->dev, conn) - where conn is either NULL if the device only has one clock, or - the device specific name if it has multiple clocks. - move half of the nvec init stuff to i2c-tegra.c - move event handling to nvec_events - finish suspend/resume support diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 2830946..9417941 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -37,8 +37,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/workqueue.h> - -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include "nvec.h" @@ -771,7 +770,7 @@ static int tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } - i2c_clk = clk_get_sys("tegra-i2c.2", "div-clk"); + i2c_clk = clk_get(&pdev->dev, "div-clk"); if (IS_ERR(i2c_clk)) { dev_err(nvec->dev, "failed to get controller clock\n"); return -ENODEV; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index acf1755..568aecc 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -2,7 +2,7 @@ * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2009 NVIDIA Corporation + * Copyright (C) 2009 - 2013 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,23 +26,28 @@ #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> - +#include <linux/usb/ehci_def.h> #include <linux/usb/tegra_usb_phy.h> #define TEGRA_USB_BASE 0xC5000000 #define TEGRA_USB2_BASE 0xC5004000 #define TEGRA_USB3_BASE 0xC5008000 +/* PORTSC registers */ +#define TEGRA_USB_PORTSC1 0x184 +#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) +#define TEGRA_USB_PORTSC1_PHCD (1 << 23) + #define TEGRA_USB_DMA_ALIGN 32 struct tegra_ehci_hcd { struct ehci_hcd *ehci; struct tegra_usb_phy *phy; struct clk *clk; - struct clk *emc_clk; struct usb_phy *transceiver; int host_resumed; int port_resuming; + bool needs_double_reset; enum tegra_usb_phy_port_speed port_speed; }; @@ -50,9 +55,8 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - clk_prepare_enable(tegra->emc_clk); clk_prepare_enable(tegra->clk); - usb_phy_set_suspend(&tegra->phy->u_phy, 0); + usb_phy_set_suspend(hcd->phy, 0); tegra->host_resumed = 1; } @@ -61,9 +65,8 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd) struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); tegra->host_resumed = 0; - usb_phy_set_suspend(&tegra->phy->u_phy, 1); + usb_phy_set_suspend(hcd->phy, 1); clk_disable_unprepare(tegra->clk); - clk_disable_unprepare(tegra->emc_clk); } static int tegra_ehci_internal_port_reset( @@ -156,7 +159,7 @@ static int tegra_ehci_hub_control( if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ tegra->port_resuming = 0; - tegra_usb_phy_postresume(tegra->phy); + tegra_usb_phy_postresume(hcd->phy); } } @@ -184,7 +187,7 @@ static int tegra_ehci_hub_control( } /* For USB1 port we need to issue Port Reset twice internally */ - if (tegra->phy->instance == 0 && + if (tegra->needs_double_reset && (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { spin_unlock_irqrestore(&ehci->lock, flags); return tegra_ehci_internal_port_reset(ehci, status_reg); @@ -209,7 +212,7 @@ static int tegra_ehci_hub_control( goto done; /* Disable disconnect detection during port resume */ - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(hcd->phy); ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); @@ -473,7 +476,7 @@ static int controller_resume(struct device *dev) } /* Force the phy to keep data lines in suspend state */ - tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); + tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed); /* Enable host mode */ tdi_reset(ehci); @@ -540,17 +543,17 @@ static int controller_resume(struct device *dev) } } - tegra_ehci_phy_restore_end(tegra->phy); + tegra_ehci_phy_restore_end(hcd->phy); goto done; restart: if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) - tegra_ehci_phy_restore_end(tegra->phy); + tegra_ehci_phy_restore_end(hcd->phy); tegra_ehci_restart(hcd); done: - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(hcd->phy); tegra->port_resuming = 1; return 0; } @@ -604,6 +607,37 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = { #endif +/* Bits of PORTSC1, which will get cleared by writing 1 into them */ +#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) + +void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) +{ + unsigned long val; + struct usb_hcd *hcd = bus_to_hcd(x->otg->host); + void __iomem *base = hcd->regs; + + val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; + val &= ~TEGRA_USB_PORTSC1_PTS(3); + val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); + writel(val, base + TEGRA_USB_PORTSC1); +} +EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); + +void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) +{ + unsigned long val; + struct usb_hcd *hcd = bus_to_hcd(x->otg->host); + void __iomem *base = hcd->regs; + + val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; + if (enable) + val |= TEGRA_USB_PORTSC1_PHCD; + else + val &= ~TEGRA_USB_PORTSC1_PHCD; + writel(val, base + TEGRA_USB_PORTSC1); +} +EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); + static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); static int tegra_ehci_probe(struct platform_device *pdev) @@ -615,6 +649,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) int err = 0; int irq; int instance = pdev->id; + struct usb_phy *u_phy; pdata = pdev->dev.platform_data; if (!pdata) { @@ -656,15 +691,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (err) goto fail_clk; - tegra->emc_clk = devm_clk_get(&pdev->dev, "emc"); - if (IS_ERR(tegra->emc_clk)) { - dev_err(&pdev->dev, "Can't get emc clock\n"); - err = PTR_ERR(tegra->emc_clk); - goto fail_emc_clk; - } - - clk_prepare_enable(tegra->emc_clk); - clk_set_rate(tegra->emc_clk, 400000000); + tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, + "nvidia,needs-double-reset"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -712,9 +740,19 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail_io; } - usb_phy_init(&tegra->phy->u_phy); + hcd->phy = u_phy = &tegra->phy->u_phy; + usb_phy_init(hcd->phy); + + u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), + GFP_KERNEL); + if (!u_phy->otg) { + dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); + err = -ENOMEM; + goto fail_io; + } + u_phy->otg->host = hcd_to_bus(hcd); - err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); + err = usb_phy_set_suspend(hcd->phy, 0); if (err) { dev_err(&pdev->dev, "Failed to power on the phy\n"); goto fail; @@ -760,10 +798,8 @@ fail: if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); #endif - usb_phy_shutdown(&tegra->phy->u_phy); + usb_phy_shutdown(hcd->phy); fail_io: - clk_disable_unprepare(tegra->emc_clk); -fail_emc_clk: clk_disable_unprepare(tegra->clk); fail_clk: usb_put_hcd(hcd); @@ -784,15 +820,12 @@ static int tegra_ehci_remove(struct platform_device *pdev) otg_set_host(tegra->transceiver->otg, NULL); #endif + usb_phy_shutdown(hcd->phy); usb_remove_hcd(hcd); usb_put_hcd(hcd); - usb_phy_shutdown(&tegra->phy->u_phy); - clk_disable_unprepare(tegra->clk); - clk_disable_unprepare(tegra->emc_clk); - return 0; } diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c index 9d13c81..5487d38 100644 --- a/drivers/usb/phy/tegra_usb_phy.c +++ b/drivers/usb/phy/tegra_usb_phy.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/usb/otg.h> #include <linux/usb/ulpi.h> @@ -35,19 +36,6 @@ #define ULPI_VIEWPORT 0x170 -#define USB_PORTSC1 0x184 -#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) -#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) -#define USB_PORTSC1_PHCD (1 << 23) -#define USB_PORTSC1_WKOC (1 << 22) -#define USB_PORTSC1_WKDS (1 << 21) -#define USB_PORTSC1_WKCN (1 << 20) -#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) -#define USB_PORTSC1_PP (1 << 12) -#define USB_PORTSC1_SUSP (1 << 7) -#define USB_PORTSC1_PE (1 << 2) -#define USB_PORTSC1_CCS (1 << 0) - #define USB_SUSP_CTRL 0x400 #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) @@ -208,11 +196,6 @@ static struct tegra_utmip_config utmip_default[] = { }, }; -static inline bool phy_is_ulpi(struct tegra_usb_phy *phy) -{ - return (phy->instance == 1); -} - static int utmip_pad_open(struct tegra_usb_phy *phy) { phy->pad_clk = clk_get_sys("utmip-pad", NULL); @@ -221,7 +204,7 @@ static int utmip_pad_open(struct tegra_usb_phy *phy) return PTR_ERR(phy->pad_clk); } - if (phy->instance == 0) { + if (phy->is_legacy_phy) { phy->pad_regs = phy->regs; } else { phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); @@ -236,7 +219,7 @@ static int utmip_pad_open(struct tegra_usb_phy *phy) static void utmip_pad_close(struct tegra_usb_phy *phy) { - if (phy->instance != 0) + if (!phy->is_legacy_phy) iounmap(phy->pad_regs); clk_put(phy->pad_clk); } @@ -305,7 +288,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; - if (phy->instance == 0) { + if (phy->is_legacy_phy) { val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_SET; writel(val, base + USB_SUSP_CTRL); @@ -315,13 +298,8 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) val = readl(base + USB_SUSP_CTRL); val &= ~USB_SUSP_SET; writel(val, base + USB_SUSP_CTRL); - } - - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val |= USB_PORTSC1_PHCD; - writel(val, base + USB_PORTSC1); - } + } else + tegra_ehci_set_phcd(&phy->u_phy, true); if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) pr_err("%s: timeout waiting for phy to stabilize\n", __func__); @@ -332,7 +310,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; - if (phy->instance == 0) { + if (phy->is_legacy_phy) { val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_CLR; writel(val, base + USB_SUSP_CTRL); @@ -342,13 +320,8 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) val = readl(base + USB_SUSP_CTRL); val &= ~USB_SUSP_CLR; writel(val, base + USB_SUSP_CTRL); - } - - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val &= ~USB_PORTSC1_PHCD; - writel(val, base + USB_PORTSC1); - } + } else + tegra_ehci_set_phcd(&phy->u_phy, false); if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, USB_PHY_CLK_VALID)) @@ -365,7 +338,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val |= UTMIP_RESET; writel(val, base + USB_SUSP_CTRL); - if (phy->instance == 0) { + if (phy->is_legacy_phy) { val = readl(base + USB1_LEGACY_CTRL); val |= USB1_NO_LEGACY_MODE; writel(val, base + USB1_LEGACY_CTRL); @@ -440,16 +413,14 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val |= UTMIP_BIAS_PDTRK_COUNT(0x5); writel(val, base + UTMIP_BIAS_CFG1); - if (phy->instance == 0) { + if (phy->is_legacy_phy) { val = readl(base + UTMIP_SPARE_CFG0); if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) val &= ~FUSE_SETUP_SEL; else val |= FUSE_SETUP_SEL; writel(val, base + UTMIP_SPARE_CFG0); - } - - if (phy->instance == 2) { + } else { val = readl(base + USB_SUSP_CTRL); val |= UTMIP_PHY_ENABLE; writel(val, base + USB_SUSP_CTRL); @@ -459,7 +430,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val &= ~UTMIP_RESET; writel(val, base + USB_SUSP_CTRL); - if (phy->instance == 0) { + if (phy->is_legacy_phy) { val = readl(base + USB1_LEGACY_CTRL); val &= ~USB1_VBUS_SENSE_CTL_MASK; val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; @@ -472,11 +443,8 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) utmi_phy_clk_enable(phy); - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val &= ~USB_PORTSC1_PTS(~0); - writel(val, base + USB_PORTSC1); - } + if (!phy->is_legacy_phy) + tegra_ehci_set_pts(&phy->u_phy, 0); return 0; } @@ -621,10 +589,6 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) return ret; } - val = readl(base + USB_PORTSC1); - val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; - writel(val, base + USB_PORTSC1); - val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_CLR; writel(val, base + USB_SUSP_CTRL); @@ -639,17 +603,8 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) static int ulpi_phy_power_off(struct tegra_usb_phy *phy) { - unsigned long val; - void __iomem *base = phy->regs; struct tegra_ulpi_config *config = phy->config; - /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB - * Controller to immediately bring the ULPI PHY out of low power - */ - val = readl(base + USB_PORTSC1); - val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN); - writel(val, base + USB_PORTSC1); - clk_disable(phy->clk); return gpio_direction_output(config->reset_gpio, 0); } @@ -660,7 +615,7 @@ static int tegra_phy_init(struct usb_phy *x) struct tegra_ulpi_config *ulpi_config; int err; - if (phy_is_ulpi(phy)) { + if (phy->is_ulpi_phy) { ulpi_config = phy->config; phy->clk = clk_get_sys(NULL, ulpi_config->clk); if (IS_ERR(phy->clk)) { @@ -698,7 +653,7 @@ static void tegra_usb_phy_close(struct usb_phy *x) { struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); - if (phy_is_ulpi(phy)) + if (phy->is_ulpi_phy) clk_put(phy->clk); else utmip_pad_close(phy); @@ -709,7 +664,7 @@ static void tegra_usb_phy_close(struct usb_phy *x) static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) { - if (phy_is_ulpi(phy)) + if (phy->is_ulpi_phy) return ulpi_phy_power_on(phy); else return utmi_phy_power_on(phy); @@ -717,7 +672,7 @@ static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) { - if (phy_is_ulpi(phy)) + if (phy->is_ulpi_phy) return ulpi_phy_power_off(phy); else return utmi_phy_power_off(phy); @@ -739,8 +694,9 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, unsigned long parent_rate; int i; int err; + struct device_node *np = dev->of_node; - phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); + phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); if (!phy) return ERR_PTR(-ENOMEM); @@ -749,9 +705,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, phy->config = config; phy->mode = phy_mode; phy->dev = dev; + phy->is_legacy_phy = + of_property_read_bool(np, "nvidia,has-legacy-mode"); + err = of_property_match_string(np, "phy_type", "ulpi"); + if (err < 0) + phy->is_ulpi_phy = false; + else + phy->is_ulpi_phy = true; if (!phy->config) { - if (phy_is_ulpi(phy)) { + if (phy->is_ulpi_phy) { pr_err("%s: ulpi phy configuration missing", __func__); err = -EINVAL; goto err0; @@ -796,45 +759,40 @@ err0: } EXPORT_SYMBOL_GPL(tegra_usb_phy_open); -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) +void tegra_usb_phy_preresume(struct usb_phy *x) { - if (!phy_is_ulpi(phy)) + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + + if (!phy->is_ulpi_phy) utmi_phy_preresume(phy); } EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) +void tegra_usb_phy_postresume(struct usb_phy *x) { - if (!phy_is_ulpi(phy)) + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + + if (!phy->is_ulpi_phy) utmi_phy_postresume(phy); } EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); -void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, +void tegra_ehci_phy_restore_start(struct usb_phy *x, enum tegra_usb_phy_port_speed port_speed) { - if (!phy_is_ulpi(phy)) + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + + if (!phy->is_ulpi_phy) utmi_phy_restore_start(phy, port_speed); } EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); -void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) +void tegra_ehci_phy_restore_end(struct usb_phy *x) { - if (!phy_is_ulpi(phy)) + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + + if (!phy->is_ulpi_phy) utmi_phy_restore_end(phy); } EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); -void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_clk_disable(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable); - -void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_clk_enable(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable); diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index b906ed1..9802de0 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -281,6 +281,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_sbd; struct lm_lockstruct *ls = &sdp->sd_lockstruct; + int lvb_needs_unlock = 0; int error; if (gl->gl_lksb.sb_lkid == 0) { @@ -294,8 +295,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl) gfs2_update_request_times(gl); /* don't want to skip dlm_unlock writing the lvb when lock is ex */ + + if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE)) + lvb_needs_unlock = 1; + if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && - gl->gl_lksb.sb_lvbptr && (gl->gl_state != LM_ST_EXCLUSIVE)) { + !lvb_needs_unlock) { gfs2_glock_free(gl); return; } diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index dd057bc..fc8dc20 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -177,11 +177,31 @@ out_nofree: return mnt; } +static int +nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_getattr(mnt, dentry, stat); + generic_fillattr(dentry->d_inode, stat); + return 0; +} + +static int +nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_setattr(dentry, attr); + return -EACCES; +} + const struct inode_operations nfs_mountpoint_inode_operations = { .getattr = nfs_getattr, + .setattr = nfs_setattr, }; const struct inode_operations nfs_referral_inode_operations = { + .getattr = nfs_namespace_getattr, + .setattr = nfs_namespace_setattr, }; static void nfs_expire_automounts(struct work_struct *work) diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index acc3472..2e9779b 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -236,11 +236,10 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, error = nfs4_discover_server_trunking(clp, &old); if (error < 0) goto error; + nfs_put_client(clp); if (clp != old) { clp->cl_preserve_clid = true; - nfs_put_client(clp); clp = old; - atomic_inc(&clp->cl_count); } return clp; @@ -306,7 +305,7 @@ int nfs40_walk_client_list(struct nfs_client *new, .clientid = new->cl_clientid, .confirm = new->cl_confirm, }; - int status; + int status = -NFS4ERR_STALE_CLIENTID; spin_lock(&nn->nfs_client_lock); list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { @@ -332,40 +331,33 @@ int nfs40_walk_client_list(struct nfs_client *new, if (prev) nfs_put_client(prev); + prev = pos; status = nfs4_proc_setclientid_confirm(pos, &clid, cred); - if (status == 0) { + switch (status) { + case -NFS4ERR_STALE_CLIENTID: + break; + case 0: nfs4_swap_callback_idents(pos, new); - nfs_put_client(pos); + prev = NULL; *result = pos; dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", __func__, pos, atomic_read(&pos->cl_count)); - return 0; - } - if (status != -NFS4ERR_STALE_CLIENTID) { - nfs_put_client(pos); - dprintk("NFS: <-- %s status = %d, no result\n", - __func__, status); - return status; + default: + goto out; } spin_lock(&nn->nfs_client_lock); - prev = pos; } + spin_unlock(&nn->nfs_client_lock); - /* - * No matching nfs_client found. This should be impossible, - * because the new nfs_client has already been added to - * nfs_client_list by nfs_get_client(). - * - * Don't BUG(), since the caller is holding a mutex. - */ + /* No match found. The server lost our clientid */ +out: if (prev) nfs_put_client(prev); - spin_unlock(&nn->nfs_client_lock); - pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); - return -NFS4ERR_STALE_CLIENTID; + dprintk("NFS: <-- %s status = %d\n", __func__, status); + return status; } #ifdef CONFIG_NFS_V4_1 @@ -432,7 +424,7 @@ int nfs41_walk_client_list(struct nfs_client *new, { struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); struct nfs_client *pos, *n, *prev = NULL; - int error; + int status = -NFS4ERR_STALE_CLIENTID; spin_lock(&nn->nfs_client_lock); list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { @@ -448,14 +440,17 @@ int nfs41_walk_client_list(struct nfs_client *new, nfs_put_client(prev); prev = pos; - error = nfs_wait_client_init_complete(pos); - if (error < 0) { + nfs4_schedule_lease_recovery(pos); + status = nfs_wait_client_init_complete(pos); + if (status < 0) { nfs_put_client(pos); spin_lock(&nn->nfs_client_lock); continue; } - + status = pos->cl_cons_state; spin_lock(&nn->nfs_client_lock); + if (status < 0) + continue; } if (pos->rpc_ops != new->rpc_ops) @@ -473,6 +468,7 @@ int nfs41_walk_client_list(struct nfs_client *new, if (!nfs4_match_serverowners(pos, new)) continue; + atomic_inc(&pos->cl_count); spin_unlock(&nn->nfs_client_lock); dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", __func__, pos, atomic_read(&pos->cl_count)); @@ -481,16 +477,10 @@ int nfs41_walk_client_list(struct nfs_client *new, return 0; } - /* - * No matching nfs_client found. This should be impossible, - * because the new nfs_client has already been added to - * nfs_client_list by nfs_get_client(). - * - * Don't BUG(), since the caller is holding a mutex. - */ + /* No matching nfs_client found. */ spin_unlock(&nn->nfs_client_lock); - pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); - return -NFS4ERR_STALE_CLIENTID; + dprintk("NFS: <-- %s status = %d\n", __func__, status); + return status; } #endif /* CONFIG_NFS_V4_1 */ diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 9448c57..e61f68d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -136,16 +136,11 @@ int nfs40_discover_server_trunking(struct nfs_client *clp, clp->cl_confirm = clid.confirm; status = nfs40_walk_client_list(clp, result, cred); - switch (status) { - case -NFS4ERR_STALE_CLIENTID: - set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); - case 0: + if (status == 0) { /* Sustain the lease, even if it's empty. If the clientid4 * goes stale it's of no use for trunking discovery. */ nfs4_schedule_state_renewal(*result); - break; } - out: return status; } @@ -1863,6 +1858,7 @@ again: case -ETIMEDOUT: case -EAGAIN: ssleep(1); + case -NFS4ERR_STALE_CLIENTID: dprintk("NFS: %s after status %d, retrying\n", __func__, status); goto again; @@ -2022,8 +2018,18 @@ static int nfs4_reset_session(struct nfs_client *clp) nfs4_begin_drain_session(clp); cred = nfs4_get_exchange_id_cred(clp); status = nfs4_proc_destroy_session(clp->cl_session, cred); - if (status && status != -NFS4ERR_BADSESSION && - status != -NFS4ERR_DEADSESSION) { + switch (status) { + case 0: + case -NFS4ERR_BADSESSION: + case -NFS4ERR_DEADSESSION: + break; + case -NFS4ERR_BACK_CHAN_BUSY: + case -NFS4ERR_DELAY: + set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); + status = 0; + ssleep(1); + goto out; + default: status = nfs4_recovery_handle_error(clp, status); goto out; } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2e7e8c8..b056b16 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2589,27 +2589,23 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, struct nfs_server *server; struct dentry *mntroot = ERR_PTR(-ENOMEM); struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod; - int error; - dprintk("--> nfs_xdev_mount_common()\n"); + dprintk("--> nfs_xdev_mount()\n"); mount_info.mntfh = mount_info.cloned->fh; /* create a new volume representation */ server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err; - } - mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod); - dprintk("<-- nfs_xdev_mount_common() = 0\n"); -out: - return mntroot; + if (IS_ERR(server)) + mntroot = ERR_CAST(server); + else + mntroot = nfs_fs_mount_common(server, flags, + dev_name, &mount_info, nfs_mod); -out_err: - dprintk("<-- nfs_xdev_mount_common() = %d [error]\n", error); - goto out; + dprintk("<-- nfs_xdev_mount() = %ld\n", + IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L); + return mntroot; } #if IS_ENABLED(CONFIG_NFS_V4) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 4111a40..5f707e5 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -86,11 +86,11 @@ xfs_destroy_ioend( } if (ioend->io_iocb) { + inode_dio_done(ioend->io_inode); if (ioend->io_isasync) { aio_complete(ioend->io_iocb, ioend->io_error ? ioend->io_error : ioend->io_result, 0); } - inode_dio_done(ioend->io_inode); } mempool_free(ioend, xfs_ioend_pool); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 0e92d12..cdb2d33 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4680,9 +4680,6 @@ __xfs_bmapi_allocate( return error; } - if (bma->flags & XFS_BMAPI_STACK_SWITCH) - bma->stack_switch = 1; - error = xfs_bmap_alloc(bma); if (error) return error; @@ -4956,6 +4953,9 @@ xfs_bmapi_write( bma.flist = flist; bma.firstblock = firstblock; + if (flags & XFS_BMAPI_STACK_SWITCH) + bma.stack_switch = 1; + while (bno < end && n < *nmap) { inhole = eof || bma.got.br_startoff > bno; wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 56d1614..fbbb9eb 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -487,6 +487,7 @@ _xfs_buf_find( struct rb_node *parent; xfs_buf_t *bp; xfs_daddr_t blkno = map[0].bm_bn; + xfs_daddr_t eofs; int numblks = 0; int i; @@ -498,6 +499,23 @@ _xfs_buf_find( ASSERT(!(numbytes < (1 << btp->bt_sshift))); ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask)); + /* + * Corrupted block numbers can get through to here, unfortunately, so we + * have to check that the buffer falls within the filesystem bounds. + */ + eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks); + if (blkno >= eofs) { + /* + * XXX (dgc): we should really be returning EFSCORRUPTED here, + * but none of the higher level infrastructure supports + * returning a specific error on buffer lookup failures. + */ + xfs_alert(btp->bt_mount, + "%s: Block out of range: block 0x%llx, EOFS 0x%llx ", + __func__, blkno, eofs); + return NULL; + } + /* get tree root */ pag = xfs_perag_get(btp->bt_mount, xfs_daddr_to_agno(btp->bt_mount, blkno)); @@ -1487,6 +1505,8 @@ restart: while (!list_empty(&btp->bt_lru)) { bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru); if (atomic_read(&bp->b_hold) > 1) { + trace_xfs_buf_wait_buftarg(bp, _RET_IP_); + list_move_tail(&bp->b_lru, &btp->bt_lru); spin_unlock(&btp->bt_lru_lock); delay(100); goto restart; diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 77b0975..3f9949f 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -652,7 +652,10 @@ xfs_buf_item_unlock( /* * If the buf item isn't tracking any data, free it, otherwise drop the - * reference we hold to it. + * reference we hold to it. If we are aborting the transaction, this may + * be the only reference to the buf item, so we free it anyway + * regardless of whether it is dirty or not. A dirty abort implies a + * shutdown, anyway. */ clean = 1; for (i = 0; i < bip->bli_format_count; i++) { @@ -664,7 +667,12 @@ xfs_buf_item_unlock( } if (clean) xfs_buf_item_relse(bp); - else + else if (aborted) { + if (atomic_dec_and_test(&bip->bli_refcount)) { + ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); + xfs_buf_item_relse(bp); + } + } else atomic_dec(&bip->bli_refcount); if (!hold) diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index d0e9c74..a8bd26b 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -246,10 +246,10 @@ xfs_swap_extents( goto out_unlock; } - error = -filemap_write_and_wait(VFS_I(ip)->i_mapping); + error = -filemap_write_and_wait(VFS_I(tip)->i_mapping); if (error) goto out_unlock; - truncate_pagecache_range(VFS_I(ip), 0, -1); + truncate_pagecache_range(VFS_I(tip), 0, -1); /* Verify O_DIRECT for ftmp */ if (VN_CACHED(VFS_I(tip)) != 0) { diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index add06b4..364818e 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -351,6 +351,15 @@ xfs_iomap_prealloc_size( } if (shift) alloc_blocks >>= shift; + + /* + * If we are still trying to allocate more space than is + * available, squash the prealloc hard. This can happen if we + * have a large file on a small filesystem and the above + * lowspace thresholds are smaller than MAXEXTLEN. + */ + while (alloc_blocks >= freesp) + alloc_blocks >>= 4; } if (alloc_blocks < mp->m_writeio_blocks) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index da50846..7d6df7c 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -658,7 +658,7 @@ xfs_sb_quiet_read_verify( return; } /* quietly fail */ - xfs_buf_ioerror(bp, EFSCORRUPTED); + xfs_buf_ioerror(bp, EWRONGFS); } static void diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 2e137d4..16a8129 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -341,6 +341,7 @@ DEFINE_BUF_EVENT(xfs_buf_item_relse); DEFINE_BUF_EVENT(xfs_buf_item_iodone); DEFINE_BUF_EVENT(xfs_buf_item_iodone_async); DEFINE_BUF_EVENT(xfs_buf_error_relse); +DEFINE_BUF_EVENT(xfs_buf_wait_buftarg); DEFINE_BUF_EVENT(xfs_trans_read_buf_io); DEFINE_BUF_EVENT(xfs_trans_read_buf_shut); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index d1ea7ce..fc62ac5 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -149,6 +149,24 @@ #define TRACE_SYSCALLS() #endif +#ifdef CONFIG_CLKSRC_OF +#define CLKSRC_OF_TABLES() . = ALIGN(8); \ + VMLINUX_SYMBOL(__clksrc_of_table) = .; \ + *(__clksrc_of_table) \ + *(__clksrc_of_table_end) +#else +#define CLKSRC_OF_TABLES() +#endif + +#ifdef CONFIG_IRQCHIP +#define IRQCHIP_OF_MATCH_TABLE() \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__irqchip_begin) = .; \ + *(__irqchip_of_table) \ + *(__irqchip_of_end) +#else +#define IRQCHIP_OF_MATCH_TABLE() +#endif #define KERNEL_DTB() \ STRUCT_ALIGN(); \ @@ -493,7 +511,9 @@ DEV_DISCARD(init.rodata) \ CPU_DISCARD(init.rodata) \ MEM_DISCARD(init.rodata) \ - KERNEL_DTB() + CLKSRC_OF_TABLES() \ + KERNEL_DTB() \ + IRQCHIP_OF_MATCH_TABLE() #define INIT_TEXT \ *(.init.text) \ diff --git a/include/linux/bcm2835_timer.h b/include/linux/bcm2835_timer.h index 25680fe..ca17aa8 100644 --- a/include/linux/bcm2835_timer.h +++ b/include/linux/bcm2835_timer.h @@ -17,6 +17,6 @@ #include <asm/mach/time.h> -extern struct sys_timer bcm2835_timer; +extern void bcm2835_timer_init(void); #endif diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/include/linux/clk/tegra.h index 9764d31..404d6f9 100644 --- a/arch/arm/mach-tegra/tegra_cpu_car.h +++ b/include/linux/clk/tegra.h @@ -14,8 +14,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __MACH_TEGRA_CPU_CAR_H -#define __MACH_TEGRA_CPU_CAR_H +#ifndef __LINUX_CLK_TEGRA_H_ +#define __LINUX_CLK_TEGRA_H_ + +#include <linux/clk.h> /* * Tegra CPU clock and reset control ops @@ -118,7 +120,8 @@ static inline void tegra_cpu_clock_resume(void) } #endif -void tegra20_cpu_car_ops_init(void); -void tegra30_cpu_car_ops_init(void); +void tegra_periph_reset_deassert(struct clk *c); +void tegra_periph_reset_assert(struct clk *c); +void tegra_clocks_init(void); -#endif /* __MACH_TEGRA_CPU_CAR_H */ +#endif /* __LINUX_CLK_TEGRA_H_ */ diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 4dceaf8..7944f14 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -332,4 +332,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *, extern int clocksource_i8253_init(void); +#ifdef CONFIG_CLKSRC_OF +extern void clocksource_of_init(void); + +#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \ + static const struct of_device_id __clksrc_of_table_##name \ + __used __section(__clksrc_of_table) \ + = { .compatible = compat, .data = fn }; +#endif + #endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h index 1148575..dd755ce 100644 --- a/include/linux/dw_apb_timer.h +++ b/include/linux/dw_apb_timer.h @@ -53,5 +53,5 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs); cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs); void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs); -extern struct sys_timer dw_apb_timer; +extern void dw_apb_timer_init(void); #endif /* __DW_APB_TIMER_H__ */ diff --git a/include/linux/efi.h b/include/linux/efi.h index 8b84916..7a9498a 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -618,18 +618,30 @@ extern int __init efi_setup_pcdp_console(char *); #endif /* - * We play games with efi_enabled so that the compiler will, if possible, remove - * EFI-related code altogether. + * We play games with efi_enabled so that the compiler will, if + * possible, remove EFI-related code altogether. */ +#define EFI_BOOT 0 /* Were we booted from EFI? */ +#define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */ +#define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ +#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ +#define EFI_MEMMAP 4 /* Can we use EFI memory map? */ +#define EFI_64BIT 5 /* Is the firmware 64-bit? */ + #ifdef CONFIG_EFI # ifdef CONFIG_X86 - extern int efi_enabled; - extern bool efi_64bit; +extern int efi_enabled(int facility); # else -# define efi_enabled 1 +static inline int efi_enabled(int facility) +{ + return 1; +} # endif #else -# define efi_enabled 0 +static inline int efi_enabled(int facility) +{ + return 0; +} #endif /* diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h new file mode 100644 index 0000000..e0006f1 --- /dev/null +++ b/include/linux/irqchip.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 Thomas Petazzoni + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _LINUX_IRQCHIP_H +#define _LINUX_IRQCHIP_H + +void irqchip_init(void); + +#endif diff --git a/arch/arm/include/asm/hardware/gic.h b/include/linux/irqchip/arm-gic.h index 4b1ce6c..a67ca55 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -1,5 +1,5 @@ /* - * arch/arm/include/asm/hardware/gic.h + * include/linux/irqchip/arm-gic.h * * Copyright (C) 2002 ARM Limited, All Rights Reserved. * @@ -7,10 +7,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef __ASM_ARM_HARDWARE_GIC_H -#define __ASM_ARM_HARDWARE_GIC_H - -#include <linux/compiler.h> +#ifndef __LINUX_IRQCHIP_ARM_GIC_H +#define __LINUX_IRQCHIP_ARM_GIC_H #define GIC_CPU_CTRL 0x00 #define GIC_CPU_PRIMASK 0x04 @@ -32,19 +30,14 @@ #define GIC_DIST_CONFIG 0xc00 #define GIC_DIST_SOFTINT 0xf00 -#ifndef __ASSEMBLY__ -#include <linux/irqdomain.h> struct device_node; extern struct irq_chip gic_arch_extn; void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, u32 offset, struct device_node *); -int gic_of_init(struct device_node *node, struct device_node *parent); void gic_secondary_init(unsigned int); -void gic_handle_irq(struct pt_regs *regs); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); -void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); static inline void gic_init(unsigned int nr, int start, void __iomem *dist , void __iomem *cpu) @@ -53,5 +46,3 @@ static inline void gic_init(unsigned int nr, int start, } #endif - -#endif diff --git a/arch/arm/include/asm/hardware/vic.h b/include/linux/irqchip/arm-vic.h index 2bebad3..e3c82dc 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -20,29 +20,11 @@ #ifndef __ASM_ARM_HARDWARE_VIC_H #define __ASM_ARM_HARDWARE_VIC_H -#define VIC_IRQ_STATUS 0x00 -#define VIC_FIQ_STATUS 0x04 +#include <linux/types.h> + #define VIC_RAW_STATUS 0x08 -#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ #define VIC_INT_ENABLE_CLEAR 0x14 -#define VIC_INT_SOFT 0x18 -#define VIC_INT_SOFT_CLEAR 0x1c -#define VIC_PROTECT 0x20 -#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */ -#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */ - -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */ -#define VIC_ITCR 0x300 /* VIC test control register */ - -#define VIC_VECT_CNTL_ENABLE (1 << 5) - -#define VIC_PL192_VECT_ADDR 0xF00 - -#ifndef __ASSEMBLY__ -#include <linux/compiler.h> -#include <linux/types.h> struct device_node; struct pt_regs; @@ -50,8 +32,5 @@ struct pt_regs; void __vic_init(void __iomem *base, int irq_start, u32 vic_sources, u32 resume_sources, struct device_node *node); void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); -int vic_of_init(struct device_node *node, struct device_node *parent); -void vic_handle_irq(struct pt_regs *regs); -#endif /* __ASSEMBLY__ */ #endif diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 2138bd3..e53dcfe 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h @@ -272,8 +272,6 @@ struct abx500_bm_data { const struct abx500_fg_parameters *fg_params; }; -extern struct abx500_bm_data ab8500_bm_data; - enum { NTC_EXTERNAL = 0, NTC_INTERNAL, diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h index 44310c9..9bd037d 100644 --- a/include/linux/mfd/abx500/ab8500-bm.h +++ b/include/linux/mfd/abx500/ab8500-bm.h @@ -422,7 +422,10 @@ struct ab8500_chargalg_platform_data { struct ab8500_btemp; struct ab8500_gpadc; struct ab8500_fg; + #ifdef CONFIG_AB8500_BM +extern struct abx500_bm_data ab8500_bm_data; + void ab8500_fg_reinit(void); void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA); struct ab8500_btemp *ab8500_btemp_get(void); @@ -434,31 +437,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res); int ab8500_fg_inst_curr_done(struct ab8500_fg *di); #else -int ab8500_fg_inst_curr_done(struct ab8500_fg *di) -{ -} -static void ab8500_fg_reinit(void) -{ -} -static void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) -{ -} -static struct ab8500_btemp *ab8500_btemp_get(void) -{ - return NULL; -} -static int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp) -{ - return 0; -} -struct ab8500_fg *ab8500_fg_get(void) -{ - return NULL; -} -static int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev) -{ - return -ENODEV; -} +static struct abx500_bm_data ab8500_bm_data; static inline int ab8500_fg_inst_curr_start(struct ab8500_fg *di) { diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h index 86dd93d..786d02e 100644 --- a/include/linux/mfd/da9052/da9052.h +++ b/include/linux/mfd/da9052/da9052.h @@ -99,6 +99,9 @@ struct da9052 { u8 chip_id; int chip_irq; + + /* SOC I/O transfer related fixes for DA9052/53 */ + int (*fix_io) (struct da9052 *da9052, unsigned char reg); }; /* ADC API */ @@ -113,32 +116,87 @@ static inline int da9052_reg_read(struct da9052 *da9052, unsigned char reg) ret = regmap_read(da9052->regmap, reg, &val); if (ret < 0) return ret; + + if (da9052->fix_io) { + ret = da9052->fix_io(da9052, reg); + if (ret < 0) + return ret; + } + return val; } static inline int da9052_reg_write(struct da9052 *da9052, unsigned char reg, unsigned char val) { - return regmap_write(da9052->regmap, reg, val); + int ret; + + ret = regmap_write(da9052->regmap, reg, val); + if (ret < 0) + return ret; + + if (da9052->fix_io) { + ret = da9052->fix_io(da9052, reg); + if (ret < 0) + return ret; + } + + return ret; } static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg, unsigned reg_cnt, unsigned char *val) { - return regmap_bulk_read(da9052->regmap, reg, val, reg_cnt); + int ret; + + ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt); + if (ret < 0) + return ret; + + if (da9052->fix_io) { + ret = da9052->fix_io(da9052, reg); + if (ret < 0) + return ret; + } + + return ret; } static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg, unsigned reg_cnt, unsigned char *val) { - return regmap_raw_write(da9052->regmap, reg, val, reg_cnt); + int ret; + + ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt); + if (ret < 0) + return ret; + + if (da9052->fix_io) { + ret = da9052->fix_io(da9052, reg); + if (ret < 0) + return ret; + } + + return ret; } static inline int da9052_reg_update(struct da9052 *da9052, unsigned char reg, unsigned char bit_mask, unsigned char reg_val) { - return regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val); + int ret; + + ret = regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val); + if (ret < 0) + return ret; + + if (da9052->fix_io) { + ret = da9052->fix_io(da9052, reg); + if (ret < 0) + return ret; + } + + return ret; } int da9052_device_init(struct da9052 *da9052, u8 chip_id); diff --git a/include/linux/mfd/da9052/reg.h b/include/linux/mfd/da9052/reg.h index b97f730..c4dd3a8 100644 --- a/include/linux/mfd/da9052/reg.h +++ b/include/linux/mfd/da9052/reg.h @@ -34,6 +34,9 @@ #define DA9052_STATUS_C_REG 3 #define DA9052_STATUS_D_REG 4 +/* PARK REGISTER */ +#define DA9052_PARK_REGISTER DA9052_STATUS_D_REG + /* EVENT REGISTERS */ #define DA9052_EVENT_A_REG 5 #define DA9052_EVENT_B_REG 6 diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h index a8d393e..2b13970 100644 --- a/include/linux/mfd/rtsx_common.h +++ b/include/linux/mfd/rtsx_common.h @@ -38,6 +38,9 @@ #define RTSX_SD_CARD 0 #define RTSX_MS_CARD 1 +#define CLK_TO_DIV_N 0 +#define DIV_N_TO_CLK 1 + struct platform_device; struct rtsx_slot { diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 060b721..4b117a3 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -158,10 +158,9 @@ #define SG_TRANS_DATA (0x02 << 4) #define SG_LINK_DESC (0x03 << 4) -/* SD bank voltage */ -#define SD_IO_3V3 0 -#define SD_IO_1V8 1 - +/* Output voltage */ +#define OUTPUT_3V3 0 +#define OUTPUT_1V8 1 /* Card Clock Enable Register */ #define SD_CLK_EN 0x04 @@ -201,6 +200,20 @@ #define CHANGE_CLK 0x01 /* LDO_CTL */ +#define BPP_ASIC_1V7 0x00 +#define BPP_ASIC_1V8 0x01 +#define BPP_ASIC_1V9 0x02 +#define BPP_ASIC_2V0 0x03 +#define BPP_ASIC_2V7 0x04 +#define BPP_ASIC_2V8 0x05 +#define BPP_ASIC_3V2 0x06 +#define BPP_ASIC_3V3 0x07 +#define BPP_REG_TUNED18 0x07 +#define BPP_TUNED18_SHIFT_8402 5 +#define BPP_TUNED18_SHIFT_8411 4 +#define BPP_PAD_MASK 0x04 +#define BPP_PAD_3V3 0x04 +#define BPP_PAD_1V8 0x00 #define BPP_LDO_POWB 0x03 #define BPP_LDO_ON 0x00 #define BPP_LDO_SUSPEND 0x02 @@ -688,7 +701,10 @@ struct pcr_ops { int (*disable_auto_blink)(struct rtsx_pcr *pcr); int (*card_power_on)(struct rtsx_pcr *pcr, int card); int (*card_power_off)(struct rtsx_pcr *pcr, int card); + int (*switch_output_voltage)(struct rtsx_pcr *pcr, + u8 voltage); unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); + int (*conv_clk_and_div_n)(int clk, int dir); }; enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN}; @@ -783,6 +799,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk); int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card); int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card); +int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage); unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr); void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr); diff --git a/include/linux/security.h b/include/linux/security.h index 0f6afc6..eee7478 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -989,17 +989,29 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * tells the LSM to decrement the number of secmark labeling rules loaded * @req_classify_flow: * Sets the flow's sid to the openreq sid. + * @tun_dev_alloc_security: + * This hook allows a module to allocate a security structure for a TUN + * device. + * @security pointer to a security structure pointer. + * Returns a zero on success, negative values on failure. + * @tun_dev_free_security: + * This hook allows a module to free the security structure for a TUN + * device. + * @security pointer to the TUN device's security structure * @tun_dev_create: * Check permissions prior to creating a new TUN device. - * @tun_dev_post_create: - * This hook allows a module to update or allocate a per-socket security - * structure. - * @sk contains the newly created sock structure. + * @tun_dev_attach_queue: + * Check permissions prior to attaching to a TUN device queue. + * @security pointer to the TUN device's security structure. * @tun_dev_attach: - * Check permissions prior to attaching to a persistent TUN device. This - * hook can also be used by the module to update any security state + * This hook can be used by the module to update any security state * associated with the TUN device's sock structure. * @sk contains the existing sock structure. + * @security pointer to the TUN device's security structure. + * @tun_dev_open: + * This hook can be used by the module to update any security state + * associated with the TUN device's security structure. + * @security pointer to the TUN devices's security structure. * * Security hooks for XFRM operations. * @@ -1620,9 +1632,12 @@ struct security_operations { void (*secmark_refcount_inc) (void); void (*secmark_refcount_dec) (void); void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl); - int (*tun_dev_create)(void); - void (*tun_dev_post_create)(struct sock *sk); - int (*tun_dev_attach)(struct sock *sk); + int (*tun_dev_alloc_security) (void **security); + void (*tun_dev_free_security) (void *security); + int (*tun_dev_create) (void); + int (*tun_dev_attach_queue) (void *security); + int (*tun_dev_attach) (struct sock *sk, void *security); + int (*tun_dev_open) (void *security); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -2566,9 +2581,12 @@ void security_inet_conn_established(struct sock *sk, int security_secmark_relabel_packet(u32 secid); void security_secmark_refcount_inc(void); void security_secmark_refcount_dec(void); +int security_tun_dev_alloc_security(void **security); +void security_tun_dev_free_security(void *security); int security_tun_dev_create(void); -void security_tun_dev_post_create(struct sock *sk); -int security_tun_dev_attach(struct sock *sk); +int security_tun_dev_attach_queue(void *security); +int security_tun_dev_attach(struct sock *sk, void *security); +int security_tun_dev_open(void *security); #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct sock *sock, @@ -2733,16 +2751,31 @@ static inline void security_secmark_refcount_dec(void) { } +static inline int security_tun_dev_alloc_security(void **security) +{ + return 0; +} + +static inline void security_tun_dev_free_security(void *security) +{ +} + static inline int security_tun_dev_create(void) { return 0; } -static inline void security_tun_dev_post_create(struct sock *sk) +static inline int security_tun_dev_attach_queue(void *security) +{ + return 0; +} + +static inline int security_tun_dev_attach(struct sock *sk, void *security) { + return 0; } -static inline int security_tun_dev_attach(struct sock *sk) +static inline int security_tun_dev_open(void *security) { return 0; } diff --git a/include/linux/sunxi_timer.h b/include/linux/sunxi_timer.h index b9165bb..1808178 100644 --- a/include/linux/sunxi_timer.h +++ b/include/linux/sunxi_timer.h @@ -19,6 +19,6 @@ #include <asm/mach/time.h> -extern struct sys_timer sunxi_timer; +void sunxi_timer_init(void); #endif diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h new file mode 100644 index 0000000..95f611d --- /dev/null +++ b/include/linux/tegra-soc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LINUX_TEGRA_SOC_H_ +#define __LINUX_TEGRA_SOC_H_ + +u32 tegra_read_chipid(void); + +#endif /* __LINUX_TEGRA_SOC_H_ */ diff --git a/include/linux/time.h b/include/linux/time.h index 4d358e9..05e32a7 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -142,9 +142,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta); * finer then tick granular time. */ #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -extern u32 arch_gettimeoffset(void); -#else -static inline u32 arch_gettimeoffset(void) { return 0; } +extern u32 (*arch_gettimeoffset)(void); #endif extern void do_gettimeofday(struct timeval *tv); diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index 176b1ca..9ebebe9 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -59,22 +59,24 @@ struct tegra_usb_phy { struct usb_phy *ulpi; struct usb_phy u_phy; struct device *dev; + bool is_legacy_phy; + bool is_ulpi_phy; }; struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); -void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy); +void tegra_usb_phy_preresume(struct usb_phy *phy); -void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy); +void tegra_usb_phy_postresume(struct usb_phy *phy); -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); +void tegra_ehci_phy_restore_start(struct usb_phy *phy, + enum tegra_usb_phy_port_speed port_speed); -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); +void tegra_ehci_phy_restore_end(struct usb_phy *phy); -void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, - enum tegra_usb_phy_port_speed port_speed); +void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val); -void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); +void tegra_ehci_set_phcd(struct usb_phy *x, bool enable); #endif /* __TEGRA_USB_PHY_H */ diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index bd45eb7..5de7a22 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -100,6 +100,7 @@ struct driver_info { #define FLAG_LINK_INTR 0x0800 /* updates link (carrier) status */ #define FLAG_POINTTOPOINT 0x1000 /* possibly use "usb%d" names */ +#define FLAG_NOARP 0x2000 /* device can't do ARP */ /* * Indicates to usbnet, that USB driver accumulates multiple IP packets. diff --git a/arch/arm/mach-vt8500/include/mach/timex.h b/include/linux/vt8500_timer.h index 8487e4c..33b0ee8 100644 --- a/arch/arm/mach-vt8500/include/mach/timex.h +++ b/include/linux/vt8500_timer.h @@ -1,7 +1,5 @@ /* - * arch/arm/mach-vt8500/include/mach/timex.h - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * Copyright 2012 Tony Prisk <linux@prisktech.co.nz> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,15 +10,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MACH_TIMEX_H -#define MACH_TIMEX_H +#ifndef __VT8500_TIMER_H +#define __VT8500_TIMER_H + +#include <asm/mach/time.h> -#define CLOCK_TICK_RATE (3000000) +void vt8500_timer_init(void); -#endif /* MACH_TIMEX_H */ +#endif diff --git a/include/net/ip.h b/include/net/ip.h index 0707fb9..a68f838 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -143,6 +143,8 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) extern int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); +extern void ip4_datagram_release_cb(struct sock *sk); + struct ip_reply_arg { struct kvec iov[1]; int flags; diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index d8f5b9f..e98aeb3 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -31,6 +31,8 @@ extern void nf_conntrack_cleanup(struct net *net); extern int nf_conntrack_proto_init(struct net *net); extern void nf_conntrack_proto_fini(struct net *net); +extern void nf_conntrack_cleanup_end(void); + extern bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff, diff --git a/init/main.c b/init/main.c index 92d728a..cee4b5c 100644 --- a/init/main.c +++ b/init/main.c @@ -604,7 +604,7 @@ asmlinkage void __init start_kernel(void) pidmap_init(); anon_vma_init(); #ifdef CONFIG_X86 - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_enter_virtual_mode(); #endif thread_info_cache_init(); @@ -632,7 +632,7 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) { + if (efi_enabled(EFI_RUNTIME_SERVICES)) { efi_late_init(); efi_free_boot_services(); } diff --git a/kernel/printk.c b/kernel/printk.c index 357f714..267ce78 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -87,12 +87,6 @@ static DEFINE_SEMAPHORE(console_sem); struct console *console_drivers; EXPORT_SYMBOL_GPL(console_drivers); -#ifdef CONFIG_LOCKDEP -static struct lockdep_map console_lock_dep_map = { - .name = "console_lock" -}; -#endif - /* * This is used for debugging the mess that is the VT code by * keeping track if we have the console semaphore held. It's @@ -1924,7 +1918,6 @@ void console_lock(void) return; console_locked = 1; console_may_schedule = 1; - mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); } EXPORT_SYMBOL(console_lock); @@ -1946,7 +1939,6 @@ int console_trylock(void) } console_locked = 1; console_may_schedule = 0; - mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_); return 1; } EXPORT_SYMBOL(console_trylock); @@ -2107,7 +2099,6 @@ skip: local_irq_restore(flags); } console_locked = 0; - mutex_release(&console_lock_dep_map, 1, _RET_IP_); /* Release the exclusive_console once it is used */ if (unlikely(exclusive_console)) diff --git a/kernel/smp.c b/kernel/smp.c index 29dd40a..69f38bd 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -33,6 +33,7 @@ struct call_function_data { struct call_single_data csd; atomic_t refs; cpumask_var_t cpumask; + cpumask_var_t cpumask_ipi; }; static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); @@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, cpu_to_node(cpu))) return notifier_from_errno(-ENOMEM); + if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL, + cpu_to_node(cpu))) + return notifier_from_errno(-ENOMEM); break; #ifdef CONFIG_HOTPLUG_CPU @@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_DEAD: case CPU_DEAD_FROZEN: free_cpumask_var(cfd->cpumask); + free_cpumask_var(cfd->cpumask_ipi); break; #endif }; @@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask, return; } + /* + * After we put an entry into the list, data->cpumask + * may be cleared again when another CPU sends another IPI for + * a SMP function call, so data->cpumask will be zero. + */ + cpumask_copy(data->cpumask_ipi, data->cpumask); raw_spin_lock_irqsave(&call_function.lock, flags); /* * Place entry at the _HEAD_ of the list, so that any cpu still @@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask, smp_mb(); /* Send a message to all CPUs in the map */ - arch_send_call_function_ipi_mask(data->cpumask); + arch_send_call_function_ipi_mask(data->cpumask_ipi); /* Optionally wait for the CPUs to complete */ if (wait) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 30b6de0..c6d6400 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -339,6 +339,7 @@ void clockevents_config_and_register(struct clock_event_device *dev, clockevents_config(dev, freq); clockevents_register_device(dev); } +EXPORT_SYMBOL_GPL(clockevents_config_and_register); /** * clockevents_update_freq - Update frequency and reprogram a clock event device. diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index cbc6acb..8ed9346 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -135,6 +135,20 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock) } /* Timekeeper helper functions. */ + +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET +u32 (*arch_gettimeoffset)(void); + +u32 get_arch_timeoffset(void) +{ + if (likely(arch_gettimeoffset)) + return arch_gettimeoffset(); + return 0; +} +#else +static inline u32 get_arch_timeoffset(void) { return 0; } +#endif + static inline s64 timekeeping_get_ns(struct timekeeper *tk) { cycle_t cycle_now, cycle_delta; @@ -151,8 +165,8 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk) nsec = cycle_delta * tk->mult + tk->xtime_nsec; nsec >>= tk->shift; - /* If arch requires, add in gettimeoffset() */ - return nsec + arch_gettimeoffset(); + /* If arch requires, add in get_arch_timeoffset() */ + return nsec + get_arch_timeoffset(); } static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) @@ -171,8 +185,8 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) /* convert delta to nanoseconds. */ nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); - /* If arch requires, add in gettimeoffset() */ - return nsec + arch_gettimeoffset(); + /* If arch requires, add in get_arch_timeoffset() */ + return nsec + get_arch_timeoffset(); } static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); @@ -254,8 +268,8 @@ static void timekeeping_forward_now(struct timekeeper *tk) tk->xtime_nsec += cycle_delta * tk->mult; - /* If arch requires, add in gettimeoffset() */ - tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; + /* If arch requires, add in get_arch_timeoffset() */ + tk->xtime_nsec += (u64)get_arch_timeoffset() << tk->shift; tk_normalize_xtime(tk); diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 8e1d89d..183f97a 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -738,6 +738,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, struct arphdr *arphdr; struct ethhdr *ethhdr; __be32 ip_src, ip_dst; + uint8_t *hw_src, *hw_dst; uint16_t type = 0; /* pull the ethernet header */ @@ -777,9 +778,23 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, ip_src = batadv_arp_ip_src(skb, hdr_size); ip_dst = batadv_arp_ip_dst(skb, hdr_size); if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) || - ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst)) + ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst) || + ipv4_is_zeronet(ip_src) || ipv4_is_lbcast(ip_src) || + ipv4_is_zeronet(ip_dst) || ipv4_is_lbcast(ip_dst)) goto out; + hw_src = batadv_arp_hw_src(skb, hdr_size); + if (is_zero_ether_addr(hw_src) || is_multicast_ether_addr(hw_src)) + goto out; + + /* we don't care about the destination MAC address in ARP requests */ + if (arphdr->ar_op != htons(ARPOP_REQUEST)) { + hw_dst = batadv_arp_hw_dst(skb, hdr_size); + if (is_zero_ether_addr(hw_dst) || + is_multicast_ether_addr(hw_dst)) + goto out; + } + type = ntohs(arphdr->ar_op); out: return type; @@ -1012,6 +1027,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, */ ret = !batadv_is_my_client(bat_priv, hw_dst); out: + if (ret) + kfree_skb(skb); /* if ret == false -> packet has to be delivered to the interface */ return ret; } diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 596660d..0f78e34 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2810,14 +2810,6 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) if (conn) { hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags) && - !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) - mgmt_device_connected(hdev, &conn->dst, conn->type, - conn->dst_type, 0, NULL, 0, - conn->dev_class); - hci_dev_unlock(hdev); - /* Send to upper protocol */ l2cap_recv_acldata(conn, skb, flags); return; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 705078a..81b4448 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2688,7 +2688,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd) { + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) queue_work(hdev->workqueue, &hdev->cmd_work); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index b2bcbe2..a7352ff 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -931,7 +931,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid->version = req->version; hid->country = req->country; - strncpy(hid->name, req->name, 128); + strncpy(hid->name, req->name, sizeof(req->name) - 1); snprintf(hid->phys, sizeof(hid->phys), "%pMR", &bt_sk(session->ctrl_sock->sk)->src); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 2c78208..22e6583 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3727,6 +3727,17 @@ sendresp: static int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) { + struct hci_dev *hdev = conn->hcon->hdev; + struct hci_conn *hcon = conn->hcon; + + hci_dev_lock(hdev); + if (test_bit(HCI_MGMT, &hdev->dev_flags) && + !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) + mgmt_device_connected(hdev, &hcon->dst, hcon->type, + hcon->dst_type, 0, NULL, 0, + hcon->dev_class); + hci_dev_unlock(hdev); + l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); return 0; } diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 531a93d..57f250c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -352,7 +352,7 @@ static void __sco_sock_close(struct sock *sk) case BT_CONNECTED: case BT_CONFIG: - if (sco_pi(sk)->conn) { + if (sco_pi(sk)->conn->hcon) { sk->sk_state = BT_DISCONN; sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); hci_conn_put(sco_pi(sk)->conn->hcon); diff --git a/net/core/request_sock.c b/net/core/request_sock.c index c31d9e8..4425148 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -186,8 +186,6 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, struct fastopen_queue *fastopenq = inet_csk(lsk)->icsk_accept_queue.fastopenq; - BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk)); - tcp_sk(sk)->fastopen_rsk = NULL; spin_lock_bh(&fastopenq->lock); fastopenq->qlen--; diff --git a/net/core/scm.c b/net/core/scm.c index 57fb1ee..905dcc6 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -35,6 +35,7 @@ #include <net/sock.h> #include <net/compat.h> #include <net/scm.h> +#include <net/cls_cgroup.h> /* @@ -302,8 +303,10 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) } /* Bump the usage count and install the file. */ sock = sock_from_file(fp[i], &err); - if (sock) + if (sock) { sock_update_netprioidx(sock->sk, current); + sock_update_classid(sock->sk, current); + } fd_install(new_fd, get_file(fp[i])); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3ab989b..a9a2ae3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1649,7 +1649,7 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) static struct page *linear_to_page(struct page *page, unsigned int *len, unsigned int *offset, - struct sk_buff *skb, struct sock *sk) + struct sock *sk) { struct page_frag *pfrag = sk_page_frag(sk); @@ -1682,14 +1682,14 @@ static bool spd_can_coalesce(const struct splice_pipe_desc *spd, static bool spd_fill_page(struct splice_pipe_desc *spd, struct pipe_inode_info *pipe, struct page *page, unsigned int *len, unsigned int offset, - struct sk_buff *skb, bool linear, + bool linear, struct sock *sk) { if (unlikely(spd->nr_pages == MAX_SKB_FRAGS)) return true; if (linear) { - page = linear_to_page(page, len, &offset, skb, sk); + page = linear_to_page(page, len, &offset, sk); if (!page) return true; } @@ -1706,23 +1706,9 @@ static bool spd_fill_page(struct splice_pipe_desc *spd, return false; } -static inline void __segment_seek(struct page **page, unsigned int *poff, - unsigned int *plen, unsigned int off) -{ - unsigned long n; - - *poff += off; - n = *poff / PAGE_SIZE; - if (n) - *page = nth_page(*page, n); - - *poff = *poff % PAGE_SIZE; - *plen -= off; -} - static bool __splice_segment(struct page *page, unsigned int poff, unsigned int plen, unsigned int *off, - unsigned int *len, struct sk_buff *skb, + unsigned int *len, struct splice_pipe_desc *spd, bool linear, struct sock *sk, struct pipe_inode_info *pipe) @@ -1737,23 +1723,19 @@ static bool __splice_segment(struct page *page, unsigned int poff, } /* ignore any bits we already processed */ - if (*off) { - __segment_seek(&page, &poff, &plen, *off); - *off = 0; - } + poff += *off; + plen -= *off; + *off = 0; do { unsigned int flen = min(*len, plen); - /* the linear region may spread across several pages */ - flen = min_t(unsigned int, flen, PAGE_SIZE - poff); - - if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk)) + if (spd_fill_page(spd, pipe, page, &flen, poff, + linear, sk)) return true; - - __segment_seek(&page, &poff, &plen, flen); + poff += flen; + plen -= flen; *len -= flen; - } while (*len && plen); return false; @@ -1777,7 +1759,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, if (__splice_segment(virt_to_page(skb->data), (unsigned long) skb->data & (PAGE_SIZE - 1), skb_headlen(skb), - offset, len, skb, spd, + offset, len, spd, skb_head_is_locked(skb), sk, pipe)) return true; @@ -1790,7 +1772,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, if (__splice_segment(skb_frag_page(f), f->page_offset, skb_frag_size(f), - offset, len, skb, spd, false, sk, pipe)) + offset, len, spd, false, sk, pipe)) return true; } diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index a0d8392..a69b4e4 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -269,7 +269,11 @@ static void ah_input_done(struct crypto_async_request *base, int err) skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, ihl); __skb_pull(skb, ah_hlen + ihl); - skb_set_transport_header(skb, -ihl); + + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -ihl); out: kfree(AH_SKB_CB(skb)->tmp); xfrm_input_resume(skb, err); @@ -381,7 +385,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, ihl); __skb_pull(skb, ah_hlen + ihl); - skb_set_transport_header(skb, -ihl); + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -ihl); err = nexthdr; @@ -413,9 +420,12 @@ static void ah4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { + atomic_inc(&flow_cache_genid); + rt_genid_bump(net); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); - else + } else ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); xfrm_state_put(x); } diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 424fafb..b28e863 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -85,3 +85,28 @@ out: return err; } EXPORT_SYMBOL(ip4_datagram_connect); + +void ip4_datagram_release_cb(struct sock *sk) +{ + const struct inet_sock *inet = inet_sk(sk); + const struct ip_options_rcu *inet_opt; + __be32 daddr = inet->inet_daddr; + struct flowi4 fl4; + struct rtable *rt; + + if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0)) + return; + + rcu_read_lock(); + inet_opt = rcu_dereference(inet->inet_opt); + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr, + inet->inet_saddr, inet->inet_dport, + inet->inet_sport, sk->sk_protocol, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); + if (!IS_ERR(rt)) + __sk_dst_set(sk, &rt->dst); + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(ip4_datagram_release_cb); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index b61e9de..3b4f0cd 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -346,7 +346,10 @@ static int esp_input_done2(struct sk_buff *skb, int err) pskb_trim(skb, skb->len - alen - padlen - 2); __skb_pull(skb, hlen); - skb_set_transport_header(skb, -ihl); + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -ihl); err = nexthdr[1]; @@ -499,9 +502,12 @@ static void esp4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { + atomic_inc(&flow_cache_genid); + rt_genid_bump(net); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); - else + } else ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); xfrm_state_put(x); } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 303012a..e81b1ca 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -963,8 +963,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev ptr--; } if (tunnel->parms.o_flags&GRE_CSUM) { + int offset = skb_transport_offset(skb); + *ptr = 0; - *(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr)); + *(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset, + skb->len - offset, + 0)); } } diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index d3ab47e..9a46dae 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -47,9 +47,12 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { + atomic_inc(&flow_cache_genid); + rt_genid_bump(net); + ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); - else + } else ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); xfrm_state_put(x); } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 8f3d054..6f9c072 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -738,6 +738,7 @@ struct proto ping_prot = { .recvmsg = ping_recvmsg, .bind = ping_bind, .backlog_rcv = ping_queue_rcv_skb, + .release_cb = ip4_datagram_release_cb, .hash = ping_v4_hash, .unhash = ping_v4_unhash, .get_port = ping_v4_get_port, diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 73d1e4d..6f08991 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -894,6 +894,7 @@ struct proto raw_prot = { .recvmsg = raw_recvmsg, .bind = raw_bind, .backlog_rcv = raw_rcv_skb, + .release_cb = ip4_datagram_release_cb, .hash = raw_hash_sk, .unhash = raw_unhash_sk, .obj_size = sizeof(struct raw_sock), diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 844a9ef..a0fcc47 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -912,6 +912,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) struct dst_entry *dst = &rt->dst; struct fib_result res; + if (dst_metric_locked(dst, RTAX_MTU)) + return; + if (dst->dev->mtu < mtu) return; @@ -962,7 +965,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, } EXPORT_SYMBOL_GPL(ipv4_update_pmtu); -void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) +static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) { const struct iphdr *iph = (const struct iphdr *) skb->data; struct flowi4 fl4; @@ -975,6 +978,53 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) ip_rt_put(rt); } } + +void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) +{ + const struct iphdr *iph = (const struct iphdr *) skb->data; + struct flowi4 fl4; + struct rtable *rt; + struct dst_entry *dst; + bool new = false; + + bh_lock_sock(sk); + rt = (struct rtable *) __sk_dst_get(sk); + + if (sock_owned_by_user(sk) || !rt) { + __ipv4_sk_update_pmtu(skb, sk, mtu); + goto out; + } + + __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); + + if (!__sk_dst_check(sk, 0)) { + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) + goto out; + + new = true; + } + + __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); + + dst = dst_check(&rt->dst, 0); + if (!dst) { + if (new) + dst_release(&rt->dst); + + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) + goto out; + + new = true; + } + + if (new) + __sk_dst_set(sk, &rt->dst); + +out: + bh_unlock_sock(sk); +} EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); void ipv4_redirect(struct sk_buff *skb, struct net *net, @@ -1120,7 +1170,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) if (!mtu || time_after_eq(jiffies, rt->dst.expires)) mtu = dst_metric_raw(dst, RTAX_MTU); - if (mtu && rt_is_output_route(rt)) + if (mtu) return mtu; mtu = dst->dev->mtu; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 54139fa..70b09ef 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -369,11 +369,10 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) * We do take care of PMTU discovery (RFC1191) special case : * we can receive locally generated ICMP messages while socket is held. */ - if (sock_owned_by_user(sk) && - type != ICMP_DEST_UNREACH && - code != ICMP_FRAG_NEEDED) - NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); - + if (sock_owned_by_user(sk)) { + if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)) + NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); + } if (sk->sk_state == TCP_CLOSE) goto out; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 79c8dbe..1f4d405 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1952,6 +1952,7 @@ struct proto udp_prot = { .recvmsg = udp_recvmsg, .sendpage = udp_sendpage, .backlog_rcv = __udp_queue_rcv_skb, + .release_cb = ip4_datagram_release_cb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, .rehash = udp_v4_rehash, diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index ecc35b9..3842331 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -472,7 +472,10 @@ static void ah6_input_done(struct crypto_async_request *base, int err) skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, hdr_len); __skb_pull(skb, ah_hlen + hdr_len); - skb_set_transport_header(skb, -hdr_len); + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -hdr_len); out: kfree(AH_SKB_CB(skb)->tmp); xfrm_input_resume(skb, err); @@ -593,9 +596,13 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, hdr_len); - skb->transport_header = skb->network_header; __skb_pull(skb, ah_hlen + hdr_len); + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -hdr_len); + err = nexthdr; out_free: diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 282f372..40ffd72 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -300,7 +300,10 @@ static int esp_input_done2(struct sk_buff *skb, int err) pskb_trim(skb, skb->len - alen - padlen - 2); __skb_pull(skb, hlen); - skb_set_transport_header(skb, -hdr_len); + if (x->props.mode == XFRM_MODE_TUNNEL) + skb_reset_transport_header(skb); + else + skb_set_transport_header(skb, -hdr_len); err = nexthdr[1]; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4a9fd5..fff5bdd 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -81,10 +81,22 @@ static inline struct sock *icmpv6_sk(struct net *net) return net->ipv6.icmp_sk[smp_processor_id()]; } +static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + struct net *net = dev_net(skb->dev); + + if (type == ICMPV6_PKT_TOOBIG) + ip6_update_pmtu(skb, net, info, 0, 0); + else if (type == NDISC_REDIRECT) + ip6_redirect(skb, net, 0, 0); +} + static int icmpv6_rcv(struct sk_buff *skb); static const struct inet6_protocol icmpv6_protocol = { .handler = icmpv6_rcv, + .err_handler = icmpv6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5552d13..0c7c03d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1213,10 +1213,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (dst_allfrag(rt->dst.path)) cork->flags |= IPCORK_ALLFRAG; cork->length = 0; - exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; + exthdrlen = (opt ? opt->opt_flen : 0); length += exthdrlen; transhdrlen += exthdrlen; - dst_exthdrlen = rt->dst.header_len; + dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; } else { rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 26dcdec..8fd154e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1710,6 +1710,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns return -EINVAL; if (get_user(v, (u32 __user *)optval)) return -EFAULT; + /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */ + if (v != RT_TABLE_DEFAULT && v >= 100000000) + return -EINVAL; if (sk == mrt->mroute6_sk) return -EBUSY; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 47e0aca..516fbc9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -164,7 +164,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sta = sta_info_get(sdata, mac_addr); else sta = sta_info_get_bss(sdata, mac_addr); - if (!sta) { + /* + * The ASSOC test makes sure the driver is ready to + * receive the key. When wpa_supplicant has roamed + * using FT, it attempts to set the key before + * association has completed, this rejects that attempt + * so it will set the key again after assocation. + * + * TODO: accept the key if we have a station entry and + * add it to the device after the station. + */ + if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { ieee80211_key_free(sdata->local, key); err = -ENOENT; goto out_unlock; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8563b9a..2ed065c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1358,10 +1358,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable); -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable); +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); +void ieee80211_offchannel_return(struct ieee80211_local *local); void ieee80211_roc_setup(struct ieee80211_local *local); void ieee80211_start_next_roc(struct ieee80211_local *local); void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 47aeee2..2659e42 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -215,6 +215,7 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, skb->priority = 7; info->control.vif = &sdata->vif; + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ieee80211_set_qos_hdr(sdata, skb); } @@ -246,11 +247,13 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, return -EAGAIN; skb = dev_alloc_skb(local->tx_headroom + + IEEE80211_ENCRYPT_HEADROOM + + IEEE80211_ENCRYPT_TAILROOM + hdr_len + 2 + 15 /* PERR IE */); if (!skb) return -1; - skb_reserve(skb, local->tx_headroom); + skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); memset(mgmt, 0, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index a5379ae..a3ad4c3 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -102,8 +102,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) ieee80211_sta_reset_conn_monitor(sdata); } -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable) +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -134,8 +133,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { netif_tx_stop_all_queues(sdata->dev); - if (offchannel_ps_enable && - (sdata->vif.type == NL80211_IFTYPE_STATION) && + if (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.associated) ieee80211_offchannel_ps_enable(sdata); } @@ -143,8 +141,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable) +void ieee80211_offchannel_return(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -163,11 +160,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, continue; /* Tell AP we're back */ - if (offchannel_ps_disable && - sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); - } + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { /* @@ -385,7 +380,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) local->tmp_channel = NULL; ieee80211_hw_config(local, 0); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); } ieee80211_recalc_idle(local); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index d59fc68..bf82e69 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -292,7 +292,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (!was_hw_scan) { ieee80211_configure_filter(local); drv_sw_scan_complete(local); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); } ieee80211_recalc_idle(local); @@ -341,7 +341,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; - ieee80211_offchannel_stop_vifs(local, true); + ieee80211_offchannel_stop_vifs(local); ieee80211_configure_filter(local); @@ -678,12 +678,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - /* - * Re-enable vifs and beaconing. Leave PS - * in off-channel state..will put that back - * on-channel at the end of scanning. - */ - ieee80211_offchannel_return(local, false); + /* disable PS */ + ieee80211_offchannel_return(local); *next_delay = HZ / 5; /* afterwards, resume scan & go to next channel */ @@ -693,8 +689,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, static void ieee80211_scan_state_resume(struct ieee80211_local *local, unsigned long *next_delay) { - /* PS already is in off-channel mode */ - ieee80211_offchannel_stop_vifs(local, false); + ieee80211_offchannel_stop_vifs(local); if (local->ops->flush) { drv_flush(local, false); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e9eadc4..467c1d1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1673,10 +1673,13 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(tmp_sdata->vif.chanctx_conf); } - if (!chanctx_conf) - goto fail_rcu; - chan = chanctx_conf->def.chan; + if (chanctx_conf) + chan = chanctx_conf->def.chan; + else if (!local->use_chanctx) + chan = local->_oper_channel; + else + goto fail_rcu; /* * Frame injection is not allowed if beaconing is not allowed diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 016d95e..e4a0c4f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1376,11 +1376,12 @@ void nf_conntrack_cleanup(struct net *net) synchronize_net(); nf_conntrack_proto_fini(net); nf_conntrack_cleanup_net(net); +} - if (net_eq(net, &init_net)) { - RCU_INIT_POINTER(nf_ct_destroy, NULL); - nf_conntrack_cleanup_init_net(); - } +void nf_conntrack_cleanup_end(void) +{ + RCU_INIT_POINTER(nf_ct_destroy, NULL); + nf_conntrack_cleanup_init_net(); } void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 363285d..e7185c68 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -575,6 +575,7 @@ static int __init nf_conntrack_standalone_init(void) static void __exit nf_conntrack_standalone_fini(void) { unregister_pernet_subsys(&nf_conntrack_net_ops); + nf_conntrack_cleanup_end(); } module_init(nf_conntrack_standalone_init); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 8d987c3..7b3a9e5 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -345,19 +345,27 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target, } EXPORT_SYMBOL_GPL(xt_find_revision); -static char *textify_hooks(char *buf, size_t size, unsigned int mask) +static char * +textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto) { - static const char *const names[] = { + static const char *const inetbr_names[] = { "PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING", "BROUTING", }; - unsigned int i; + static const char *const arp_names[] = { + "INPUT", "FORWARD", "OUTPUT", + }; + const char *const *names; + unsigned int i, max; char *p = buf; bool np = false; int res; + names = (nfproto == NFPROTO_ARP) ? arp_names : inetbr_names; + max = (nfproto == NFPROTO_ARP) ? ARRAY_SIZE(arp_names) : + ARRAY_SIZE(inetbr_names); *p = '\0'; - for (i = 0; i < ARRAY_SIZE(names); ++i) { + for (i = 0; i < max; ++i) { if (!(mask & (1 << i))) continue; res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]); @@ -402,8 +410,10 @@ int xt_check_match(struct xt_mtchk_param *par, pr_err("%s_tables: %s match: used from hooks %s, but only " "valid from %s\n", xt_prefix[par->family], par->match->name, - textify_hooks(used, sizeof(used), par->hook_mask), - textify_hooks(allow, sizeof(allow), par->match->hooks)); + textify_hooks(used, sizeof(used), par->hook_mask, + par->family), + textify_hooks(allow, sizeof(allow), par->match->hooks, + par->family)); return -EINVAL; } if (par->match->proto && (par->match->proto != proto || inv_proto)) { @@ -575,8 +585,10 @@ int xt_check_target(struct xt_tgchk_param *par, pr_err("%s_tables: %s target: used from hooks %s, but only " "usable from %s\n", xt_prefix[par->family], par->target->name, - textify_hooks(used, sizeof(used), par->hook_mask), - textify_hooks(allow, sizeof(allow), par->target->hooks)); + textify_hooks(used, sizeof(used), par->hook_mask, + par->family), + textify_hooks(allow, sizeof(allow), par->target->hooks, + par->family)); return -EINVAL; } if (par->target->proto && (par->target->proto != proto || inv_proto)) { diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 2a08430..bde009e 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -109,7 +109,7 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) struct xt_ct_target_info *info = par->targinfo; struct nf_conntrack_tuple t; struct nf_conn *ct; - int ret; + int ret = -EOPNOTSUPP; if (info->flags & ~XT_CT_NOTRACK) return -EINVAL; @@ -247,7 +247,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) struct xt_ct_target_info_v1 *info = par->targinfo; struct nf_conntrack_tuple t; struct nf_conn *ct; - int ret; + int ret = -EOPNOTSUPP; if (info->flags & ~XT_CT_NOTRACK) return -EINVAL; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 379c81d..9bcdbd0 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -224,7 +224,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) /* Free the outqueue structure and any related pending chunks. */ -void sctp_outq_teardown(struct sctp_outq *q) +static void __sctp_outq_teardown(struct sctp_outq *q) { struct sctp_transport *transport; struct list_head *lchunk, *temp; @@ -277,8 +277,6 @@ void sctp_outq_teardown(struct sctp_outq *q) sctp_chunk_free(chunk); } - q->error = 0; - /* Throw away any leftover control chunks. */ list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { list_del_init(&chunk->list); @@ -286,11 +284,17 @@ void sctp_outq_teardown(struct sctp_outq *q) } } +void sctp_outq_teardown(struct sctp_outq *q) +{ + __sctp_outq_teardown(q); + sctp_outq_init(q->asoc, q); +} + /* Free the outqueue structure and any related pending chunks. */ void sctp_outq_free(struct sctp_outq *q) { /* Throw away leftover chunks. */ - sctp_outq_teardown(q); + __sctp_outq_teardown(q); /* If we were kmalloc()'d, free the memory. */ if (q->malloced) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 618ec7e..5131fcf 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1779,8 +1779,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, /* Update the content of current association. */ sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, + SCTP_STATE(SCTP_STATE_ESTABLISHED)); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); return SCTP_DISPOSITION_CONSUME; nomem_ev: diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 043889a..bf3c6e8 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -366,7 +366,11 @@ int sctp_sysctl_net_register(struct net *net) void sctp_sysctl_net_unregister(struct net *net) { + struct ctl_table *table; + + table = net->sctp.sysctl_header->ctl_table_arg; unregister_net_sysctl_table(net->sctp.sysctl_header); + kfree(table); } static struct ctl_table_header * sctp_sysctl_header; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index bfa3171..fb20f25 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -98,9 +98,25 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); } +static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue) +{ + struct list_head *q = &queue->tasks[queue->priority]; + struct rpc_task *task; + + if (!list_empty(q)) { + task = list_first_entry(q, struct rpc_task, u.tk_wait.list); + if (task->tk_owner == queue->owner) + list_move_tail(&task->u.tk_wait.list, q); + } +} + static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) { - queue->priority = priority; + if (queue->priority != priority) { + /* Fairness: rotate the list when changing priority */ + rpc_rotate_queue_owner(queue); + queue->priority = priority; + } } static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 41eabc4..07c5857 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2656,7 +2656,7 @@ static void xfrm_policy_fini(struct net *net) WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir])); htab = &net->xfrm.policy_bydst[dir]; - sz = (htab->hmask + 1); + sz = (htab->hmask + 1) * sizeof(struct hlist_head); WARN_ON(!hlist_empty(htab->table)); xfrm_hash_free(htab->table, sz); } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 765f6fe..35754cc 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -242,11 +242,13 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq) u32 diff; struct xfrm_replay_state_esn *replay_esn = x->replay_esn; u32 seq = ntohl(net_seq); - u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; + u32 pos; if (!replay_esn->replay_window) return; + pos = (replay_esn->seq - 1) % replay_esn->replay_window; + if (seq > replay_esn->seq) { diff = seq - replay_esn->seq; diff --git a/security/capability.c b/security/capability.c index 0fe5a02..5797750 100644 --- a/security/capability.c +++ b/security/capability.c @@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req, { } +static int cap_tun_dev_alloc_security(void **security) +{ + return 0; +} + +static void cap_tun_dev_free_security(void *security) +{ +} + static int cap_tun_dev_create(void) { return 0; } -static void cap_tun_dev_post_create(struct sock *sk) +static int cap_tun_dev_attach_queue(void *security) +{ + return 0; +} + +static int cap_tun_dev_attach(struct sock *sk, void *security) { + return 0; } -static int cap_tun_dev_attach(struct sock *sk) +static int cap_tun_dev_open(void *security) { return 0; } @@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, secmark_refcount_inc); set_to_cap_if_null(ops, secmark_refcount_dec); set_to_cap_if_null(ops, req_classify_flow); + set_to_cap_if_null(ops, tun_dev_alloc_security); + set_to_cap_if_null(ops, tun_dev_free_security); set_to_cap_if_null(ops, tun_dev_create); - set_to_cap_if_null(ops, tun_dev_post_create); + set_to_cap_if_null(ops, tun_dev_open); + set_to_cap_if_null(ops, tun_dev_attach_queue); set_to_cap_if_null(ops, tun_dev_attach); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/security/security.c b/security/security.c index daa97f4..7b88c6a 100644 --- a/security/security.c +++ b/security/security.c @@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void) } EXPORT_SYMBOL(security_secmark_refcount_dec); +int security_tun_dev_alloc_security(void **security) +{ + return security_ops->tun_dev_alloc_security(security); +} +EXPORT_SYMBOL(security_tun_dev_alloc_security); + +void security_tun_dev_free_security(void *security) +{ + security_ops->tun_dev_free_security(security); +} +EXPORT_SYMBOL(security_tun_dev_free_security); + int security_tun_dev_create(void) { return security_ops->tun_dev_create(); } EXPORT_SYMBOL(security_tun_dev_create); -void security_tun_dev_post_create(struct sock *sk) +int security_tun_dev_attach_queue(void *security) { - return security_ops->tun_dev_post_create(sk); + return security_ops->tun_dev_attach_queue(security); } -EXPORT_SYMBOL(security_tun_dev_post_create); +EXPORT_SYMBOL(security_tun_dev_attach_queue); -int security_tun_dev_attach(struct sock *sk) +int security_tun_dev_attach(struct sock *sk, void *security) { - return security_ops->tun_dev_attach(sk); + return security_ops->tun_dev_attach(sk, security); } EXPORT_SYMBOL(security_tun_dev_attach); +int security_tun_dev_open(void *security) +{ + return security_ops->tun_dev_open(security); +} +EXPORT_SYMBOL(security_tun_dev_open); + #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 61a5336..ef26e96 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4399,6 +4399,24 @@ static void selinux_req_classify_flow(const struct request_sock *req, fl->flowi_secid = req->secid; } +static int selinux_tun_dev_alloc_security(void **security) +{ + struct tun_security_struct *tunsec; + + tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL); + if (!tunsec) + return -ENOMEM; + tunsec->sid = current_sid(); + + *security = tunsec; + return 0; +} + +static void selinux_tun_dev_free_security(void *security) +{ + kfree(security); +} + static int selinux_tun_dev_create(void) { u32 sid = current_sid(); @@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void) NULL); } -static void selinux_tun_dev_post_create(struct sock *sk) +static int selinux_tun_dev_attach_queue(void *security) { + struct tun_security_struct *tunsec = security; + + return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET, + TUN_SOCKET__ATTACH_QUEUE, NULL); +} + +static int selinux_tun_dev_attach(struct sock *sk, void *security) +{ + struct tun_security_struct *tunsec = security; struct sk_security_struct *sksec = sk->sk_security; /* we don't currently perform any NetLabel based labeling here and it @@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk) * cause confusion to the TUN user that had no idea network labeling * protocols were being used */ - /* see the comments in selinux_tun_dev_create() about why we don't use - * the sockcreate SID here */ - - sksec->sid = current_sid(); + sksec->sid = tunsec->sid; sksec->sclass = SECCLASS_TUN_SOCKET; + + return 0; } -static int selinux_tun_dev_attach(struct sock *sk) +static int selinux_tun_dev_open(void *security) { - struct sk_security_struct *sksec = sk->sk_security; + struct tun_security_struct *tunsec = security; u32 sid = current_sid(); int err; - err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, + err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__RELABELFROM, NULL); if (err) return err; @@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk) TUN_SOCKET__RELABELTO, NULL); if (err) return err; - - sksec->sid = sid; + tunsec->sid = sid; return 0; } @@ -5642,9 +5667,12 @@ static struct security_operations selinux_ops = { .secmark_refcount_inc = selinux_secmark_refcount_inc, .secmark_refcount_dec = selinux_secmark_refcount_dec, .req_classify_flow = selinux_req_classify_flow, + .tun_dev_alloc_security = selinux_tun_dev_alloc_security, + .tun_dev_free_security = selinux_tun_dev_free_security, .tun_dev_create = selinux_tun_dev_create, - .tun_dev_post_create = selinux_tun_dev_post_create, + .tun_dev_attach_queue = selinux_tun_dev_attach_queue, .tun_dev_attach = selinux_tun_dev_attach, + .tun_dev_open = selinux_tun_dev_open, #ifdef CONFIG_SECURITY_NETWORK_XFRM .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index df2de54..14d04e6 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -150,6 +150,6 @@ struct security_class_mapping secclass_map[] = { NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", - { COMMON_SOCK_PERMS, NULL } }, + { COMMON_SOCK_PERMS, "attach_queue", NULL } }, { NULL } }; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 26c7eee..aa47bca 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -110,6 +110,10 @@ struct sk_security_struct { u16 sclass; /* sock security class */ }; +struct tun_security_struct { + u32 sid; /* SID for the tun device sockets */ +}; + struct key_security_struct { u32 sid; /* SID of key */ }; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0b6aeba..c78286f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -656,29 +656,43 @@ static char *driver_short_names[] = { #define get_azx_dev(substream) (substream->runtime->private_data) #ifdef CONFIG_X86 -static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on) +static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) { + int pages; + if (azx_snoop(chip)) return; - if (addr && size) { - int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (!dmab || !dmab->area || !dmab->bytes) + return; + +#ifdef CONFIG_SND_DMA_SGBUF + if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { + struct snd_sg_buf *sgbuf = dmab->private_data; if (on) - set_memory_wc((unsigned long)addr, pages); + set_pages_array_wc(sgbuf->page_table, sgbuf->pages); else - set_memory_wb((unsigned long)addr, pages); + set_pages_array_wb(sgbuf->page_table, sgbuf->pages); + return; } +#endif + + pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (on) + set_memory_wc((unsigned long)dmab->area, pages); + else + set_memory_wb((unsigned long)dmab->area, pages); } static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, bool on) { - __mark_pages_wc(chip, buf->area, buf->bytes, on); + __mark_pages_wc(chip, buf, on); } static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) + struct snd_pcm_substream *substream, bool on) { if (azx_dev->wc_marked != on) { - __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on); + __mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on); azx_dev->wc_marked = on; } } @@ -689,7 +703,7 @@ static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, { } static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) + struct snd_pcm_substream *substream, bool on) { } #endif @@ -1968,11 +1982,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; struct azx_dev *azx_dev = get_azx_dev(substream); int ret; - mark_runtime_wc(chip, azx_dev, runtime, false); + mark_runtime_wc(chip, azx_dev, substream, false); azx_dev->bufsize = 0; azx_dev->period_bytes = 0; azx_dev->format_val = 0; @@ -1980,7 +1993,7 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, params_buffer_bytes(hw_params)); if (ret < 0) return ret; - mark_runtime_wc(chip, azx_dev, runtime, true); + mark_runtime_wc(chip, azx_dev, substream, true); return ret; } @@ -1989,7 +2002,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx_dev *azx_dev = get_azx_dev(substream); struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; /* reset BDL address */ @@ -2002,7 +2014,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) snd_hda_codec_cleanup(apcm->codec, hinfo, substream); - mark_runtime_wc(chip, azx_dev, runtime, false); + mark_runtime_wc(chip, azx_dev, substream, false); return snd_pcm_lib_free_pages(substream); } @@ -3613,13 +3625,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* 5 Series/3400 */ { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, - /* SCH */ + /* Poulsbo */ { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Oaktrail */ { PCI_DEVICE(0x8086, 0x080a), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* ICH */ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cf38861..5faaad2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4694,6 +4694,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), @@ -5708,6 +5709,7 @@ static const struct alc_model_fixup alc268_fixup_models[] = { }; static const struct snd_pci_quirk alc268_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC), /* below is codec SSID since multiple Toshiba laptops have the * same PCI SSID 1179:ff00 */ diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1d8bb59..ef62c43 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -685,7 +685,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, } sr_val = i; - lrclk = snd_soc_params_to_bclk(params) / params_rate(params); + lrclk = rates[bclk] / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); @@ -1082,6 +1082,9 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, id, ret); } + regmap_update_bits(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_FREERUN, 0); + return 0; } EXPORT_SYMBOL_GPL(arizona_init_fll); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index e6cefe1..d8c65f5 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1019,8 +1019,6 @@ static const char *wm2200_mixer_texts[] = { "EQR", "LHPF1", "LHPF2", - "LHPF3", - "LHPF4", "DSP1.1", "DSP1.2", "DSP1.3", @@ -1053,7 +1051,6 @@ static int wm2200_mixer_values[] = { 0x25, 0x50, /* EQ */ 0x51, - 0x52, 0x60, /* LHPF1 */ 0x61, /* LHPF2 */ 0x68, /* DSP1 */ diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 7a9048d..1440b3f 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -896,8 +896,7 @@ static const unsigned int wm5102_aec_loopback_values[] = { static const struct soc_enum wm5102_aec_loopback = SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, - ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, ARRAY_SIZE(wm5102_aec_loopback_texts), wm5102_aec_loopback_texts, wm5102_aec_loopback_values); diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index ae80c8c..7a09096 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -344,8 +344,7 @@ static const unsigned int wm5110_aec_loopback_values[] = { static const struct soc_enum wm5110_aec_loopback = SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, - ARIZONA_AEC_LOOPBACK_SRC_MASK, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, ARRAY_SIZE(wm5110_aec_loopback_texts), wm5110_aec_loopback_texts, wm5110_aec_loopback_values); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 7b198c3..b6b6548 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -324,7 +324,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) if (reg) { buf = kmemdup(region->data, le32_to_cpu(region->len), - GFP_KERNEL); + GFP_KERNEL | GFP_DMA); if (!buf) { adsp_err(dsp, "Out of memory\n"); return -ENOMEM; @@ -396,7 +396,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) hdr = (void*)&firmware->data[0]; if (memcmp(hdr->magic, "WMDR", 4) != 0) { adsp_err(dsp, "%s: invalid magic\n", file); - return -EINVAL; + goto out_fw; } adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, @@ -439,7 +439,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) if (reg) { buf = kmemdup(blk->data, le32_to_cpu(blk->len), - GFP_KERNEL); + GFP_KERNEL | GFP_DMA); if (!buf) { adsp_err(dsp, "Out of memory\n"); return -ENOMEM; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3b98159..a210c8d 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -108,18 +108,13 @@ if SND_IMX_SOC config SND_SOC_IMX_SSI tristate -config SND_SOC_IMX_PCM - tristate - config SND_SOC_IMX_PCM_FIQ - bool + tristate select FIQ - select SND_SOC_IMX_PCM config SND_SOC_IMX_PCM_DMA - bool + tristate select SND_SOC_DMAENGINE_PCM - select SND_SOC_IMX_PCM config SND_SOC_IMX_AUDMUX tristate diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index afd3479..ec14579 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -41,7 +41,10 @@ endif obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o -obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o +obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += snd-soc-imx-pcm-fiq.o +snd-soc-imx-pcm-fiq-y := imx-pcm-fiq.o imx-pcm.o +obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += snd-soc-imx-pcm-dma.o +snd-soc-imx-pcm-dma-y := imx-pcm-dma.o imx-pcm.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c index d5cd9ef..0c9f188 100644 --- a/sound/soc/fsl/imx-pcm.c +++ b/sound/soc/fsl/imx-pcm.c @@ -31,7 +31,6 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); return ret; } -EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) { @@ -80,7 +79,6 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) out: return ret; } -EXPORT_SYMBOL_GPL(imx_pcm_new); void imx_pcm_free(struct snd_pcm *pcm) { @@ -102,7 +100,6 @@ void imx_pcm_free(struct snd_pcm *pcm) buf->area = NULL; } } -EXPORT_SYMBOL_GPL(imx_pcm_free); MODULE_DESCRIPTION("Freescale i.MX PCM driver"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1e36bc8..258acad 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1023,7 +1023,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, if (SND_SOC_DAPM_EVENT_ON(event)) { if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { - ret = regulator_allow_bypass(w->regulator, true); + ret = regulator_allow_bypass(w->regulator, false); if (ret != 0) dev_warn(w->dapm->dev, "ASoC: Failed to bypass %s: %d\n", @@ -1033,7 +1033,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, return regulator_enable(w->regulator); } else { if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { - ret = regulator_allow_bypass(w->regulator, false); + ret = regulator_allow_bypass(w->regulator, true); if (ret != 0) dev_warn(w->dapm->dev, "ASoC: Failed to unbypass %s: %d\n", @@ -3039,6 +3039,14 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->name, ret); return NULL; } + + if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { + ret = regulator_allow_bypass(w->regulator, true); + if (ret != 0) + dev_warn(w->dapm->dev, + "ASoC: Failed to unbypass %s: %d\n", + w->name, ret); + } break; case snd_soc_dapm_clock_supply: #ifdef CONFIG_CLKDEV_LOOKUP diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index f354dc3..2355630 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -25,7 +25,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <mach/clk.h> +#include <linux/clk/tegra.h> #include <sound/soc.h> #include "tegra30_ahub.h" @@ -299,15 +299,6 @@ static const char * const configlink_clocks[] = { "spdif_in", }; -struct of_dev_auxdata ahub_auxdata[] = { - OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080600, "tegra30-i2s.3", NULL), - OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080700, "tegra30-i2s.4", NULL), - {} -}; - #define LAST_REG(name) \ (TEGRA30_AHUB_##name + \ (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4) @@ -451,7 +442,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) * Ensure that here. */ for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) { - clk = clk_get_sys(NULL, configlink_clocks[i]); + clk = clk_get(&pdev->dev, configlink_clocks[i]); if (IS_ERR(clk)) { dev_err(&pdev->dev, "Can't get clock %s\n", configlink_clocks[i]); @@ -569,8 +560,7 @@ static int tegra30_ahub_probe(struct platform_device *pdev) goto err_pm_disable; } - of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata, - &pdev->dev); + of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); return 0; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ed4d89c8..e90daf8 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1331,16 +1331,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; + if (hdr->bLength < 7 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } else { struct uac2_feature_unit_descriptor *ftr = _ftr; csize = 4; channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; - } - - if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); - return -EINVAL; + if (hdr->bLength < 6 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } /* parse the source unit */ |