aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/clk.txt27
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt23
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt30
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt30
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt23
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt40
-rw-r--r--Documentation/devicetree/bindings/clock/clock-bindings.txt7
-rw-r--r--Documentation/devicetree/bindings/clock/csr,atlas7-car.txt55
-rw-r--r--Documentation/devicetree/bindings/clock/emev2-clock.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/marvell,pxa1928.txt21
-rw-r--r--Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/ti,cdce925.txt42
-rw-r--r--Documentation/devicetree/bindings/usb/renesas_usbhs.txt6
-rw-r--r--MAINTAINERS13
-rw-r--r--Makefile2
-rw-r--r--arch/arm/boot/dts/atlas7.dtsi15
-rw-r--r--arch/ia64/kernel/smpboot.c3
-rw-r--r--arch/mips/ath79/setup.c2
-rw-r--r--arch/mips/kernel/cpu-probe.c3
-rw-r--r--arch/mips/kernel/irq.c2
-rw-r--r--arch/mips/kvm/emulate.c2
-rw-r--r--arch/mips/loongson/loongson-3/smp.c2
-rw-r--r--arch/mips/mm/c-r4k.c2
-rw-r--r--arch/mips/net/bpf_jit.c6
-rw-r--r--arch/mips/ralink/ill_acc.c2
-rw-r--r--arch/sparc/include/asm/cpudata_64.h3
-rw-r--r--arch/sparc/include/asm/pgtable_64.h22
-rw-r--r--arch/sparc/include/asm/topology_64.h3
-rw-r--r--arch/sparc/include/asm/trap_block.h2
-rw-r--r--arch/sparc/kernel/entry.h2
-rw-r--r--arch/sparc/kernel/leon_pci_grpci2.c1
-rw-r--r--arch/sparc/kernel/mdesc.c136
-rw-r--r--arch/sparc/kernel/pci.c59
-rw-r--r--arch/sparc/kernel/setup_64.c21
-rw-r--r--arch/sparc/kernel/smp_64.c13
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
-rw-r--r--arch/sparc/mm/init_64.c74
-rw-r--r--arch/x86/boot/compressed/misc.h11
-rw-r--r--arch/x86/include/asm/ptrace.h2
-rw-r--r--arch/x86/include/asm/segment.h14
-rw-r--r--arch/x86/kernel/cpu/perf_event.c83
-rw-r--r--arch/x86/kernel/cpu/perf_event.h24
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c45
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_pt.c36
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c9
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.h1
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/head_32.S33
-rw-r--r--arch/x86/kernel/head_64.S20
-rw-r--r--block/genhd.c1
-rw-r--r--drivers/base/cacheinfo.c2
-rw-r--r--drivers/base/init.c2
-rw-r--r--drivers/block/nvme-core.c10
-rw-r--r--drivers/clk/Kconfig20
-rw-r--r--drivers/clk/Makefile7
-rw-r--r--drivers/clk/at91/clk-main.c2
-rw-r--r--drivers/clk/at91/clk-master.c2
-rw-r--r--drivers/clk/at91/clk-programmable.c2
-rw-r--r--drivers/clk/at91/clk-slow.c4
-rw-r--r--drivers/clk/at91/clk-smd.c2
-rw-r--r--drivers/clk/at91/clk-usb.c2
-rw-r--r--drivers/clk/at91/pmc.c2
-rw-r--r--drivers/clk/bcm/clk-kona-setup.c4
-rw-r--r--drivers/clk/bcm/clk-kona.c2
-rw-r--r--drivers/clk/bcm/clk-kona.h2
-rw-r--r--drivers/clk/berlin/berlin2-pll.c9
-rw-r--r--drivers/clk/clk-asm9260.c2
-rw-r--r--drivers/clk/clk-axm5516.c2
-rw-r--r--drivers/clk/clk-cdce706.c5
-rw-r--r--drivers/clk/clk-cdce925.c749
-rw-r--r--drivers/clk/clk-composite.c6
-rw-r--r--drivers/clk/clk-conf.c7
-rw-r--r--drivers/clk/clk-divider.c6
-rw-r--r--drivers/clk/clk-fixed-factor.c12
-rw-r--r--drivers/clk/clk-fixed-rate.c6
-rw-r--r--drivers/clk/clk-fractional-divider.c4
-rw-r--r--drivers/clk/clk-gate.c6
-rw-r--r--drivers/clk/clk-gpio-gate.c3
-rw-r--r--drivers/clk/clk-ls1x.c6
-rw-r--r--drivers/clk/clk-max-gen.c2
-rw-r--r--drivers/clk/clk-moxart.c4
-rw-r--r--drivers/clk/clk-mux.c6
-rw-r--r--drivers/clk/clk-si5351.c26
-rw-r--r--drivers/clk/clk-u300.c1
-rw-r--r--drivers/clk/clk-xgene.c22
-rw-r--r--drivers/clk/clk.c1607
-rw-r--r--drivers/clk/hisilicon/Kconfig6
-rw-r--r--drivers/clk/hisilicon/Makefile3
-rw-r--r--drivers/clk/hisilicon/clk-hi3620.c70
-rw-r--r--drivers/clk/hisilicon/clk-hi6220.c284
-rw-r--r--drivers/clk/hisilicon/clk-hix5hd2.c11
-rw-r--r--drivers/clk/hisilicon/clk.c29
-rw-r--r--drivers/clk/hisilicon/clk.h41
-rw-r--r--drivers/clk/hisilicon/clkdivider-hi6220.c156
-rw-r--r--drivers/clk/mediatek/Makefile4
-rw-r--r--drivers/clk/mediatek/clk-gate.c137
-rw-r--r--drivers/clk/mediatek/clk-gate.h49
-rw-r--r--drivers/clk/mediatek/clk-mt8135.c644
-rw-r--r--drivers/clk/mediatek/clk-mt8173.c830
-rw-r--r--drivers/clk/mediatek/clk-mtk.c220
-rw-r--r--drivers/clk/mediatek/clk-mtk.h169
-rw-r--r--drivers/clk/mediatek/clk-pll.c332
-rw-r--r--drivers/clk/mediatek/reset.c97
-rw-r--r--drivers/clk/meson/Makefile6
-rw-r--r--drivers/clk/meson/clk-cpu.c242
-rw-r--r--drivers/clk/meson/clk-pll.c227
-rw-r--r--drivers/clk/meson/clkc.c250
-rw-r--r--drivers/clk/meson/clkc.h187
-rw-r--r--drivers/clk/meson/meson8b-clkc.c196
-rw-r--r--drivers/clk/mmp/Makefile2
-rw-r--r--drivers/clk/mmp/clk-apbc.c2
-rw-r--r--drivers/clk/mmp/clk-apmu.c2
-rw-r--r--drivers/clk/mmp/clk-mmp2.c4
-rw-r--r--drivers/clk/mmp/clk-of-mmp2.c10
-rw-r--r--drivers/clk/mmp/clk-of-pxa168.c8
-rw-r--r--drivers/clk/mmp/clk-of-pxa1928.c265
-rw-r--r--drivers/clk/mmp/clk-of-pxa910.c12
-rw-r--r--drivers/clk/mvebu/armada-370.c1
-rw-r--r--drivers/clk/mxs/clk-imx23.c12
-rw-r--r--drivers/clk/mxs/clk-imx28.c18
-rw-r--r--drivers/clk/mxs/clk.h2
-rw-r--r--drivers/clk/pistachio/clk-pll.c115
-rw-r--r--drivers/clk/pxa/clk-pxa.h4
-rw-r--r--drivers/clk/rockchip/clk-cpu.c2
-rw-r--r--drivers/clk/rockchip/clk-mmc-phase.c2
-rw-r--r--drivers/clk/rockchip/clk-pll.c8
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c2
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c2
-rw-r--r--drivers/clk/rockchip/clk.c8
-rw-r--r--drivers/clk/rockchip/clk.h20
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c100
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c10
-rw-r--r--drivers/clk/samsung/clk-exynos5433.c81
-rw-r--r--drivers/clk/samsung/clk-pll.c4
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c6
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c88
-rw-r--r--drivers/clk/samsung/clk.c15
-rw-r--r--drivers/clk/samsung/clk.h18
-rw-r--r--drivers/clk/shmobile/clk-emev2.c2
-rw-r--r--drivers/clk/sirf/Makefile2
-rw-r--r--drivers/clk/sirf/clk-atlas7.c1632
-rw-r--r--drivers/clk/sirf/clk-common.c16
-rw-r--r--drivers/clk/socfpga/Makefile1
-rw-r--r--drivers/clk/socfpga/clk-gate-a10.c190
-rw-r--r--drivers/clk/socfpga/clk-gate.c12
-rw-r--r--drivers/clk/socfpga/clk-periph-a10.c138
-rw-r--r--drivers/clk/socfpga/clk-periph.c2
-rw-r--r--drivers/clk/socfpga/clk-pll-a10.c129
-rw-r--r--drivers/clk/socfpga/clk-pll.c7
-rw-r--r--drivers/clk/socfpga/clk.c7
-rw-r--r--drivers/clk/socfpga/clk.h11
-rw-r--r--drivers/clk/st/clk-flexgen.c8
-rw-r--r--drivers/clk/st/clkgen-fsyn.c4
-rw-r--r--drivers/clk/st/clkgen-mux.c16
-rw-r--r--drivers/clk/st/clkgen-pll.c10
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c9
-rw-r--r--drivers/clk/ti/clk.c4
-rw-r--r--drivers/clk/ti/clockdomain.c2
-rw-r--r--drivers/clk/ti/dpll.c2
-rw-r--r--drivers/clk/ti/fapll.c6
-rw-r--r--drivers/clk/ux500/u8500_clk.c7
-rw-r--r--drivers/clk/ux500/u8500_of_clk.c4
-rw-r--r--drivers/clk/versatile/clk-sp810.c4
-rw-r--r--drivers/clk/zynq/clkc.c25
-rw-r--r--drivers/dma/hsu/hsu.c5
-rw-r--r--drivers/dma/pl330.c3
-rw-r--r--drivers/firmware/iscsi_ibft.c36
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c4
-rw-r--r--drivers/gpu/drm/drm_sysfs.c2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c3
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c5
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c6
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c14
-rw-r--r--drivers/gpu/drm/radeon/dce3_1_afmt.c2
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c1
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c2
-rw-r--r--drivers/iio/imu/adis16400.h2
-rw-r--r--drivers/iio/imu/adis16400_buffer.c26
-rw-r--r--drivers/iio/imu/adis16400_core.c41
-rw-r--r--drivers/input/mouse/alps.c5
-rw-r--r--drivers/input/mouse/elantech.c8
-rw-r--r--drivers/iommu/amd_iommu.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c9
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c20
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c4
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c4
-rw-r--r--drivers/net/ethernet/brocade/bna/cna_fwimg.c7
-rw-r--r--drivers/net/ethernet/sfc/rx.c42
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h6
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c4
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c23
-rw-r--r--drivers/net/xen-netback/netback.c2
-rw-r--r--drivers/net/xen-netback/xenbus.c33
-rw-r--r--drivers/of/base.c8
-rw-r--r--drivers/of/dynamic.c2
-rw-r--r--drivers/pci/setup-bus.c9
-rw-r--r--drivers/phy/Kconfig10
-rw-r--r--drivers/phy/phy-core.c4
-rw-r--r--drivers/phy/phy-omap-usb2.c1
-rw-r--r--drivers/phy/phy-rcar-gen2.c4
-rw-r--r--drivers/staging/ozwpan/ozhcd.c8
-rw-r--r--drivers/staging/ozwpan/ozusbif.h4
-rw-r--r--drivers/staging/ozwpan/ozusbsvc1.c19
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c144
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c2
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c2
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c2
-rw-r--r--drivers/tty/n_tty.c21
-rw-r--r--drivers/tty/serial/8250/8250_omap.c82
-rw-r--r--drivers/tty/serial/amba-pl011.c16
-rw-r--r--drivers/tty/serial/imx.c8
-rw-r--r--drivers/usb/dwc3/core.h4
-rw-r--r--drivers/usb/gadget/function/f_fs.c15
-rw-r--r--drivers/usb/gadget/function/f_midi.c8
-rw-r--r--drivers/usb/gadget/function/f_uac1.c5
-rw-r--r--drivers/usb/gadget/legacy/g_ffs.c4
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c2
-rw-r--r--drivers/usb/host/xhci.c57
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/musb/musb_core.c14
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c6
-rw-r--r--drivers/usb/phy/phy-tahvo.c3
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c38
-rw-r--r--drivers/usb/serial/cp210x.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c1
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h1
-rw-r--r--fs/fhandle.c5
-rw-r--r--include/dt-bindings/clock/hi6220-clock.h173
-rw-r--r--include/dt-bindings/clock/marvell,mmp2.h1
-rw-r--r--include/dt-bindings/clock/marvell,pxa168.h3
-rw-r--r--include/dt-bindings/clock/marvell,pxa1928.h57
-rw-r--r--include/dt-bindings/clock/marvell,pxa910.h4
-rw-r--r--include/dt-bindings/clock/meson8b-clkc.h25
-rw-r--r--include/dt-bindings/clock/mt8135-clk.h194
-rw-r--r--include/dt-bindings/clock/mt8173-clk.h235
-rw-r--r--include/dt-bindings/reset-controller/mt8135-resets.h64
-rw-r--r--include/dt-bindings/reset-controller/mt8173-resets.h63
-rw-r--r--include/linux/backing-dev.h1
-rw-r--r--include/linux/clk-provider.h14
-rw-r--r--include/linux/of.h6
-rw-r--r--include/linux/perf_event.h4
-rw-r--r--include/net/inet_connection_sock.h3
-rw-r--r--include/net/mac80211.h7
-rw-r--r--include/trace/events/writeback.h1
-rw-r--r--include/uapi/linux/virtio_balloon.h1
-rw-r--r--kernel/compat.c6
-rw-r--r--kernel/events/core.c3
-rw-r--r--kernel/events/ring_buffer.c14
-rw-r--r--lib/strnlen_user.c12
-rw-r--r--lib/swiotlb.c5
-rw-r--r--mm/backing-dev.c18
-rw-r--r--net/bridge/br_multicast.c2
-rw-r--r--net/bridge/netfilter/ebtables.c4
-rw-r--r--net/core/ethtool.c10
-rw-r--r--net/dsa/dsa.c4
-rw-r--r--net/ipv4/esp4.c3
-rw-r--r--net/ipv4/ip_vti.c14
-rw-r--r--net/ipv4/tcp_cong.c5
-rw-r--r--net/ipv4/tcp_minisocks.c5
-rw-r--r--net/ipv4/udp.c6
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/ip6_vti.c27
-rw-r--r--net/ipv6/udp.c6
-rw-r--r--net/xfrm/xfrm_input.c17
-rw-r--r--net/xfrm/xfrm_replay.c2
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--sound/pci/hda/patch_realtek.c8
-rw-r--r--sound/pci/hda/patch_via.c10
-rw-r--r--sound/usb/mixer.c10
-rw-r--r--sound/usb/mixer_maps.c5
-rw-r--r--sound/usb/quirks.c1
-rw-r--r--tools/testing/selftests/x86/Makefile6
-rw-r--r--tools/testing/selftests/x86/entry_from_vm86.c114
280 files changed, 10951 insertions, 1894 deletions
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 0e4f90aa1c13..f463bdc37f88 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -230,30 +230,7 @@ clk_register(...)
See the basic clock types in drivers/clk/clk-*.c for examples.
- Part 5 - static initialization of clock data
-
-For platforms with many clocks (often numbering into the hundreds) it
-may be desirable to statically initialize some clock data. This
-presents a problem since the definition of struct clk should be hidden
-from everyone except for the clock core in drivers/clk/clk.c.
-
-To get around this problem struct clk's definition is exposed in
-include/linux/clk-private.h along with some macros for more easily
-initializing instances of the basic clock types. These clocks must
-still be initialized with the common clock framework via a call to
-__clk_init.
-
-clk-private.h must NEVER be included by code which implements struct
-clk_ops callbacks, nor must it be included by any logic which pokes
-around inside of struct clk at run-time. To do so is a layering
-violation.
-
-To better enforce this policy, always follow this simple rule: any
-statically initialized clock data MUST be defined in a separate file
-from the logic that implements its ops. Basically separate the logic
-from the data and all is well.
-
- Part 6 - Disabling clock gating of unused clocks
+ Part 5 - Disabling clock gating of unused clocks
Sometimes during development it can be useful to be able to bypass the
default disabling of unused clocks. For example, if drivers aren't enabling
@@ -264,7 +241,7 @@ are sorted out.
To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
kernel.
- Part 7 - Locking
+ Part 6 - Locking
The common clock framework uses two global locks, the prepare lock and the
enable lock.
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
new file mode 100644
index 000000000000..936166fbee09
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -0,0 +1,23 @@
+Mediatek apmixedsys controller
+==============================
+
+The Mediatek apmixedsys controller provides the PLLs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8135-apmixedsys"
+ - "mediatek,mt8173-apmixedsys"
+- #clock-cells: Must be 1
+
+The apmixedsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+apmixedsys: clock-controller@10209000 {
+ compatible = "mediatek,mt8173-apmixedsys";
+ reg = <0 0x10209000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
new file mode 100644
index 000000000000..f6cd3e4192ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -0,0 +1,30 @@
+Mediatek infracfg controller
+============================
+
+The Mediatek infracfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8135-infracfg", "syscon"
+ - "mediatek,mt8173-infracfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The infracfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+infracfg: power-controller@10001000 {
+ compatible = "mediatek,mt8173-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
new file mode 100644
index 000000000000..f25b85499a6f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -0,0 +1,30 @@
+Mediatek pericfg controller
+===========================
+
+The Mediatek pericfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8135-pericfg", "syscon"
+ - "mediatek,mt8173-pericfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The pericfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+pericfg: power-controller@10003000 {
+ compatible = "mediatek,mt8173-pericfg", "syscon";
+ reg = <0 0x10003000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
new file mode 100644
index 000000000000..f9e917994ced
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -0,0 +1,23 @@
+Mediatek topckgen controller
+============================
+
+The Mediatek topckgen controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8135-topckgen"
+ - "mediatek,mt8173-topckgen"
+- #clock-cells: Must be 1
+
+The topckgen controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+topckgen: power-controller@10000000 {
+ compatible = "mediatek,mt8173-topckgen";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
new file mode 100644
index 000000000000..2b7b3fa588d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
@@ -0,0 +1,40 @@
+* Amlogic Meson8b Clock and Reset Unit
+
+The Amlogic Meson8b clock controller generates and supplies clock to various
+controllers within the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,meson8b-clkc"
+- reg: it must be composed by two tuples:
+ 0) physical base address of the xtal register and length of memory
+ mapped region.
+ 1) physical base address of the clock controller and length of memory
+ mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
+used in device tree sources.
+
+Example: Clock controller node:
+
+ clkc: clock-controller@c1104000 {
+ #clock-cells = <1>;
+ compatible = "amlogic,meson8b-clkc";
+ reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
+ };
+
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart_AO: serial@c81004c0 {
+ compatible = "amlogic,meson-uart";
+ reg = <0xc81004c0 0x14>;
+ interrupts = <0 90 1>;
+ clocks = <&clkc CLKID_CLK81>;
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d541c89..2ec489eebe72 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -138,9 +138,10 @@ Some platforms may require initial configuration of default parent clocks
and clock frequencies. Such a configuration can be specified in a device tree
node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
properties. The assigned-clock-parents property should contain a list of parent
-clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
-property the list of assigned clock frequency values - corresponding to clocks
-listed in the assigned-clocks property.
+clocks in the form of a phandle and clock specifier pair and the
+assigned-clock-rates property should contain a list of frequencies in Hz. Both
+these properties should correspond to the clocks listed in the assigned-clocks
+property.
To skip setting parent or rate of a clock its corresponding entry should be
set to 0, or can be omitted if it is not followed by any non-zero entry.
diff --git a/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
new file mode 100644
index 000000000000..54d6d1358339
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
@@ -0,0 +1,55 @@
+* Clock and reset bindings for CSR atlas7
+
+Required properties:
+- compatible: Should be "sirf,atlas7-car"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- #reset-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c
+
+The reset consumer should specify the desired reset by having the reset
+ID in its "reset" phandle cell.
+The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c
+
+Examples: Clock and reset controller node:
+
+car: clock-controller@18620000 {
+ compatible = "sirf,atlas7-car";
+ reg = <0x18620000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+};
+
+Examples: Consumers using clock or reset:
+
+timer@10dc0000 {
+ compatible = "sirf,macro-tick";
+ reg = <0x10dc0000 0x1000>;
+ clocks = <&car 54>;
+ interrupts = <0 0 0>,
+ <0 1 0>,
+ <0 2 0>,
+ <0 49 0>,
+ <0 50 0>,
+ <0 51 0>;
+};
+
+uart1: uart@18020000 {
+ cell-index = <1>;
+ compatible = "sirf,macro-uart";
+ reg = <0x18020000 0x1000>;
+ clocks = <&clks 95>;
+ interrupts = <0 18 0>;
+ fifosize = <32>;
+};
+
+vpp@13110000 {
+ compatible = "sirf,prima2-vpp";
+ reg = <0x13110000 0x10000>;
+ interrupts = <0 31 0>;
+ clocks = <&car 85>;
+ resets = <&car 29>;
+};
diff --git a/Documentation/devicetree/bindings/clock/emev2-clock.txt b/Documentation/devicetree/bindings/clock/emev2-clock.txt
index 60bbb1a8c69a..268ca615459e 100644
--- a/Documentation/devicetree/bindings/clock/emev2-clock.txt
+++ b/Documentation/devicetree/bindings/clock/emev2-clock.txt
@@ -52,7 +52,7 @@ usia_u0_sclk: usia_u0_sclk {
Example of consumer:
-uart@e1020000 {
+serial@e1020000 {
compatible = "renesas,em-uart";
reg = <0xe1020000 0x38>;
interrupts = <0 8 0>;
diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
new file mode 100644
index 000000000000..809c5a2d8d9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
@@ -0,0 +1,21 @@
+* Marvell PXA1928 Clock Controllers
+
+The PXA1928 clock subsystem generates and supplies clock to various
+controllers within the PXA1928 SoC. The PXA1928 contains 3 clock controller
+blocks called APMU, MPMU, and APBC roughly corresponding to internal buses.
+
+Required Properties:
+
+- compatible: should be one of the following.
+ - "marvell,pxa1928-apmu" - APMU controller compatible
+ - "marvell,pxa1928-mpmu" - MPMU controller compatible
+ - "marvell,pxa1928-apbc" - APBC controller compatible
+- reg: physical base address of the clock controller and length of memory mapped
+ region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use the clock controller
+phandle and this identifier to specify the clock which they consume.
+
+All these identifiers can be found in <dt-bindings/clock/marvell,pxa1928.h>.
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
index 31c7c0c1ce8f..660e64912cce 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -19,6 +19,7 @@ ID Clock Peripheral
9 pex1 PCIe Cntrl 1
15 sata0 SATA Host 0
17 sdio SDHCI Host
+23 crypto CESA (crypto engine)
25 tdm Time Division Mplx
28 ddr DDR Cntrl
30 sata1 SATA Host 0
diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.txt b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
new file mode 100644
index 000000000000..4c7669ad681b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
@@ -0,0 +1,42 @@
+Binding for TO CDCE925 programmable I2C clock synthesizers.
+
+Reference
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] http://www.ti.com/product/cdce925
+
+The driver provides clock sources for each output Y1 through Y5.
+
+Required properties:
+ - compatible: Shall be "ti,cdce925"
+ - reg: I2C device address.
+ - clocks: Points to a fixed parent clock that provides the input frequency.
+ - #clock-cells: From common clock bindings: Shall be 1.
+
+Optional properties:
+ - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
+ board, or to compensate for external influences.
+
+For both PLL1 and PLL2 an optional child node can be used to specify spread
+spectrum clocking parameters for a board.
+ - spread-spectrum: SSC mode as defined in the data sheet.
+ - spread-spectrum-center: Use "centered" mode instead of "max" mode. When
+ present, the clock runs at the requested frequency on average. Otherwise
+ the requested frequency is the maximum value of the SCC range.
+
+
+Example:
+
+ clockgen: cdce925pw@64 {
+ compatible = "cdce925";
+ reg = <0x64>;
+ clocks = <&xtal_27Mhz>;
+ #clock-cells = <1>;
+ xtal-load-pf = <5>;
+ /* PLL options to get SSC 1% centered */
+ PLL2 {
+ spread-spectrum = <4>;
+ spread-spectrum-center;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt
index dc2a18f0b3a1..ddbe304beb21 100644
--- a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt
+++ b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt
@@ -15,10 +15,8 @@ Optional properties:
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
- dmas: Must contain a list of references to DMA specifiers.
- - dma-names : Must contain a list of DMA names:
- - tx0 ... tx<n>
- - rx0 ... rx<n>
- - This <n> means DnFIFO in USBHS module.
+ - dma-names : named "ch%d", where %d is the channel number ranging from zero
+ to the number of channels (DnFIFOs) minus one.
Example:
usbhs: usb@e6590000 {
diff --git a/MAINTAINERS b/MAINTAINERS
index af802b357b6a..d8afd2953678 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -51,9 +51,9 @@ trivial patch so apply some common sense.
or does something very odd once a month document it.
PLEASE remember that submissions must be made under the terms
- of the OSDL certificate of contribution and should include a
- Signed-off-by: line. The current version of this "Developer's
- Certificate of Origin" (DCO) is listed in the file
+ of the Linux Foundation certificate of contribution and should
+ include a Signed-off-by: line. The current version of this
+ "Developer's Certificate of Origin" (DCO) is listed in the file
Documentation/SubmittingPatches.
6. Make sure you have the right to send any changes you make. If you
@@ -7575,6 +7575,7 @@ F: drivers/pci/host/pci-exynos.c
PCI DRIVER FOR SYNOPSIS DESIGNWARE
M: Jingoo Han <jingoohan1@gmail.com>
+M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: drivers/pci/host/*designware*
@@ -7588,8 +7589,9 @@ F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
F: drivers/pci/host/pci-host-generic.c
PCIE DRIVER FOR ST SPEAR13XX
+M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
-S: Orphan
+S: Maintained
F: drivers/pci/host/*spear*
PCMCIA SUBSYSTEM
@@ -10587,8 +10589,7 @@ F: drivers/virtio/virtio_input.c
F: include/uapi/linux/virtio_input.h
VIA RHINE NETWORK DRIVER
-M: Roger Luethi <rl@hellgate.ch>
-S: Maintained
+S: Orphan
F: drivers/net/ethernet/via/via-rhine.c
VIA SD/MMC CARD CONTROLLER DRIVER
diff --git a/Makefile b/Makefile
index aee7e5cb4c15..40a8b068ac26 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 1
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
NAME = Hurr durr I'ma sheep
# *DOCUMENTATION*
diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi
index a753178abc85..5dfd3a44bf82 100644
--- a/arch/arm/boot/dts/atlas7.dtsi
+++ b/arch/arm/boot/dts/atlas7.dtsi
@@ -38,6 +38,21 @@
};
};
+ clocks {
+ xinw {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "xinw";
+ };
+ xin {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "xin";
+ };
+ };
+
noc {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 15051e9c2c6f..b054c5c6e713 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -127,7 +127,7 @@ int smp_num_siblings = 1;
volatile int ia64_cpu_to_sapicid[NR_CPUS];
EXPORT_SYMBOL(ia64_cpu_to_sapicid);
-static volatile cpumask_t cpu_callin_map;
+static cpumask_t cpu_callin_map;
struct smp_boot_data smp_boot_data __initdata;
@@ -477,6 +477,7 @@ do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
for (timeout = 0; timeout < 100000; timeout++) {
if (cpumask_test_cpu(cpu, &cpu_callin_map))
break; /* It has booted */
+ barrier(); /* Make sure we re-read cpu_callin_map */
udelay(100);
}
Dprintk("\n");
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index a73c93c3d44a..7fc8397d16f2 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -225,7 +225,7 @@ void __init plat_time_init(void)
ddr_clk_rate = ath79_get_sys_clk_rate("ddr");
ref_clk_rate = ath79_get_sys_clk_rate("ref");
- pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz",
+ pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz\n",
cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000,
ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000,
ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000,
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e36515dcd3b2..209e5b76c1bc 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -74,13 +74,12 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
{
unsigned long sr, mask, fcsr, fcsr0, fcsr1;
+ fcsr = c->fpu_csr31;
mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
sr = read_c0_status();
__enable_fpu(FPU_AS_IS);
- fcsr = read_32bit_cp1_register(CP1_STATUS);
-
fcsr0 = fcsr & mask;
write_32bit_cp1_register(CP1_STATUS, fcsr0);
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 51f57d841662..3c8a18a00a65 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -109,7 +109,7 @@ void __init init_IRQ(void)
#endif
}
-#ifdef DEBUG_STACKOVERFLOW
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
static inline void check_stack_overflow(void)
{
unsigned long sp;
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 4b50c5787e25..d5fa3eaf39a1 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -2409,7 +2409,7 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
if (vcpu->mmio_needed == 2)
*gpr = *(int16_t *) run->mmio.data;
else
- *gpr = *(int16_t *) run->mmio.data;
+ *gpr = *(uint16_t *)run->mmio.data;
break;
case 1:
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index e3c68b5da18d..509877c6e9d9 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -272,7 +272,7 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
c0count = read_c0_count();
- for (i = 1; i < loongson_sysconf.nr_cpus; i++)
+ for (i = 1; i < num_possible_cpus(); i++)
per_cpu(core0_c0count, i) = c0count;
}
}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 0dbb65a51ce5..2e03ab173591 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1372,7 +1372,7 @@ static int probe_scache(void)
scache_size = addr;
c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
c->scache.ways = 1;
- c->dcache.waybit = 0; /* does not matter */
+ c->scache.waybit = 0; /* does not matter */
return 1;
}
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 5d6139390bf8..e23fdf2a9c80 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -681,11 +681,7 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
sp_off += config_enabled(CONFIG_64BIT) ?
(ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE;
- /*
- * Subtract the bytes for the last registers since we only care about
- * the location on the stack pointer.
- */
- return sp_off - RSIZE;
+ return sp_off;
}
static void build_prologue(struct jit_ctx *ctx)
diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c
index e20b02e3ae28..e10d10b9e82a 100644
--- a/arch/mips/ralink/ill_acc.c
+++ b/arch/mips/ralink/ill_acc.c
@@ -41,7 +41,7 @@ static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
type & ILL_ACC_LEN_M);
- rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE);
+ rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
return IRQ_HANDLED;
}
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
index a6e424d185d0..a6cfdabb6054 100644
--- a/arch/sparc/include/asm/cpudata_64.h
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -24,7 +24,8 @@ typedef struct {
unsigned int icache_line_size;
unsigned int ecache_size;
unsigned int ecache_line_size;
- int core_id;
+ unsigned short sock_id;
+ unsigned short core_id;
int proc_id;
} cpuinfo_sparc;
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index dc165ebdf05a..2a52c91d2c8a 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -308,12 +308,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
" sllx %1, 32, %1\n"
" or %0, %1, %0\n"
" .previous\n"
+ " .section .sun_m7_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%4), %1\n"
+ " sethi %%hi(%4), %0\n"
+ " .word 662b\n"
+ " or %1, %%ulo(%4), %1\n"
+ " or %0, %%lo(%4), %0\n"
+ " .word 663b\n"
+ " sllx %1, 32, %1\n"
+ " or %0, %1, %0\n"
+ " .previous\n"
: "=r" (mask), "=r" (tmp)
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
+ _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V),
+ "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
+ _PAGE_CP_4V | _PAGE_E_4V |
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
@@ -342,9 +356,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
" andn %0, %4, %0\n"
" or %0, %5, %0\n"
" .previous\n"
+ " .section .sun_m7_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " andn %0, %6, %0\n"
+ " or %0, %5, %0\n"
+ " .previous\n"
: "=r" (val)
: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
- "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
+ "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V),
+ "i" (_PAGE_CP_4V));
return __pgprot(val);
}
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
index ed8f071132e4..d1761df5cca6 100644
--- a/arch/sparc/include/asm/topology_64.h
+++ b/arch/sparc/include/asm/topology_64.h
@@ -40,11 +40,12 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
#ifdef CONFIG_SMP
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
-#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define topology_core_cpumask(cpu) (&cpu_core_sib_map[cpu])
#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
#endif /* CONFIG_SMP */
extern cpumask_t cpu_core_map[NR_CPUS];
+extern cpumask_t cpu_core_sib_map[NR_CPUS];
static inline const struct cpumask *cpu_coregroup_mask(int cpu)
{
return &cpu_core_map[cpu];
diff --git a/arch/sparc/include/asm/trap_block.h b/arch/sparc/include/asm/trap_block.h
index 6fd4436d32f0..ec9c04de3664 100644
--- a/arch/sparc/include/asm/trap_block.h
+++ b/arch/sparc/include/asm/trap_block.h
@@ -79,6 +79,8 @@ struct sun4v_2insn_patch_entry {
};
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
__sun4v_2insn_patch_end;
+extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
+ __sun_m7_2insn_patch_end;
#endif /* !(__ASSEMBLY__) */
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index 07cc49e541f4..0f679421b468 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
struct sun4v_1insn_patch_entry *);
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
struct sun4v_2insn_patch_entry *);
+void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+ struct sun4v_2insn_patch_entry *);
extern unsigned int dcache_parity_tl1_occurred;
extern unsigned int icache_parity_tl1_occurred;
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
index 94e392bdee7d..814fb1729b12 100644
--- a/arch/sparc/kernel/leon_pci_grpci2.c
+++ b/arch/sparc/kernel/leon_pci_grpci2.c
@@ -723,7 +723,6 @@ static int grpci2_of_probe(struct platform_device *ofdev)
err = -ENOMEM;
goto err1;
}
- memset(grpci2priv, 0, sizeof(*grpci2priv));
priv->regs = regs;
priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */
priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT;
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 26c80e18d7b1..6f80936e0eea 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -614,45 +614,68 @@ static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
}
}
-static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
+static void find_back_node_value(struct mdesc_handle *hp, u64 node,
+ char *srch_val,
+ void (*func)(struct mdesc_handle *, u64, int),
+ u64 val, int depth)
{
- u64 a;
-
- mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
- u64 t = mdesc_arc_target(hp, a);
- const char *name;
- const u64 *id;
+ u64 arc;
- name = mdesc_node_name(hp, t);
- if (!strcmp(name, "cpu")) {
- id = mdesc_get_property(hp, t, "id", NULL);
- if (*id < NR_CPUS)
- cpu_data(*id).core_id = core_id;
- } else {
- u64 j;
+ /* Since we have an estimate of recursion depth, do a sanity check. */
+ if (depth == 0)
+ return;
- mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
- u64 n = mdesc_arc_target(hp, j);
- const char *n_name;
+ mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
+ u64 n = mdesc_arc_target(hp, arc);
+ const char *name = mdesc_node_name(hp, n);
- n_name = mdesc_node_name(hp, n);
- if (strcmp(n_name, "cpu"))
- continue;
+ if (!strcmp(srch_val, name))
+ (*func)(hp, n, val);
- id = mdesc_get_property(hp, n, "id", NULL);
- if (*id < NR_CPUS)
- cpu_data(*id).core_id = core_id;
- }
- }
+ find_back_node_value(hp, n, srch_val, func, val, depth-1);
}
}
+static void __mark_core_id(struct mdesc_handle *hp, u64 node,
+ int core_id)
+{
+ const u64 *id = mdesc_get_property(hp, node, "id", NULL);
+
+ if (*id < num_possible_cpus())
+ cpu_data(*id).core_id = core_id;
+}
+
+static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
+ int sock_id)
+{
+ const u64 *id = mdesc_get_property(hp, node, "id", NULL);
+
+ if (*id < num_possible_cpus())
+ cpu_data(*id).sock_id = sock_id;
+}
+
+static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
+ int core_id)
+{
+ find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
+}
+
+static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
+ int sock_id)
+{
+ find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
+}
+
static void set_core_ids(struct mdesc_handle *hp)
{
int idx;
u64 mp;
idx = 1;
+
+ /* Identify unique cores by looking for cpus backpointed to by
+ * level 1 instruction caches.
+ */
mdesc_for_each_node_by_name(hp, mp, "cache") {
const u64 *level;
const char *type;
@@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp)
continue;
mark_core_ids(hp, mp, idx);
+ idx++;
+ }
+}
+
+static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
+{
+ u64 mp;
+ int idx = 1;
+ int fnd = 0;
+
+ /* Identify unique sockets by looking for cpus backpointed to by
+ * shared level n caches.
+ */
+ mdesc_for_each_node_by_name(hp, mp, "cache") {
+ const u64 *cur_lvl;
+
+ cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
+ if (*cur_lvl != level)
+ continue;
+
+ mark_sock_ids(hp, mp, idx);
+ idx++;
+ fnd = 1;
+ }
+ return fnd;
+}
+
+static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
+{
+ int idx = 1;
+ mdesc_for_each_node_by_name(hp, mp, "socket") {
+ u64 a;
+
+ mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+ u64 t = mdesc_arc_target(hp, a);
+ const char *name;
+ const u64 *id;
+
+ name = mdesc_node_name(hp, t);
+ if (strcmp(name, "cpu"))
+ continue;
+
+ id = mdesc_get_property(hp, t, "id", NULL);
+ if (*id < num_possible_cpus())
+ cpu_data(*id).sock_id = idx;
+ }
idx++;
}
}
+static void set_sock_ids(struct mdesc_handle *hp)
+{
+ u64 mp;
+
+ /* If machine description exposes sockets data use it.
+ * Otherwise fallback to use shared L3 or L2 caches.
+ */
+ mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
+ if (mp != MDESC_NODE_NULL)
+ return set_sock_ids_by_socket(hp, mp);
+
+ if (!set_sock_ids_by_cache(hp, 3))
+ set_sock_ids_by_cache(hp, 2);
+}
+
static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
{
u64 a;
@@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
continue;
mark_proc_ids(hp, mp, idx);
-
idx++;
}
}
@@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
set_core_ids(hp);
set_proc_ids(hp);
+ set_sock_ids(hp);
mdesc_release(hp);
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 6f7251fd2eab..c928bc64b4ba 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -1002,6 +1002,38 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init);
#ifdef CONFIG_SYSFS
+
+#define SLOT_NAME_SIZE 11 /* Max decimal digits + null in u32 */
+
+static void pcie_bus_slot_names(struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+ struct pci_bus *bus;
+
+ list_for_each_entry(pdev, &pbus->devices, bus_list) {
+ char name[SLOT_NAME_SIZE];
+ struct pci_slot *pci_slot;
+ const u32 *slot_num;
+ int len;
+
+ slot_num = of_get_property(pdev->dev.of_node,
+ "physical-slot#", &len);
+
+ if (slot_num == NULL || len != 4)
+ continue;
+
+ snprintf(name, sizeof(name), "%u", slot_num[0]);
+ pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL);
+
+ if (IS_ERR(pci_slot))
+ pr_err("PCI: pci_create_slot returned %ld.\n",
+ PTR_ERR(pci_slot));
+ }
+
+ list_for_each_entry(bus, &pbus->children, node)
+ pcie_bus_slot_names(bus);
+}
+
static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
{
const struct pci_slot_names {
@@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void)
while ((pbus = pci_find_next_bus(pbus)) != NULL) {
struct device_node *node;
+ struct pci_dev *pdev;
+
+ pdev = list_first_entry(&pbus->devices, struct pci_dev,
+ bus_list);
- if (pbus->self) {
- /* PCI->PCI bridge */
- node = pbus->self->dev.of_node;
+ if (pdev && pci_is_pcie(pdev)) {
+ pcie_bus_slot_names(pbus);
} else {
- struct pci_pbm_info *pbm = pbus->sysdata;
- /* Host PCI controller */
- node = pbm->op->dev.of_node;
- }
+ if (pbus->self) {
+
+ /* PCI->PCI bridge */
+ node = pbus->self->dev.of_node;
+
+ } else {
+ struct pci_pbm_info *pbm = pbus->sysdata;
- pci_bus_slot_names(node, pbus);
+ /* Host PCI controller */
+ node = pbm->op->dev.of_node;
+ }
+
+ pci_bus_slot_names(node, pbus);
+ }
}
return 0;
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index c38d19fc27ba..f7b261749383 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
}
}
+void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+ struct sun4v_2insn_patch_entry *end)
+{
+ while (start < end) {
+ unsigned long addr = start->addr;
+
+ *(unsigned int *) (addr + 0) = start->insns[0];
+ wmb();
+ __asm__ __volatile__("flush %0" : : "r" (addr + 0));
+
+ *(unsigned int *) (addr + 4) = start->insns[1];
+ wmb();
+ __asm__ __volatile__("flush %0" : : "r" (addr + 4));
+
+ start++;
+ }
+}
+
static void __init sun4v_patch(void)
{
extern void sun4v_hvapi_init(void);
@@ -267,6 +285,9 @@ static void __init sun4v_patch(void)
sun4v_patch_2insn_range(&__sun4v_2insn_patch,
&__sun4v_2insn_patch_end);
+ if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7)
+ sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
+ &__sun_m7_2insn_patch_end);
sun4v_hvapi_init();
}
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 61139d9924ca..19cd08d18672 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -60,8 +60,12 @@ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = {
+ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
EXPORT_SYMBOL(cpu_core_map);
+EXPORT_SYMBOL(cpu_core_sib_map);
static cpumask_t smp_commenced_mask;
@@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void)
}
}
+ for_each_present_cpu(i) {
+ unsigned int j;
+
+ for_each_present_cpu(j) {
+ if (cpu_data(i).sock_id == cpu_data(j).sock_id)
+ cpumask_set_cpu(j, &cpu_core_sib_map[i]);
+ }
+ }
+
for_each_present_cpu(i) {
unsigned int j;
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 09243057cb0b..f1a2f688b28a 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -138,6 +138,11 @@ SECTIONS
*(.pause_3insn_patch)
__pause_3insn_patch_end = .;
}
+ .sun_m7_2insn_patch : {
+ __sun_m7_2insn_patch = .;
+ *(.sun_m7_2insn_patch)
+ __sun_m7_2insn_patch_end = .;
+ }
PERCPU_SECTION(SMP_CACHE_BYTES)
. = ALIGN(PAGE_SIZE);
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 4ca0d6ba5ec8..559cb744112c 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -54,6 +54,7 @@
#include "init_64.h"
unsigned long kern_linear_pte_xor[4] __read_mostly;
+static unsigned long page_cache4v_flag;
/* A bitmap, two bits for every 256MB of physical memory. These two
* bits determine what page size we use for kernel linear
@@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)
static void __init sun4v_linear_pte_xor_finalize(void)
{
+ unsigned long pagecv_flag;
+
+ /* Bit 9 of TTE is no longer CV bit on M7 processor and it instead
+ * enables MCD error. Do not set bit 9 on M7 processor.
+ */
+ switch (sun4v_chip_type) {
+ case SUN4V_CHIP_SPARC_M7:
+ pagecv_flag = 0x00;
+ break;
+ default:
+ pagecv_flag = _PAGE_CV_4V;
+ break;
+ }
#ifndef CONFIG_DEBUG_PAGEALLOC
if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
PAGE_OFFSET;
- kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+ kern_linear_pte_xor[1] |= (_PAGE_CP_4V | pagecv_flag |
_PAGE_P_4V | _PAGE_W_4V);
} else {
kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
@@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
PAGE_OFFSET;
- kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+ kern_linear_pte_xor[2] |= (_PAGE_CP_4V | pagecv_flag |
_PAGE_P_4V | _PAGE_W_4V);
} else {
kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
@@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
PAGE_OFFSET;
- kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+ kern_linear_pte_xor[3] |= (_PAGE_CP_4V | pagecv_flag |
_PAGE_P_4V | _PAGE_W_4V);
} else {
kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
@@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)
return available;
}
+#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
+#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
+#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
+#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
+#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
+#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
+
/* We need to exclude reserved regions. This exclusion will include
* vmlinux and initrd. To be more precise the initrd size could be used to
* compute a new lower limit because it is freed later during initialization.
@@ -2034,6 +2055,25 @@ void __init paging_init(void)
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
#endif
+ /* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde
+ * bit on M7 processor. This is a conflicting usage of the same
+ * bit. Enabling TTE.cv on M7 would turn on Memory Corruption
+ * Detection error on all pages and this will lead to problems
+ * later. Kernel does not run with MCD enabled and hence rest
+ * of the required steps to fully configure memory corruption
+ * detection are not taken. We need to ensure TTE.mcde is not
+ * set on M7 processor. Compute the value of cacheability
+ * flag for use later taking this into consideration.
+ */
+ switch (sun4v_chip_type) {
+ case SUN4V_CHIP_SPARC_M7:
+ page_cache4v_flag = _PAGE_CP_4V;
+ break;
+ default:
+ page_cache4v_flag = _PAGE_CACHE_4V;
+ break;
+ }
+
if (tlb_type == hypervisor)
sun4v_pgprot_init();
else
@@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
#endif
-#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
-#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
-#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
-#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
-#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
-#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
-
pgprot_t PAGE_KERNEL __read_mostly;
EXPORT_SYMBOL(PAGE_KERNEL);
@@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
_PAGE_P_4U | _PAGE_W_4U);
if (tlb_type == hypervisor)
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
- _PAGE_CP_4V | _PAGE_CV_4V |
- _PAGE_P_4V | _PAGE_W_4V);
+ page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);
pte_base |= _PAGE_PMD_HUGE;
@@ -2450,14 +2482,14 @@ static void __init sun4v_pgprot_init(void)
int i;
PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
- _PAGE_CACHE_4V | _PAGE_P_4V |
+ page_cache4v_flag | _PAGE_P_4V |
__ACCESS_BITS_4V | __DIRTY_BITS_4V |
_PAGE_EXEC_4V);
PAGE_KERNEL_LOCKED = PAGE_KERNEL;
_PAGE_IE = _PAGE_IE_4V;
_PAGE_E = _PAGE_E_4V;
- _PAGE_CACHE = _PAGE_CACHE_4V;
+ _PAGE_CACHE = page_cache4v_flag;
#ifdef CONFIG_DEBUG_PAGEALLOC
kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
@@ -2465,8 +2497,8 @@ static void __init sun4v_pgprot_init(void)
kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
PAGE_OFFSET;
#endif
- kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
- _PAGE_P_4V | _PAGE_W_4V);
+ kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V |
+ _PAGE_W_4V);
for (i = 1; i < 4; i++)
kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
@@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)
_PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
_PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
- page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V;
- page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
+ page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag;
+ page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
__ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V);
- page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
+ page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
- page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
+ page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
page_exec_bit = _PAGE_EXEC_4V;
@@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)
_PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
if (tlb_type == hypervisor)
val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
- _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V |
+ page_cache4v_flag | _PAGE_P_4V |
_PAGE_EXEC_4V | _PAGE_W_4V);
return val | paddr;
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 89dd0d78013a..805d25ca5f1d 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -2,15 +2,14 @@
#define BOOT_COMPRESSED_MISC_H
/*
- * we have to be careful, because no indirections are allowed here, and
- * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
- * we just keep it from happening
+ * Special hack: we have to be careful, because no indirections are allowed here,
+ * and paravirt_ops is a kind of one. As it will only run in baremetal anyway,
+ * we just keep it from happening. (This list needs to be extended when new
+ * paravirt and debugging variants are added.)
*/
#undef CONFIG_PARAVIRT
+#undef CONFIG_PARAVIRT_SPINLOCKS
#undef CONFIG_KASAN
-#ifdef CONFIG_X86_32
-#define _ASM_X86_DESC_H 1
-#endif
#include <linux/linkage.h>
#include <linux/screen_info.h>
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 19507ffa5d28..5fabf1362942 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -107,7 +107,7 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
static inline int user_mode(struct pt_regs *regs)
{
#ifdef CONFIG_X86_32
- return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL;
+ return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL;
#else
return !!(regs->cs & 3);
#endif
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 5a9856eb12ba..7d5a1929d76b 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -231,11 +231,21 @@
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8)
#ifdef __KERNEL__
+
+/*
+ * early_idt_handler_array is an array of entry points referenced in the
+ * early IDT. For simplicity, it's a real array with one entry point
+ * every nine bytes. That leaves room for an optional 'push $0' if the
+ * vector has no error code (two bytes), a 'push $vector_number' (two
+ * bytes), and a jump to the common entry code (up to five bytes).
+ */
+#define EARLY_IDT_HANDLER_SIZE 9
+
#ifndef __ASSEMBLY__
-extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
+extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
#ifdef CONFIG_TRACING
-# define trace_early_idt_handlers early_idt_handlers
+# define trace_early_idt_handler_array early_idt_handler_array
#endif
/*
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 87848ebe2bb7..4f7001f28936 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -190,6 +190,7 @@ static bool check_hw_exists(void)
u64 val, val_fail, val_new= ~0;
int i, reg, reg_fail, ret = 0;
int bios_fail = 0;
+ int reg_safe = -1;
/*
* Check to see if the BIOS enabled any of the counters, if so
@@ -204,6 +205,8 @@ static bool check_hw_exists(void)
bios_fail = 1;
val_fail = val;
reg_fail = reg;
+ } else {
+ reg_safe = i;
}
}
@@ -222,11 +225,22 @@ static bool check_hw_exists(void)
}
/*
+ * If all the counters are enabled, the below test will always
+ * fail. The tools will also become useless in this scenario.
+ * Just fail and disable the hardware counters.
+ */
+
+ if (reg_safe == -1) {
+ reg = reg_safe;
+ goto msr_fail;
+ }
+
+ /*
* Read the current value, change it and read it back to see if it
* matches, this is needed to detect certain hardware emulators
* (qemu/kvm) that don't trap on the MSR access and always return 0s.
*/
- reg = x86_pmu_event_addr(0);
+ reg = x86_pmu_event_addr(reg_safe);
if (rdmsrl_safe(reg, &val))
goto msr_fail;
val ^= 0xffffUL;
@@ -611,6 +625,7 @@ struct sched_state {
int event; /* event index */
int counter; /* counter index */
int unassigned; /* number of events to be assigned left */
+ int nr_gp; /* number of GP counters used */
unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
};
@@ -620,27 +635,29 @@ struct sched_state {
struct perf_sched {
int max_weight;
int max_events;
- struct perf_event **events;
- struct sched_state state;
+ int max_gp;
int saved_states;
+ struct event_constraint **constraints;
+ struct sched_state state;
struct sched_state saved[SCHED_STATES_MAX];
};
/*
* Initialize interator that runs through all events and counters.
*/
-static void perf_sched_init(struct perf_sched *sched, struct perf_event **events,
- int num, int wmin, int wmax)
+static void perf_sched_init(struct perf_sched *sched, struct event_constraint **constraints,
+ int num, int wmin, int wmax, int gpmax)
{
int idx;
memset(sched, 0, sizeof(*sched));
sched->max_events = num;
sched->max_weight = wmax;
- sched->events = events;
+ sched->max_gp = gpmax;
+ sched->constraints = constraints;
for (idx = 0; idx < num; idx++) {
- if (events[idx]->hw.constraint->weight == wmin)
+ if (constraints[idx]->weight == wmin)
break;
}
@@ -687,7 +704,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
if (sched->state.event >= sched->max_events)
return false;
- c = sched->events[sched->state.event]->hw.constraint;
+ c = sched->constraints[sched->state.event];
/* Prefer fixed purpose counters */
if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
idx = INTEL_PMC_IDX_FIXED;
@@ -696,11 +713,16 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
goto done;
}
}
+
/* Grab the first unused counter starting with idx */
idx = sched->state.counter;
for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
- if (!__test_and_set_bit(idx, sched->state.used))
+ if (!__test_and_set_bit(idx, sched->state.used)) {
+ if (sched->state.nr_gp++ >= sched->max_gp)
+ return false;
+
goto done;
+ }
}
return false;
@@ -745,7 +767,7 @@ static bool perf_sched_next_event(struct perf_sched *sched)
if (sched->state.weight > sched->max_weight)
return false;
}
- c = sched->events[sched->state.event]->hw.constraint;
+ c = sched->constraints[sched->state.event];
} while (c->weight != sched->state.weight);
sched->state.counter = 0; /* start with first counter */
@@ -756,12 +778,12 @@ static bool perf_sched_next_event(struct perf_sched *sched)
/*
* Assign a counter for each event.
*/
-int perf_assign_events(struct perf_event **events, int n,
- int wmin, int wmax, int *assign)
+int perf_assign_events(struct event_constraint **constraints, int n,
+ int wmin, int wmax, int gpmax, int *assign)
{
struct perf_sched sched;
- perf_sched_init(&sched, events, n, wmin, wmax);
+ perf_sched_init(&sched, constraints, n, wmin, wmax, gpmax);
do {
if (!perf_sched_find_counter(&sched))
@@ -788,9 +810,9 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
x86_pmu.start_scheduling(cpuc);
for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
- hwc = &cpuc->event_list[i]->hw;
+ cpuc->event_constraint[i] = NULL;
c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
- hwc->constraint = c;
+ cpuc->event_constraint[i] = c;
wmin = min(wmin, c->weight);
wmax = max(wmax, c->weight);
@@ -801,7 +823,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
*/
for (i = 0; i < n; i++) {
hwc = &cpuc->event_list[i]->hw;
- c = hwc->constraint;
+ c = cpuc->event_constraint[i];
/* never assigned */
if (hwc->idx == -1)
@@ -821,9 +843,26 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
}
/* slow path */
- if (i != n)
- unsched = perf_assign_events(cpuc->event_list, n, wmin,
- wmax, assign);
+ if (i != n) {
+ int gpmax = x86_pmu.num_counters;
+
+ /*
+ * Do not allow scheduling of more than half the available
+ * generic counters.
+ *
+ * This helps avoid counter starvation of sibling thread by
+ * ensuring at most half the counters cannot be in exclusive
+ * mode. There is no designated counters for the limits. Any
+ * N/2 counters can be used. This helps with events with
+ * specific counter constraints.
+ */
+ if (is_ht_workaround_enabled() && !cpuc->is_fake &&
+ READ_ONCE(cpuc->excl_cntrs->exclusive_present))
+ gpmax /= 2;
+
+ unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
+ wmax, gpmax, assign);
+ }
/*
* In case of success (unsched = 0), mark events as committed,
@@ -840,7 +879,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
e = cpuc->event_list[i];
e->hw.flags |= PERF_X86_EVENT_COMMITTED;
if (x86_pmu.commit_scheduling)
- x86_pmu.commit_scheduling(cpuc, e, assign[i]);
+ x86_pmu.commit_scheduling(cpuc, i, assign[i]);
}
}
@@ -1292,8 +1331,10 @@ static void x86_pmu_del(struct perf_event *event, int flags)
x86_pmu.put_event_constraints(cpuc, event);
/* Delete the array entry. */
- while (++i < cpuc->n_events)
+ while (++i < cpuc->n_events) {
cpuc->event_list[i-1] = cpuc->event_list[i];
+ cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
+ }
--cpuc->n_events;
perf_event_update_userpage(event);
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 6ac5cb7a9e14..ef78516850fb 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -74,6 +74,7 @@ struct event_constraint {
#define PERF_X86_EVENT_EXCL 0x0040 /* HT exclusivity on counter */
#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
+#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */
struct amd_nb {
@@ -134,8 +135,6 @@ enum intel_excl_state_type {
struct intel_excl_states {
enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
enum intel_excl_state_type state[X86_PMC_IDX_MAX];
- int num_alloc_cntrs;/* #counters allocated */
- int max_alloc_cntrs;/* max #counters allowed */
bool sched_started; /* true if scheduling has started */
};
@@ -144,6 +143,11 @@ struct intel_excl_cntrs {
struct intel_excl_states states[2];
+ union {
+ u16 has_exclusive[2];
+ u32 exclusive_present;
+ };
+
int refcnt; /* per-core: #HT threads */
unsigned core_id; /* per-core: core id */
};
@@ -172,7 +176,11 @@ struct cpu_hw_events {
added in the current transaction */
int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
u64 tags[X86_PMC_IDX_MAX];
+
struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
+ struct event_constraint *event_constraint[X86_PMC_IDX_MAX];
+
+ int n_excl; /* the number of exclusive events */
unsigned int group_flag;
int is_fake;
@@ -519,9 +527,7 @@ struct x86_pmu {
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
struct perf_event *event);
- void (*commit_scheduling)(struct cpu_hw_events *cpuc,
- struct perf_event *event,
- int cntr);
+ void (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
void (*start_scheduling)(struct cpu_hw_events *cpuc);
@@ -717,8 +723,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
void x86_pmu_enable_all(int added);
-int perf_assign_events(struct perf_event **events, int n,
- int wmin, int wmax, int *assign);
+int perf_assign_events(struct event_constraint **constraints, int n,
+ int wmin, int wmax, int gpmax, int *assign);
int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
void x86_pmu_stop(struct perf_event *event, int flags);
@@ -929,4 +935,8 @@ static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
return NULL;
}
+static inline int is_ht_workaround_enabled(void)
+{
+ return 0;
+}
#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 3998131d1a68..a1e35c9f06b9 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1923,7 +1923,6 @@ intel_start_scheduling(struct cpu_hw_events *cpuc)
xl = &excl_cntrs->states[tid];
xl->sched_started = true;
- xl->num_alloc_cntrs = 0;
/*
* lock shared state until we are done scheduling
* in stop_event_scheduling()
@@ -2000,6 +1999,11 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
* across HT threads
*/
is_excl = c->flags & PERF_X86_EVENT_EXCL;
+ if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
+ event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
+ if (!cpuc->n_excl++)
+ WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
+ }
/*
* xl = state of current HT
@@ -2008,18 +2012,6 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
xl = &excl_cntrs->states[tid];
xlo = &excl_cntrs->states[o_tid];
- /*
- * do not allow scheduling of more than max_alloc_cntrs
- * which is set to half the available generic counters.
- * this helps avoid counter starvation of sibling thread
- * by ensuring at most half the counters cannot be in
- * exclusive mode. There is not designated counters for the
- * limits. Any N/2 counters can be used. This helps with
- * events with specifix counter constraints
- */
- if (xl->num_alloc_cntrs++ == xl->max_alloc_cntrs)
- return &emptyconstraint;
-
cx = c;
/*
@@ -2106,7 +2098,7 @@ static struct event_constraint *
intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
struct perf_event *event)
{
- struct event_constraint *c1 = event->hw.constraint;
+ struct event_constraint *c1 = cpuc->event_constraint[idx];
struct event_constraint *c2;
/*
@@ -2150,6 +2142,11 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
xl = &excl_cntrs->states[tid];
xlo = &excl_cntrs->states[o_tid];
+ if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
+ hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
+ if (!--cpuc->n_excl)
+ WRITE_ONCE(excl_cntrs->has_exclusive[tid], 0);
+ }
/*
* put_constraint may be called from x86_schedule_events()
@@ -2188,8 +2185,6 @@ intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
struct perf_event *event)
{
- struct event_constraint *c = event->hw.constraint;
-
intel_put_shared_regs_event_constraints(cpuc, event);
/*
@@ -2197,19 +2192,14 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
* all events are subject to and must call the
* put_excl_constraints() routine
*/
- if (c && cpuc->excl_cntrs)
+ if (cpuc->excl_cntrs)
intel_put_excl_constraints(cpuc, event);
-
- /* cleanup dynamic constraint */
- if (c && (c->flags & PERF_X86_EVENT_DYNAMIC))
- event->hw.constraint = NULL;
}
-static void intel_commit_scheduling(struct cpu_hw_events *cpuc,
- struct perf_event *event, int cntr)
+static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
{
struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
- struct event_constraint *c = event->hw.constraint;
+ struct event_constraint *c = cpuc->event_constraint[idx];
struct intel_excl_states *xlo, *xl;
int tid = cpuc->excl_thread_id;
int o_tid = 1 - tid;
@@ -2639,8 +2629,6 @@ static void intel_pmu_cpu_starting(int cpu)
cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
- int h = x86_pmu.num_counters >> 1;
-
for_each_cpu(i, topology_thread_cpumask(cpu)) {
struct intel_excl_cntrs *c;
@@ -2654,11 +2642,6 @@ static void intel_pmu_cpu_starting(int cpu)
}
cpuc->excl_cntrs->core_id = core_id;
cpuc->excl_cntrs->refcnt++;
- /*
- * set hard limit to half the number of generic counters
- */
- cpuc->excl_cntrs->states[0].max_alloc_cntrs = h;
- cpuc->excl_cntrs->states[1].max_alloc_cntrs = h;
}
}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 813f75d71175..7f73b3553e2e 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -706,9 +706,9 @@ void intel_pmu_pebs_disable(struct perf_event *event)
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
- if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_LDLAT)
+ if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
- else if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_ST)
+ else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
cpuc->pebs_enabled &= ~(1ULL << 63);
if (cpuc->enabled)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index ffe666c2c6b5..123ff1bb2f60 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -151,7 +151,7 @@ static int __init pt_pmu_hw_init(void)
de_attr->attr.attr.name = pt_caps[i].name;
- sysfs_attr_init(&de_attrs->attr.attr);
+ sysfs_attr_init(&de_attr->attr.attr);
de_attr->attr.attr.mode = S_IRUGO;
de_attr->attr.show = pt_cap_show;
@@ -615,7 +615,8 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
struct perf_output_handle *handle)
{
- unsigned long idx, npages, end;
+ unsigned long head = local64_read(&buf->head);
+ unsigned long idx, npages, wakeup;
if (buf->snapshot)
return 0;
@@ -634,17 +635,26 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
buf->topa_index[buf->stop_pos]->stop = 0;
buf->topa_index[buf->intr_pos]->intr = 0;
- if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
- npages = (handle->size + 1) >> PAGE_SHIFT;
- end = (local64_read(&buf->head) >> PAGE_SHIFT) + npages;
- /*if (end > handle->wakeup >> PAGE_SHIFT)
- end = handle->wakeup >> PAGE_SHIFT;*/
- idx = end & (buf->nr_pages - 1);
- buf->stop_pos = idx;
- idx = (local64_read(&buf->head) >> PAGE_SHIFT) + npages - 1;
- idx &= buf->nr_pages - 1;
- buf->intr_pos = idx;
- }
+ /* how many pages till the STOP marker */
+ npages = handle->size >> PAGE_SHIFT;
+
+ /* if it's on a page boundary, fill up one more page */
+ if (!offset_in_page(head + handle->size + 1))
+ npages++;
+
+ idx = (head >> PAGE_SHIFT) + npages;
+ idx &= buf->nr_pages - 1;
+ buf->stop_pos = idx;
+
+ wakeup = handle->wakeup >> PAGE_SHIFT;
+
+ /* in the worst case, wake up the consumer one page before hard stop */
+ idx = (head >> PAGE_SHIFT) + npages - 1;
+ if (idx > wakeup)
+ idx = wakeup;
+
+ idx &= buf->nr_pages - 1;
+ buf->intr_pos = idx;
buf->topa_index[buf->stop_pos]->stop = 1;
buf->topa_index[buf->intr_pos]->intr = 1;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index c635b8b49e93..dd319e59246b 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -365,9 +365,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
- hwc = &box->event_list[i]->hw;
c = uncore_get_event_constraint(box, box->event_list[i]);
- hwc->constraint = c;
+ box->event_constraint[i] = c;
wmin = min(wmin, c->weight);
wmax = max(wmax, c->weight);
}
@@ -375,7 +374,7 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
/* fastpath, try to reuse previous register */
for (i = 0; i < n; i++) {
hwc = &box->event_list[i]->hw;
- c = hwc->constraint;
+ c = box->event_constraint[i];
/* never assigned */
if (hwc->idx == -1)
@@ -395,8 +394,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
}
/* slow path */
if (i != n)
- ret = perf_assign_events(box->event_list, n,
- wmin, wmax, assign);
+ ret = perf_assign_events(box->event_constraint, n,
+ wmin, wmax, n, assign);
if (!assign || ret) {
for (i = 0; i < n; i++)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index 6c8c1e7e69d8..f789ec9a0133 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -97,6 +97,7 @@ struct intel_uncore_box {
atomic_t refcnt;
struct perf_event *events[UNCORE_PMC_IDX_MAX];
struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
+ struct event_constraint *event_constraint[UNCORE_PMC_IDX_MAX];
unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
u64 tags[UNCORE_PMC_IDX_MAX];
struct pci_dev *pci_dev;
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 2b55ee6db053..5a4668136e98 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -167,7 +167,7 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
clear_bss();
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
- set_intr_gate(i, early_idt_handlers[i]);
+ set_intr_gate(i, early_idt_handler_array[i]);
load_idt((const struct desc_ptr *)&idt_descr);
copy_bootdata(__va(real_mode_data));
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index d031bad9e07e..53eeb226657c 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -478,21 +478,22 @@ is486:
__INIT
setup_once:
/*
- * Set up a idt with 256 entries pointing to ignore_int,
- * interrupt gates. It doesn't actually load idt - that needs
- * to be done on each CPU. Interrupts are enabled elsewhere,
- * when we can be relatively sure everything is ok.
+ * Set up a idt with 256 interrupt gates that push zero if there
+ * is no error code and then jump to early_idt_handler_common.
+ * It doesn't actually load the idt - that needs to be done on
+ * each CPU. Interrupts are enabled elsewhere, when we can be
+ * relatively sure everything is ok.
*/
movl $idt_table,%edi
- movl $early_idt_handlers,%eax
+ movl $early_idt_handler_array,%eax
movl $NUM_EXCEPTION_VECTORS,%ecx
1:
movl %eax,(%edi)
movl %eax,4(%edi)
/* interrupt gate, dpl=0, present */
movl $(0x8E000000 + __KERNEL_CS),2(%edi)
- addl $9,%eax
+ addl $EARLY_IDT_HANDLER_SIZE,%eax
addl $8,%edi
loop 1b
@@ -524,26 +525,28 @@ setup_once:
andl $0,setup_once_ref /* Once is enough, thanks */
ret
-ENTRY(early_idt_handlers)
+ENTRY(early_idt_handler_array)
# 36(%esp) %eflags
# 32(%esp) %cs
# 28(%esp) %eip
# 24(%rsp) error code
i = 0
.rept NUM_EXCEPTION_VECTORS
- .if (EXCEPTION_ERRCODE_MASK >> i) & 1
- ASM_NOP2
- .else
+ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
pushl $0 # Dummy error code, to make stack frame uniform
.endif
pushl $i # 20(%esp) Vector number
- jmp early_idt_handler
+ jmp early_idt_handler_common
i = i + 1
+ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
.endr
-ENDPROC(early_idt_handlers)
+ENDPROC(early_idt_handler_array)
- /* This is global to keep gas from relaxing the jumps */
-ENTRY(early_idt_handler)
+early_idt_handler_common:
+ /*
+ * The stack is the hardware frame, an error code or zero, and the
+ * vector number.
+ */
cld
cmpl $2,(%esp) # X86_TRAP_NMI
@@ -603,7 +606,7 @@ ex_entry:
is_nmi:
addl $8,%esp /* drop vector number and error code */
iret
-ENDPROC(early_idt_handler)
+ENDPROC(early_idt_handler_common)
/* This is the default interrupt "handler" :-) */
ALIGN
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index ae6588b301c2..df7e78057ae0 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -321,26 +321,28 @@ bad_address:
jmp bad_address
__INIT
- .globl early_idt_handlers
-early_idt_handlers:
+ENTRY(early_idt_handler_array)
# 104(%rsp) %rflags
# 96(%rsp) %cs
# 88(%rsp) %rip
# 80(%rsp) error code
i = 0
.rept NUM_EXCEPTION_VECTORS
- .if (EXCEPTION_ERRCODE_MASK >> i) & 1
- ASM_NOP2
- .else
+ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
pushq $0 # Dummy error code, to make stack frame uniform
.endif
pushq $i # 72(%rsp) Vector number
- jmp early_idt_handler
+ jmp early_idt_handler_common
i = i + 1
+ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
.endr
+ENDPROC(early_idt_handler_array)
-/* This is global to keep gas from relaxing the jumps */
-ENTRY(early_idt_handler)
+early_idt_handler_common:
+ /*
+ * The stack is the hardware frame, an error code or zero, and the
+ * vector number.
+ */
cld
cmpl $2,(%rsp) # X86_TRAP_NMI
@@ -412,7 +414,7 @@ ENTRY(early_idt_handler)
is_nmi:
addq $16,%rsp # drop vector number and error code
INTERRUPT_RETURN
-ENDPROC(early_idt_handler)
+ENDPROC(early_idt_handler_common)
__INITDATA
diff --git a/block/genhd.c b/block/genhd.c
index 0a536dc05f3b..666e11b83983 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -653,7 +653,6 @@ void del_gendisk(struct gendisk *disk)
disk->flags &= ~GENHD_FL_UP;
sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
- bdi_unregister(&disk->queue->backing_dev_info);
blk_unregister_queue(disk);
blk_unregister_region(disk_devt(disk), disk->minors);
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 9c2ba1c97c42..df0c66cb7ad3 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -179,7 +179,7 @@ static int detect_cache_attributes(unsigned int cpu)
{
int ret;
- if (init_cache_level(cpu))
+ if (init_cache_level(cpu) || !cache_leaves(cpu))
return -ENOENT;
per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
diff --git a/drivers/base/init.c b/drivers/base/init.c
index da033d3bab3c..48c0e220acc0 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/memory.h>
+#include <linux/of.h>
#include "base.h"
@@ -34,4 +35,5 @@ void __init driver_init(void)
cpu_dev_init();
memory_dev_init();
container_dev_init();
+ of_core_init();
}
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 85b8036deaa3..683dff272562 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1750,6 +1750,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
struct nvme_iod *iod;
dma_addr_t meta_dma = 0;
void *meta = NULL;
+ void __user *metadata;
if (copy_from_user(&io, uio, sizeof(io)))
return -EFAULT;
@@ -1763,6 +1764,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
meta_len = 0;
}
+ metadata = (void __user *)(unsigned long)io.metadata;
+
write = io.opcode & 1;
switch (io.opcode) {
@@ -1786,13 +1789,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
if (meta_len) {
meta = dma_alloc_coherent(&dev->pci_dev->dev, meta_len,
&meta_dma, GFP_KERNEL);
+
if (!meta) {
status = -ENOMEM;
goto unmap;
}
if (write) {
- if (copy_from_user(meta, (void __user *)io.metadata,
- meta_len)) {
+ if (copy_from_user(meta, metadata, meta_len)) {
status = -EFAULT;
goto unmap;
}
@@ -1819,8 +1822,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
nvme_free_iod(dev, iod);
if (meta) {
if (status == NVME_SC_SUCCESS && !write) {
- if (copy_to_user((void __user *)io.metadata, meta,
- meta_len))
+ if (copy_to_user(metadata, meta, meta_len))
status = -EFAULT;
}
dma_free_coherent(&dev->pci_dev->dev, meta_len, meta, meta_dma);
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9897f353bf1a..1dd4f9d8bcb6 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -78,6 +78,23 @@ config COMMON_CLK_SI570
This driver supports Silicon Labs 570/571/598/599 programmable
clock generators.
+config COMMON_CLK_CDCE925
+ tristate "Clock driver for TI CDCE925 devices"
+ depends on I2C
+ depends on OF
+ select REGMAP_I2C
+ help
+ ---help---
+ This driver supports the TI CDCE925 programmable clock synthesizer.
+ The chip contains two PLLs with spread-spectrum clocking support and
+ five output dividers. The driver only supports the following setup,
+ and uses a fixed setting for the output muxes.
+ Y1 is derived from the input clock
+ Y2 and Y3 derive from PLL1
+ Y4 and Y5 derive from PLL2
+ Given a target output frequency, the driver will set the PLL and
+ divider to best approximate the desired output.
+
config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
depends on MFD_SEC_CORE
@@ -150,11 +167,12 @@ config COMMON_CLK_CDCE706
---help---
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
+source "drivers/clk/bcm/Kconfig"
+source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/qcom/Kconfig"
endmenu
-source "drivers/clk/bcm/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/samsung/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..3233f0e8bf43 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
+obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
@@ -47,14 +48,14 @@ obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
-obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
-obj-$(CONFIG_ARCH_HIP04) += hisilicon/
-obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
+obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
endif
obj-$(CONFIG_PLAT_ORION) += mvebu/
+obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 59fa3cc96c9e..c2400456a044 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -614,7 +614,7 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
const char *name = np->name;
int i;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index c1af80bcdf20..f98eafe9b12d 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -224,7 +224,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
const char *name = np->name;
struct clk_master_characteristics *characteristics;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
return;
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 86c8a073dcc3..8c86c0f7847a 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -237,7 +237,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
const char *name;
struct device_node *progclknp;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
return;
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index 2f13bd5246b5..98a84a865fe1 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -373,7 +373,7 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
const char *name = np->name;
int i;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > 2)
return;
@@ -451,7 +451,7 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
const char *name = np->name;
int i;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 144d47ecfe63..3817ea865ca2 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -150,7 +150,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
return;
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 0b7c3e8840ba..b0cbd2b1ff59 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -378,7 +378,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
- num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ num_parents = of_clk_get_parent_count(np);
if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
return;
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 3f27d21fb729..39be2be82b0a 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -153,7 +153,7 @@ static int pmc_irq_domain_xlate(struct irq_domain *d,
return 0;
}
-static struct irq_domain_ops pmc_irq_ops = {
+static const struct irq_domain_ops pmc_irq_ops = {
.map = pmc_irq_map,
.xlate = pmc_irq_domain_xlate,
};
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index e5aededdd322..deaa7f962b84 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -21,8 +21,6 @@
#define selector_clear_exists(sel) ((sel)->width = 0)
#define trigger_clear_exists(trig) FLAG_CLEAR(trig, TRIG, EXISTS)
-LIST_HEAD(ccu_list); /* The list of set up CCUs */
-
/* Validity checking */
static bool ccu_data_offsets_valid(struct ccu_data *ccu)
@@ -773,7 +771,6 @@ static void kona_ccu_teardown(struct ccu_data *ccu)
of_clk_del_provider(ccu->node); /* safe if never added */
ccu_clks_teardown(ccu);
- list_del(&ccu->links);
of_node_put(ccu->node);
ccu->node = NULL;
iounmap(ccu->base);
@@ -847,7 +844,6 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
goto out_err;
}
ccu->node = of_node_get(node);
- list_add_tail(&ccu->links, &ccu_list);
/*
* Set up each defined kona clock and save the result in
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index a0ef4f75d457..79a98506c433 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1240,7 +1240,7 @@ static bool __kona_clk_init(struct kona_clk *bcm_clk)
default:
BUG();
}
- return -EINVAL;
+ return false;
}
/* Set a CCU and all its clocks into their desired initial state */
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 6849a64baf6d..906576ec97b6 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -480,7 +480,6 @@ struct ccu_data {
spinlock_t lock; /* serialization lock */
bool write_enabled; /* write access is currently enabled */
struct ccu_policy policy;
- struct list_head links; /* for ccu_list */
struct device_node *node;
struct clk_onecell_data clk_data;
const char *name;
@@ -492,7 +491,6 @@ struct ccu_data {
#define KONA_CCU_COMMON(_prefix, _name, _ccuname) \
.name = #_name "_ccu", \
.lock = __SPIN_LOCK_UNLOCKED(_name ## _ccu_data.lock), \
- .links = LIST_HEAD_INIT(_name ## _ccu_data.links), \
.clk_data = { \
.clk_num = _prefix ## _ ## _ccuname ## _CCU_CLOCK_COUNT, \
}
diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c
index bdc506b03824..f4b8d324b083 100644
--- a/drivers/clk/berlin/berlin2-pll.c
+++ b/drivers/clk/berlin/berlin2-pll.c
@@ -25,14 +25,7 @@
#include <asm/div64.h>
#include "berlin2-div.h"
-
-struct berlin2_pll_map {
- const u8 vcodiv[16];
- u8 mult;
- u8 fbdiv_shift;
- u8 rfdiv_shift;
- u8 divsel_shift;
-};
+#include "berlin2-pll.h"
struct berlin2_pll {
struct clk_hw hw;
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
index 88f4ff6916fe..90897af8d9f7 100644
--- a/drivers/clk/clk-asm9260.c
+++ b/drivers/clk/clk-asm9260.c
@@ -274,7 +274,7 @@ static void __init asm9260_acc_init(struct device_node *np)
u32 accuracy = 0;
base = of_io_request_and_map(np, 0, np->name);
- if (!base)
+ if (IS_ERR(base))
panic("%s: unable to map resource", np->name);
/* register pll */
diff --git a/drivers/clk/clk-axm5516.c b/drivers/clk/clk-axm5516.c
index 0f6368ceec4c..c7c91a5ecf8b 100644
--- a/drivers/clk/clk-axm5516.c
+++ b/drivers/clk/clk-axm5516.c
@@ -556,7 +556,7 @@ static int axmclk_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
num_clks = ARRAY_SIZE(axmclk_clocks);
- pr_info("axmclk: supporting %u clocks\n", num_clks);
+ pr_info("axmclk: supporting %zu clocks\n", num_clks);
priv = devm_kzalloc(dev, sizeof(*priv) + sizeof(*priv->clks) * num_clks,
GFP_KERNEL);
if (!priv)
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index b8e4f8a822e9..f01164fada5d 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -94,7 +94,7 @@ static const char * const cdce706_source_name[] = {
"clk_in0", "clk_in1",
};
-static const char *cdce706_clkin_name[] = {
+static const char * const cdce706_clkin_name[] = {
"clk_in",
};
@@ -102,7 +102,7 @@ static const char * const cdce706_pll_name[] = {
"pll1", "pll2", "pll3",
};
-static const char *cdce706_divider_parent_name[] = {
+static const char * const cdce706_divider_parent_name[] = {
"clk_in", "pll1", "pll2", "pll2", "pll3",
};
@@ -666,6 +666,7 @@ static int cdce706_probe(struct i2c_client *client,
static int cdce706_remove(struct i2c_client *client)
{
+ of_clk_del_provider(client->dev.of_node);
return 0;
}
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
new file mode 100644
index 000000000000..85fafb41e6ca
--- /dev/null
+++ b/drivers/clk/clk-cdce925.c
@@ -0,0 +1,749 @@
+/*
+ * Driver for TI Dual PLL CDCE925 clock synthesizer
+ *
+ * This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1
+ * and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve
+ * basis. Clients can directly request any frequency that the chip can
+ * deliver using the standard clk framework. In addition, the device can
+ * be configured and activated via the devicetree.
+ *
+ * Copyright (C) 2014, Topic Embedded Products
+ * Licenced under GPL
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/gcd.h>
+
+/* The chip has 2 PLLs which can be routed through dividers to 5 outputs.
+ * Model this as 2 PLL clocks which are parents to the outputs.
+ */
+#define NUMBER_OF_PLLS 2
+#define NUMBER_OF_OUTPUTS 5
+
+#define CDCE925_REG_GLOBAL1 0x01
+#define CDCE925_REG_Y1SPIPDIVH 0x02
+#define CDCE925_REG_PDIVL 0x03
+#define CDCE925_REG_XCSEL 0x05
+/* PLL parameters start at 0x10, steps of 0x10 */
+#define CDCE925_OFFSET_PLL 0x10
+/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */
+#define CDCE925_PLL_MUX_OUTPUTS 0x14
+#define CDCE925_PLL_MULDIV 0x18
+
+#define CDCE925_PLL_FREQUENCY_MIN 80000000ul
+#define CDCE925_PLL_FREQUENCY_MAX 230000000ul
+struct clk_cdce925_chip;
+
+struct clk_cdce925_output {
+ struct clk_hw hw;
+ struct clk_cdce925_chip *chip;
+ u8 index;
+ u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */
+};
+#define to_clk_cdce925_output(_hw) \
+ container_of(_hw, struct clk_cdce925_output, hw)
+
+struct clk_cdce925_pll {
+ struct clk_hw hw;
+ struct clk_cdce925_chip *chip;
+ u8 index;
+ u16 m; /* 1..511 */
+ u16 n; /* 1..4095 */
+};
+#define to_clk_cdce925_pll(_hw) container_of(_hw, struct clk_cdce925_pll, hw)
+
+struct clk_cdce925_chip {
+ struct regmap *regmap;
+ struct i2c_client *i2c_client;
+ struct clk_cdce925_pll pll[NUMBER_OF_PLLS];
+ struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS];
+ struct clk *dt_clk[NUMBER_OF_OUTPUTS];
+ struct clk_onecell_data onecell;
+};
+
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+
+static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate,
+ u16 n, u16 m)
+{
+ if ((!m || !n) || (m == n))
+ return parent_rate; /* In bypass mode runs at same frequency */
+ return mult_frac(parent_rate, (unsigned long)n, (unsigned long)m);
+}
+
+static unsigned long cdce925_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ /* Output frequency of PLL is Fout = (Fin/Pdiv)*(N/M) */
+ struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+ return cdce925_pll_calculate_rate(parent_rate, data->n, data->m);
+}
+
+static void cdce925_pll_find_rate(unsigned long rate,
+ unsigned long parent_rate, u16 *n, u16 *m)
+{
+ unsigned long un;
+ unsigned long um;
+ unsigned long g;
+
+ if (rate <= parent_rate) {
+ /* Can always deliver parent_rate in bypass mode */
+ rate = parent_rate;
+ *n = 0;
+ *m = 0;
+ } else {
+ /* In PLL mode, need to apply min/max range */
+ if (rate < CDCE925_PLL_FREQUENCY_MIN)
+ rate = CDCE925_PLL_FREQUENCY_MIN;
+ else if (rate > CDCE925_PLL_FREQUENCY_MAX)
+ rate = CDCE925_PLL_FREQUENCY_MAX;
+
+ g = gcd(rate, parent_rate);
+ um = parent_rate / g;
+ un = rate / g;
+ /* When outside hw range, reduce to fit (rounding errors) */
+ while ((un > 4095) || (um > 511)) {
+ un >>= 1;
+ um >>= 1;
+ }
+ if (un == 0)
+ un = 1;
+ if (um == 0)
+ um = 1;
+
+ *n = un;
+ *m = um;
+ }
+}
+
+static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u16 n, m;
+
+ cdce925_pll_find_rate(rate, *parent_rate, &n, &m);
+ return (long)cdce925_pll_calculate_rate(*parent_rate, n, m);
+}
+
+static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+ if (!rate || (rate == parent_rate)) {
+ data->m = 0; /* Bypass mode */
+ data->n = 0;
+ return 0;
+ }
+
+ if ((rate < CDCE925_PLL_FREQUENCY_MIN) ||
+ (rate > CDCE925_PLL_FREQUENCY_MAX)) {
+ pr_debug("%s: rate %lu outside PLL range.\n", __func__, rate);
+ return -EINVAL;
+ }
+
+ if (rate < parent_rate) {
+ pr_debug("%s: rate %lu less than parent rate %lu.\n", __func__,
+ rate, parent_rate);
+ return -EINVAL;
+ }
+
+ cdce925_pll_find_rate(rate, parent_rate, &data->n, &data->m);
+ return 0;
+}
+
+
+/* calculate p = max(0, 4 - int(log2 (n/m))) */
+static u8 cdce925_pll_calc_p(u16 n, u16 m)
+{
+ u8 p;
+ u16 r = n / m;
+
+ if (r >= 16)
+ return 0;
+ p = 4;
+ while (r > 1) {
+ r >>= 1;
+ --p;
+ }
+ return p;
+}
+
+/* Returns VCO range bits for VCO1_0_RANGE */
+static u8 cdce925_pll_calc_range_bits(struct clk_hw *hw, u16 n, u16 m)
+{
+ struct clk *parent = clk_get_parent(hw->clk);
+ unsigned long rate = clk_get_rate(parent);
+
+ rate = mult_frac(rate, (unsigned long)n, (unsigned long)m);
+ if (rate >= 175000000)
+ return 0x3;
+ if (rate >= 150000000)
+ return 0x02;
+ if (rate >= 125000000)
+ return 0x01;
+ return 0x00;
+}
+
+/* I2C clock, hence everything must happen in (un)prepare because this
+ * may sleep */
+static int cdce925_pll_prepare(struct clk_hw *hw)
+{
+ struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+ u16 n = data->n;
+ u16 m = data->m;
+ u16 r;
+ u8 q;
+ u8 p;
+ u16 nn;
+ u8 pll[4]; /* Bits are spread out over 4 byte registers */
+ u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+ unsigned i;
+
+ if ((!m || !n) || (m == n)) {
+ /* Set PLL mux to bypass mode, leave the rest as is */
+ regmap_update_bits(data->chip->regmap,
+ reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+ } else {
+ /* According to data sheet: */
+ /* p = max(0, 4 - int(log2 (n/m))) */
+ p = cdce925_pll_calc_p(n, m);
+ /* nn = n * 2^p */
+ nn = n * BIT(p);
+ /* q = int(nn/m) */
+ q = nn / m;
+ if ((q < 16) || (1 > 64)) {
+ pr_debug("%s invalid q=%d\n", __func__, q);
+ return -EINVAL;
+ }
+ r = nn - (m*q);
+ if (r > 511) {
+ pr_debug("%s invalid r=%d\n", __func__, r);
+ return -EINVAL;
+ }
+ pr_debug("%s n=%d m=%d p=%d q=%d r=%d\n", __func__,
+ n, m, p, q, r);
+ /* encode into register bits */
+ pll[0] = n >> 4;
+ pll[1] = ((n & 0x0F) << 4) | ((r >> 5) & 0x0F);
+ pll[2] = ((r & 0x1F) << 3) | ((q >> 3) & 0x07);
+ pll[3] = ((q & 0x07) << 5) | (p << 2) |
+ cdce925_pll_calc_range_bits(hw, n, m);
+ /* Write to registers */
+ for (i = 0; i < ARRAY_SIZE(pll); ++i)
+ regmap_write(data->chip->regmap,
+ reg_ofs + CDCE925_PLL_MULDIV + i, pll[i]);
+ /* Enable PLL */
+ regmap_update_bits(data->chip->regmap,
+ reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x00);
+ }
+
+ return 0;
+}
+
+static void cdce925_pll_unprepare(struct clk_hw *hw)
+{
+ struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+ u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+
+ regmap_update_bits(data->chip->regmap,
+ reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+}
+
+static const struct clk_ops cdce925_pll_ops = {
+ .prepare = cdce925_pll_prepare,
+ .unprepare = cdce925_pll_unprepare,
+ .recalc_rate = cdce925_pll_recalc_rate,
+ .round_rate = cdce925_pll_round_rate,
+ .set_rate = cdce925_pll_set_rate,
+};
+
+
+static void cdce925_clk_set_pdiv(struct clk_cdce925_output *data, u16 pdiv)
+{
+ switch (data->index) {
+ case 0:
+ regmap_update_bits(data->chip->regmap,
+ CDCE925_REG_Y1SPIPDIVH,
+ 0x03, (pdiv >> 8) & 0x03);
+ regmap_write(data->chip->regmap, 0x03, pdiv & 0xFF);
+ break;
+ case 1:
+ regmap_update_bits(data->chip->regmap, 0x16, 0x7F, pdiv);
+ break;
+ case 2:
+ regmap_update_bits(data->chip->regmap, 0x17, 0x7F, pdiv);
+ break;
+ case 3:
+ regmap_update_bits(data->chip->regmap, 0x26, 0x7F, pdiv);
+ break;
+ case 4:
+ regmap_update_bits(data->chip->regmap, 0x27, 0x7F, pdiv);
+ break;
+ }
+}
+
+static void cdce925_clk_activate(struct clk_cdce925_output *data)
+{
+ switch (data->index) {
+ case 0:
+ regmap_update_bits(data->chip->regmap,
+ CDCE925_REG_Y1SPIPDIVH, 0x0c, 0x0c);
+ break;
+ case 1:
+ case 2:
+ regmap_update_bits(data->chip->regmap, 0x14, 0x03, 0x03);
+ break;
+ case 3:
+ case 4:
+ regmap_update_bits(data->chip->regmap, 0x24, 0x03, 0x03);
+ break;
+ }
+}
+
+static int cdce925_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+ cdce925_clk_set_pdiv(data, data->pdiv);
+ cdce925_clk_activate(data);
+ return 0;
+}
+
+static void cdce925_clk_unprepare(struct clk_hw *hw)
+{
+ struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+ /* Disable clock by setting divider to "0" */
+ cdce925_clk_set_pdiv(data, 0);
+}
+
+static unsigned long cdce925_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+ if (data->pdiv)
+ return parent_rate / data->pdiv;
+ return 0;
+}
+
+static u16 cdce925_calc_divider(unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned long divider;
+
+ if (!rate)
+ return 0;
+ if (rate >= parent_rate)
+ return 1;
+
+ divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+ if (divider > 0x7F)
+ divider = 0x7F;
+
+ return (u16)divider;
+}
+
+static unsigned long cdce925_clk_best_parent_rate(
+ struct clk_hw *hw, unsigned long rate)
+{
+ struct clk *pll = clk_get_parent(hw->clk);
+ struct clk *root = clk_get_parent(pll);
+ unsigned long root_rate = clk_get_rate(root);
+ unsigned long best_rate_error = rate;
+ u16 pdiv_min;
+ u16 pdiv_max;
+ u16 pdiv_best;
+ u16 pdiv_now;
+
+ if (root_rate % rate == 0)
+ return root_rate; /* Don't need the PLL, use bypass */
+
+ pdiv_min = (u16)max(1ul, DIV_ROUND_UP(CDCE925_PLL_FREQUENCY_MIN, rate));
+ pdiv_max = (u16)min(127ul, CDCE925_PLL_FREQUENCY_MAX / rate);
+
+ if (pdiv_min > pdiv_max)
+ return 0; /* No can do? */
+
+ pdiv_best = pdiv_min;
+ for (pdiv_now = pdiv_min; pdiv_now < pdiv_max; ++pdiv_now) {
+ unsigned long target_rate = rate * pdiv_now;
+ long pll_rate = clk_round_rate(pll, target_rate);
+ unsigned long actual_rate;
+ unsigned long rate_error;
+
+ if (pll_rate <= 0)
+ continue;
+ actual_rate = pll_rate / pdiv_now;
+ rate_error = abs((long)actual_rate - (long)rate);
+ if (rate_error < best_rate_error) {
+ pdiv_best = pdiv_now;
+ best_rate_error = rate_error;
+ }
+ /* TODO: Consider PLL frequency based on smaller n/m values
+ * and pick the better one if the error is equal */
+ }
+
+ return rate * pdiv_best;
+}
+
+static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long l_parent_rate = *parent_rate;
+ u16 divider = cdce925_calc_divider(rate, l_parent_rate);
+
+ if (l_parent_rate / divider != rate) {
+ l_parent_rate = cdce925_clk_best_parent_rate(hw, rate);
+ divider = cdce925_calc_divider(rate, l_parent_rate);
+ *parent_rate = l_parent_rate;
+ }
+
+ if (divider)
+ return (long)(l_parent_rate / divider);
+ return 0;
+}
+
+static int cdce925_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+ data->pdiv = cdce925_calc_divider(rate, parent_rate);
+
+ return 0;
+}
+
+static const struct clk_ops cdce925_clk_ops = {
+ .prepare = cdce925_clk_prepare,
+ .unprepare = cdce925_clk_unprepare,
+ .recalc_rate = cdce925_clk_recalc_rate,
+ .round_rate = cdce925_clk_round_rate,
+ .set_rate = cdce925_clk_set_rate,
+};
+
+
+static u16 cdce925_y1_calc_divider(unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned long divider;
+
+ if (!rate)
+ return 0;
+ if (rate >= parent_rate)
+ return 1;
+
+ divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+ if (divider > 0x3FF) /* Y1 has 10-bit divider */
+ divider = 0x3FF;
+
+ return (u16)divider;
+}
+
+static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long l_parent_rate = *parent_rate;
+ u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate);
+
+ if (divider)
+ return (long)(l_parent_rate / divider);
+ return 0;
+}
+
+static int cdce925_clk_y1_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+ data->pdiv = cdce925_y1_calc_divider(rate, parent_rate);
+
+ return 0;
+}
+
+static const struct clk_ops cdce925_clk_y1_ops = {
+ .prepare = cdce925_clk_prepare,
+ .unprepare = cdce925_clk_unprepare,
+ .recalc_rate = cdce925_clk_recalc_rate,
+ .round_rate = cdce925_clk_y1_round_rate,
+ .set_rate = cdce925_clk_y1_set_rate,
+};
+
+
+static struct regmap_config cdce925_regmap_config = {
+ .name = "configuration0",
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = 0x2F,
+};
+
+#define CDCE925_I2C_COMMAND_BLOCK_TRANSFER 0x00
+#define CDCE925_I2C_COMMAND_BYTE_TRANSFER 0x80
+
+static int cdce925_regmap_i2c_write(
+ void *context, const void *data, size_t count)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ int ret;
+ u8 reg_data[2];
+
+ if (count != 2)
+ return -ENOTSUPP;
+
+ /* First byte is command code */
+ reg_data[0] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)data)[0];
+ reg_data[1] = ((u8 *)data)[1];
+
+ dev_dbg(&i2c->dev, "%s(%zu) %#x %#x\n", __func__, count,
+ reg_data[0], reg_data[1]);
+
+ ret = i2c_master_send(i2c, reg_data, count);
+ if (likely(ret == count))
+ return 0;
+ else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+static int cdce925_regmap_i2c_read(void *context,
+ const void *reg, size_t reg_size, void *val, size_t val_size)
+{
+ struct device *dev = context;
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct i2c_msg xfer[2];
+ int ret;
+ u8 reg_data[2];
+
+ if (reg_size != 1)
+ return -ENOTSUPP;
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].buf = reg_data;
+ if (val_size == 1) {
+ reg_data[0] =
+ CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)reg)[0];
+ xfer[0].len = 1;
+ } else {
+ reg_data[0] =
+ CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ((u8 *)reg)[0];
+ reg_data[1] = val_size;
+ xfer[0].len = 2;
+ }
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = val_size;
+ xfer[1].buf = val;
+
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (likely(ret == 2)) {
+ dev_dbg(&i2c->dev, "%s(%zu, %zu) %#x %#x\n", __func__,
+ reg_size, val_size, reg_data[0], *((u8 *)val));
+ return 0;
+ } else if (ret < 0)
+ return ret;
+ else
+ return -EIO;
+}
+
+/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
+ * just weird, so just use the single byte mode exclusively. */
+static struct regmap_bus regmap_cdce925_bus = {
+ .write = cdce925_regmap_i2c_write,
+ .read = cdce925_regmap_i2c_read,
+};
+
+static int cdce925_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct clk_cdce925_chip *data;
+ struct device_node *node = client->dev.of_node;
+ const char *parent_name;
+ const char *pll_clk_name[NUMBER_OF_PLLS] = {NULL,};
+ struct clk_init_data init;
+ struct clk *clk;
+ u32 value;
+ int i;
+ int err;
+ struct device_node *np_output;
+ char child_name[6];
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->i2c_client = client;
+ data->regmap = devm_regmap_init(&client->dev, &regmap_cdce925_bus,
+ &client->dev, &cdce925_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "failed to allocate register map\n");
+ return PTR_ERR(data->regmap);
+ }
+ i2c_set_clientdata(client, data);
+
+ parent_name = of_clk_get_parent_name(node, 0);
+ if (!parent_name) {
+ dev_err(&client->dev, "missing parent clock\n");
+ return -ENODEV;
+ }
+ dev_dbg(&client->dev, "parent is: %s\n", parent_name);
+
+ if (of_property_read_u32(node, "xtal-load-pf", &value) == 0)
+ regmap_write(data->regmap,
+ CDCE925_REG_XCSEL, (value << 3) & 0xF8);
+ /* PWDN bit */
+ regmap_update_bits(data->regmap, CDCE925_REG_GLOBAL1, BIT(4), 0);
+
+ /* Set input source for Y1 to be the XTAL */
+ regmap_update_bits(data->regmap, 0x02, BIT(7), 0);
+
+ init.ops = &cdce925_pll_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = parent_name ? 1 : 0;
+
+ /* Register PLL clocks */
+ for (i = 0; i < NUMBER_OF_PLLS; ++i) {
+ pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
+ client->dev.of_node->name, i);
+ init.name = pll_clk_name[i];
+ data->pll[i].chip = data;
+ data->pll[i].hw.init = &init;
+ data->pll[i].index = i;
+ clk = devm_clk_register(&client->dev, &data->pll[i].hw);
+ if (IS_ERR(clk)) {
+ dev_err(&client->dev, "Failed register PLL %d\n", i);
+ err = PTR_ERR(clk);
+ goto error;
+ }
+ sprintf(child_name, "PLL%d", i+1);
+ np_output = of_get_child_by_name(node, child_name);
+ if (!np_output)
+ continue;
+ if (!of_property_read_u32(np_output,
+ "clock-frequency", &value)) {
+ err = clk_set_rate(clk, value);
+ if (err)
+ dev_err(&client->dev,
+ "unable to set PLL frequency %ud\n",
+ value);
+ }
+ if (!of_property_read_u32(np_output,
+ "spread-spectrum", &value)) {
+ u8 flag = of_property_read_bool(np_output,
+ "spread-spectrum-center") ? 0x80 : 0x00;
+ regmap_update_bits(data->regmap,
+ 0x16 + (i*CDCE925_OFFSET_PLL),
+ 0x80, flag);
+ regmap_update_bits(data->regmap,
+ 0x12 + (i*CDCE925_OFFSET_PLL),
+ 0x07, value & 0x07);
+ }
+ }
+
+ /* Register output clock Y1 */
+ init.ops = &cdce925_clk_y1_ops;
+ init.flags = 0;
+ init.num_parents = 1;
+ init.parent_names = &parent_name; /* Mux Y1 to input */
+ init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
+ data->clk[0].chip = data;
+ data->clk[0].hw.init = &init;
+ data->clk[0].index = 0;
+ data->clk[0].pdiv = 1;
+ clk = devm_clk_register(&client->dev, &data->clk[0].hw);
+ kfree(init.name); /* clock framework made a copy of the name */
+ if (IS_ERR(clk)) {
+ dev_err(&client->dev, "clock registration Y1 failed\n");
+ err = PTR_ERR(clk);
+ goto error;
+ }
+ data->dt_clk[0] = clk;
+
+ /* Register output clocks Y2 .. Y5*/
+ init.ops = &cdce925_clk_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.num_parents = 1;
+ for (i = 1; i < NUMBER_OF_OUTPUTS; ++i) {
+ init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
+ client->dev.of_node->name, i+1);
+ data->clk[i].chip = data;
+ data->clk[i].hw.init = &init;
+ data->clk[i].index = i;
+ data->clk[i].pdiv = 1;
+ switch (i) {
+ case 1:
+ case 2:
+ /* Mux Y2/3 to PLL1 */
+ init.parent_names = &pll_clk_name[0];
+ break;
+ case 3:
+ case 4:
+ /* Mux Y4/5 to PLL2 */
+ init.parent_names = &pll_clk_name[1];
+ break;
+ }
+ clk = devm_clk_register(&client->dev, &data->clk[i].hw);
+ kfree(init.name); /* clock framework made a copy of the name */
+ if (IS_ERR(clk)) {
+ dev_err(&client->dev, "clock registration failed\n");
+ err = PTR_ERR(clk);
+ goto error;
+ }
+ data->dt_clk[i] = clk;
+ }
+
+ /* Register the output clocks */
+ data->onecell.clk_num = NUMBER_OF_OUTPUTS;
+ data->onecell.clks = data->dt_clk;
+ err = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
+ &data->onecell);
+ if (err)
+ dev_err(&client->dev, "unable to add OF clock provider\n");
+
+ err = 0;
+
+error:
+ for (i = 0; i < NUMBER_OF_PLLS; ++i)
+ /* clock framework made a copy of the name */
+ kfree(pll_clk_name[i]);
+
+ return err;
+}
+
+static const struct i2c_device_id cdce925_id[] = {
+ { "cdce925", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cdce925_id);
+
+static const struct of_device_id clk_cdce925_of_match[] = {
+ { .compatible = "ti,cdce925" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, clk_cdce925_of_match);
+
+static struct i2c_driver cdce925_driver = {
+ .driver = {
+ .name = "cdce925",
+ .of_match_table = of_match_ptr(clk_cdce925_of_match),
+ },
+ .probe = cdce925_probe,
+ .id_table = cdce925_id,
+};
+module_i2c_driver(cdce925_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("cdce925 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 956b7e54fa1c..616f5aef3c26 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
}
struct clk *clk_register_composite(struct device *dev, const char *name,
- const char **parent_names, int num_parents,
+ const char * const *parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
@@ -200,10 +200,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
struct clk_ops *clk_composite_ops;
composite = kzalloc(sizeof(*composite), GFP_KERNEL);
- if (!composite) {
- pr_err("%s: could not allocate composite clk\n", __func__);
+ if (!composite)
return ERR_PTR(-ENOMEM);
- }
init.name = name;
init.flags = flags | CLK_IS_BASIC;
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 48a65b2b4027..43a218f35b19 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -106,8 +106,9 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
rc = clk_set_rate(clk, rate);
if (rc < 0)
- pr_err("clk: couldn't set %s clock rate: %d\n",
- __clk_get_name(clk), rc);
+ pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+ __clk_get_name(clk), rate, rc,
+ clk_get_rate(clk));
clk_put(clk);
}
index++;
@@ -124,7 +125,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
* and sets any specified clock parents and rates. The @clk_supplier argument
* should be set to true if @node may be also a clock supplier of any clock
* listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
- * If @clk_supplier is false the function exits returnning 0 as soon as it
+ * If @clk_supplier is false the function exits returning 0 as soon as it
* determines the @node is also a supplier of any of the clocks.
*/
int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 25006a8bb8e6..706b5783c360 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -430,11 +430,9 @@ static struct clk *_register_divider(struct device *dev, const char *name,
}
/* allocate the divider */
- div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
- if (!div) {
- pr_err("%s: could not allocate divider clk\n", __func__);
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
return ERR_PTR(-ENOMEM);
- }
init.name = name;
init.ops = &clk_divider_ops;
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index d9e3f671c2ea..fccabe497f6e 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -55,10 +55,16 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
+ /*
+ * We must report success but we can do so unconditionally because
+ * clk_factor_round_rate returns values that ensure this call is a
+ * nop.
+ */
+
return 0;
}
-struct clk_ops clk_fixed_factor_ops = {
+const struct clk_ops clk_fixed_factor_ops = {
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
.recalc_rate = clk_factor_recalc_rate,
@@ -74,10 +80,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
struct clk *clk;
fix = kmalloc(sizeof(*fix), GFP_KERNEL);
- if (!fix) {
- pr_err("%s: could not allocate fixed factor clk\n", __func__);
+ if (!fix)
return ERR_PTR(-ENOMEM);
- }
/* struct clk_fixed_factor assignments */
fix->mult = mult;
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab6e844..f85ec8d1711f 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -65,11 +65,9 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
struct clk_init_data init;
/* allocate fixed-rate clock */
- fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
- if (!fixed) {
- pr_err("%s: could not allocate fixed clk\n", __func__);
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
return ERR_PTR(-ENOMEM);
- }
init.name = name;
init.ops = &clk_fixed_rate_ops;
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 6aa72d9d79ba..140eb5844dc4 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -109,10 +109,8 @@ struct clk *clk_register_fractional_divider(struct device *dev,
struct clk *clk;
fd = kzalloc(sizeof(*fd), GFP_KERNEL);
- if (!fd) {
- dev_err(dev, "could not allocate fractional divider clk\n");
+ if (!fd)
return ERR_PTR(-ENOMEM);
- }
init.name = name;
init.ops = &clk_fractional_divider_ops;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 3f0e4200cb5d..551dd0672794 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -135,11 +135,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
}
/* allocate the gate */
- gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
- if (!gate) {
- pr_err("%s: could not allocate gated clk\n", __func__);
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
return ERR_PTR(-ENOMEM);
- }
init.name = name;
init.ops = &clk_gate_ops;
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
index a71cabedda93..f564e624fb93 100644
--- a/drivers/clk/clk-gpio-gate.c
+++ b/drivers/clk/clk-gpio-gate.c
@@ -189,7 +189,7 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
/**
* of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
*/
-void __init of_gpio_gate_clk_setup(struct device_node *node)
+static void __init of_gpio_gate_clk_setup(struct device_node *node)
{
struct clk_gpio_gate_delayed_register_data *data;
@@ -203,6 +203,5 @@ void __init of_gpio_gate_clk_setup(struct device_node *node)
of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
}
-EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
#endif
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
index ca80103ac188..d4c61985f448 100644
--- a/drivers/clk/clk-ls1x.c
+++ b/drivers/clk/clk-ls1x.c
@@ -80,9 +80,9 @@ static struct clk *__init clk_register_pll(struct device *dev,
return clk;
}
-static const char const *cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char const *ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char const *dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
+static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
+static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
void __init ls1x_clk_init(void)
{
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
index 6505049d50f1..35af9cb6da4f 100644
--- a/drivers/clk/clk-max-gen.c
+++ b/drivers/clk/clk-max-gen.c
@@ -31,6 +31,8 @@
#include <linux/of.h>
#include <linux/export.h>
+#include "clk-max-gen.h"
+
struct max_gen_clk {
struct regmap *regmap;
u32 mask;
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
index 30a3b6999e10..5181b89c3cb2 100644
--- a/drivers/clk/clk-moxart.c
+++ b/drivers/clk/clk-moxart.c
@@ -15,7 +15,7 @@
#include <linux/of_address.h>
#include <linux/clkdev.h>
-void __init moxart_of_pll_clk_init(struct device_node *node)
+static void __init moxart_of_pll_clk_init(struct device_node *node)
{
static void __iomem *base;
struct clk *clk, *ref_clk;
@@ -53,7 +53,7 @@ void __init moxart_of_pll_clk_init(struct device_node *node)
CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
moxart_of_pll_clk_init);
-void __init moxart_of_apb_clk_init(struct device_node *node)
+static void __init moxart_of_apb_clk_init(struct device_node *node)
{
static void __iomem *base;
struct clk *clk, *pll_clk;
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 69a094c3783d..6066a01b20ea 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -114,7 +114,8 @@ const struct clk_ops clk_mux_ro_ops = {
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
struct clk *clk_register_mux_table(struct device *dev, const char *name,
- const char **parent_names, u8 num_parents, unsigned long flags,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{
@@ -166,7 +167,8 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
EXPORT_SYMBOL_GPL(clk_register_mux_table);
struct clk *clk_register_mux(struct device *dev, const char *name,
- const char **parent_names, u8 num_parents, unsigned long flags,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock)
{
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 30335d3b99af..e39e1e680b3c 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -552,7 +552,8 @@ static const struct clk_ops si5351_pll_ops = {
* MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
* MSx_P3[19:0] = c
*
- * MS[6,7] are integer (P1) divide only, P2 = 0, P3 = 0
+ * MS[6,7] are integer (P1) divide only, P1 = divide value,
+ * P2 and P3 are not applicable
*
* for 150MHz < fOUT <= 160MHz:
*
@@ -606,9 +607,6 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
if (!hwdata->params.valid)
si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
- if (hwdata->params.p3 == 0)
- return parent_rate;
-
/*
* multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3)
* multisync6-7: fOUT = fIN / P1
@@ -616,6 +614,8 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
rate = parent_rate;
if (hwdata->num > 5) {
m = hwdata->params.p1;
+ } else if (hwdata->params.p3 == 0) {
+ return parent_rate;
} else if ((si5351_reg_read(hwdata->drvdata, reg + 2) &
SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) {
m = 4;
@@ -679,6 +679,16 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
c = 1;
*parent_rate = a * rate;
+ } else if (hwdata->num >= 6) {
+ /* determine the closest integer divider */
+ a = DIV_ROUND_CLOSEST(*parent_rate, rate);
+ if (a < SI5351_MULTISYNTH_A_MIN)
+ a = SI5351_MULTISYNTH_A_MIN;
+ if (a > SI5351_MULTISYNTH67_A_MAX)
+ a = SI5351_MULTISYNTH67_A_MAX;
+
+ b = 0;
+ c = 1;
} else {
unsigned long rfrac, denom;
@@ -692,9 +702,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
a = *parent_rate / rate;
if (a < SI5351_MULTISYNTH_A_MIN)
a = SI5351_MULTISYNTH_A_MIN;
- if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX)
- a = SI5351_MULTISYNTH67_A_MAX;
- else if (a > SI5351_MULTISYNTH_A_MAX)
+ if (a > SI5351_MULTISYNTH_A_MAX)
a = SI5351_MULTISYNTH_A_MAX;
/* find best approximation for b/c = fVCO mod fOUT */
@@ -723,6 +731,10 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
hwdata->params.p3 = 1;
hwdata->params.p2 = 0;
hwdata->params.p1 = 0;
+ } else if (hwdata->num >= 6) {
+ hwdata->params.p3 = 0;
+ hwdata->params.p2 = 0;
+ hwdata->params.p1 = a;
} else {
hwdata->params.p3 = c;
hwdata->params.p2 = (128 * b) % c;
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index 406bfc1375b2..18bf5e576b93 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -12,6 +12,7 @@
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <linux/of.h>
+#include <linux/platform_data/clk-u300.h>
/* APP side SYSCON registers */
/* CLK Control Register 16bit (R/W) */
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index dd8a62d8f11f..f26b3ac36b27 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -42,12 +42,12 @@
static DEFINE_SPINLOCK(clk_lock);
-static inline u32 xgene_clk_read(void *csr)
+static inline u32 xgene_clk_read(void __iomem *csr)
{
return readl_relaxed(csr);
}
-static inline void xgene_clk_write(u32 data, void *csr)
+static inline void xgene_clk_write(u32 data, void __iomem *csr)
{
return writel_relaxed(data, csr);
}
@@ -119,7 +119,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
return fvco / nout;
}
-const struct clk_ops xgene_clk_pll_ops = {
+static const struct clk_ops xgene_clk_pll_ops = {
.is_enabled = xgene_clk_pll_is_enabled,
.recalc_rate = xgene_clk_pll_recalc_rate,
};
@@ -167,7 +167,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty
{
const char *clk_name = np->full_name;
struct clk *clk;
- void *reg;
+ void __iomem *reg;
reg = of_iomap(np, 0);
if (reg == NULL) {
@@ -222,20 +222,22 @@ static int xgene_clk_enable(struct clk_hw *hw)
struct xgene_clk *pclk = to_xgene_clk(hw);
unsigned long flags = 0;
u32 data;
+ phys_addr_t reg;
if (pclk->lock)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
pr_debug("%s clock enabled\n", pclk->name);
+ reg = __pa(pclk->param.csr_reg);
/* First enable the clock */
data = xgene_clk_read(pclk->param.csr_reg +
pclk->param.reg_clk_offset);
data |= pclk->param.reg_clk_mask;
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_clk_offset);
- pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n",
- pclk->name, __pa(pclk->param.csr_reg),
+ pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
+ pclk->name, &reg,
pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
data);
@@ -245,8 +247,8 @@ static int xgene_clk_enable(struct clk_hw *hw)
data &= ~pclk->param.reg_csr_mask;
xgene_clk_write(data, pclk->param.csr_reg +
pclk->param.reg_csr_offset);
- pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n",
- pclk->name, __pa(pclk->param.csr_reg),
+ pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
+ pclk->name, &reg,
pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
data);
}
@@ -386,7 +388,7 @@ static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
return parent_rate / divider;
}
-const struct clk_ops xgene_clk_ops = {
+static const struct clk_ops xgene_clk_ops = {
.enable = xgene_clk_enable,
.disable = xgene_clk_disable,
.is_enabled = xgene_clk_is_enabled,
@@ -456,7 +458,7 @@ static void __init xgene_devclk_init(struct device_node *np)
parameters.csr_reg = NULL;
parameters.divider_reg = NULL;
for (i = 0; i < 2; i++) {
- void *map_res;
+ void __iomem *map_res;
rc = of_address_to_resource(np, i, &res);
if (rc != 0) {
if (i == 0) {
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5b0f41868b42..1cf479b9f3b4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/clkdev.h>
#include "clk.h"
@@ -37,13 +38,6 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
-static long clk_core_get_accuracy(struct clk_core *clk);
-static unsigned long clk_core_get_rate(struct clk_core *clk);
-static int clk_core_get_phase(struct clk_core *clk);
-static bool clk_core_is_prepared(struct clk_core *clk);
-static bool clk_core_is_enabled(struct clk_core *clk);
-static struct clk_core *clk_core_lookup(const char *name);
-
/*** private data structures ***/
struct clk_core {
@@ -68,11 +62,11 @@ struct clk_core {
int phase;
struct hlist_head children;
struct hlist_node child_node;
- struct hlist_node debug_node;
struct hlist_head clks;
unsigned int notifier_count;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
+ struct hlist_node debug_node;
#endif
struct kref ref;
};
@@ -145,382 +139,71 @@ static void clk_enable_unlock(unsigned long flags)
spin_unlock_irqrestore(&enable_lock, flags);
}
-/*** debugfs support ***/
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-
-static struct dentry *rootdir;
-static int inited = 0;
-static DEFINE_MUTEX(clk_debug_lock);
-static HLIST_HEAD(clk_debug_list);
-
-static struct hlist_head *all_lists[] = {
- &clk_root_list,
- &clk_orphan_list,
- NULL,
-};
-
-static struct hlist_head *orphan_list[] = {
- &clk_orphan_list,
- NULL,
-};
-
-static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
- int level)
-{
- if (!c)
- return;
-
- seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
- level * 3 + 1, "",
- 30 - level * 3, c->name,
- c->enable_count, c->prepare_count, clk_core_get_rate(c),
- clk_core_get_accuracy(c), clk_core_get_phase(c));
-}
-
-static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
- int level)
-{
- struct clk_core *child;
-
- if (!c)
- return;
-
- clk_summary_show_one(s, c, level);
-
- hlist_for_each_entry(child, &c->children, child_node)
- clk_summary_show_subtree(s, child, level + 1);
-}
-
-static int clk_summary_show(struct seq_file *s, void *data)
-{
- struct clk_core *c;
- struct hlist_head **lists = (struct hlist_head **)s->private;
-
- seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy phase\n");
- seq_puts(s, "----------------------------------------------------------------------------------------\n");
-
- clk_prepare_lock();
-
- for (; *lists; lists++)
- hlist_for_each_entry(c, *lists, child_node)
- clk_summary_show_subtree(s, c, 0);
-
- clk_prepare_unlock();
-
- return 0;
-}
-
-
-static int clk_summary_open(struct inode *inode, struct file *file)
+static bool clk_core_is_prepared(struct clk_core *core)
{
- return single_open(file, clk_summary_show, inode->i_private);
-}
-
-static const struct file_operations clk_summary_fops = {
- .open = clk_summary_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
-{
- if (!c)
- return;
-
- seq_printf(s, "\"%s\": { ", c->name);
- seq_printf(s, "\"enable_count\": %d,", c->enable_count);
- seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
- seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
- seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
- seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
-}
-
-static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
-{
- struct clk_core *child;
-
- if (!c)
- return;
-
- clk_dump_one(s, c, level);
-
- hlist_for_each_entry(child, &c->children, child_node) {
- seq_printf(s, ",");
- clk_dump_subtree(s, child, level + 1);
- }
-
- seq_printf(s, "}");
-}
-
-static int clk_dump(struct seq_file *s, void *data)
-{
- struct clk_core *c;
- bool first_node = true;
- struct hlist_head **lists = (struct hlist_head **)s->private;
-
- seq_printf(s, "{");
-
- clk_prepare_lock();
-
- for (; *lists; lists++) {
- hlist_for_each_entry(c, *lists, child_node) {
- if (!first_node)
- seq_puts(s, ",");
- first_node = false;
- clk_dump_subtree(s, c, 0);
- }
- }
-
- clk_prepare_unlock();
-
- seq_printf(s, "}");
- return 0;
-}
-
-
-static int clk_dump_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_dump, inode->i_private);
-}
-
-static const struct file_operations clk_dump_fops = {
- .open = clk_dump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
-{
- struct dentry *d;
- int ret = -ENOMEM;
-
- if (!clk || !pdentry) {
- ret = -EINVAL;
- goto out;
- }
-
- d = debugfs_create_dir(clk->name, pdentry);
- if (!d)
- goto out;
-
- clk->dentry = d;
-
- d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
- (u32 *)&clk->rate);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("clk_accuracy", S_IRUGO, clk->dentry,
- (u32 *)&clk->accuracy);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
- (u32 *)&clk->phase);
- if (!d)
- goto err_out;
-
- d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
- (u32 *)&clk->flags);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
- (u32 *)&clk->prepare_count);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
- (u32 *)&clk->enable_count);
- if (!d)
- goto err_out;
-
- d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
- (u32 *)&clk->notifier_count);
- if (!d)
- goto err_out;
-
- if (clk->ops->debug_init) {
- ret = clk->ops->debug_init(clk->hw, clk->dentry);
- if (ret)
- goto err_out;
- }
-
- ret = 0;
- goto out;
-
-err_out:
- debugfs_remove_recursive(clk->dentry);
- clk->dentry = NULL;
-out:
- return ret;
-}
-
-/**
- * clk_debug_register - add a clk node to the debugfs clk tree
- * @clk: the clk being added to the debugfs clk tree
- *
- * Dynamically adds a clk to the debugfs clk tree if debugfs has been
- * initialized. Otherwise it bails out early since the debugfs clk tree
- * will be created lazily by clk_debug_init as part of a late_initcall.
- */
-static int clk_debug_register(struct clk_core *clk)
-{
- int ret = 0;
-
- mutex_lock(&clk_debug_lock);
- hlist_add_head(&clk->debug_node, &clk_debug_list);
-
- if (!inited)
- goto unlock;
-
- ret = clk_debug_create_one(clk, rootdir);
-unlock:
- mutex_unlock(&clk_debug_lock);
-
- return ret;
-}
-
- /**
- * clk_debug_unregister - remove a clk node from the debugfs clk tree
- * @clk: the clk being removed from the debugfs clk tree
- *
- * Dynamically removes a clk and all it's children clk nodes from the
- * debugfs clk tree if clk->dentry points to debugfs created by
- * clk_debug_register in __clk_init.
- */
-static void clk_debug_unregister(struct clk_core *clk)
-{
- mutex_lock(&clk_debug_lock);
- hlist_del_init(&clk->debug_node);
- debugfs_remove_recursive(clk->dentry);
- clk->dentry = NULL;
- mutex_unlock(&clk_debug_lock);
-}
-
-struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
- void *data, const struct file_operations *fops)
-{
- struct dentry *d = NULL;
-
- if (hw->core->dentry)
- d = debugfs_create_file(name, mode, hw->core->dentry, data,
- fops);
+ /*
+ * .is_prepared is optional for clocks that can prepare
+ * fall back to software usage counter if it is missing
+ */
+ if (!core->ops->is_prepared)
+ return core->prepare_count;
- return d;
+ return core->ops->is_prepared(core->hw);
}
-EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
-/**
- * clk_debug_init - lazily create the debugfs clk tree visualization
- *
- * clks are often initialized very early during boot before memory can
- * be dynamically allocated and well before debugfs is setup.
- * clk_debug_init walks the clk tree hierarchy while holding
- * prepare_lock and creates the topology as part of a late_initcall,
- * thus insuring that clks initialized very early will still be
- * represented in the debugfs clk tree. This function should only be
- * called once at boot-time, and all other clks added dynamically will
- * be done so with clk_debug_register.
- */
-static int __init clk_debug_init(void)
+static bool clk_core_is_enabled(struct clk_core *core)
{
- struct clk_core *clk;
- struct dentry *d;
-
- rootdir = debugfs_create_dir("clk", NULL);
-
- if (!rootdir)
- return -ENOMEM;
-
- d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
- &clk_summary_fops);
- if (!d)
- return -ENOMEM;
-
- d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
- &clk_dump_fops);
- if (!d)
- return -ENOMEM;
-
- d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
- &orphan_list, &clk_summary_fops);
- if (!d)
- return -ENOMEM;
-
- d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
- &orphan_list, &clk_dump_fops);
- if (!d)
- return -ENOMEM;
-
- mutex_lock(&clk_debug_lock);
- hlist_for_each_entry(clk, &clk_debug_list, debug_node)
- clk_debug_create_one(clk, rootdir);
-
- inited = 1;
- mutex_unlock(&clk_debug_lock);
+ /*
+ * .is_enabled is only mandatory for clocks that gate
+ * fall back to software usage counter if .is_enabled is missing
+ */
+ if (!core->ops->is_enabled)
+ return core->enable_count;
- return 0;
+ return core->ops->is_enabled(core->hw);
}
-late_initcall(clk_debug_init);
-#else
-static inline int clk_debug_register(struct clk_core *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk_core *clk,
- struct clk_core *new_parent)
-{
-}
-static inline void clk_debug_unregister(struct clk_core *clk)
-{
-}
-#endif
-/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk_core *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *core)
{
struct clk_core *child;
lockdep_assert_held(&prepare_lock);
- hlist_for_each_entry(child, &clk->children, child_node)
+ hlist_for_each_entry(child, &core->children, child_node)
clk_unprepare_unused_subtree(child);
- if (clk->prepare_count)
+ if (core->prepare_count)
return;
- if (clk->flags & CLK_IGNORE_UNUSED)
+ if (core->flags & CLK_IGNORE_UNUSED)
return;
- if (clk_core_is_prepared(clk)) {
- trace_clk_unprepare(clk);
- if (clk->ops->unprepare_unused)
- clk->ops->unprepare_unused(clk->hw);
- else if (clk->ops->unprepare)
- clk->ops->unprepare(clk->hw);
- trace_clk_unprepare_complete(clk);
+ if (clk_core_is_prepared(core)) {
+ trace_clk_unprepare(core);
+ if (core->ops->unprepare_unused)
+ core->ops->unprepare_unused(core->hw);
+ else if (core->ops->unprepare)
+ core->ops->unprepare(core->hw);
+ trace_clk_unprepare_complete(core);
}
}
-/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk_core *clk)
+static void clk_disable_unused_subtree(struct clk_core *core)
{
struct clk_core *child;
unsigned long flags;
lockdep_assert_held(&prepare_lock);
- hlist_for_each_entry(child, &clk->children, child_node)
+ hlist_for_each_entry(child, &core->children, child_node)
clk_disable_unused_subtree(child);
flags = clk_enable_lock();
- if (clk->enable_count)
+ if (core->enable_count)
goto unlock_out;
- if (clk->flags & CLK_IGNORE_UNUSED)
+ if (core->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
/*
@@ -528,13 +211,13 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
* sequence. call .disable_unused if available, otherwise fall
* back to .disable
*/
- if (clk_core_is_enabled(clk)) {
- trace_clk_disable(clk);
- if (clk->ops->disable_unused)
- clk->ops->disable_unused(clk->hw);
- else if (clk->ops->disable)
- clk->ops->disable(clk->hw);
- trace_clk_disable_complete(clk);
+ if (clk_core_is_enabled(core)) {
+ trace_clk_disable(core);
+ if (core->ops->disable_unused)
+ core->ops->disable_unused(core->hw);
+ else if (core->ops->disable)
+ core->ops->disable(core->hw);
+ trace_clk_disable_complete(core);
}
unlock_out:
@@ -551,7 +234,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
static int clk_disable_unused(void)
{
- struct clk_core *clk;
+ struct clk_core *core;
if (clk_ignore_unused) {
pr_warn("clk: Not disabling unused clocks\n");
@@ -560,17 +243,17 @@ static int clk_disable_unused(void)
clk_prepare_lock();
- hlist_for_each_entry(clk, &clk_root_list, child_node)
- clk_disable_unused_subtree(clk);
+ hlist_for_each_entry(core, &clk_root_list, child_node)
+ clk_disable_unused_subtree(core);
- hlist_for_each_entry(clk, &clk_orphan_list, child_node)
- clk_disable_unused_subtree(clk);
+ hlist_for_each_entry(core, &clk_orphan_list, child_node)
+ clk_disable_unused_subtree(core);
- hlist_for_each_entry(clk, &clk_root_list, child_node)
- clk_unprepare_unused_subtree(clk);
+ hlist_for_each_entry(core, &clk_root_list, child_node)
+ clk_unprepare_unused_subtree(core);
- hlist_for_each_entry(clk, &clk_orphan_list, child_node)
- clk_unprepare_unused_subtree(clk);
+ hlist_for_each_entry(core, &clk_orphan_list, child_node)
+ clk_unprepare_unused_subtree(core);
clk_prepare_unlock();
@@ -608,18 +291,61 @@ struct clk *__clk_get_parent(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_get_parent);
-static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
+static struct clk_core *__clk_lookup_subtree(const char *name,
+ struct clk_core *core)
+{
+ struct clk_core *child;
+ struct clk_core *ret;
+
+ if (!strcmp(core->name, name))
+ return core;
+
+ hlist_for_each_entry(child, &core->children, child_node) {
+ ret = __clk_lookup_subtree(name, child);
+ if (ret)
+ return ret;
+ }
+
+ return NULL;
+}
+
+static struct clk_core *clk_core_lookup(const char *name)
+{
+ struct clk_core *root_clk;
+ struct clk_core *ret;
+
+ if (!name)
+ return NULL;
+
+ /* search the 'proper' clk tree first */
+ hlist_for_each_entry(root_clk, &clk_root_list, child_node) {
+ ret = __clk_lookup_subtree(name, root_clk);
+ if (ret)
+ return ret;
+ }
+
+ /* if not found, then search the orphan tree */
+ hlist_for_each_entry(root_clk, &clk_orphan_list, child_node) {
+ ret = __clk_lookup_subtree(name, root_clk);
+ if (ret)
+ return ret;
+ }
+
+ return NULL;
+}
+
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
u8 index)
{
- if (!clk || index >= clk->num_parents)
+ if (!core || index >= core->num_parents)
return NULL;
- else if (!clk->parents)
- return clk_core_lookup(clk->parent_names[index]);
- else if (!clk->parents[index])
- return clk->parents[index] =
- clk_core_lookup(clk->parent_names[index]);
+ else if (!core->parents)
+ return clk_core_lookup(core->parent_names[index]);
+ else if (!core->parents[index])
+ return core->parents[index] =
+ clk_core_lookup(core->parent_names[index]);
else
- return clk->parents[index];
+ return core->parents[index];
}
struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
@@ -640,21 +366,21 @@ unsigned int __clk_get_enable_count(struct clk *clk)
return !clk ? 0 : clk->core->enable_count;
}
-static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
+static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
{
unsigned long ret;
- if (!clk) {
+ if (!core) {
ret = 0;
goto out;
}
- ret = clk->rate;
+ ret = core->rate;
- if (clk->flags & CLK_IS_ROOT)
+ if (core->flags & CLK_IS_ROOT)
goto out;
- if (!clk->parent)
+ if (!core->parent)
ret = 0;
out:
@@ -670,12 +396,12 @@ unsigned long __clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_get_rate);
-static unsigned long __clk_get_accuracy(struct clk_core *clk)
+static unsigned long __clk_get_accuracy(struct clk_core *core)
{
- if (!clk)
+ if (!core)
return 0;
- return clk->accuracy;
+ return core->accuracy;
}
unsigned long __clk_get_flags(struct clk *clk)
@@ -684,27 +410,6 @@ unsigned long __clk_get_flags(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
-static bool clk_core_is_prepared(struct clk_core *clk)
-{
- int ret;
-
- if (!clk)
- return false;
-
- /*
- * .is_prepared is optional for clocks that can prepare
- * fall back to software usage counter if it is missing
- */
- if (!clk->ops->is_prepared) {
- ret = clk->prepare_count ? 1 : 0;
- goto out;
- }
-
- ret = clk->ops->is_prepared(clk->hw);
-out:
- return !!ret;
-}
-
bool __clk_is_prepared(struct clk *clk)
{
if (!clk)
@@ -713,27 +418,6 @@ bool __clk_is_prepared(struct clk *clk)
return clk_core_is_prepared(clk->core);
}
-static bool clk_core_is_enabled(struct clk_core *clk)
-{
- int ret;
-
- if (!clk)
- return false;
-
- /*
- * .is_enabled is only mandatory for clocks that gate
- * fall back to software usage counter if .is_enabled is missing
- */
- if (!clk->ops->is_enabled) {
- ret = clk->enable_count ? 1 : 0;
- goto out;
- }
-
- ret = clk->ops->is_enabled(clk->hw);
-out:
- return !!ret;
-}
-
bool __clk_is_enabled(struct clk *clk)
{
if (!clk)
@@ -743,49 +427,6 @@ bool __clk_is_enabled(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
-static struct clk_core *__clk_lookup_subtree(const char *name,
- struct clk_core *clk)
-{
- struct clk_core *child;
- struct clk_core *ret;
-
- if (!strcmp(clk->name, name))
- return clk;
-
- hlist_for_each_entry(child, &clk->children, child_node) {
- ret = __clk_lookup_subtree(name, child);
- if (ret)
- return ret;
- }
-
- return NULL;
-}
-
-static struct clk_core *clk_core_lookup(const char *name)
-{
- struct clk_core *root_clk;
- struct clk_core *ret;
-
- if (!name)
- return NULL;
-
- /* search the 'proper' clk tree first */
- hlist_for_each_entry(root_clk, &clk_root_list, child_node) {
- ret = __clk_lookup_subtree(name, root_clk);
- if (ret)
- return ret;
- }
-
- /* if not found, then search the orphan tree */
- hlist_for_each_entry(root_clk, &clk_orphan_list, child_node) {
- ret = __clk_lookup_subtree(name, root_clk);
- if (ret)
- return ret;
- }
-
- return NULL;
-}
-
static bool mux_is_better_rate(unsigned long rate, unsigned long now,
unsigned long best, unsigned long flags)
{
@@ -853,7 +494,7 @@ struct clk *__clk_lookup(const char *name)
return !core ? NULL : core->hw->clk;
}
-static void clk_core_get_boundaries(struct clk_core *clk,
+static void clk_core_get_boundaries(struct clk_core *core,
unsigned long *min_rate,
unsigned long *max_rate)
{
@@ -862,10 +503,10 @@ static void clk_core_get_boundaries(struct clk_core *clk,
*min_rate = 0;
*max_rate = ULONG_MAX;
- hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+ hlist_for_each_entry(clk_user, &core->clks, clks_node)
*min_rate = max(*min_rate, clk_user->min_rate);
- hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+ hlist_for_each_entry(clk_user, &core->clks, clks_node)
*max_rate = min(*max_rate, clk_user->max_rate);
}
@@ -901,26 +542,28 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
/*** clk api ***/
-static void clk_core_unprepare(struct clk_core *clk)
+static void clk_core_unprepare(struct clk_core *core)
{
- if (!clk)
+ lockdep_assert_held(&prepare_lock);
+
+ if (!core)
return;
- if (WARN_ON(clk->prepare_count == 0))
+ if (WARN_ON(core->prepare_count == 0))
return;
- if (--clk->prepare_count > 0)
+ if (--core->prepare_count > 0)
return;
- WARN_ON(clk->enable_count > 0);
+ WARN_ON(core->enable_count > 0);
- trace_clk_unprepare(clk);
+ trace_clk_unprepare(core);
- if (clk->ops->unprepare)
- clk->ops->unprepare(clk->hw);
+ if (core->ops->unprepare)
+ core->ops->unprepare(core->hw);
- trace_clk_unprepare_complete(clk);
- clk_core_unprepare(clk->parent);
+ trace_clk_unprepare_complete(core);
+ clk_core_unprepare(core->parent);
}
/**
@@ -945,32 +588,34 @@ void clk_unprepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unprepare);
-static int clk_core_prepare(struct clk_core *clk)
+static int clk_core_prepare(struct clk_core *core)
{
int ret = 0;
- if (!clk)
+ lockdep_assert_held(&prepare_lock);
+
+ if (!core)
return 0;
- if (clk->prepare_count == 0) {
- ret = clk_core_prepare(clk->parent);
+ if (core->prepare_count == 0) {
+ ret = clk_core_prepare(core->parent);
if (ret)
return ret;
- trace_clk_prepare(clk);
+ trace_clk_prepare(core);
- if (clk->ops->prepare)
- ret = clk->ops->prepare(clk->hw);
+ if (core->ops->prepare)
+ ret = core->ops->prepare(core->hw);
- trace_clk_prepare_complete(clk);
+ trace_clk_prepare_complete(core);
if (ret) {
- clk_core_unprepare(clk->parent);
+ clk_core_unprepare(core->parent);
return ret;
}
}
- clk->prepare_count++;
+ core->prepare_count++;
return 0;
}
@@ -1002,33 +647,27 @@ int clk_prepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_prepare);
-static void clk_core_disable(struct clk_core *clk)
+static void clk_core_disable(struct clk_core *core)
{
- if (!clk)
+ lockdep_assert_held(&enable_lock);
+
+ if (!core)
return;
- if (WARN_ON(clk->enable_count == 0))
+ if (WARN_ON(core->enable_count == 0))
return;
- if (--clk->enable_count > 0)
+ if (--core->enable_count > 0)
return;
- trace_clk_disable(clk);
+ trace_clk_disable(core);
- if (clk->ops->disable)
- clk->ops->disable(clk->hw);
+ if (core->ops->disable)
+ core->ops->disable(core->hw);
- trace_clk_disable_complete(clk);
+ trace_clk_disable_complete(core);
- clk_core_disable(clk->parent);
-}
-
-static void __clk_disable(struct clk *clk)
-{
- if (!clk)
- return;
-
- clk_core_disable(clk->core);
+ clk_core_disable(core->parent);
}
/**
@@ -1051,52 +690,46 @@ void clk_disable(struct clk *clk)
return;
flags = clk_enable_lock();
- __clk_disable(clk);
+ clk_core_disable(clk->core);
clk_enable_unlock(flags);
}
EXPORT_SYMBOL_GPL(clk_disable);
-static int clk_core_enable(struct clk_core *clk)
+static int clk_core_enable(struct clk_core *core)
{
int ret = 0;
- if (!clk)
+ lockdep_assert_held(&enable_lock);
+
+ if (!core)
return 0;
- if (WARN_ON(clk->prepare_count == 0))
+ if (WARN_ON(core->prepare_count == 0))
return -ESHUTDOWN;
- if (clk->enable_count == 0) {
- ret = clk_core_enable(clk->parent);
+ if (core->enable_count == 0) {
+ ret = clk_core_enable(core->parent);
if (ret)
return ret;
- trace_clk_enable(clk);
+ trace_clk_enable(core);
- if (clk->ops->enable)
- ret = clk->ops->enable(clk->hw);
+ if (core->ops->enable)
+ ret = core->ops->enable(core->hw);
- trace_clk_enable_complete(clk);
+ trace_clk_enable_complete(core);
if (ret) {
- clk_core_disable(clk->parent);
+ clk_core_disable(core->parent);
return ret;
}
}
- clk->enable_count++;
+ core->enable_count++;
return 0;
}
-static int __clk_enable(struct clk *clk)
-{
- if (!clk)
- return 0;
-
- return clk_core_enable(clk->core);
-}
-
/**
* clk_enable - ungate a clock
* @clk: the clk being ungated
@@ -1115,15 +748,18 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret;
+ if (!clk)
+ return 0;
+
flags = clk_enable_lock();
- ret = __clk_enable(clk);
+ ret = clk_core_enable(clk->core);
clk_enable_unlock(flags);
return ret;
}
EXPORT_SYMBOL_GPL(clk_enable);
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate)
@@ -1134,25 +770,25 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
lockdep_assert_held(&prepare_lock);
- if (!clk)
+ if (!core)
return 0;
- parent = clk->parent;
+ parent = core->parent;
if (parent)
parent_rate = parent->rate;
- if (clk->ops->determine_rate) {
+ if (core->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
- return clk->ops->determine_rate(clk->hw, rate,
+ return core->ops->determine_rate(core->hw, rate,
min_rate, max_rate,
&parent_rate, &parent_hw);
- } else if (clk->ops->round_rate)
- return clk->ops->round_rate(clk->hw, rate, &parent_rate);
- else if (clk->flags & CLK_SET_RATE_PARENT)
- return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+ } else if (core->ops->round_rate)
+ return core->ops->round_rate(core->hw, rate, &parent_rate);
+ else if (core->flags & CLK_SET_RATE_PARENT)
+ return clk_core_round_rate_nolock(core->parent, rate, min_rate,
max_rate);
else
- return clk->rate;
+ return core->rate;
}
/**
@@ -1162,8 +798,7 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
* @min_rate: returned rate must be greater than this rate
* @max_rate: returned rate must be less than this rate
*
- * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate and
- * .determine_rate.
+ * Useful for clk_ops such as .set_rate and .determine_rate.
*/
unsigned long __clk_determine_rate(struct clk_hw *hw,
unsigned long rate,
@@ -1182,7 +817,7 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate);
* @clk: round the rate of this clock
* @rate: the rate which is to be rounded
*
- * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
+ * Useful for clk_ops such as .set_rate
*/
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
{
@@ -1224,7 +859,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
/**
* __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
+ * @core: clk that is changing rate
* @msg: clk notifier type (see include/linux/clk.h)
* @old_rate: old clk rate
* @new_rate: new clk rate
@@ -1236,7 +871,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
-static int __clk_notify(struct clk_core *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *core, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
@@ -1247,7 +882,7 @@ static int __clk_notify(struct clk_core *clk, unsigned long msg,
cnd.new_rate = new_rate;
list_for_each_entry(cn, &clk_notifier_list, node) {
- if (cn->clk->core == clk) {
+ if (cn->clk->core == core) {
cnd.clk = cn->clk;
ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
&cnd);
@@ -1259,44 +894,42 @@ static int __clk_notify(struct clk_core *clk, unsigned long msg,
/**
* __clk_recalc_accuracies
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
*
* Walks the subtree of clks starting with clk and recalculates accuracies as
* it goes. Note that if a clk does not implement the .recalc_accuracy
- * callback then it is assumed that the clock will take on the accuracy of it's
+ * callback then it is assumed that the clock will take on the accuracy of its
* parent.
- *
- * Caller must hold prepare_lock.
*/
-static void __clk_recalc_accuracies(struct clk_core *clk)
+static void __clk_recalc_accuracies(struct clk_core *core)
{
unsigned long parent_accuracy = 0;
struct clk_core *child;
lockdep_assert_held(&prepare_lock);
- if (clk->parent)
- parent_accuracy = clk->parent->accuracy;
+ if (core->parent)
+ parent_accuracy = core->parent->accuracy;
- if (clk->ops->recalc_accuracy)
- clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
+ if (core->ops->recalc_accuracy)
+ core->accuracy = core->ops->recalc_accuracy(core->hw,
parent_accuracy);
else
- clk->accuracy = parent_accuracy;
+ core->accuracy = parent_accuracy;
- hlist_for_each_entry(child, &clk->children, child_node)
+ hlist_for_each_entry(child, &core->children, child_node)
__clk_recalc_accuracies(child);
}
-static long clk_core_get_accuracy(struct clk_core *clk)
+static long clk_core_get_accuracy(struct clk_core *core)
{
unsigned long accuracy;
clk_prepare_lock();
- if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
- __clk_recalc_accuracies(clk);
+ if (core && (core->flags & CLK_GET_ACCURACY_NOCACHE))
+ __clk_recalc_accuracies(core);
- accuracy = __clk_get_accuracy(clk);
+ accuracy = __clk_get_accuracy(core);
clk_prepare_unlock();
return accuracy;
@@ -1320,17 +953,17 @@ long clk_get_accuracy(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
-static unsigned long clk_recalc(struct clk_core *clk,
+static unsigned long clk_recalc(struct clk_core *core,
unsigned long parent_rate)
{
- if (clk->ops->recalc_rate)
- return clk->ops->recalc_rate(clk->hw, parent_rate);
+ if (core->ops->recalc_rate)
+ return core->ops->recalc_rate(core->hw, parent_rate);
return parent_rate;
}
/**
* __clk_recalc_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
* @msg: notification type (see include/linux/clk.h)
*
* Walks the subtree of clks starting with clk and recalculates rates as it
@@ -1339,10 +972,8 @@ static unsigned long clk_recalc(struct clk_core *clk,
*
* clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
* if necessary.
- *
- * Caller must hold prepare_lock.
*/
-static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
{
unsigned long old_rate;
unsigned long parent_rate = 0;
@@ -1350,34 +981,34 @@ static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
lockdep_assert_held(&prepare_lock);
- old_rate = clk->rate;
+ old_rate = core->rate;
- if (clk->parent)
- parent_rate = clk->parent->rate;
+ if (core->parent)
+ parent_rate = core->parent->rate;
- clk->rate = clk_recalc(clk, parent_rate);
+ core->rate = clk_recalc(core, parent_rate);
/*
* ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
* & ABORT_RATE_CHANGE notifiers
*/
- if (clk->notifier_count && msg)
- __clk_notify(clk, msg, old_rate, clk->rate);
+ if (core->notifier_count && msg)
+ __clk_notify(core, msg, old_rate, core->rate);
- hlist_for_each_entry(child, &clk->children, child_node)
+ hlist_for_each_entry(child, &core->children, child_node)
__clk_recalc_rates(child, msg);
}
-static unsigned long clk_core_get_rate(struct clk_core *clk)
+static unsigned long clk_core_get_rate(struct clk_core *core)
{
unsigned long rate;
clk_prepare_lock();
- if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
- __clk_recalc_rates(clk, 0);
+ if (core && (core->flags & CLK_GET_RATE_NOCACHE))
+ __clk_recalc_rates(core, 0);
- rate = clk_core_get_rate_nolock(clk);
+ rate = clk_core_get_rate_nolock(core);
clk_prepare_unlock();
return rate;
@@ -1400,15 +1031,15 @@ unsigned long clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_get_rate);
-static int clk_fetch_parent_index(struct clk_core *clk,
+static int clk_fetch_parent_index(struct clk_core *core,
struct clk_core *parent)
{
int i;
- if (!clk->parents) {
- clk->parents = kcalloc(clk->num_parents,
+ if (!core->parents) {
+ core->parents = kcalloc(core->num_parents,
sizeof(struct clk *), GFP_KERNEL);
- if (!clk->parents)
+ if (!core->parents)
return -ENOMEM;
}
@@ -1417,15 +1048,15 @@ static int clk_fetch_parent_index(struct clk_core *clk,
* or if not yet cached, use string name comparison and cache
* them now to avoid future calls to clk_core_lookup.
*/
- for (i = 0; i < clk->num_parents; i++) {
- if (clk->parents[i] == parent)
+ for (i = 0; i < core->num_parents; i++) {
+ if (core->parents[i] == parent)
return i;
- if (clk->parents[i])
+ if (core->parents[i])
continue;
- if (!strcmp(clk->parent_names[i], parent->name)) {
- clk->parents[i] = clk_core_lookup(parent->name);
+ if (!strcmp(core->parent_names[i], parent->name)) {
+ core->parents[i] = clk_core_lookup(parent->name);
return i;
}
}
@@ -1433,28 +1064,28 @@ static int clk_fetch_parent_index(struct clk_core *clk,
return -EINVAL;
}
-static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
+static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
{
- hlist_del(&clk->child_node);
+ hlist_del(&core->child_node);
if (new_parent) {
/* avoid duplicate POST_RATE_CHANGE notifications */
- if (new_parent->new_child == clk)
+ if (new_parent->new_child == core)
new_parent->new_child = NULL;
- hlist_add_head(&clk->child_node, &new_parent->children);
+ hlist_add_head(&core->child_node, &new_parent->children);
} else {
- hlist_add_head(&clk->child_node, &clk_orphan_list);
+ hlist_add_head(&core->child_node, &clk_orphan_list);
}
- clk->parent = new_parent;
+ core->parent = new_parent;
}
-static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+static struct clk_core *__clk_set_parent_before(struct clk_core *core,
struct clk_core *parent)
{
unsigned long flags;
- struct clk_core *old_parent = clk->parent;
+ struct clk_core *old_parent = core->parent;
/*
* Migrate prepare state between parents and prevent race with
@@ -1473,17 +1104,17 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
*
* See also: Comment for clk_set_parent() below.
*/
- if (clk->prepare_count) {
+ if (core->prepare_count) {
clk_core_prepare(parent);
flags = clk_enable_lock();
clk_core_enable(parent);
- clk_core_enable(clk);
+ clk_core_enable(core);
clk_enable_unlock(flags);
}
/* update the clk tree topology */
flags = clk_enable_lock();
- clk_reparent(clk, parent);
+ clk_reparent(core, parent);
clk_enable_unlock(flags);
return old_parent;
@@ -1508,31 +1139,31 @@ static void __clk_set_parent_after(struct clk_core *core,
}
}
-static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
u8 p_index)
{
unsigned long flags;
int ret = 0;
struct clk_core *old_parent;
- old_parent = __clk_set_parent_before(clk, parent);
+ old_parent = __clk_set_parent_before(core, parent);
- trace_clk_set_parent(clk, parent);
+ trace_clk_set_parent(core, parent);
/* change clock input source */
- if (parent && clk->ops->set_parent)
- ret = clk->ops->set_parent(clk->hw, p_index);
+ if (parent && core->ops->set_parent)
+ ret = core->ops->set_parent(core->hw, p_index);
- trace_clk_set_parent_complete(clk, parent);
+ trace_clk_set_parent_complete(core, parent);
if (ret) {
flags = clk_enable_lock();
- clk_reparent(clk, old_parent);
+ clk_reparent(core, old_parent);
clk_enable_unlock(flags);
- if (clk->prepare_count) {
+ if (core->prepare_count) {
flags = clk_enable_lock();
- clk_core_disable(clk);
+ clk_core_disable(core);
clk_core_disable(parent);
clk_enable_unlock(flags);
clk_core_unprepare(parent);
@@ -1540,14 +1171,14 @@ static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
return ret;
}
- __clk_set_parent_after(clk, parent, old_parent);
+ __clk_set_parent_after(core, parent, old_parent);
return 0;
}
/**
* __clk_speculate_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
* @parent_rate: the "future" rate of clk's parent
*
* Walks the subtree of clks starting with clk, speculating rates as it
@@ -1558,10 +1189,8 @@ static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
* subtree have subscribed to the notifications. Note that if a clk does not
* implement the .recalc_rate callback then it is assumed that the clock will
* take on the rate of its parent.
- *
- * Caller must hold prepare_lock.
*/
-static int __clk_speculate_rates(struct clk_core *clk,
+static int __clk_speculate_rates(struct clk_core *core,
unsigned long parent_rate)
{
struct clk_core *child;
@@ -1570,19 +1199,19 @@ static int __clk_speculate_rates(struct clk_core *clk,
lockdep_assert_held(&prepare_lock);
- new_rate = clk_recalc(clk, parent_rate);
+ new_rate = clk_recalc(core, parent_rate);
/* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
- if (clk->notifier_count)
- ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+ if (core->notifier_count)
+ ret = __clk_notify(core, PRE_RATE_CHANGE, core->rate, new_rate);
if (ret & NOTIFY_STOP_MASK) {
pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n",
- __func__, clk->name, ret);
+ __func__, core->name, ret);
goto out;
}
- hlist_for_each_entry(child, &clk->children, child_node) {
+ hlist_for_each_entry(child, &core->children, child_node) {
ret = __clk_speculate_rates(child, new_rate);
if (ret & NOTIFY_STOP_MASK)
break;
@@ -1592,20 +1221,20 @@ out:
return ret;
}
-static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
struct clk_core *new_parent, u8 p_index)
{
struct clk_core *child;
- clk->new_rate = new_rate;
- clk->new_parent = new_parent;
- clk->new_parent_index = p_index;
+ core->new_rate = new_rate;
+ core->new_parent = new_parent;
+ core->new_parent_index = p_index;
/* include clk in new parent's PRE_RATE_CHANGE notifications */
- clk->new_child = NULL;
- if (new_parent && new_parent != clk->parent)
- new_parent->new_child = clk;
+ core->new_child = NULL;
+ if (new_parent && new_parent != core->parent)
+ new_parent->new_child = core;
- hlist_for_each_entry(child, &clk->children, child_node) {
+ hlist_for_each_entry(child, &core->children, child_node) {
child->new_rate = clk_recalc(child, new_rate);
clk_calc_subtree(child, child->new_rate, NULL, 0);
}
@@ -1615,10 +1244,10 @@ static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
-static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+static struct clk_core *clk_calc_new_rates(struct clk_core *core,
unsigned long rate)
{
- struct clk_core *top = clk;
+ struct clk_core *top = core;
struct clk_core *old_parent, *parent;
struct clk_hw *parent_hw;
unsigned long best_parent_rate = 0;
@@ -1629,20 +1258,20 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
long ret;
/* sanity */
- if (IS_ERR_OR_NULL(clk))
+ if (IS_ERR_OR_NULL(core))
return NULL;
/* save parent rate, if it exists */
- parent = old_parent = clk->parent;
+ parent = old_parent = core->parent;
if (parent)
best_parent_rate = parent->rate;
- clk_core_get_boundaries(clk, &min_rate, &max_rate);
+ clk_core_get_boundaries(core, &min_rate, &max_rate);
/* find the closest rate and parent clk/rate */
- if (clk->ops->determine_rate) {
+ if (core->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
- ret = clk->ops->determine_rate(clk->hw, rate,
+ ret = core->ops->determine_rate(core->hw, rate,
min_rate,
max_rate,
&best_parent_rate,
@@ -1652,8 +1281,8 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
new_rate = ret;
parent = parent_hw ? parent_hw->core : NULL;
- } else if (clk->ops->round_rate) {
- ret = clk->ops->round_rate(clk->hw, rate,
+ } else if (core->ops->round_rate) {
+ ret = core->ops->round_rate(core->hw, rate,
&best_parent_rate);
if (ret < 0)
return NULL;
@@ -1661,9 +1290,9 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
new_rate = ret;
if (new_rate < min_rate || new_rate > max_rate)
return NULL;
- } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
+ } else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
/* pass-through clock without adjustable parent */
- clk->new_rate = clk->rate;
+ core->new_rate = core->rate;
return NULL;
} else {
/* pass-through clock with adjustable parent */
@@ -1674,28 +1303,28 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
/* some clocks must be gated to change parent */
if (parent != old_parent &&
- (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+ (core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
pr_debug("%s: %s not gated but wants to reparent\n",
- __func__, clk->name);
+ __func__, core->name);
return NULL;
}
/* try finding the new parent index */
- if (parent && clk->num_parents > 1) {
- p_index = clk_fetch_parent_index(clk, parent);
+ if (parent && core->num_parents > 1) {
+ p_index = clk_fetch_parent_index(core, parent);
if (p_index < 0) {
pr_debug("%s: clk %s can not be parent of clk %s\n",
- __func__, parent->name, clk->name);
+ __func__, parent->name, core->name);
return NULL;
}
}
- if ((clk->flags & CLK_SET_RATE_PARENT) && parent &&
+ if ((core->flags & CLK_SET_RATE_PARENT) && parent &&
best_parent_rate != parent->rate)
top = clk_calc_new_rates(parent, best_parent_rate);
out:
- clk_calc_subtree(clk, new_rate, parent, p_index);
+ clk_calc_subtree(core, new_rate, parent, p_index);
return top;
}
@@ -1705,33 +1334,33 @@ out:
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
-static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
unsigned long event)
{
struct clk_core *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
- if (clk->rate == clk->new_rate)
+ if (core->rate == core->new_rate)
return NULL;
- if (clk->notifier_count) {
- ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
+ if (core->notifier_count) {
+ ret = __clk_notify(core, event, core->rate, core->new_rate);
if (ret & NOTIFY_STOP_MASK)
- fail_clk = clk;
+ fail_clk = core;
}
- hlist_for_each_entry(child, &clk->children, child_node) {
+ hlist_for_each_entry(child, &core->children, child_node) {
/* Skip children who will be reparented to another clock */
- if (child->new_parent && child->new_parent != clk)
+ if (child->new_parent && child->new_parent != core)
continue;
tmp_clk = clk_propagate_rate_change(child, event);
if (tmp_clk)
fail_clk = tmp_clk;
}
- /* handle the new child who might not be in clk->children yet */
- if (clk->new_child) {
- tmp_clk = clk_propagate_rate_change(clk->new_child, event);
+ /* handle the new child who might not be in core->children yet */
+ if (core->new_child) {
+ tmp_clk = clk_propagate_rate_change(core->new_child, event);
if (tmp_clk)
fail_clk = tmp_clk;
}
@@ -1743,7 +1372,7 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
-static void clk_change_rate(struct clk_core *clk)
+static void clk_change_rate(struct clk_core *core)
{
struct clk_core *child;
struct hlist_node *tmp;
@@ -1752,77 +1381,77 @@ static void clk_change_rate(struct clk_core *clk)
bool skip_set_rate = false;
struct clk_core *old_parent;
- old_rate = clk->rate;
+ old_rate = core->rate;
- if (clk->new_parent)
- best_parent_rate = clk->new_parent->rate;
- else if (clk->parent)
- best_parent_rate = clk->parent->rate;
+ if (core->new_parent)
+ best_parent_rate = core->new_parent->rate;
+ else if (core->parent)
+ best_parent_rate = core->parent->rate;
- if (clk->new_parent && clk->new_parent != clk->parent) {
- old_parent = __clk_set_parent_before(clk, clk->new_parent);
- trace_clk_set_parent(clk, clk->new_parent);
+ if (core->new_parent && core->new_parent != core->parent) {
+ old_parent = __clk_set_parent_before(core, core->new_parent);
+ trace_clk_set_parent(core, core->new_parent);
- if (clk->ops->set_rate_and_parent) {
+ if (core->ops->set_rate_and_parent) {
skip_set_rate = true;
- clk->ops->set_rate_and_parent(clk->hw, clk->new_rate,
+ core->ops->set_rate_and_parent(core->hw, core->new_rate,
best_parent_rate,
- clk->new_parent_index);
- } else if (clk->ops->set_parent) {
- clk->ops->set_parent(clk->hw, clk->new_parent_index);
+ core->new_parent_index);
+ } else if (core->ops->set_parent) {
+ core->ops->set_parent(core->hw, core->new_parent_index);
}
- trace_clk_set_parent_complete(clk, clk->new_parent);
- __clk_set_parent_after(clk, clk->new_parent, old_parent);
+ trace_clk_set_parent_complete(core, core->new_parent);
+ __clk_set_parent_after(core, core->new_parent, old_parent);
}
- trace_clk_set_rate(clk, clk->new_rate);
+ trace_clk_set_rate(core, core->new_rate);
- if (!skip_set_rate && clk->ops->set_rate)
- clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
+ if (!skip_set_rate && core->ops->set_rate)
+ core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
- trace_clk_set_rate_complete(clk, clk->new_rate);
+ trace_clk_set_rate_complete(core, core->new_rate);
- clk->rate = clk_recalc(clk, best_parent_rate);
+ core->rate = clk_recalc(core, best_parent_rate);
- if (clk->notifier_count && old_rate != clk->rate)
- __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+ if (core->notifier_count && old_rate != core->rate)
+ __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
/*
* Use safe iteration, as change_rate can actually swap parents
* for certain clock types.
*/
- hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
+ hlist_for_each_entry_safe(child, tmp, &core->children, child_node) {
/* Skip children who will be reparented to another clock */
- if (child->new_parent && child->new_parent != clk)
+ if (child->new_parent && child->new_parent != core)
continue;
clk_change_rate(child);
}
- /* handle the new child who might not be in clk->children yet */
- if (clk->new_child)
- clk_change_rate(clk->new_child);
+ /* handle the new child who might not be in core->children yet */
+ if (core->new_child)
+ clk_change_rate(core->new_child);
}
-static int clk_core_set_rate_nolock(struct clk_core *clk,
+static int clk_core_set_rate_nolock(struct clk_core *core,
unsigned long req_rate)
{
struct clk_core *top, *fail_clk;
unsigned long rate = req_rate;
int ret = 0;
- if (!clk)
+ if (!core)
return 0;
/* bail early if nothing to do */
- if (rate == clk_core_get_rate_nolock(clk))
+ if (rate == clk_core_get_rate_nolock(core))
return 0;
- if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+ if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
return -EBUSY;
/* calculate new rates and get the topmost changed clock */
- top = clk_calc_new_rates(clk, rate);
+ top = clk_calc_new_rates(core, rate);
if (!top)
return -EINVAL;
@@ -1838,7 +1467,7 @@ static int clk_core_set_rate_nolock(struct clk_core *clk,
/* change the rates */
clk_change_rate(top);
- clk->req_rate = req_rate;
+ core->req_rate = req_rate;
return ret;
}
@@ -1977,55 +1606,55 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
* .parents array exists, and if so use it to avoid an expensive tree
* traversal. If .parents does not exist then walk the tree.
*/
-static struct clk_core *__clk_init_parent(struct clk_core *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *core)
{
struct clk_core *ret = NULL;
u8 index;
/* handle the trivial cases */
- if (!clk->num_parents)
+ if (!core->num_parents)
goto out;
- if (clk->num_parents == 1) {
- if (IS_ERR_OR_NULL(clk->parent))
- clk->parent = clk_core_lookup(clk->parent_names[0]);
- ret = clk->parent;
+ if (core->num_parents == 1) {
+ if (IS_ERR_OR_NULL(core->parent))
+ core->parent = clk_core_lookup(core->parent_names[0]);
+ ret = core->parent;
goto out;
}
- if (!clk->ops->get_parent) {
- WARN(!clk->ops->get_parent,
+ if (!core->ops->get_parent) {
+ WARN(!core->ops->get_parent,
"%s: multi-parent clocks must implement .get_parent\n",
__func__);
goto out;
};
/*
- * Do our best to cache parent clocks in clk->parents. This prevents
- * unnecessary and expensive lookups. We don't set clk->parent here;
+ * Do our best to cache parent clocks in core->parents. This prevents
+ * unnecessary and expensive lookups. We don't set core->parent here;
* that is done by the calling function.
*/
- index = clk->ops->get_parent(clk->hw);
+ index = core->ops->get_parent(core->hw);
- if (!clk->parents)
- clk->parents =
- kcalloc(clk->num_parents, sizeof(struct clk *),
+ if (!core->parents)
+ core->parents =
+ kcalloc(core->num_parents, sizeof(struct clk *),
GFP_KERNEL);
- ret = clk_core_get_parent_by_index(clk, index);
+ ret = clk_core_get_parent_by_index(core, index);
out:
return ret;
}
-static void clk_core_reparent(struct clk_core *clk,
+static void clk_core_reparent(struct clk_core *core,
struct clk_core *new_parent)
{
- clk_reparent(clk, new_parent);
- __clk_recalc_accuracies(clk);
- __clk_recalc_rates(clk, POST_RATE_CHANGE);
+ clk_reparent(core, new_parent);
+ __clk_recalc_accuracies(core);
+ __clk_recalc_rates(core, POST_RATE_CHANGE);
}
/**
@@ -2062,61 +1691,61 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
}
EXPORT_SYMBOL_GPL(clk_has_parent);
-static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
+static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
{
int ret = 0;
int p_index = 0;
unsigned long p_rate = 0;
- if (!clk)
+ if (!core)
return 0;
/* prevent racing with updates to the clock topology */
clk_prepare_lock();
- if (clk->parent == parent)
+ if (core->parent == parent)
goto out;
/* verify ops for for multi-parent clks */
- if ((clk->num_parents > 1) && (!clk->ops->set_parent)) {
+ if ((core->num_parents > 1) && (!core->ops->set_parent)) {
ret = -ENOSYS;
goto out;
}
/* check that we are allowed to re-parent if the clock is in use */
- if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+ if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
ret = -EBUSY;
goto out;
}
/* try finding the new parent index */
if (parent) {
- p_index = clk_fetch_parent_index(clk, parent);
+ p_index = clk_fetch_parent_index(core, parent);
p_rate = parent->rate;
if (p_index < 0) {
pr_debug("%s: clk %s can not be parent of clk %s\n",
- __func__, parent->name, clk->name);
+ __func__, parent->name, core->name);
ret = p_index;
goto out;
}
}
/* propagate PRE_RATE_CHANGE notifications */
- ret = __clk_speculate_rates(clk, p_rate);
+ ret = __clk_speculate_rates(core, p_rate);
/* abort if a driver objects */
if (ret & NOTIFY_STOP_MASK)
goto out;
/* do the re-parent */
- ret = __clk_set_parent(clk, parent, p_index);
+ ret = __clk_set_parent(core, parent, p_index);
/* propagate rate an accuracy recalculation accordingly */
if (ret) {
- __clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+ __clk_recalc_rates(core, ABORT_RATE_CHANGE);
} else {
- __clk_recalc_rates(clk, POST_RATE_CHANGE);
- __clk_recalc_accuracies(clk);
+ __clk_recalc_rates(core, POST_RATE_CHANGE);
+ __clk_recalc_accuracies(core);
}
out:
@@ -2201,21 +1830,16 @@ int clk_set_phase(struct clk *clk, int degrees)
}
EXPORT_SYMBOL_GPL(clk_set_phase);
-static int clk_core_get_phase(struct clk_core *clk)
+static int clk_core_get_phase(struct clk_core *core)
{
- int ret = 0;
-
- if (!clk)
- goto out;
+ int ret;
clk_prepare_lock();
- ret = clk->phase;
+ ret = core->phase;
clk_prepare_unlock();
-out:
return ret;
}
-EXPORT_SYMBOL_GPL(clk_get_phase);
/**
* clk_get_phase - return the phase shift of a clock signal
@@ -2231,6 +1855,7 @@ int clk_get_phase(struct clk *clk)
return clk_core_get_phase(clk->core);
}
+EXPORT_SYMBOL_GPL(clk_get_phase);
/**
* clk_is_match - check if two clk's point to the same hardware clock
@@ -2258,6 +1883,337 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
}
EXPORT_SYMBOL_GPL(clk_is_match);
+/*** debugfs support ***/
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+static struct dentry *rootdir;
+static int inited = 0;
+static DEFINE_MUTEX(clk_debug_lock);
+static HLIST_HEAD(clk_debug_list);
+
+static struct hlist_head *all_lists[] = {
+ &clk_root_list,
+ &clk_orphan_list,
+ NULL,
+};
+
+static struct hlist_head *orphan_list[] = {
+ &clk_orphan_list,
+ NULL,
+};
+
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+ int level)
+{
+ if (!c)
+ return;
+
+ seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
+ level * 3 + 1, "",
+ 30 - level * 3, c->name,
+ c->enable_count, c->prepare_count, clk_core_get_rate(c),
+ clk_core_get_accuracy(c), clk_core_get_phase(c));
+}
+
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+ int level)
+{
+ struct clk_core *child;
+
+ if (!c)
+ return;
+
+ clk_summary_show_one(s, c, level);
+
+ hlist_for_each_entry(child, &c->children, child_node)
+ clk_summary_show_subtree(s, child, level + 1);
+}
+
+static int clk_summary_show(struct seq_file *s, void *data)
+{
+ struct clk_core *c;
+ struct hlist_head **lists = (struct hlist_head **)s->private;
+
+ seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy phase\n");
+ seq_puts(s, "----------------------------------------------------------------------------------------\n");
+
+ clk_prepare_lock();
+
+ for (; *lists; lists++)
+ hlist_for_each_entry(c, *lists, child_node)
+ clk_summary_show_subtree(s, c, 0);
+
+ clk_prepare_unlock();
+
+ return 0;
+}
+
+
+static int clk_summary_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_summary_show, inode->i_private);
+}
+
+static const struct file_operations clk_summary_fops = {
+ .open = clk_summary_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
+{
+ if (!c)
+ return;
+
+ /* This should be JSON format, i.e. elements separated with a comma */
+ seq_printf(s, "\"%s\": { ", c->name);
+ seq_printf(s, "\"enable_count\": %d,", c->enable_count);
+ seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
+ seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
+ seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
+ seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+}
+
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
+{
+ struct clk_core *child;
+
+ if (!c)
+ return;
+
+ clk_dump_one(s, c, level);
+
+ hlist_for_each_entry(child, &c->children, child_node) {
+ seq_printf(s, ",");
+ clk_dump_subtree(s, child, level + 1);
+ }
+
+ seq_printf(s, "}");
+}
+
+static int clk_dump(struct seq_file *s, void *data)
+{
+ struct clk_core *c;
+ bool first_node = true;
+ struct hlist_head **lists = (struct hlist_head **)s->private;
+
+ seq_printf(s, "{");
+
+ clk_prepare_lock();
+
+ for (; *lists; lists++) {
+ hlist_for_each_entry(c, *lists, child_node) {
+ if (!first_node)
+ seq_puts(s, ",");
+ first_node = false;
+ clk_dump_subtree(s, c, 0);
+ }
+ }
+
+ clk_prepare_unlock();
+
+ seq_puts(s, "}\n");
+ return 0;
+}
+
+
+static int clk_dump_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_dump, inode->i_private);
+}
+
+static const struct file_operations clk_dump_fops = {
+ .open = clk_dump_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
+{
+ struct dentry *d;
+ int ret = -ENOMEM;
+
+ if (!core || !pdentry) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ d = debugfs_create_dir(core->name, pdentry);
+ if (!d)
+ goto out;
+
+ core->dentry = d;
+
+ d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
+ (u32 *)&core->rate);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
+ (u32 *)&core->accuracy);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry,
+ (u32 *)&core->phase);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_x32("clk_flags", S_IRUGO, core->dentry,
+ (u32 *)&core->flags);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry,
+ (u32 *)&core->prepare_count);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
+ (u32 *)&core->enable_count);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
+ (u32 *)&core->notifier_count);
+ if (!d)
+ goto err_out;
+
+ if (core->ops->debug_init) {
+ ret = core->ops->debug_init(core->hw, core->dentry);
+ if (ret)
+ goto err_out;
+ }
+
+ ret = 0;
+ goto out;
+
+err_out:
+ debugfs_remove_recursive(core->dentry);
+ core->dentry = NULL;
+out:
+ return ret;
+}
+
+/**
+ * clk_debug_register - add a clk node to the debugfs clk directory
+ * @core: the clk being added to the debugfs clk directory
+ *
+ * Dynamically adds a clk to the debugfs clk directory if debugfs has been
+ * initialized. Otherwise it bails out early since the debugfs clk directory
+ * will be created lazily by clk_debug_init as part of a late_initcall.
+ */
+static int clk_debug_register(struct clk_core *core)
+{
+ int ret = 0;
+
+ mutex_lock(&clk_debug_lock);
+ hlist_add_head(&core->debug_node, &clk_debug_list);
+
+ if (!inited)
+ goto unlock;
+
+ ret = clk_debug_create_one(core, rootdir);
+unlock:
+ mutex_unlock(&clk_debug_lock);
+
+ return ret;
+}
+
+ /**
+ * clk_debug_unregister - remove a clk node from the debugfs clk directory
+ * @core: the clk being removed from the debugfs clk directory
+ *
+ * Dynamically removes a clk and all its child nodes from the
+ * debugfs clk directory if clk->dentry points to debugfs created by
+ * clk_debug_register in __clk_init.
+ */
+static void clk_debug_unregister(struct clk_core *core)
+{
+ mutex_lock(&clk_debug_lock);
+ hlist_del_init(&core->debug_node);
+ debugfs_remove_recursive(core->dentry);
+ core->dentry = NULL;
+ mutex_unlock(&clk_debug_lock);
+}
+
+struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
+ void *data, const struct file_operations *fops)
+{
+ struct dentry *d = NULL;
+
+ if (hw->core->dentry)
+ d = debugfs_create_file(name, mode, hw->core->dentry, data,
+ fops);
+
+ return d;
+}
+EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
+
+/**
+ * clk_debug_init - lazily populate the debugfs clk directory
+ *
+ * clks are often initialized very early during boot before memory can be
+ * dynamically allocated and well before debugfs is setup. This function
+ * populates the debugfs clk directory once at boot-time when we know that
+ * debugfs is setup. It should only be called once at boot-time, all other clks
+ * added dynamically will be done so with clk_debug_register.
+ */
+static int __init clk_debug_init(void)
+{
+ struct clk_core *core;
+ struct dentry *d;
+
+ rootdir = debugfs_create_dir("clk", NULL);
+
+ if (!rootdir)
+ return -ENOMEM;
+
+ d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
+ &clk_summary_fops);
+ if (!d)
+ return -ENOMEM;
+
+ d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
+ &clk_dump_fops);
+ if (!d)
+ return -ENOMEM;
+
+ d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
+ &orphan_list, &clk_summary_fops);
+ if (!d)
+ return -ENOMEM;
+
+ d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
+ &orphan_list, &clk_dump_fops);
+ if (!d)
+ return -ENOMEM;
+
+ mutex_lock(&clk_debug_lock);
+ hlist_for_each_entry(core, &clk_debug_list, debug_node)
+ clk_debug_create_one(core, rootdir);
+
+ inited = 1;
+ mutex_unlock(&clk_debug_lock);
+
+ return 0;
+}
+late_initcall(clk_debug_init);
+#else
+static inline int clk_debug_register(struct clk_core *core) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *core,
+ struct clk_core *new_parent)
+{
+}
+static inline void clk_debug_unregister(struct clk_core *core)
+{
+}
+#endif
+
/**
* __clk_init - initialize the data structures in a struct clk
* @dev: device initializing this clk, placeholder for now
@@ -2271,67 +2227,67 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
int i, ret = 0;
struct clk_core *orphan;
struct hlist_node *tmp2;
- struct clk_core *clk;
+ struct clk_core *core;
unsigned long rate;
if (!clk_user)
return -EINVAL;
- clk = clk_user->core;
+ core = clk_user->core;
clk_prepare_lock();
/* check to see if a clock with this name is already registered */
- if (clk_core_lookup(clk->name)) {
+ if (clk_core_lookup(core->name)) {
pr_debug("%s: clk %s already initialized\n",
- __func__, clk->name);
+ __func__, core->name);
ret = -EEXIST;
goto out;
}
/* check that clk_ops are sane. See Documentation/clk.txt */
- if (clk->ops->set_rate &&
- !((clk->ops->round_rate || clk->ops->determine_rate) &&
- clk->ops->recalc_rate)) {
+ if (core->ops->set_rate &&
+ !((core->ops->round_rate || core->ops->determine_rate) &&
+ core->ops->recalc_rate)) {
pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
- __func__, clk->name);
+ __func__, core->name);
ret = -EINVAL;
goto out;
}
- if (clk->ops->set_parent && !clk->ops->get_parent) {
+ if (core->ops->set_parent && !core->ops->get_parent) {
pr_warning("%s: %s must implement .get_parent & .set_parent\n",
- __func__, clk->name);
+ __func__, core->name);
ret = -EINVAL;
goto out;
}
- if (clk->ops->set_rate_and_parent &&
- !(clk->ops->set_parent && clk->ops->set_rate)) {
+ if (core->ops->set_rate_and_parent &&
+ !(core->ops->set_parent && core->ops->set_rate)) {
pr_warn("%s: %s must implement .set_parent & .set_rate\n",
- __func__, clk->name);
+ __func__, core->name);
ret = -EINVAL;
goto out;
}
/* throw a WARN if any entries in parent_names are NULL */
- for (i = 0; i < clk->num_parents; i++)
- WARN(!clk->parent_names[i],
+ for (i = 0; i < core->num_parents; i++)
+ WARN(!core->parent_names[i],
"%s: invalid NULL in %s's .parent_names\n",
- __func__, clk->name);
+ __func__, core->name);
/*
* Allocate an array of struct clk *'s to avoid unnecessary string
* look-ups of clk's possible parents. This can fail for clocks passed
- * in to clk_init during early boot; thus any access to clk->parents[]
+ * in to clk_init during early boot; thus any access to core->parents[]
* must always check for a NULL pointer and try to populate it if
* necessary.
*
- * If clk->parents is not NULL we skip this entire block. This allows
- * for clock drivers to statically initialize clk->parents.
+ * If core->parents is not NULL we skip this entire block. This allows
+ * for clock drivers to statically initialize core->parents.
*/
- if (clk->num_parents > 1 && !clk->parents) {
- clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+ if (core->num_parents > 1 && !core->parents) {
+ core->parents = kcalloc(core->num_parents, sizeof(struct clk *),
GFP_KERNEL);
/*
* clk_core_lookup returns NULL for parents that have not been
@@ -2339,16 +2295,16 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
* for a NULL pointer. We can always perform lazy lookups for
* missing parents later on.
*/
- if (clk->parents)
- for (i = 0; i < clk->num_parents; i++)
- clk->parents[i] =
- clk_core_lookup(clk->parent_names[i]);
+ if (core->parents)
+ for (i = 0; i < core->num_parents; i++)
+ core->parents[i] =
+ clk_core_lookup(core->parent_names[i]);
}
- clk->parent = __clk_init_parent(clk);
+ core->parent = __clk_init_parent(core);
/*
- * Populate clk->parent if parent has already been __clk_init'd. If
+ * Populate core->parent if parent has already been __clk_init'd. If
* parent has not yet been __clk_init'd then place clk in the orphan
* list. If clk has set the CLK_IS_ROOT flag then place it in the root
* clk list.
@@ -2357,13 +2313,13 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
* clocks and re-parent any that are children of the clock currently
* being clk_init'd.
*/
- if (clk->parent)
- hlist_add_head(&clk->child_node,
- &clk->parent->children);
- else if (clk->flags & CLK_IS_ROOT)
- hlist_add_head(&clk->child_node, &clk_root_list);
+ if (core->parent)
+ hlist_add_head(&core->child_node,
+ &core->parent->children);
+ else if (core->flags & CLK_IS_ROOT)
+ hlist_add_head(&core->child_node, &clk_root_list);
else
- hlist_add_head(&clk->child_node, &clk_orphan_list);
+ hlist_add_head(&core->child_node, &clk_orphan_list);
/*
* Set clk's accuracy. The preferred method is to use
@@ -2372,23 +2328,23 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
* parent (or is orphaned) then accuracy is set to zero (perfect
* clock).
*/
- if (clk->ops->recalc_accuracy)
- clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
- __clk_get_accuracy(clk->parent));
- else if (clk->parent)
- clk->accuracy = clk->parent->accuracy;
+ if (core->ops->recalc_accuracy)
+ core->accuracy = core->ops->recalc_accuracy(core->hw,
+ __clk_get_accuracy(core->parent));
+ else if (core->parent)
+ core->accuracy = core->parent->accuracy;
else
- clk->accuracy = 0;
+ core->accuracy = 0;
/*
* Set clk's phase.
* Since a phase is by definition relative to its parent, just
* query the current clock phase, or just assume it's in phase.
*/
- if (clk->ops->get_phase)
- clk->phase = clk->ops->get_phase(clk->hw);
+ if (core->ops->get_phase)
+ core->phase = core->ops->get_phase(core->hw);
else
- clk->phase = 0;
+ core->phase = 0;
/*
* Set clk's rate. The preferred method is to use .recalc_rate. For
@@ -2396,14 +2352,14 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
* parent's rate. If a clock doesn't have a parent (or is orphaned)
* then rate is set to zero.
*/
- if (clk->ops->recalc_rate)
- rate = clk->ops->recalc_rate(clk->hw,
- clk_core_get_rate_nolock(clk->parent));
- else if (clk->parent)
- rate = clk->parent->rate;
+ if (core->ops->recalc_rate)
+ rate = core->ops->recalc_rate(core->hw,
+ clk_core_get_rate_nolock(core->parent));
+ else if (core->parent)
+ rate = core->parent->rate;
else
rate = 0;
- clk->rate = clk->req_rate = rate;
+ core->rate = core->req_rate = rate;
/*
* walk the list of orphan clocks and reparent any that are children of
@@ -2412,14 +2368,14 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
if (orphan->num_parents && orphan->ops->get_parent) {
i = orphan->ops->get_parent(orphan->hw);
- if (!strcmp(clk->name, orphan->parent_names[i]))
- clk_core_reparent(orphan, clk);
+ if (!strcmp(core->name, orphan->parent_names[i]))
+ clk_core_reparent(orphan, core);
continue;
}
for (i = 0; i < orphan->num_parents; i++)
- if (!strcmp(clk->name, orphan->parent_names[i])) {
- clk_core_reparent(orphan, clk);
+ if (!strcmp(core->name, orphan->parent_names[i])) {
+ clk_core_reparent(orphan, core);
break;
}
}
@@ -2432,15 +2388,15 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
* Please consider other ways of solving initialization problems before
* using this callback, as its use is discouraged.
*/
- if (clk->ops->init)
- clk->ops->init(clk->hw);
+ if (core->ops->init)
+ core->ops->init(core->hw);
- kref_init(&clk->ref);
+ kref_init(&core->ref);
out:
clk_prepare_unlock();
if (!ret)
- clk_debug_register(clk);
+ clk_debug_register(core);
return ret;
}
@@ -2486,63 +2442,58 @@ void __clk_free_clk(struct clk *clk)
*
* clk_register is the primary interface for populating the clock tree with new
* clock nodes. It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
+ * cannot be dereferenced by driver code but may be used in conjunction with the
* rest of the clock API. In the event of an error clk_register will return an
* error code; drivers must test for an error code after calling clk_register.
*/
struct clk *clk_register(struct device *dev, struct clk_hw *hw)
{
int i, ret;
- struct clk_core *clk;
+ struct clk_core *core;
- clk = kzalloc(sizeof(*clk), GFP_KERNEL);
- if (!clk) {
- pr_err("%s: could not allocate clk\n", __func__);
+ core = kzalloc(sizeof(*core), GFP_KERNEL);
+ if (!core) {
ret = -ENOMEM;
goto fail_out;
}
- clk->name = kstrdup_const(hw->init->name, GFP_KERNEL);
- if (!clk->name) {
- pr_err("%s: could not allocate clk->name\n", __func__);
+ core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
+ if (!core->name) {
ret = -ENOMEM;
goto fail_name;
}
- clk->ops = hw->init->ops;
+ core->ops = hw->init->ops;
if (dev && dev->driver)
- clk->owner = dev->driver->owner;
- clk->hw = hw;
- clk->flags = hw->init->flags;
- clk->num_parents = hw->init->num_parents;
- hw->core = clk;
+ core->owner = dev->driver->owner;
+ core->hw = hw;
+ core->flags = hw->init->flags;
+ core->num_parents = hw->init->num_parents;
+ hw->core = core;
/* allocate local copy in case parent_names is __initdata */
- clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
+ core->parent_names = kcalloc(core->num_parents, sizeof(char *),
GFP_KERNEL);
- if (!clk->parent_names) {
- pr_err("%s: could not allocate clk->parent_names\n", __func__);
+ if (!core->parent_names) {
ret = -ENOMEM;
goto fail_parent_names;
}
/* copy each string name in case parent_names is __initdata */
- for (i = 0; i < clk->num_parents; i++) {
- clk->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
+ for (i = 0; i < core->num_parents; i++) {
+ core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
GFP_KERNEL);
- if (!clk->parent_names[i]) {
- pr_err("%s: could not copy parent_names\n", __func__);
+ if (!core->parent_names[i]) {
ret = -ENOMEM;
goto fail_parent_names_copy;
}
}
- INIT_HLIST_HEAD(&clk->clks);
+ INIT_HLIST_HEAD(&core->clks);
hw->clk = __clk_create_clk(hw, NULL, NULL);
if (IS_ERR(hw->clk)) {
- pr_err("%s: could not allocate per-user clk\n", __func__);
ret = PTR_ERR(hw->clk);
goto fail_parent_names_copy;
}
@@ -2556,35 +2507,32 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
fail_parent_names_copy:
while (--i >= 0)
- kfree_const(clk->parent_names[i]);
- kfree(clk->parent_names);
+ kfree_const(core->parent_names[i]);
+ kfree(core->parent_names);
fail_parent_names:
- kfree_const(clk->name);
+ kfree_const(core->name);
fail_name:
- kfree(clk);
+ kfree(core);
fail_out:
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(clk_register);
-/*
- * Free memory allocated for a clock.
- * Caller must hold prepare_lock.
- */
+/* Free memory allocated for a clock. */
static void __clk_release(struct kref *ref)
{
- struct clk_core *clk = container_of(ref, struct clk_core, ref);
- int i = clk->num_parents;
+ struct clk_core *core = container_of(ref, struct clk_core, ref);
+ int i = core->num_parents;
lockdep_assert_held(&prepare_lock);
- kfree(clk->parents);
+ kfree(core->parents);
while (--i >= 0)
- kfree_const(clk->parent_names[i]);
+ kfree_const(core->parent_names[i]);
- kfree(clk->parent_names);
- kfree_const(clk->name);
- kfree(clk);
+ kfree(core->parent_names);
+ kfree_const(core->name);
+ kfree(core);
}
/*
@@ -3068,6 +3016,27 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
}
EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
+/**
+ * of_clk_parent_fill() - Fill @parents with names of @np's parents and return
+ * number of parents
+ * @np: Device node pointer associated with clock provider
+ * @parents: pointer to char array that hold the parents' names
+ * @size: size of the @parents array
+ *
+ * Return: number of parents for the clock node.
+ */
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+ unsigned int size)
+{
+ unsigned int i = 0;
+
+ while (i < size && (parents[i] = of_clk_get_parent_name(np, i)) != NULL)
+ i++;
+
+ return i;
+}
+EXPORT_SYMBOL_GPL(of_clk_parent_fill);
+
struct clock_provider {
of_clk_init_cb_t clk_init_cb;
struct device_node *np;
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 000000000000..b4165ba75d9f
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,6 @@
+config COMMON_CLK_HI6220
+ bool "Hi6220 Clock Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ default ARCH_HISI
+ help
+ Build the Hisilicon Hi6220 clock driver based on the common clock framework.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f4d0e7..48f0116a032a 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,8 +2,9 @@
# Hisilicon Clock specific Makefile
#
-obj-y += clk.o clkgate-separated.o
+obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 472dd2cb10b3..715d34a5ef9b 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -38,44 +38,44 @@
#include "clk.h"
/* clock parent list */
-static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
+static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
/* share axi parent */
-static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
-static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
-static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
+static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
-static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
-static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
-static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
/* fixed rate clocks */
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 000000000000..4563343b6420
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon Hi6220 clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * 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/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+#include "clk.h"
+
+
+/* clocks in AO (always on) controller */
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+ { HI6220_REF32K, "ref32k", NULL, CLK_IS_ROOT, 32764, },
+ { HI6220_CLK_TCXO, "clk_tcxo", NULL, CLK_IS_ROOT, 19200000, },
+ { HI6220_MMC1_PAD, "mmc1_pad", NULL, CLK_IS_ROOT, 100000000, },
+ { HI6220_MMC2_PAD, "mmc2_pad", NULL, CLK_IS_ROOT, 100000000, },
+ { HI6220_MMC0_PAD, "mmc0_pad", NULL, CLK_IS_ROOT, 200000000, },
+ { HI6220_PLL_BBP, "bbppll0", NULL, CLK_IS_ROOT, 245760000, },
+ { HI6220_PLL_GPU, "gpupll", NULL, CLK_IS_ROOT, 1000000000,},
+ { HI6220_PLL1_DDR, "ddrpll1", NULL, CLK_IS_ROOT, 1066000000,},
+ { HI6220_PLL_SYS, "syspll", NULL, CLK_IS_ROOT, 1200000000,},
+ { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
+ { HI6220_DDR_SRC, "ddr_sel_src", NULL, CLK_IS_ROOT, 1200000000,},
+ { HI6220_PLL_MEDIA, "media_pll", NULL, CLK_IS_ROOT, 1440000000,},
+ { HI6220_PLL_DDR, "ddrpll0", NULL, CLK_IS_ROOT, 1600000000,},
+};
+
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+ { HI6220_300M, "clk_300m", "syspll", 1, 4, 0, },
+ { HI6220_150M, "clk_150m", "clk_300m", 1, 2, 0, },
+ { HI6220_PICOPHY_SRC, "picophy_src", "clk_150m", 1, 4, 0, },
+ { HI6220_MMC0_SRC_SEL, "mmc0srcsel", "mmc0_sel", 1, 8, 0, },
+ { HI6220_MMC1_SRC_SEL, "mmc1srcsel", "mmc1_sel", 1, 8, 0, },
+ { HI6220_MMC2_SRC_SEL, "mmc2srcsel", "mmc2_sel", 1, 8, 0, },
+ { HI6220_VPU_CODEC, "vpucodec", "codec_jpeg_aclk", 1, 2, 0, },
+ { HI6220_MMC0_SMP, "mmc0_sample", "mmc0_sel", 1, 8, 0, },
+ { HI6220_MMC1_SMP, "mmc1_sample", "mmc1_sel", 1, 8, 0, },
+ { HI6220_MMC2_SMP, "mmc2_sample", "mmc2_sel", 1, 8, 0, },
+};
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+ { HI6220_WDT0_PCLK, "wdt0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
+ { HI6220_WDT1_PCLK, "wdt1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
+ { HI6220_WDT2_PCLK, "wdt2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
+ { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
+ { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
+ { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
+ { HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
+ { HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
+ { HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
+ { HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
+ { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
+ { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
+ { HI6220_UART0_PCLK, "uart0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+};
+
+static void __init hi6220_clk_ao_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data_ao;
+
+ clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+ if (!clk_data_ao)
+ return;
+
+ hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+ ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data_ao);
+
+ hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+ ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data_ao);
+
+ hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+ ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initdata = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initdata = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initdata = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[] __initdata = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initdata = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[] __initdata = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initdata = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initdata = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initdata = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initdata = { "syspll", "pll_media_gate", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+ { HI6220_MMC0_CLK, "mmc0_clk", "mmc0_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
+ { HI6220_MMC0_CIUCLK, "mmc0_ciuclk", "mmc0_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0, 0, },
+ { HI6220_MMC1_CLK, "mmc1_clk", "mmc1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, },
+ { HI6220_MMC1_CIUCLK, "mmc1_ciuclk", "mmc1_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1, 0, },
+ { HI6220_MMC2_CLK, "mmc2_clk", "mmc2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, },
+ { HI6220_MMC2_CIUCLK, "mmc2_ciuclk", "mmc2_smp_in", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2, 0, },
+ { HI6220_USBOTG_HCLK, "usbotg_hclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4, 0, },
+ { HI6220_CLK_PICOPHY, "clk_picophy", "cs_dapb", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5, 0, },
+ { HI6220_HIFI, "hifi_clk", "hifi_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0, 0, },
+ { HI6220_DACODEC_PCLK, "dacodec_pclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5, 0, },
+ { HI6220_EDMAC_ACLK, "edmac_aclk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2, 0, },
+ { HI6220_CS_ATB, "cs_atb", "cs_atb_div", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0, 0, },
+ { HI6220_I2C0_CLK, "i2c0_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1, 0, },
+ { HI6220_I2C1_CLK, "i2c1_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2, 0, },
+ { HI6220_I2C2_CLK, "i2c2_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3, 0, },
+ { HI6220_I2C3_CLK, "i2c3_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4, 0, },
+ { HI6220_UART1_PCLK, "uart1_pclk", "uart1_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5, 0, },
+ { HI6220_UART2_PCLK, "uart2_pclk", "uart2_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6, 0, },
+ { HI6220_UART3_PCLK, "uart3_pclk", "uart3_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7, 0, },
+ { HI6220_UART4_PCLK, "uart4_pclk", "uart4_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8, 0, },
+ { HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9, 0, },
+ { HI6220_TSENSOR_CLK, "tsensor_clk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 0, },
+ { HI6220_MMU_CLK, "mmu_clk", "ddrc_axi1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
+ { HI6220_HIFI_SEL, "hifi_sel", "hifi_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0, 0, },
+ { HI6220_MMC0_SYSPLL, "mmc0_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1, 0, },
+ { HI6220_MMC1_SYSPLL, "mmc1_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2, 0, },
+ { HI6220_MMC2_SYSPLL, "mmc2_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3, 0, },
+ { HI6220_MMC0_SEL, "mmc0_sel", "mmc0_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6, 0, },
+ { HI6220_MMC1_SEL, "mmc1_sel", "mmc1_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7, 0, },
+ { HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, },
+ { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
+ { HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
+ { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+ { HI6220_MMC0_SRC, "mmc0_src", mmc0_src_p, ARRAY_SIZE(mmc0_src_p), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
+ { HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4, 0, 1, 0, },
+ { HI6220_MMC1_SRC, "mmc1_src", mmc1_src_p, ARRAY_SIZE(mmc1_src_p), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, },
+ { HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4, 2, 1, 0, },
+ { HI6220_MMC2_SRC, "mmc2_src", mmc2_src_p, ARRAY_SIZE(mmc2_src_p), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, },
+ { HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4, 4, 1, 0, },
+ { HI6220_HIFI_SRC, "hifi_src", hifi_src, ARRAY_SIZE(hifi_src), CLK_SET_RATE_PARENT, 0x400, 0, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_UART1_SRC, "uart1_src", uart1_src, ARRAY_SIZE(uart1_src), CLK_SET_RATE_PARENT, 0x400, 1, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_UART2_SRC, "uart2_src", uart2_src, ARRAY_SIZE(uart2_src), CLK_SET_RATE_PARENT, 0x400, 2, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_UART3_SRC, "uart3_src", uart3_src, ARRAY_SIZE(uart3_src), CLK_SET_RATE_PARENT, 0x400, 3, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_UART4_SRC, "uart4_src", uart4_src, ARRAY_SIZE(uart4_src), CLK_SET_RATE_PARENT, 0x400, 4, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC0_MUX0, "mmc0_mux0", mmc0_mux0_p, ARRAY_SIZE(mmc0_mux0_p), CLK_SET_RATE_PARENT, 0x400, 5, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC1_MUX0, "mmc1_mux0", mmc1_mux0_p, ARRAY_SIZE(mmc1_mux0_p), CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC2_MUX0, "mmc2_mux0", mmc2_mux0_p, ARRAY_SIZE(mmc2_mux0_p), CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC0_MUX1, "mmc0_mux1", mmc0_mux1_p, ARRAY_SIZE(mmc0_mux1_p), CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC1_MUX1, "mmc1_mux1", mmc1_mux1_p, ARRAY_SIZE(mmc1_mux1_p), CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
+ { HI6220_MMC2_MUX1, "mmc2_mux1", mmc2_mux1_p, ARRAY_SIZE(mmc2_mux1_p), CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+ { HI6220_CLK_BUS, "clk_bus", "clk_300m", CLK_SET_RATE_PARENT, 0x490, 0, 4, 7, },
+ { HI6220_MMC0_DIV, "mmc0_div", "mmc0_syspll", CLK_SET_RATE_PARENT, 0x494, 0, 6, 7, },
+ { HI6220_MMC1_DIV, "mmc1_div", "mmc1_syspll", CLK_SET_RATE_PARENT, 0x498, 0, 6, 7, },
+ { HI6220_MMC2_DIV, "mmc2_div", "mmc2_syspll", CLK_SET_RATE_PARENT, 0x49c, 0, 6, 7, },
+ { HI6220_HIFI_DIV, "hifi_div", "hifi_sel", CLK_SET_RATE_PARENT, 0x4a0, 0, 4, 7, },
+ { HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel", CLK_SET_RATE_PARENT, 0x4a0, 8, 6, 15,},
+ { HI6220_CS_DAPB, "cs_dapb", "picophy_src", CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
+ { HI6220_CS_ATB_DIV, "cs_atb_div", "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0, 4, 7, },
+};
+
+static void __init hi6220_clk_sys_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+
+ clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
+ ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
+
+ hisi_clk_register_mux(hi6220_mux_clks_sys,
+ ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
+
+ hi6220_clk_register_divider(hi6220_div_clks_sys,
+ ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initdata = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initdata = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initdata = { "pll_gpu_gate", "media_pll_src", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+ { HI6220_DSI_PCLK, "dsi_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0, 0, },
+ { HI6220_G3D_PCLK, "g3d_pclk", "vpucodec", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1, 0, },
+ { HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3, 0, },
+ { HI6220_ISP_SCLK, "isp_sclk", "isp_sclk_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5, 0, },
+ { HI6220_ADE_CORE, "ade_core", "ade_core_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6, 0, },
+ { HI6220_MED_MMU, "media_mmu", "mmu_clk", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8, 0, },
+ { HI6220_CFG_CSI4PHY, "cfg_csi4phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9, 0, },
+ { HI6220_CFG_CSI2PHY, "cfg_csi2phy", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
+ { HI6220_ISP_SCLK_GATE, "isp_sclk_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
+ { HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
+ { HI6220_ADE_CORE_GATE, "ade_core_gate", "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
+ { HI6220_CODEC_VPU_GATE, "codec_vpu_gate", "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
+ { HI6220_MED_SYSPLL, "media_syspll_src", "media_syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+ { HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
+ { HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
+ { HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+ { HI6220_CODEC_JPEG, "codec_jpeg_aclk", "media_pll_src", CLK_SET_RATE_PARENT, 0xcbc, 0, 4, 23, },
+ { HI6220_ISP_SCLK_SRC, "isp_sclk_src", "isp_sclk_gate", CLK_SET_RATE_PARENT, 0xcbc, 8, 4, 15, },
+ { HI6220_ISP_SCLK1, "isp_sclk1", "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
+ { HI6220_ADE_CORE_SRC, "ade_core_src", "ade_core_gate", CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
+ { HI6220_ADE_PIX_SRC, "ade_pix_src", "clk_1440_1200", CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
+ { HI6220_G3D_CLK, "g3d_clk", "clk_1000_1200", CLK_SET_RATE_PARENT, 0xcc4, 8, 4, 15, },
+ { HI6220_CODEC_VPU_SRC, "codec_vpu_src", "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
+};
+
+static void __init hi6220_clk_media_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+
+ clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
+ ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
+
+ hisi_clk_register_mux(hi6220_mux_clks_media,
+ ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
+
+ hi6220_clk_register_divider(hi6220_div_clks_media,
+ ARRAY_SIZE(hi6220_div_clks_media), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
+
+
+/* clocks in pmctrl */
+static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+ { HI6220_PLL_GPU_GATE, "pll_gpu_gate", "gpupll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8, 0, 0, },
+ { HI6220_PLL1_DDR_GATE, "pll1_ddr_gate", "ddrpll1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0, 0, },
+ { HI6220_PLL_DDR_GATE, "pll_ddr_gate", "ddrpll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0, 0, },
+ { HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0, 0, },
+ { HI6220_PLL0_BBP_GATE, "pll0_bbp_gate", "bbppll0", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+ { HI6220_DDRC_SRC, "ddrc_src", "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
+ { HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src", CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
+};
+
+static void __init hi6220_clk_power_init(struct device_node *np)
+{
+ struct hisi_clock_data *clk_data;
+
+ clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
+ if (!clk_data)
+ return;
+
+ hisi_clk_register_gate(hi6220_gate_clks_power,
+ ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
+
+ hi6220_clk_register_divider(hi6220_div_clks_power,
+ ARRAY_SIZE(hi6220_div_clks_power), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index f1d239435826..0aaf29da8491 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -46,15 +46,15 @@ static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
{ HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
};
-static const char *sfc_mux_p[] __initdata = {
+static const char *const sfc_mux_p[] __initconst = {
"24m", "150m", "200m", "100m", "75m", };
static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
-static const char *sdio_mux_p[] __initdata = {
+static const char *const sdio_mux_p[] __initconst = {
"75m", "100m", "50m", "15m", };
static u32 sdio_mux_table[] = {0, 1, 2, 3};
-static const char *fephy_mux_p[] __initdata = { "25m", "125m"};
+static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
static u32 fephy_mux_table[] = {0, 1};
@@ -252,8 +252,9 @@ static struct clk_ops clk_complex_ops = {
.disable = clk_complex_disable,
};
-void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
- int nums, struct hisi_clock_data *data)
+static void __init
+hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
+ struct hisi_clock_data *data)
{
void __iomem *base = data->base;
int i;
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84f7b05..c90a89739b03 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
data->clk_data.clks[clks[i].id] = clk;
}
}
+
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+ int nums, struct hisi_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = hi6220_register_clkdiv(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags,
+ base + clks[i].offset,
+ clks[i].shift,
+ clks[i].width,
+ clks[i].mask_bit,
+ &hisi_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ continue;
+ }
+
+ if (clks[i].alias)
+ clk_register_clkdev(clk, clks[i].alias, NULL);
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ffc0650..b56fbc1c5f27 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -55,7 +55,7 @@ struct hisi_fixed_factor_clock {
struct hisi_mux_clock {
unsigned int id;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
unsigned long offset;
@@ -79,6 +79,18 @@ struct hisi_divider_clock {
const char *alias;
};
+struct hi6220_divider_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long offset;
+ u8 shift;
+ u8 width;
+ u32 mask_bit;
+ const char *alias;
+};
+
struct hisi_gate_clock {
unsigned int id;
const char *name;
@@ -94,18 +106,23 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
const char *, unsigned long,
void __iomem *, u8,
u8, spinlock_t *);
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags, void __iomem *reg,
+ u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
-struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
-void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
- int, struct hisi_clock_data *);
-void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
- int, struct hisi_clock_data *);
-void __init hisi_clk_register_mux(struct hisi_mux_clock *, int,
+struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
+void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
+ int, struct hisi_clock_data *);
+void hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
+ int, struct hisi_clock_data *);
+void hisi_clk_register_mux(struct hisi_mux_clock *, int,
struct hisi_clock_data *);
-void __init hisi_clk_register_divider(struct hisi_divider_clock *,
+void hisi_clk_register_divider(struct hisi_divider_clock *,
+ int, struct hisi_clock_data *);
+void hisi_clk_register_gate(struct hisi_gate_clock *,
+ int, struct hisi_clock_data *);
+void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
+ int, struct hisi_clock_data *);
+void hi6220_clk_register_divider(struct hi6220_divider_clock *,
int, struct hisi_clock_data *);
-void __init hisi_clk_register_gate(struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
-void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
#endif /* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
new file mode 100644
index 000000000000..113eee8ed23a
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,156 @@
+/*
+ * Hisilicon hi6220 SoC divider clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * 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/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+
+#define div_mask(width) ((1 << (width)) - 1)
+
+/**
+ * struct hi6220_clk_divider - divider clock for hi6220
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: register containing divider
+ * @shift: shift to the divider bit field
+ * @width: width of the divider bit field
+ * @mask: mask for setting divider rate
+ * @table: the div table that the divider supports
+ * @lock: register lock
+ */
+struct hi6220_clk_divider {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 shift;
+ u8 width;
+ u32 mask;
+ const struct clk_div_table *table;
+ spinlock_t *lock;
+};
+
+#define to_hi6220_clk_divider(_hw) \
+ container_of(_hw, struct hi6220_clk_divider, hw)
+
+static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned int val;
+ struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+ val = readl_relaxed(dclk->reg) >> dclk->shift;
+ val &= div_mask(dclk->width);
+
+ return divider_recalc_rate(hw, parent_rate, val, dclk->table,
+ CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+ return divider_round_rate(hw, rate, prate, dclk->table,
+ dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int value;
+ unsigned long flags = 0;
+ u32 data;
+ struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+ value = divider_get_val(rate, parent_rate, dclk->table,
+ dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+
+ if (dclk->lock)
+ spin_lock_irqsave(dclk->lock, flags);
+
+ data = readl_relaxed(dclk->reg);
+ data &= ~(div_mask(dclk->width) << dclk->shift);
+ data |= value << dclk->shift;
+ data |= dclk->mask;
+
+ writel_relaxed(data, dclk->reg);
+
+ if (dclk->lock)
+ spin_unlock_irqrestore(dclk->lock, flags);
+
+ return 0;
+}
+
+static const struct clk_ops hi6220_clkdiv_ops = {
+ .recalc_rate = hi6220_clkdiv_recalc_rate,
+ .round_rate = hi6220_clkdiv_round_rate,
+ .set_rate = hi6220_clkdiv_set_rate,
+};
+
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags, void __iomem *reg,
+ u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
+{
+ struct hi6220_clk_divider *div;
+ struct clk *clk;
+ struct clk_init_data init;
+ struct clk_div_table *table;
+ u32 max_div, min_div;
+ int i;
+
+ /* allocate the divider */
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ /* Init the divider table */
+ max_div = div_mask(width) + 1;
+ min_div = 1;
+
+ table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
+ if (!table) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0; i < max_div; i++) {
+ table[i].div = min_div + i;
+ table[i].val = table[i].div - 1;
+ }
+
+ init.name = name;
+ init.ops = &hi6220_clkdiv_ops;
+ init.flags = flags;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ /* struct hi6220_clk_divider assignments */
+ div->reg = reg;
+ div->shift = shift;
+ div->width = width;
+ div->mask = mask_bit ? BIT(mask_bit) : 0;
+ div->lock = lock;
+ div->hw.init = &init;
+ div->table = table;
+
+ /* register the clock */
+ clk = clk_register(dev, &div->hw);
+ if (IS_ERR(clk)) {
+ kfree(table);
+ kfree(div);
+ }
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 000000000000..8e4b2a4635b9
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1,4 @@
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o
+obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 000000000000..57020368a693
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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_address.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+ u32 val;
+
+ regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+ val &= BIT(cg->bit);
+
+ return val == 0;
+}
+
+static int mtk_cg_bit_is_set(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+ u32 val;
+
+ regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+ val &= BIT(cg->bit);
+
+ return val != 0;
+}
+
+static void mtk_cg_set_bit(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+ regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+}
+
+static void mtk_cg_clr_bit(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+ regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+}
+
+static int mtk_cg_enable(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable(struct clk_hw *hw)
+{
+ mtk_cg_set_bit(hw);
+}
+
+static int mtk_cg_enable_inv(struct clk_hw *hw)
+{
+ mtk_cg_set_bit(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable_inv(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit(hw);
+}
+
+const struct clk_ops mtk_clk_gate_ops_setclr = {
+ .is_enabled = mtk_cg_bit_is_cleared,
+ .enable = mtk_cg_enable,
+ .disable = mtk_cg_disable,
+};
+
+const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
+ .is_enabled = mtk_cg_bit_is_set,
+ .enable = mtk_cg_enable_inv,
+ .disable = mtk_cg_disable_inv,
+};
+
+struct clk *mtk_clk_register_gate(
+ const char *name,
+ const char *parent_name,
+ struct regmap *regmap,
+ int set_ofs,
+ int clr_ofs,
+ int sta_ofs,
+ u8 bit,
+ const struct clk_ops *ops)
+{
+ struct mtk_clk_gate *cg;
+ struct clk *clk;
+ struct clk_init_data init = {};
+
+ cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+ if (!cg)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.ops = ops;
+
+ cg->regmap = regmap;
+ cg->set_ofs = set_ofs;
+ cg->clr_ofs = clr_ofs;
+ cg->sta_ofs = sta_ofs;
+ cg->bit = bit;
+
+ cg->hw.init = &init;
+
+ clk = clk_register(NULL, &cg->hw);
+ if (IS_ERR(clk))
+ kfree(cg);
+
+ return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 000000000000..6b6780b1e9c5
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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 __DRV_CLK_GATE_H
+#define __DRV_CLK_GATE_H
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ int set_ofs;
+ int clr_ofs;
+ int sta_ofs;
+ u8 bit;
+};
+
+static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_clk_gate, hw);
+}
+
+extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+
+struct clk *mtk_clk_register_gate(
+ const char *name,
+ const char *parent_name,
+ struct regmap *regmap,
+ int set_ofs,
+ int clr_ofs,
+ int sta_ofs,
+ u8 bit,
+ const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 000000000000..08b4b849b491
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/mt8135-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static DEFINE_SPINLOCK(mt8135_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+ FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
+
+ FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
+
+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
+ FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+ FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+ FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
+
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
+ FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
+
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
+
+ FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
+
+ FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
+
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
+
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
+
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+
+ FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
+ FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
+ FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
+ FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
+ FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
+
+ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+ FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
+ FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
+
+ FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
+
+ FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
+ FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
+
+ FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
+ FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
+
+ FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+ "clk26m",
+ "syspll_d3",
+ "syspll_d4",
+ "syspll_d6",
+ "univpll_d5",
+ "univpll2_d2",
+ "syspll_d3p5"
+};
+
+static const char * const smi_parents[] __initconst = {
+ "clk26m",
+ "clkph_mck",
+ "syspll_d2p5",
+ "syspll_d3",
+ "syspll_d8",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll1_d6",
+ "mmpll_d3",
+ "mmpll_d4",
+ "mmpll_d5",
+ "mmpll_d6",
+ "mmpll_d7",
+ "vdecpll",
+ "lvdspll"
+};
+
+static const char * const mfg_parents[] __initconst = {
+ "clk26m",
+ "univpll1_d4",
+ "syspll_d2",
+ "syspll_d2p5",
+ "syspll_d3",
+ "univpll_d5",
+ "univpll1_d2",
+ "mmpll_d2",
+ "mmpll_d3",
+ "mmpll_d4",
+ "mmpll_d5",
+ "mmpll_d6",
+ "mmpll_d7"
+};
+
+static const char * const irda_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8",
+ "univpll1_d6"
+};
+
+static const char * const cam_parents[] __initconst = {
+ "clk26m",
+ "syspll_d3",
+ "syspll_d3p5",
+ "syspll_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "univpll_d7",
+ "univpll1_d4"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+ "clk26m",
+ "syspll_d6",
+ "univpll_d10"
+};
+
+static const char * const jpg_parents[] __initconst = {
+ "clk26m",
+ "syspll_d5",
+ "syspll_d4",
+ "syspll_d3",
+ "univpll_d7",
+ "univpll2_d2",
+ "univpll_d5"
+};
+
+static const char * const disp_parents[] __initconst = {
+ "clk26m",
+ "syspll_d3p5",
+ "syspll_d3",
+ "univpll2_d2",
+ "univpll_d5",
+ "univpll1_d2",
+ "lvdspll",
+ "vdecpll"
+};
+
+static const char * const msdc30_parents[] __initconst = {
+ "clk26m",
+ "syspll_d6",
+ "syspll_d5",
+ "univpll1_d4",
+ "univpll2_d4",
+ "msdcpll"
+};
+
+static const char * const usb20_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d6",
+ "univpll1_d10"
+};
+
+static const char * const venc_parents[] __initconst = {
+ "clk26m",
+ "syspll_d3",
+ "syspll_d8",
+ "univpll_d5",
+ "univpll1_d6",
+ "mmpll_d4",
+ "mmpll_d5",
+ "mmpll_d6"
+};
+
+static const char * const spi_parents[] __initconst = {
+ "clk26m",
+ "syspll_d6",
+ "syspll_d8",
+ "syspll_d10",
+ "univpll1_d6",
+ "univpll1_d8"
+};
+
+static const char * const uart_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const mem_parents[] __initconst = {
+ "clk26m",
+ "clkph_mck"
+};
+
+static const char * const camtg_parents[] __initconst = {
+ "clk26m",
+ "univpll_d26",
+ "univpll1_d6",
+ "syspll_d16",
+ "syspll_d8"
+};
+
+static const char * const audio_parents[] __initconst = {
+ "clk26m",
+ "syspll_d24"
+};
+
+static const char * const fix_parents[] __initconst = {
+ "rtc32k",
+ "clk26m",
+ "univpll_d5",
+ "univpll_d7",
+ "univpll1_d2",
+ "univpll1_d4",
+ "univpll1_d6",
+ "univpll1_d8"
+};
+
+static const char * const vdec_parents[] __initconst = {
+ "clk26m",
+ "vdecpll",
+ "clkph_mck",
+ "syspll_d2p5",
+ "syspll_d3",
+ "syspll_d3p5",
+ "syspll_d4",
+ "syspll_d5",
+ "syspll_d6",
+ "syspll_d8",
+ "univpll1_d2",
+ "univpll2_d2",
+ "univpll_d7",
+ "univpll_d10",
+ "univpll2_d4",
+ "lvdspll"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+ "clk26m",
+ "axi_sel",
+ "syspll_d12"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+ "clk26m",
+ "lvdspll",
+ "lvdspll_d2",
+ "lvdspll_d4",
+ "lvdspll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d6",
+ "syspll_d8",
+ "syspll_d10",
+ "univpll1_d10",
+ "mempll_mck_d4",
+ "univpll_d26",
+ "syspll_d24"
+};
+
+static const char * const smi_mfg_as_parents[] __initconst = {
+ "clk26m",
+ "smi_sel",
+ "mfg_sel",
+ "mem_sel"
+};
+
+static const char * const gcpu_parents[] __initconst = {
+ "clk26m",
+ "syspll_d4",
+ "univpll_d7",
+ "syspll_d5",
+ "syspll_d6"
+};
+
+static const char * const dpi1_parents[] __initconst = {
+ "clk26m",
+ "tvhdmi_h_ck",
+ "tvhdmi_d2",
+ "tvhdmi_d4"
+};
+
+static const char * const cci_parents[] __initconst = {
+ "clk26m",
+ "mainpll_537p3m",
+ "univpll_d3",
+ "syspll_d2p5",
+ "syspll_d3",
+ "syspll_d5"
+};
+
+static const char * const apll_parents[] __initconst = {
+ "clk26m",
+ "apll_ck",
+ "apll_d4",
+ "apll_d8",
+ "apll_d16",
+ "apll_d24"
+};
+
+static const char * const hdmipll_parents[] __initconst = {
+ "clk26m",
+ "hdmitx_clkdig_cts",
+ "hdmitx_clkdig_d2",
+ "hdmitx_clkdig_d3"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+ /* CLK_CFG_0 */
+ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+ 0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
+ MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
+ /* CLK_CFG_1 */
+ MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
+ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+ 0x0144, 8, 2, 15),
+ MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
+ MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
+ /* CLK_CFG_2 */
+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
+ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
+ MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
+ /* CLK_CFG_3 */
+ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
+ /* CLK_CFG_4 */
+ MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
+ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
+ /* CLK_CFG_6 */
+ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
+ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
+ /* CLK_CFG_7 */
+ MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
+ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
+ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+ 0x015c, 16, 2, 23),
+ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
+ /* CLK_CFG_8 */
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
+ MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
+ 0x0164, 16, 2, 23),
+ MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
+ /* CLK_CFG_9 */
+ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
+ MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
+ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
+ MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = 0x0040,
+ .clr_ofs = 0x0044,
+ .sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate infra_clks[] __initconst = {
+ GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+ GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
+ GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
+ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
+ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+ GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
+ GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
+ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
+ GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
+ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
+ GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x0010,
+ .sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+ .set_ofs = 0x000c,
+ .clr_ofs = 0x0014,
+ .sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate peri_gates[] __initconst = {
+ /* PERI0 */
+ GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
+ GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
+ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
+ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
+ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
+ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
+ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
+ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
+ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
+ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
+ GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
+ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
+ GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
+ GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
+ GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
+ GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
+ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
+ GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
+ GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
+ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
+ /* PERI1 */
+ GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
+ GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
+ GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
+ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
+ GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
+ GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
+ GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
+ GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
+ GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+ "clk26m",
+ "uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+ mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+ &mt8135_clk_lock, clk_data);
+
+ clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+ clk_data);
+
+ clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+ mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+ clk_data);
+ mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+ &mt8135_clk_lock, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
+
+#define MT8135_PLL_FMAX (2000 * MHZ)
+#define CON0_MT8135_RST_BAR BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT8135_RST_BAR, \
+ .fmax = MT8135_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ }
+
+static const struct mtk_pll_data plls[] = {
+ PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+ PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
+ PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
+ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ if (!clk_data)
+ return;
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+ mtk_apmixedsys_init);
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
new file mode 100644
index 000000000000..4b9e04cdf7e8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+static DEFINE_SPINLOCK(mt8173_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+ FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
+ FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
+ FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
+
+ FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+
+ FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
+
+ FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+
+ FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
+ FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
+ FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
+
+ FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
+ FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
+
+ FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
+ FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
+
+ FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+ FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+
+ FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
+ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+ FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+ FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
+
+ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+ FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
+
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+
+ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
+
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+
+ FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
+ FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
+
+ FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
+ FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
+ FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const mem_parents[] __initconst = {
+ "clk26m",
+ "dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const mm_parents[] __initconst = {
+ "clk26m",
+ "vencpll_d2",
+ "main_h364m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_d2"
+};
+
+static const char * const pwm_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4"
+};
+
+static const char * const vdec_parents[] __initconst = {
+ "clk26m",
+ "vcodecpll_ck",
+ "tvdpll_445p5m",
+ "univpll_d3",
+ "vencpll_d2",
+ "syspll_d3",
+ "univpll1_d2",
+ "mmpll_d2",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const venc_parents[] __initconst = {
+ "clk26m",
+ "vcodecpll_ck",
+ "tvdpll_445p5m",
+ "univpll_d3",
+ "vencpll_d2",
+ "syspll_d3",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const mfg_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+ "dmpll_ck",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "syspll_d3",
+ "syspll1_d2",
+ "syspll_d5",
+ "univpll_d3",
+ "univpll1_d2",
+ "univpll_d5",
+ "univpll2_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+ "syspll3_d2",
+ "syspll3_d4",
+ "univpll1_d4"
+};
+
+static const char * const uart_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll1_d4",
+ "syspll4_d2",
+ "univpll3_d2",
+ "univpll2_d4",
+ "univpll1_d8"
+};
+
+static const char * const usb20_parents[] __initconst = {
+ "clk26m",
+ "univpll1_d8",
+ "univpll3_d4"
+};
+
+static const char * const usb30_parents[] __initconst = {
+ "clk26m",
+ "univpll3_d2",
+ "usb_syspll_125m",
+ "univpll2_d4"
+};
+
+static const char * const msdc50_0_h_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll2_d2",
+ "syspll4_d2",
+ "univpll_d5",
+ "univpll1_d4"
+};
+
+static const char * const msdc50_0_parents[] __initconst = {
+ "clk26m",
+ "msdcpll_ck",
+ "msdcpll_d2",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "msdcpll_d4",
+ "vencpll_d4",
+ "tvdpll_ck",
+ "univpll_d2",
+ "univpll1_d2",
+ "mmpll_ck",
+ "msdcpll2_ck",
+ "msdcpll2_d2",
+ "msdcpll2_d4"
+};
+
+static const char * const msdc30_1_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll_d7",
+ "vencpll_d4"
+};
+
+static const char * const msdc30_2_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d2",
+ "msdcpll_d4",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll_d7",
+ "vencpll_d2"
+};
+
+static const char * const msdc30_3_parents[] __initconst = {
+ "clk26m",
+ "msdcpll2_ck",
+ "msdcpll2_d2",
+ "univpll2_d2",
+ "msdcpll2_d4",
+ "msdcpll_d4",
+ "univpll1_d4",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll_d7",
+ "vencpll_d4",
+ "msdcpll_ck",
+ "msdcpll_d2",
+ "msdcpll_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d4",
+ "syspll4_d4",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll4_d2",
+ "univpll3_d2",
+ "univpll2_d8",
+ "dmpll_d4",
+ "dmpll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8",
+ "syspll3_d4",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll_d26",
+ "dmpll_d8",
+ "dmpll_d16"
+};
+
+static const char * const scp_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll_d5",
+ "syspll_d5",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const atb_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll_d5",
+ "dmpll_d2"
+};
+
+static const char * const venc_lt_parents[] __initconst = {
+ "clk26m",
+ "univpll_d3",
+ "vcodecpll_ck",
+ "tvdpll_445p5m",
+ "vencpll_d2",
+ "syspll_d3",
+ "univpll1_d2",
+ "univpll2_d2",
+ "syspll1_d2",
+ "univpll_d5",
+ "vcodecpll_370p5",
+ "dmpll_ck"
+};
+
+static const char * const dpi0_parents[] __initconst = {
+ "clk26m",
+ "tvdpll_d2",
+ "tvdpll_d4",
+ "clk26m",
+ "clk26m",
+ "tvdpll_d8",
+ "tvdpll_d16"
+};
+
+static const char * const irda_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d4",
+ "syspll2_d4"
+};
+
+static const char * const cci400_parents[] __initconst = {
+ "clk26m",
+ "vencpll_ck",
+ "armca7pll_754m",
+ "armca7pll_502m",
+ "univpll_d2",
+ "syspll_d2",
+ "msdcpll_ck",
+ "dmpll_ck"
+};
+
+static const char * const aud_1_parents[] __initconst = {
+ "clk26m",
+ "apll1_ck",
+ "univpll2_d4",
+ "univpll2_d8"
+};
+
+static const char * const aud_2_parents[] __initconst = {
+ "clk26m",
+ "apll2_ck",
+ "univpll2_d4",
+ "univpll2_d8"
+};
+
+static const char * const mem_mfg_in_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+ "dmpll_ck",
+ "clk26m"
+};
+
+static const char * const axi_mfg_in_parents[] __initconst = {
+ "clk26m",
+ "axi_sel",
+ "dmpll_d2"
+};
+
+static const char * const scam_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d2",
+ "univpll2_d4",
+ "dmpll_d4"
+};
+
+static const char * const spinfi_ifr_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8",
+ "univpll3_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll3_d2",
+ "syspll1_d4",
+ "univpll1_d4"
+};
+
+static const char * const hdmi_parents[] __initconst = {
+ "clk26m",
+ "hdmitx_dig_cts",
+ "hdmitxpll_d2",
+ "hdmitxpll_d3"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+ "clk26m",
+ "lvdspll",
+ "lvdspll_d2",
+ "lvdspll_d4",
+ "lvdspll_d8",
+ "fpc_ck"
+};
+
+static const char * const msdc50_2_h_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll2_d2",
+ "syspll4_d2",
+ "univpll_d5",
+ "univpll1_d4"
+};
+
+static const char * const hdcp_parents[] __initconst = {
+ "clk26m",
+ "syspll4_d2",
+ "syspll3_d4",
+ "univpll2_d4"
+};
+
+static const char * const hdcp_24m_parents[] __initconst = {
+ "clk26m",
+ "univpll_d26",
+ "univpll_d52",
+ "univpll2_d8"
+};
+
+static const char * const rtc_parents[] __initconst = {
+ "clkrtc_int",
+ "clkrtc_ext",
+ "clk26m",
+ "univpll3_d8"
+};
+
+static const char * const i2s0_m_ck_parents[] __initconst = {
+ "apll1_div1",
+ "apll2_div1"
+};
+
+static const char * const i2s1_m_ck_parents[] __initconst = {
+ "apll1_div2",
+ "apll2_div2"
+};
+
+static const char * const i2s2_m_ck_parents[] __initconst = {
+ "apll1_div3",
+ "apll2_div3"
+};
+
+static const char * const i2s3_m_ck_parents[] __initconst = {
+ "apll1_div4",
+ "apll2_div4"
+};
+
+static const char * const i2s3_b_ck_parents[] __initconst = {
+ "apll1_div5",
+ "apll2_div5"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+ /* CLK_CFG_0 */
+ MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
+ MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
+ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
+ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
+ /* CLK_CFG_1 */
+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+ MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
+ /* CLK_CFG_2 */
+ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
+ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
+ /* CLK_CFG_3 */
+ MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
+ MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
+ MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
+ /* CLK_CFG_4 */
+ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
+ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
+ /* CLK_CFG_5 */
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
+ MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
+ MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
+ /* CLK_CFG_6 */
+ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
+ MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
+ /* CLK_CFG_7 */
+ MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
+ /* CLK_CFG_12 */
+ MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
+ /* CLK_CFG_13 */
+ MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
+ MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
+
+ DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
+ DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
+ DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
+ DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
+ DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
+ DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
+
+ DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
+ DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
+ DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
+ DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
+ DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
+ DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
+
+ MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
+ MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
+ MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
+ MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
+ MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = 0x0040,
+ .clr_ofs = 0x0044,
+ .sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate infra_clks[] __initconst = {
+ GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+ GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
+ GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
+ GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
+ GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
+ GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
+ GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
+ GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
+ GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
+ GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
+ GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x0010,
+ .sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+ .set_ofs = 0x000c,
+ .clr_ofs = 0x0014,
+ .sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate peri_gates[] __initconst = {
+ /* PERI0 */
+ GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
+ GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
+ GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
+ GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
+ GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
+ GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
+ GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
+ GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
+ GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
+ GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
+ GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
+ GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
+ GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
+ GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
+ GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
+ GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
+ GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
+ GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
+ GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
+ GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
+ GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
+ GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
+ GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
+ GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
+ GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
+ GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
+ GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
+ GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
+ GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
+ GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
+ GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
+ GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
+ /* PERI1 */
+ GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
+ GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
+ GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+ "clk26m",
+ "uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+ mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+ &mt8173_clk_lock, clk_data);
+
+ clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+ mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+ clk_data);
+ mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+ &mt8173_clk_lock, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+
+#define MT8173_PLL_FMAX (3000UL * MHZ)
+
+#define CON0_MT8173_RST_BAR BIT(24)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
+ _tuner_reg, _pcw_reg, _pcw_shift) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT8173_RST_BAR, \
+ .fmax = MT8173_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ }
+
+static const struct mtk_pll_data plls[] = {
+ PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+ PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
+ PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
+ PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
+ PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
+ PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
+ PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
+ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+ PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ if (!clk_data)
+ return;
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+ clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
+ mtk_apmixedsys_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 000000000000..18444aea63c9
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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_address.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+{
+ int i;
+ struct clk_onecell_data *clk_data;
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ return NULL;
+
+ clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err_out;
+
+ clk_data->clk_num = clk_num;
+
+ for (i = 0; i < clk_num; i++)
+ clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+ return clk_data;
+err_out:
+ kfree(clk_data);
+
+ return NULL;
+}
+
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
+ struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_fixed_factor *ff = &clks[i];
+
+ clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+ CLK_SET_RATE_PARENT, ff->mult, ff->div);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ ff->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[ff->id] = clk;
+ }
+}
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+ int num, struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+ struct regmap *regmap;
+
+ if (!clk_data)
+ return -ENOMEM;
+
+ regmap = syscon_node_to_regmap(node);
+ if (IS_ERR(regmap)) {
+ pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+ PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_gate *gate = &clks[i];
+
+ clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+ regmap,
+ gate->regs->set_ofs,
+ gate->regs->clr_ofs,
+ gate->regs->sta_ofs,
+ gate->shift, gate->ops);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ gate->name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[gate->id] = clk;
+ }
+
+ return 0;
+}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+ void __iomem *base, spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_mux *mux = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_divider *div = NULL;
+ struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
+ const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
+ const char * const *parent_names;
+ const char *parent;
+ int num_parents;
+ int ret;
+
+ if (mc->mux_shift >= 0) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = base + mc->mux_reg;
+ mux->mask = BIT(mc->mux_width) - 1;
+ mux->shift = mc->mux_shift;
+ mux->lock = lock;
+
+ mux_hw = &mux->hw;
+ mux_ops = &clk_mux_ops;
+
+ parent_names = mc->parent_names;
+ num_parents = mc->num_parents;
+ } else {
+ parent = mc->parent;
+ parent_names = &parent;
+ num_parents = 1;
+ }
+
+ if (mc->gate_shift >= 0) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ gate->reg = base + mc->gate_reg;
+ gate->bit_idx = mc->gate_shift;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = lock;
+
+ gate_hw = &gate->hw;
+ gate_ops = &clk_gate_ops;
+ }
+
+ if (mc->divider_shift >= 0) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ div->reg = base + mc->divider_reg;
+ div->shift = mc->divider_shift;
+ div->width = mc->divider_width;
+ div->lock = lock;
+
+ div_hw = &div->hw;
+ div_ops = &clk_divider_ops;
+ }
+
+ clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
+ mux_hw, mux_ops,
+ div_hw, div_ops,
+ gate_hw, gate_ops,
+ mc->flags);
+
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+ return clk;
+err_out:
+ kfree(mux);
+
+ return ERR_PTR(ret);
+}
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_composite *mc = &mcs[i];
+
+ clk = mtk_clk_register_composite(mc, base, lock);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ mc->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[mc->id] = clk;
+ }
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 000000000000..9dda9d8ad10b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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 __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define MAX_MUX_GATE_BIT 31
+#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
+
+#define MHZ (1000 * 1000)
+
+struct mtk_fixed_factor {
+ int id;
+ const char *name;
+ const char *parent_name;
+ int mult;
+ int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .mult = _mult, \
+ .div = _div, \
+ }
+
+extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+ int num, struct clk_onecell_data *clk_data);
+
+struct mtk_composite {
+ int id;
+ const char *name;
+ const char * const *parent_names;
+ const char *parent;
+ unsigned flags;
+
+ uint32_t mux_reg;
+ uint32_t divider_reg;
+ uint32_t gate_reg;
+
+ signed char mux_shift;
+ signed char mux_width;
+ signed char gate_shift;
+
+ signed char divider_shift;
+ signed char divider_width;
+
+ signed char num_parents;
+};
+
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \
+ .id = _id, \
+ .name = _name, \
+ .mux_reg = _reg, \
+ .mux_shift = _shift, \
+ .mux_width = _width, \
+ .gate_reg = _reg, \
+ .gate_shift = _gate, \
+ .divider_shift = -1, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = CLK_SET_RATE_PARENT, \
+ }
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
+ .id = _id, \
+ .name = _name, \
+ .mux_reg = _reg, \
+ .mux_shift = _shift, \
+ .mux_width = _width, \
+ .gate_shift = -1, \
+ .divider_shift = -1, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = CLK_SET_RATE_PARENT, \
+ }
+
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
+ .id = _id, \
+ .parent = _parent, \
+ .name = _name, \
+ .divider_reg = _div_reg, \
+ .divider_shift = _div_shift, \
+ .divider_width = _div_width, \
+ .gate_reg = _gate_reg, \
+ .gate_shift = _gate_shift, \
+ .mux_shift = -1, \
+ .flags = 0, \
+ }
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+ void __iomem *base, spinlock_t *lock);
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data);
+
+struct mtk_gate_regs {
+ u32 sta_ofs;
+ u32 clr_ofs;
+ u32 set_ofs;
+};
+
+struct mtk_gate {
+ int id;
+ const char *name;
+ const char *parent_name;
+ const struct mtk_gate_regs *regs;
+ int shift;
+ const struct clk_ops *ops;
+};
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+ int num, struct clk_onecell_data *clk_data);
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
+
+#define HAVE_RST_BAR BIT(0)
+
+struct mtk_pll_data {
+ int id;
+ const char *name;
+ uint32_t reg;
+ uint32_t pwr_reg;
+ uint32_t en_mask;
+ uint32_t pd_reg;
+ uint32_t tuner_reg;
+ int pd_shift;
+ unsigned int flags;
+ const struct clk_ops *ops;
+ u32 rst_bar_mask;
+ unsigned long fmax;
+ int pcwbits;
+ uint32_t pcw_reg;
+ int pcw_shift;
+};
+
+void __init mtk_clk_register_plls(struct device_node *node,
+ const struct mtk_pll_data *plls, int num_plls,
+ struct clk_onecell_data *clk_data);
+
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+ unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+ unsigned int num_regs, int regofs)
+{
+}
+#endif
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 000000000000..44409e98c52f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+
+#define REG_CON0 0
+#define REG_CON1 4
+
+#define CON0_BASE_EN BIT(0)
+#define CON0_PWR_ON BIT(0)
+#define CON0_ISO_EN BIT(1)
+#define CON0_PCW_CHG BIT(31)
+
+#define AUDPLL_TUNER_EN BIT(31)
+
+#define POSTDIV_MASK 0x7
+#define INTEGER_BITS 7
+
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+ struct clk_hw hw;
+ void __iomem *base_addr;
+ void __iomem *pd_addr;
+ void __iomem *pwr_addr;
+ void __iomem *tuner_addr;
+ void __iomem *pcw_addr;
+ const struct mtk_pll_data *data;
+};
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+static int mtk_pll_is_prepared(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
+}
+
+static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
+ u32 pcw, int postdiv)
+{
+ int pcwbits = pll->data->pcwbits;
+ int pcwfbits;
+ u64 vco;
+ u8 c = 0;
+
+ /* The fractional part of the PLL divider. */
+ pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+
+ vco = (u64)fin * pcw;
+
+ if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+ c = 1;
+
+ vco >>= pcwfbits;
+
+ if (c)
+ vco++;
+
+ return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+ int postdiv)
+{
+ u32 con1, pd, val;
+ int pll_en;
+
+ /* set postdiv */
+ pd = readl(pll->pd_addr);
+ pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
+ pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+ writel(pd, pll->pd_addr);
+
+ pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+
+ /* set pcw */
+ val = readl(pll->pcw_addr);
+
+ val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
+ pll->data->pcw_shift);
+ val |= pcw << pll->data->pcw_shift;
+ writel(val, pll->pcw_addr);
+
+ con1 = readl(pll->base_addr + REG_CON1);
+
+ if (pll_en)
+ con1 |= CON0_PCW_CHG;
+
+ writel(con1, pll->base_addr + REG_CON1);
+ if (pll->tuner_addr)
+ writel(con1 + 1, pll->tuner_addr);
+
+ if (pll_en)
+ udelay(20);
+}
+
+/*
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @pll: The pll
+ * @pcw: The pcw value (output)
+ * @postdiv: The post divider (output)
+ * @freq: The desired target frequency
+ * @fin: The input frequency
+ *
+ */
+static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+ u32 freq, u32 fin)
+{
+ unsigned long fmin = 1000 * MHZ;
+ u64 _pcw;
+ u32 val;
+
+ if (freq > pll->data->fmax)
+ freq = pll->data->fmax;
+
+ for (val = 0; val < 4; val++) {
+ *postdiv = 1 << val;
+ if (freq * *postdiv >= fmin)
+ break;
+ }
+
+ /* _pcw = freq * postdiv / fin * 2^pcwfbits */
+ _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+ do_div(_pcw, fin);
+
+ *pcw = (u32)_pcw;
+}
+
+static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 pcw = 0;
+ u32 postdiv;
+
+ mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+ mtk_pll_set_rate_regs(pll, pcw, postdiv);
+
+ return 0;
+}
+
+static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 postdiv;
+ u32 pcw;
+
+ postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
+ postdiv = 1 << postdiv;
+
+ pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
+ pcw &= GENMASK(pll->data->pcwbits - 1, 0);
+
+ return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
+}
+
+static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 pcw = 0;
+ int postdiv;
+
+ mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
+
+ return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
+}
+
+static int mtk_pll_prepare(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ r = readl(pll->pwr_addr) | CON0_PWR_ON;
+ writel(r, pll->pwr_addr);
+ udelay(1);
+
+ r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
+ writel(r, pll->pwr_addr);
+ udelay(1);
+
+ r = readl(pll->base_addr + REG_CON0);
+ r |= pll->data->en_mask;
+ writel(r, pll->base_addr + REG_CON0);
+
+ if (pll->tuner_addr) {
+ r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+ writel(r, pll->tuner_addr);
+ }
+
+ udelay(20);
+
+ if (pll->data->flags & HAVE_RST_BAR) {
+ r = readl(pll->base_addr + REG_CON0);
+ r |= pll->data->rst_bar_mask;
+ writel(r, pll->base_addr + REG_CON0);
+ }
+
+ return 0;
+}
+
+static void mtk_pll_unprepare(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ u32 r;
+
+ if (pll->data->flags & HAVE_RST_BAR) {
+ r = readl(pll->base_addr + REG_CON0);
+ r &= ~pll->data->rst_bar_mask;
+ writel(r, pll->base_addr + REG_CON0);
+ }
+
+ if (pll->tuner_addr) {
+ r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+ writel(r, pll->tuner_addr);
+ }
+
+ r = readl(pll->base_addr + REG_CON0);
+ r &= ~CON0_BASE_EN;
+ writel(r, pll->base_addr + REG_CON0);
+
+ r = readl(pll->pwr_addr) | CON0_ISO_EN;
+ writel(r, pll->pwr_addr);
+
+ r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
+ writel(r, pll->pwr_addr);
+}
+
+static const struct clk_ops mtk_pll_ops = {
+ .is_prepared = mtk_pll_is_prepared,
+ .prepare = mtk_pll_prepare,
+ .unprepare = mtk_pll_unprepare,
+ .recalc_rate = mtk_pll_recalc_rate,
+ .round_rate = mtk_pll_round_rate,
+ .set_rate = mtk_pll_set_rate,
+};
+
+static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
+ void __iomem *base)
+{
+ struct mtk_clk_pll *pll;
+ struct clk_init_data init = {};
+ struct clk *clk;
+ const char *parent_name = "clk26m";
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ pll->base_addr = base + data->reg;
+ pll->pwr_addr = base + data->pwr_reg;
+ pll->pd_addr = base + data->pd_reg;
+ pll->pcw_addr = base + data->pcw_reg;
+ if (data->tuner_reg)
+ pll->tuner_addr = base + data->tuner_reg;
+ pll->hw.init = &init;
+ pll->data = data;
+
+ init.name = data->name;
+ init.ops = &mtk_pll_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &pll->hw);
+
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
+
+void __init mtk_clk_register_plls(struct device_node *node,
+ const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
+{
+ void __iomem *base;
+ int r, i;
+ struct clk *clk;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num_plls; i++) {
+ const struct mtk_pll_data *pll = &plls[i];
+
+ clk = mtk_clk_register_pll(pll, base);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ pll->name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[pll->id] = clk;
+ }
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
new file mode 100644
index 000000000000..9e9fe4b19ac4
--- /dev/null
+++ b/drivers/clk/mediatek/reset.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014 MediaTek 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.
+ *
+ * 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/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+struct mtk_reset {
+ struct regmap *regmap;
+ int regofs;
+ struct reset_controller_dev rcdev;
+};
+
+static int mtk_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+ return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+ BIT(id % 32), ~0);
+}
+
+static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+ return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+ BIT(id % 32), 0);
+}
+
+static int mtk_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = mtk_reset_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return mtk_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_reset_ops = {
+ .assert = mtk_reset_assert,
+ .deassert = mtk_reset_deassert,
+ .reset = mtk_reset,
+};
+
+void mtk_register_reset_controller(struct device_node *np,
+ unsigned int num_regs, int regofs)
+{
+ struct mtk_reset *data;
+ int ret;
+ struct regmap *regmap;
+
+ regmap = syscon_node_to_regmap(np);
+ if (IS_ERR(regmap)) {
+ pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
+ PTR_ERR(regmap));
+ return;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+
+ data->regmap = regmap;
+ data->regofs = regofs;
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = num_regs * 32;
+ data->rcdev.ops = &mtk_reset_ops;
+ data->rcdev.of_node = np;
+
+ ret = reset_controller_register(&data->rcdev);
+ if (ret) {
+ pr_err("could not register reset controller: %d\n", ret);
+ kfree(data);
+ return;
+ }
+}
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
new file mode 100644
index 000000000000..6d45531df9ab
--- /dev/null
+++ b/drivers/clk/meson/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Meson specific clk
+#
+
+obj-y += clkc.o clk-pll.o clk-cpu.o
+obj-y += meson8b-clkc.o
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
new file mode 100644
index 000000000000..71ad493b94df
--- /dev/null
+++ b/drivers/clk/meson/clk-cpu.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * 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/>.
+ */
+
+/*
+ * CPU clock path:
+ *
+ * +-[/N]-----|3|
+ * MUX2 +--[/3]-+----------|2| MUX1
+ * [sys_pll]---|1| |--[/2]------------|1|-|1|
+ * | |---+------------------|0| | |----- [a5_clk]
+ * +--|0| | |
+ * [xtal]---+-------------------------------|0|
+ *
+ *
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#define MESON_CPU_CLK_CNTL1 0x00
+#define MESON_CPU_CLK_CNTL 0x40
+
+#define MESON_CPU_CLK_MUX1 BIT(7)
+#define MESON_CPU_CLK_MUX2 BIT(0)
+
+#define MESON_N_WIDTH 9
+#define MESON_N_SHIFT 20
+#define MESON_SEL_WIDTH 2
+#define MESON_SEL_SHIFT 2
+
+#include "clkc.h"
+
+struct meson_clk_cpu {
+ struct notifier_block clk_nb;
+ const struct clk_div_table *div_table;
+ struct clk_hw hw;
+ void __iomem *base;
+ u16 reg_off;
+};
+#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
+#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
+
+static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+
+ return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
+ MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+ unsigned int div, sel, N = 0;
+ u32 reg;
+
+ div = DIV_ROUND_UP(parent_rate, rate);
+
+ if (div <= 3) {
+ sel = div - 1;
+ } else {
+ sel = 3;
+ N = div / 2;
+ }
+
+ reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+ reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
+ writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+
+ reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+ reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
+ writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+
+ return 0;
+}
+
+static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+ unsigned int N, sel;
+ unsigned int div = 1;
+ u32 reg;
+
+ reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+ N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
+
+ reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+ sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
+
+ if (sel < 3)
+ div = sel + 1;
+ else
+ div = 2 * N;
+
+ return parent_rate / div;
+}
+
+static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
+ struct clk_notifier_data *ndata)
+{
+ u32 cpu_clk_cntl;
+
+ /* switch MUX1 to xtal */
+ cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+ + MESON_CPU_CLK_CNTL);
+ cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
+ writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ + MESON_CPU_CLK_CNTL);
+ udelay(100);
+
+ /* switch MUX2 to sys-pll */
+ cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
+ writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ + MESON_CPU_CLK_CNTL);
+
+ return 0;
+}
+
+static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
+ struct clk_notifier_data *ndata)
+{
+ u32 cpu_clk_cntl;
+
+ /* switch MUX1 to divisors' output */
+ cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+ + MESON_CPU_CLK_CNTL);
+ cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
+ writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+ + MESON_CPU_CLK_CNTL);
+ udelay(100);
+
+ return 0;
+}
+
+/*
+ * This clock notifier is called when the frequency of the of the parent
+ * PLL clock is to be changed. We use the xtal input as temporary parent
+ * while the PLL frequency is stabilized.
+ */
+static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct clk_notifier_data *ndata = data;
+ struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
+ int ret = 0;
+
+ if (event == PRE_RATE_CHANGE)
+ ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
+ else if (event == POST_RATE_CHANGE)
+ ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
+
+ return notifier_from_errno(ret);
+}
+
+static const struct clk_ops meson_clk_cpu_ops = {
+ .recalc_rate = meson_clk_cpu_recalc_rate,
+ .round_rate = meson_clk_cpu_round_rate,
+ .set_rate = meson_clk_cpu_set_rate,
+};
+
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+ void __iomem *reg_base,
+ spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk *pclk;
+ struct meson_clk_cpu *clk_cpu;
+ struct clk_init_data init;
+ int ret;
+
+ clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
+ if (!clk_cpu)
+ return ERR_PTR(-ENOMEM);
+
+ clk_cpu->base = reg_base;
+ clk_cpu->reg_off = clk_conf->reg_off;
+ clk_cpu->div_table = clk_conf->conf.div_table;
+ clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
+
+ init.name = clk_conf->clk_name;
+ init.ops = &meson_clk_cpu_ops;
+ init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+ init.flags |= CLK_SET_RATE_PARENT;
+ init.parent_names = clk_conf->clks_parent;
+ init.num_parents = 1;
+
+ clk_cpu->hw.init = &init;
+
+ pclk = __clk_lookup(clk_conf->clks_parent[0]);
+ if (!pclk) {
+ pr_err("%s: could not lookup parent clock %s\n",
+ __func__, clk_conf->clks_parent[0]);
+ ret = -EINVAL;
+ goto free_clk;
+ }
+
+ ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
+ if (ret) {
+ pr_err("%s: failed to register clock notifier for %s\n",
+ __func__, clk_conf->clk_name);
+ goto free_clk;
+ }
+
+ clk = clk_register(NULL, &clk_cpu->hw);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto unregister_clk_nb;
+ }
+
+ return clk;
+
+unregister_clk_nb:
+ clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
+free_clk:
+ kfree(clk_cpu);
+
+ return ERR_PTR(ret);
+}
+
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
new file mode 100644
index 000000000000..664edf0708ea
--- /dev/null
+++ b/drivers/clk/meson/clk-pll.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * 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/>.
+ */
+
+/*
+ * In the most basic form, a Meson PLL is composed as follows:
+ *
+ * PLL
+ * +------------------------------+
+ * | |
+ * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
+ * | ^ ^ |
+ * +------------------------------+
+ * | |
+ * FREF VCO
+ *
+ * out = (in * M / N) >> OD
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "clkc.h"
+
+#define MESON_PLL_RESET BIT(29)
+#define MESON_PLL_LOCK BIT(31)
+
+struct meson_clk_pll {
+ struct clk_hw hw;
+ void __iomem *base;
+ struct pll_conf *conf;
+ unsigned int rate_count;
+ spinlock_t *lock;
+};
+#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
+
+static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+ struct parm *p;
+ unsigned long parent_rate_mhz = parent_rate / 1000000;
+ unsigned long rate_mhz;
+ u16 n, m, od;
+ u32 reg;
+
+ p = &pll->conf->n;
+ reg = readl(pll->base + p->reg_off);
+ n = PARM_GET(p->width, p->shift, reg);
+
+ p = &pll->conf->m;
+ reg = readl(pll->base + p->reg_off);
+ m = PARM_GET(p->width, p->shift, reg);
+
+ p = &pll->conf->od;
+ reg = readl(pll->base + p->reg_off);
+ od = PARM_GET(p->width, p->shift, reg);
+
+ rate_mhz = (parent_rate_mhz * m / n) >> od;
+
+ return rate_mhz * 1000000;
+}
+
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+ const struct pll_rate_table *rate_table = pll->conf->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate <= rate_table[i].rate)
+ return rate_table[i].rate;
+ }
+
+ /* else return the smallest value */
+ return rate_table[0].rate;
+}
+
+static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
+ unsigned long rate)
+{
+ const struct pll_rate_table *rate_table = pll->conf->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+ }
+ return NULL;
+}
+
+static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
+ struct parm *p_n)
+{
+ int delay = 24000000;
+ u32 reg;
+
+ while (delay > 0) {
+ reg = readl(pll->base + p_n->reg_off);
+
+ if (reg & MESON_PLL_LOCK)
+ return 0;
+ delay--;
+ }
+ return -ETIMEDOUT;
+}
+
+static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+ struct parm *p;
+ const struct pll_rate_table *rate_set;
+ unsigned long old_rate;
+ int ret = 0;
+ u32 reg;
+
+ if (parent_rate == 0 || rate == 0)
+ return -EINVAL;
+
+ old_rate = rate;
+
+ rate_set = meson_clk_get_pll_settings(pll, rate);
+ if (!rate_set)
+ return -EINVAL;
+
+ /* PLL reset */
+ p = &pll->conf->n;
+ reg = readl(pll->base + p->reg_off);
+ writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
+
+ reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
+ writel(reg, pll->base + p->reg_off);
+
+ p = &pll->conf->m;
+ reg = readl(pll->base + p->reg_off);
+ reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
+ writel(reg, pll->base + p->reg_off);
+
+ p = &pll->conf->od;
+ reg = readl(pll->base + p->reg_off);
+ reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
+ writel(reg, pll->base + p->reg_off);
+
+ p = &pll->conf->n;
+ ret = meson_clk_pll_wait_lock(pll, p);
+ if (ret) {
+ pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+ __func__, old_rate);
+ meson_clk_pll_set_rate(hw, old_rate, parent_rate);
+ }
+
+ return ret;
+}
+
+static const struct clk_ops meson_clk_pll_ops = {
+ .recalc_rate = meson_clk_pll_recalc_rate,
+ .round_rate = meson_clk_pll_round_rate,
+ .set_rate = meson_clk_pll_set_rate,
+};
+
+static const struct clk_ops meson_clk_pll_ro_ops = {
+ .recalc_rate = meson_clk_pll_recalc_rate,
+};
+
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+ void __iomem *reg_base,
+ spinlock_t *lock)
+{
+ struct clk *clk;
+ struct meson_clk_pll *clk_pll;
+ struct clk_init_data init;
+
+ clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+ if (!clk_pll)
+ return ERR_PTR(-ENOMEM);
+
+ clk_pll->base = reg_base + clk_conf->reg_off;
+ clk_pll->lock = lock;
+ clk_pll->conf = clk_conf->conf.pll;
+
+ init.name = clk_conf->clk_name;
+ init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+
+ init.parent_names = &clk_conf->clks_parent[0];
+ init.num_parents = 1;
+ init.ops = &meson_clk_pll_ro_ops;
+
+ /* If no rate_table is specified we assume the PLL is read-only */
+ if (clk_pll->conf->rate_table) {
+ int len;
+
+ for (len = 0; clk_pll->conf->rate_table[len].rate != 0; )
+ len++;
+
+ clk_pll->rate_count = len;
+ init.ops = &meson_clk_pll_ops;
+ }
+
+ clk_pll->hw.init = &init;
+
+ clk = clk_register(NULL, &clk_pll->hw);
+ if (IS_ERR(clk))
+ kfree(clk_pll);
+
+ return clk;
+}
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
new file mode 100644
index 000000000000..b8c511c5e7a7
--- /dev/null
+++ b/drivers/clk/meson/clkc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * 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/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clkc.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk **clks;
+static struct clk_onecell_data clk_data;
+
+struct clk ** __init meson_clk_init(struct device_node *np,
+ unsigned long nr_clks)
+{
+ clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return ERR_PTR(-ENOMEM);
+
+ clk_data.clks = clks;
+ clk_data.clk_num = nr_clks;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+ return clks;
+}
+
+static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+ if (clks && id)
+ clks[id] = clk;
+}
+
+static struct clk * __init
+meson_clk_register_composite(const struct clk_conf *clk_conf,
+ void __iomem *clk_base)
+{
+ struct clk *clk;
+ struct clk_mux *mux = NULL;
+ struct clk_divider *div = NULL;
+ struct clk_gate *gate = NULL;
+ const struct clk_ops *mux_ops = NULL;
+ const struct composite_conf *composite_conf;
+
+ composite_conf = clk_conf->conf.composite;
+
+ if (clk_conf->num_parents > 1) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = clk_base + clk_conf->reg_off
+ + composite_conf->mux_parm.reg_off;
+ mux->shift = composite_conf->mux_parm.shift;
+ mux->mask = BIT(composite_conf->mux_parm.width) - 1;
+ mux->flags = composite_conf->mux_flags;
+ mux->lock = &clk_lock;
+ mux->table = composite_conf->mux_table;
+ mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
+ &clk_mux_ro_ops : &clk_mux_ops;
+ }
+
+ if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div) {
+ clk = ERR_PTR(-ENOMEM);
+ goto error;
+ }
+
+ div->reg = clk_base + clk_conf->reg_off
+ + composite_conf->div_parm.reg_off;
+ div->shift = composite_conf->div_parm.shift;
+ div->width = composite_conf->div_parm.width;
+ div->lock = &clk_lock;
+ div->flags = composite_conf->div_flags;
+ div->table = composite_conf->div_table;
+ }
+
+ if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ clk = ERR_PTR(-ENOMEM);
+ goto error;
+ }
+
+ gate->reg = clk_base + clk_conf->reg_off
+ + composite_conf->div_parm.reg_off;
+ gate->bit_idx = composite_conf->gate_parm.shift;
+ gate->flags = composite_conf->gate_flags;
+ gate->lock = &clk_lock;
+ }
+
+ clk = clk_register_composite(NULL, clk_conf->clk_name,
+ clk_conf->clks_parent,
+ clk_conf->num_parents,
+ mux ? &mux->hw : NULL, mux_ops,
+ div ? &div->hw : NULL, &clk_divider_ops,
+ gate ? &gate->hw : NULL, &clk_gate_ops,
+ clk_conf->flags);
+ if (IS_ERR(clk))
+ goto error;
+
+ return clk;
+
+error:
+ kfree(gate);
+ kfree(div);
+ kfree(mux);
+
+ return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
+ void __iomem *clk_base)
+{
+ struct clk *clk;
+ const struct fixed_fact_conf *fixed_fact_conf;
+ const struct parm *p;
+ unsigned int mult, div;
+ u32 reg;
+
+ fixed_fact_conf = &clk_conf->conf.fixed_fact;
+
+ mult = clk_conf->conf.fixed_fact.mult;
+ div = clk_conf->conf.fixed_fact.div;
+
+ if (!mult) {
+ mult = 1;
+ p = &fixed_fact_conf->mult_parm;
+ if (MESON_PARM_APPLICABLE(p)) {
+ reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+ mult = PARM_GET(p->width, p->shift, reg);
+ }
+ }
+
+ if (!div) {
+ div = 1;
+ p = &fixed_fact_conf->div_parm;
+ if (MESON_PARM_APPLICABLE(p)) {
+ reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+ mult = PARM_GET(p->width, p->shift, reg);
+ }
+ }
+
+ clk = clk_register_fixed_factor(NULL,
+ clk_conf->clk_name,
+ clk_conf->clks_parent[0],
+ clk_conf->flags,
+ mult, div);
+
+ return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
+ void __iomem *clk_base)
+{
+ struct clk *clk;
+ const struct fixed_rate_conf *fixed_rate_conf;
+ const struct parm *r;
+ unsigned long rate;
+ u32 reg;
+
+ fixed_rate_conf = &clk_conf->conf.fixed_rate;
+ rate = fixed_rate_conf->rate;
+
+ if (!rate) {
+ r = &fixed_rate_conf->rate_parm;
+ reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
+ rate = PARM_GET(r->width, r->shift, reg);
+ }
+
+ rate *= 1000000;
+
+ clk = clk_register_fixed_rate(NULL,
+ clk_conf->clk_name,
+ clk_conf->num_parents
+ ? clk_conf->clks_parent[0] : NULL,
+ clk_conf->flags, rate);
+
+ return clk;
+}
+
+void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
+ size_t nr_confs,
+ void __iomem *clk_base)
+{
+ unsigned int i;
+ struct clk *clk = NULL;
+
+ for (i = 0; i < nr_confs; i++) {
+ const struct clk_conf *clk_conf = &clk_confs[i];
+
+ switch (clk_conf->clk_type) {
+ case CLK_FIXED_RATE:
+ clk = meson_clk_register_fixed_rate(clk_conf,
+ clk_base);
+ break;
+ case CLK_FIXED_FACTOR:
+ clk = meson_clk_register_fixed_factor(clk_conf,
+ clk_base);
+ break;
+ case CLK_COMPOSITE:
+ clk = meson_clk_register_composite(clk_conf,
+ clk_base);
+ break;
+ case CLK_CPU:
+ clk = meson_clk_register_cpu(clk_conf, clk_base,
+ &clk_lock);
+ break;
+ case CLK_PLL:
+ clk = meson_clk_register_pll(clk_conf, clk_base,
+ &clk_lock);
+ break;
+ default:
+ clk = NULL;
+ }
+
+ if (!clk) {
+ pr_err("%s: unknown clock type %d\n", __func__,
+ clk_conf->clk_type);
+ continue;
+ }
+
+ if (IS_ERR(clk)) {
+ pr_warn("%s: Unable to create %s clock\n", __func__,
+ clk_conf->clk_name);
+ continue;
+ }
+
+ meson_clk_add_lookup(clk, clk_conf->clk_id);
+ }
+}
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
new file mode 100644
index 000000000000..609ae92cc13f
--- /dev/null
+++ b/drivers/clk/meson/clkc.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * 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 __CLKC_H
+#define __CLKC_H
+
+#define PMASK(width) GENMASK(width - 1, 0)
+#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
+#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
+
+#define PARM_GET(width, shift, reg) \
+ (((reg) & SETPMASK(width, shift)) >> (shift))
+#define PARM_SET(width, shift, reg, val) \
+ (((reg) & CLRPMASK(width, shift)) | (val << (shift)))
+
+#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
+
+struct parm {
+ u16 reg_off;
+ u8 shift;
+ u8 width;
+};
+#define PARM(_r, _s, _w) \
+ { \
+ .reg_off = (_r), \
+ .shift = (_s), \
+ .width = (_w), \
+ } \
+
+struct pll_rate_table {
+ unsigned long rate;
+ u16 m;
+ u16 n;
+ u16 od;
+};
+#define PLL_RATE(_r, _m, _n, _od) \
+ { \
+ .rate = (_r), \
+ .m = (_m), \
+ .n = (_n), \
+ .od = (_od), \
+ } \
+
+struct pll_conf {
+ const struct pll_rate_table *rate_table;
+ struct parm m;
+ struct parm n;
+ struct parm od;
+};
+
+struct fixed_fact_conf {
+ unsigned int div;
+ unsigned int mult;
+ struct parm div_parm;
+ struct parm mult_parm;
+};
+
+struct fixed_rate_conf {
+ unsigned long rate;
+ struct parm rate_parm;
+};
+
+struct composite_conf {
+ struct parm mux_parm;
+ struct parm div_parm;
+ struct parm gate_parm;
+ struct clk_div_table *div_table;
+ u32 *mux_table;
+ u8 mux_flags;
+ u8 div_flags;
+ u8 gate_flags;
+};
+
+#define PNAME(x) static const char *x[]
+
+enum clk_type {
+ CLK_FIXED_FACTOR,
+ CLK_FIXED_RATE,
+ CLK_COMPOSITE,
+ CLK_CPU,
+ CLK_PLL,
+};
+
+struct clk_conf {
+ u16 reg_off;
+ enum clk_type clk_type;
+ unsigned int clk_id;
+ const char *clk_name;
+ const char **clks_parent;
+ int num_parents;
+ unsigned long flags;
+ union {
+ struct fixed_fact_conf fixed_fact;
+ struct fixed_rate_conf fixed_rate;
+ const struct composite_conf *composite;
+ struct pll_conf *pll;
+ const struct clk_div_table *div_table;
+ } conf;
+};
+
+#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c) \
+ { \
+ .reg_off = (_ro), \
+ .clk_type = CLK_FIXED_RATE, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .flags = (_f), \
+ .conf.fixed_rate.rate_parm = _c, \
+ } \
+
+#define FIXED_RATE(_ci, _cn, _f, _r) \
+ { \
+ .clk_type = CLK_FIXED_RATE, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .flags = (_f), \
+ .conf.fixed_rate.rate = (_r), \
+ } \
+
+#define PLL(_ro, _ci, _cn, _cp, _f, _c) \
+ { \
+ .reg_off = (_ro), \
+ .clk_type = CLK_PLL, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .clks_parent = (_cp), \
+ .num_parents = ARRAY_SIZE(_cp), \
+ .flags = (_f), \
+ .conf.pll = (_c), \
+ } \
+
+#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d) \
+ { \
+ .clk_type = CLK_FIXED_FACTOR, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .clks_parent = (_cp), \
+ .num_parents = ARRAY_SIZE(_cp), \
+ .conf.fixed_fact.div = (_d), \
+ } \
+
+#define CPU(_ro, _ci, _cn, _cp, _dt) \
+ { \
+ .reg_off = (_ro), \
+ .clk_type = CLK_CPU, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .clks_parent = (_cp), \
+ .num_parents = ARRAY_SIZE(_cp), \
+ .conf.div_table = (_dt), \
+ } \
+
+#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \
+ { \
+ .reg_off = (_ro), \
+ .clk_type = CLK_COMPOSITE, \
+ .clk_id = (_ci), \
+ .clk_name = (_cn), \
+ .clks_parent = (_cp), \
+ .num_parents = ARRAY_SIZE(_cp), \
+ .flags = (_f), \
+ .conf.composite = (_c), \
+ } \
+
+struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
+void meson_clk_register_clks(const struct clk_conf *clk_confs,
+ unsigned int nr_confs, void __iomem *clk_base);
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+ void __iomem *reg_base, spinlock_t *lock);
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+ void __iomem *reg_base, spinlock_t *lock);
+
+#endif /* __CLKC_H */
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c
new file mode 100644
index 000000000000..61f6d55c4ac7
--- /dev/null
+++ b/drivers/clk/meson/meson8b-clkc.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * 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/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/meson8b-clkc.h>
+
+#include "clkc.h"
+
+#define MESON8B_REG_CTL0_ADDR 0x0000
+#define MESON8B_REG_SYS_CPU_CNTL1 0x015c
+#define MESON8B_REG_HHI_MPEG 0x0174
+#define MESON8B_REG_MALI 0x01b0
+#define MESON8B_REG_PLL_FIXED 0x0280
+#define MESON8B_REG_PLL_SYS 0x0300
+#define MESON8B_REG_PLL_VID 0x0320
+
+static const struct pll_rate_table sys_pll_rate_table[] = {
+ PLL_RATE(312000000, 52, 1, 2),
+ PLL_RATE(336000000, 56, 1, 2),
+ PLL_RATE(360000000, 60, 1, 2),
+ PLL_RATE(384000000, 64, 1, 2),
+ PLL_RATE(408000000, 68, 1, 2),
+ PLL_RATE(432000000, 72, 1, 2),
+ PLL_RATE(456000000, 76, 1, 2),
+ PLL_RATE(480000000, 80, 1, 2),
+ PLL_RATE(504000000, 84, 1, 2),
+ PLL_RATE(528000000, 88, 1, 2),
+ PLL_RATE(552000000, 92, 1, 2),
+ PLL_RATE(576000000, 96, 1, 2),
+ PLL_RATE(600000000, 50, 1, 1),
+ PLL_RATE(624000000, 52, 1, 1),
+ PLL_RATE(648000000, 54, 1, 1),
+ PLL_RATE(672000000, 56, 1, 1),
+ PLL_RATE(696000000, 58, 1, 1),
+ PLL_RATE(720000000, 60, 1, 1),
+ PLL_RATE(744000000, 62, 1, 1),
+ PLL_RATE(768000000, 64, 1, 1),
+ PLL_RATE(792000000, 66, 1, 1),
+ PLL_RATE(816000000, 68, 1, 1),
+ PLL_RATE(840000000, 70, 1, 1),
+ PLL_RATE(864000000, 72, 1, 1),
+ PLL_RATE(888000000, 74, 1, 1),
+ PLL_RATE(912000000, 76, 1, 1),
+ PLL_RATE(936000000, 78, 1, 1),
+ PLL_RATE(960000000, 80, 1, 1),
+ PLL_RATE(984000000, 82, 1, 1),
+ PLL_RATE(1008000000, 84, 1, 1),
+ PLL_RATE(1032000000, 86, 1, 1),
+ PLL_RATE(1056000000, 88, 1, 1),
+ PLL_RATE(1080000000, 90, 1, 1),
+ PLL_RATE(1104000000, 92, 1, 1),
+ PLL_RATE(1128000000, 94, 1, 1),
+ PLL_RATE(1152000000, 96, 1, 1),
+ PLL_RATE(1176000000, 98, 1, 1),
+ PLL_RATE(1200000000, 50, 1, 0),
+ PLL_RATE(1224000000, 51, 1, 0),
+ PLL_RATE(1248000000, 52, 1, 0),
+ PLL_RATE(1272000000, 53, 1, 0),
+ PLL_RATE(1296000000, 54, 1, 0),
+ PLL_RATE(1320000000, 55, 1, 0),
+ PLL_RATE(1344000000, 56, 1, 0),
+ PLL_RATE(1368000000, 57, 1, 0),
+ PLL_RATE(1392000000, 58, 1, 0),
+ PLL_RATE(1416000000, 59, 1, 0),
+ PLL_RATE(1440000000, 60, 1, 0),
+ PLL_RATE(1464000000, 61, 1, 0),
+ PLL_RATE(1488000000, 62, 1, 0),
+ PLL_RATE(1512000000, 63, 1, 0),
+ PLL_RATE(1536000000, 64, 1, 0),
+ { /* sentinel */ },
+};
+
+static const struct clk_div_table cpu_div_table[] = {
+ { .val = 1, .div = 1 },
+ { .val = 2, .div = 2 },
+ { .val = 3, .div = 3 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 6 },
+ { .val = 4, .div = 8 },
+ { .val = 5, .div = 10 },
+ { .val = 6, .div = 12 },
+ { .val = 7, .div = 14 },
+ { .val = 8, .div = 16 },
+ { /* sentinel */ },
+};
+
+PNAME(p_xtal) = { "xtal" };
+PNAME(p_fclk_div) = { "fixed_pll" };
+PNAME(p_cpu_clk) = { "sys_pll" };
+PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" };
+PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5",
+ "fclk_div7", "zero" };
+
+static u32 mux_table_clk81[] = { 6, 5, 7 };
+static u32 mux_table_mali[] = { 6, 5, 7, 4, 0 };
+
+static struct pll_conf pll_confs = {
+ .m = PARM(0x00, 0, 9),
+ .n = PARM(0x00, 9, 5),
+ .od = PARM(0x00, 16, 2),
+};
+
+static struct pll_conf sys_pll_conf = {
+ .m = PARM(0x00, 0, 9),
+ .n = PARM(0x00, 9, 5),
+ .od = PARM(0x00, 16, 2),
+ .rate_table = sys_pll_rate_table,
+};
+
+static const struct composite_conf clk81_conf __initconst = {
+ .mux_table = mux_table_clk81,
+ .mux_flags = CLK_MUX_READ_ONLY,
+ .mux_parm = PARM(0x00, 12, 3),
+ .div_parm = PARM(0x00, 0, 7),
+ .gate_parm = PARM(0x00, 7, 1),
+};
+
+static const struct composite_conf mali_conf __initconst = {
+ .mux_table = mux_table_mali,
+ .mux_parm = PARM(0x00, 9, 3),
+ .div_parm = PARM(0x00, 0, 7),
+ .gate_parm = PARM(0x00, 8, 1),
+};
+
+static const struct clk_conf meson8b_xtal_conf __initconst =
+ FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal",
+ CLK_IS_ROOT, PARM(0x00, 4, 7));
+
+static const struct clk_conf meson8b_clk_confs[] __initconst = {
+ FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0),
+ PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
+ p_xtal, 0, &pll_confs),
+ PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
+ p_xtal, 0, &pll_confs),
+ PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll",
+ p_xtal, 0, &sys_pll_conf),
+ FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2),
+ FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3),
+ FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4),
+ FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5),
+ FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7),
+ CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
+ cpu_div_table),
+ COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
+ CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
+ COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
+ CLK_IGNORE_UNUSED, &mali_conf),
+};
+
+static void __init meson8b_clkc_init(struct device_node *np)
+{
+ void __iomem *clk_base;
+
+ if (!meson_clk_init(np, CLK_NR_CLKS))
+ return;
+
+ /* XTAL */
+ clk_base = of_iomap(np, 0);
+ if (!clk_base) {
+ pr_err("%s: Unable to map xtal base\n", __func__);
+ return;
+ }
+
+ meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base);
+ iounmap(clk_base);
+
+ /* Generic clocks and PLLs */
+ clk_base = of_iomap(np, 1);
+ if (!clk_base) {
+ pr_err("%s: Unable to map clk base\n", __func__);
+ return;
+ }
+
+ meson_clk_register_clks(meson8b_clk_confs,
+ ARRAY_SIZE(meson8b_clk_confs),
+ clk_base);
+}
+CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init);
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 3caaf7cc169c..9d4bc41e4239 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
+
+obj-y += clk-of-pxa1928.o
diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c
index d14120eaa71f..09d41c717c52 100644
--- a/drivers/clk/mmp/clk-apbc.c
+++ b/drivers/clk/mmp/clk-apbc.c
@@ -115,7 +115,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw)
spin_unlock_irqrestore(apbc->lock, flags);
}
-struct clk_ops clk_apbc_ops = {
+static struct clk_ops clk_apbc_ops = {
.prepare = clk_apbc_prepare,
.unprepare = clk_apbc_unprepare,
};
diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c
index abe182b2377f..cdcf2d7f321e 100644
--- a/drivers/clk/mmp/clk-apmu.c
+++ b/drivers/clk/mmp/clk-apmu.c
@@ -61,7 +61,7 @@ static void clk_apmu_disable(struct clk_hw *hw)
spin_unlock_irqrestore(apmu->lock, flags);
}
-struct clk_ops clk_apmu_ops = {
+static struct clk_ops clk_apmu_ops = {
.enable = clk_apmu_enable,
.disable = clk_apmu_disable,
};
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 5c90a4230fa3..09d2832fbd78 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -63,10 +63,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
};
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 14634, .den = 2165}, /*14.745MHZ */
+ {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689}, /*19.23MHZ */
- {.num = 9679, .den = 5728}, /*58.9824MHZ */
- {.num = 15850, .den = 9451}, /*59.429MHZ */
};
static const char *uart_parent[] = {"uart_pll", "vctcxo"};
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 2cbc2b43ae52..251533d87c65 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -30,6 +30,7 @@
#define APBC_TWSI4 0x7c
#define APBC_TWSI5 0x80
#define APBC_KPC 0x18
+#define APBC_TIMER 0x24
#define APBC_UART0 0x2c
#define APBC_UART1 0x30
#define APBC_UART2 0x34
@@ -98,10 +99,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
};
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
- {.num = 14634, .den = 2165}, /*14.745MHZ */
+ {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689}, /*19.23MHZ */
- {.num = 9679, .den = 5728}, /*58.9824MHZ */
- {.num = 15850, .den = 9451}, /*59.429MHZ */
};
static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
@@ -134,6 +133,9 @@ static DEFINE_SPINLOCK(ssp2_lock);
static DEFINE_SPINLOCK(ssp3_lock);
static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
+
static DEFINE_SPINLOCK(reset_lock);
static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -145,6 +147,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
+ {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
};
static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -170,6 +173,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock},
{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock},
{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock},
+ {MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
};
static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 5b1810dc4bd2..64eaf4141c69 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -32,6 +32,7 @@
#define APBC_PWM1 0x10
#define APBC_PWM2 0x14
#define APBC_PWM3 0x18
+#define APBC_TIMER 0x34
#define APBC_SSP0 0x81c
#define APBC_SSP1 0x820
#define APBC_SSP2 0x84c
@@ -58,6 +59,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+ {PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
};
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
@@ -70,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+ {PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -119,6 +122,9 @@ static DEFINE_SPINLOCK(ssp3_lock);
static DEFINE_SPINLOCK(ssp4_lock);
static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", "pll1_192"};
+
static DEFINE_SPINLOCK(reset_lock);
static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -130,6 +136,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
+ {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
};
static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -151,6 +158,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
{PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock},
{PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock},
{PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock},
+ {PXA168_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x3, 0x3, 0x0, 0, &timer_lock},
};
static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
new file mode 100644
index 000000000000..433a5ae1eae0
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -0,0 +1,265 @@
+/*
+ * pxa1928 clock framework source file
+ *
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on drivers/clk/mmp/clk-of-mmp2.c:
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.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/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1928.h>
+
+#include "clk.h"
+#include "reset.h"
+
+#define MPMU_UART_PLL 0x14
+
+struct pxa1928_clk_unit {
+ struct mmp_clk_unit unit;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbc_base;
+ void __iomem *apbcp_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+ {0, "clk32", NULL, CLK_IS_ROOT, 32768},
+ {0, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
+ {0, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
+ {0, "pll5p", NULL, CLK_IS_ROOT, 832000000},
+ {0, "pll5", NULL, CLK_IS_ROOT, 1248000000},
+ {0, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+ {0, "pll1_d2", "pll1_624", 1, 2, 0},
+ {0, "pll1_d9", "pll1_624", 1, 9, 0},
+ {0, "pll1_d12", "pll1_624", 1, 12, 0},
+ {0, "pll1_d16", "pll1_624", 1, 16, 0},
+ {0, "pll1_d20", "pll1_624", 1, 20, 0},
+ {0, "pll1_416", "pll1_624", 2, 3, 0},
+ {0, "vctcxo_d2", "vctcxo", 1, 2, 0},
+ {0, "vctcxo_d4", "vctcxo", 1, 4, 0},
+};
+
+static struct mmp_clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = 0x1fff,
+ .den_mask = 0x1fff,
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
+ {.num = 832, .den = 234}, /*58.5MHZ */
+ {.num = 1, .den = 1}, /*26MHZ */
+};
+
+static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
+{
+ struct clk *clk;
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
+ ARRAY_SIZE(fixed_rate_clks));
+
+ mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
+ ARRAY_SIZE(fixed_factor_clks));
+
+ clk = mmp_clk_register_factor("uart_pll", "pll1_416",
+ CLK_SET_RATE_PARENT,
+ pxa_unit->mpmu_base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl), NULL);
+}
+
+static DEFINE_SPINLOCK(uart0_lock);
+static DEFINE_SPINLOCK(uart1_lock);
+static DEFINE_SPINLOCK(uart2_lock);
+static DEFINE_SPINLOCK(uart3_lock);
+static const char *uart_parent_names[] = {"uart_pll", "vctcxo"};
+
+static DEFINE_SPINLOCK(ssp0_lock);
+static DEFINE_SPINLOCK(ssp1_lock);
+static const char *ssp_parent_names[] = {"vctcxo_d4", "vctcxo_d2", "vctcxo", "pll1_d12"};
+
+static DEFINE_SPINLOCK(reset_lock);
+
+static struct mmp_param_mux_clk apbc_mux_clks[] = {
+ {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 4, 3, 0, &uart0_lock},
+ {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 4, 3, 0, &uart1_lock},
+ {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 4, 3, 0, &uart2_lock},
+ {0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 4, 3, 0, &uart3_lock},
+ {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 4, 3, 0, &ssp0_lock},
+ {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 4, 3, 0, &ssp1_lock},
+};
+
+static struct mmp_param_gate_clk apbc_gate_clks[] = {
+ {PXA1928_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI4 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI5 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_GPIO * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_KPC * 4, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+ {PXA1928_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_RTC * 4, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+ {PXA1928_CLK_PWM0, "pwm0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_PWM1, "pwm1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_PWM2, "pwm2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ {PXA1928_CLK_PWM3, "pwm3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+ /* The gate clocks has mux parent. */
+ {PXA1928_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 0x3, 0x3, 0x0, 0, &uart0_lock},
+ {PXA1928_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 0x3, 0x3, 0x0, 0, &uart1_lock},
+ {PXA1928_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 0x3, 0x3, 0x0, 0, &uart2_lock},
+ {PXA1928_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 0x3, 0x3, 0x0, 0, &uart3_lock},
+ {PXA1928_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 0x3, 0x3, 0x0, 0, &ssp0_lock},
+ {PXA1928_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+};
+
+static void pxa1928_apb_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
+ ARRAY_SIZE(apbc_mux_clks));
+
+ mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
+ ARRAY_SIZE(apbc_gate_clks));
+}
+
+static DEFINE_SPINLOCK(sdh0_lock);
+static DEFINE_SPINLOCK(sdh1_lock);
+static DEFINE_SPINLOCK(sdh2_lock);
+static DEFINE_SPINLOCK(sdh3_lock);
+static DEFINE_SPINLOCK(sdh4_lock);
+static const char *sdh_parent_names[] = {"pll1_624", "pll5p", "pll5", "pll1_416"};
+
+static DEFINE_SPINLOCK(usb_lock);
+
+static struct mmp_param_mux_clk apmu_mux_clks[] = {
+ {0, "sdh_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 8, 2, 0, &sdh0_lock},
+};
+
+static struct mmp_param_div_clk apmu_div_clks[] = {
+ {0, "sdh_div", "sdh_mux", 0, PXA1928_CLK_SDH0 * 4, 10, 4, CLK_DIVIDER_ONE_BASED, &sdh0_lock},
+};
+
+static struct mmp_param_gate_clk apmu_gate_clks[] = {
+ {PXA1928_CLK_USB, "usb_clk", "usb_pll", 0, PXA1928_CLK_USB * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+ {PXA1928_CLK_HSIC, "hsic_clk", "usb_pll", 0, PXA1928_CLK_HSIC * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+ /* The gate clocks has mux parent. */
+ {PXA1928_CLK_SDH0, "sdh0_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 0x1b, 0x1b, 0x0, 0, &sdh0_lock},
+ {PXA1928_CLK_SDH1, "sdh1_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH1 * 4, 0x1b, 0x1b, 0x0, 0, &sdh1_lock},
+ {PXA1928_CLK_SDH2, "sdh2_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH2 * 4, 0x1b, 0x1b, 0x0, 0, &sdh2_lock},
+ {PXA1928_CLK_SDH3, "sdh3_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH3 * 4, 0x1b, 0x1b, 0x0, 0, &sdh3_lock},
+ {PXA1928_CLK_SDH4, "sdh4_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH4 * 4, 0x1b, 0x1b, 0x0, 0, &sdh4_lock},
+};
+
+static void pxa1928_axi_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+ struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+ mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base,
+ ARRAY_SIZE(apmu_mux_clks));
+
+ mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base,
+ ARRAY_SIZE(apmu_div_clks));
+
+ mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
+ ARRAY_SIZE(apmu_gate_clks));
+}
+
+static void pxa1928_clk_reset_init(struct device_node *np,
+ struct pxa1928_clk_unit *pxa_unit)
+{
+ struct mmp_clk_reset_cell *cells;
+ int i, base, nr_resets;
+
+ nr_resets = ARRAY_SIZE(apbc_gate_clks);
+ cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL);
+ if (!cells)
+ return;
+
+ base = 0;
+ for (i = 0; i < nr_resets; i++) {
+ cells[base + i].clk_id = apbc_gate_clks[i].id;
+ cells[base + i].reg =
+ pxa_unit->apbc_base + apbc_gate_clks[i].offset;
+ cells[base + i].flags = 0;
+ cells[base + i].lock = apbc_gate_clks[i].lock;
+ cells[base + i].bits = 0x4;
+ }
+
+ mmp_clk_reset_register(np, cells, nr_resets);
+}
+
+static void __init pxa1928_mpmu_clk_init(struct device_node *np)
+{
+ struct pxa1928_clk_unit *pxa_unit;
+
+ pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+ if (!pxa_unit)
+ return;
+
+ pxa_unit->mpmu_base = of_iomap(np, 0);
+ if (!pxa_unit->mpmu_base) {
+ pr_err("failed to map mpmu registers\n");
+ return;
+ }
+
+ pxa1928_pll_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_mpmu_clk, "marvell,pxa1928-mpmu", pxa1928_mpmu_clk_init);
+
+static void __init pxa1928_apmu_clk_init(struct device_node *np)
+{
+ struct pxa1928_clk_unit *pxa_unit;
+
+ pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+ if (!pxa_unit)
+ return;
+
+ pxa_unit->apmu_base = of_iomap(np, 0);
+ if (!pxa_unit->apmu_base) {
+ pr_err("failed to map apmu registers\n");
+ return;
+ }
+
+ mmp_clk_init(np, &pxa_unit->unit, PXA1928_APMU_NR_CLKS);
+
+ pxa1928_axi_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apmu_clk, "marvell,pxa1928-apmu", pxa1928_apmu_clk_init);
+
+static void __init pxa1928_apbc_clk_init(struct device_node *np)
+{
+ struct pxa1928_clk_unit *pxa_unit;
+
+ pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+ if (!pxa_unit)
+ return;
+
+ pxa_unit->apbc_base = of_iomap(np, 0);
+ if (!pxa_unit->apbc_base) {
+ pr_err("failed to map apbc registers\n");
+ return;
+ }
+
+ mmp_clk_init(np, &pxa_unit->unit, PXA1928_APBC_NR_CLKS);
+
+ pxa1928_apb_periph_clk_init(pxa_unit);
+ pxa1928_clk_reset_init(np, pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apbc_clk, "marvell,pxa1928-apbc", pxa1928_apbc_clk_init);
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 5e3c80dad336..13d6173326a4 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -35,6 +35,8 @@
#define APBC_SSP0 0x1c
#define APBC_SSP1 0x20
#define APBC_SSP2 0x4c
+#define APBC_TIMER0 0x30
+#define APBC_TIMER1 0x44
#define APBCP_TWSI1 0x28
#define APBCP_UART2 0x1c
#define APMU_SDH0 0x54
@@ -57,6 +59,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+ {PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
};
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
@@ -69,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
{PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
{PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
{PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+ {PXA910_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
{PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
{PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
{PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -115,6 +119,10 @@ static DEFINE_SPINLOCK(ssp0_lock);
static DEFINE_SPINLOCK(ssp1_lock);
static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static DEFINE_SPINLOCK(timer0_lock);
+static DEFINE_SPINLOCK(timer1_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96"};
+
static DEFINE_SPINLOCK(reset_lock);
static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -122,6 +130,8 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock},
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
+ {0, "timer0_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER0, 4, 3, 0, &timer0_lock},
+ {0, "timer1_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER1, 4, 3, 0, &timer1_lock},
};
static struct mmp_param_mux_clk apbcp_mux_clks[] = {
@@ -142,6 +152,8 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
{PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock},
{PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock},
{PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+ {PXA910_CLK_TIMER0, "timer0_clk", "timer0_mux", CLK_SET_RATE_PARENT, APBC_TIMER0, 0x3, 0x3, 0x0, 0, &timer0_lock},
+ {PXA910_CLK_TIMER1, "timer1_clk", "timer1_mux", CLK_SET_RATE_PARENT, APBC_TIMER1, 0x3, 0x3, 0x0, 0, &timer1_lock},
};
static struct mmp_param_gate_clk apbcp_gate_clks[] = {
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index 756f0f39d6a3..c19fd77e6c27 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -163,6 +163,7 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
{ "pex1", "pex1_en", 9, 0 },
{ "sata0", NULL, 15, 0 },
{ "sdio", NULL, 17, 0 },
+ { "crypto", NULL, 23, 0 },
{ "tdm", NULL, 25, 0 },
{ "ddr", NULL, 28, CLK_IGNORE_UNUSED },
{ "sata1", NULL, 30, 0 },
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index 22d136aa699f..32216f9b7f03 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -77,12 +77,12 @@ static void __init clk_misc_init(void)
writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
}
-static const char *sel_pll[] __initdata = { "pll", "ref_xtal", };
-static const char *sel_cpu[] __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_pix[] __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_io[] __initdata = { "ref_io", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
+static const char *const sel_pll[] __initconst = { "pll", "ref_xtal", };
+static const char *const sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_io[] __initconst = { "ref_io", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
enum imx23_clk {
ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index b1be3746ce95..a68670868baa 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -125,15 +125,15 @@ static void __init clk_misc_init(void)
writel_relaxed(val, FRAC0);
}
-static const char *sel_cpu[] __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_io0[] __initdata = { "ref_io0", "ref_xtal", };
-static const char *sel_io1[] __initdata = { "ref_io1", "ref_xtal", };
-static const char *sel_pix[] __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_gpmi[] __initdata = { "ref_gpmi", "ref_xtal", };
-static const char *sel_pll0[] __initdata = { "pll0", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
-static const char *ptp_sels[] __initdata = { "ref_xtal", "pll0", };
+static const char *const sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_io0[] __initconst = { "ref_io0", "ref_xtal", };
+static const char *const sel_io1[] __initconst = { "ref_io1", "ref_xtal", };
+static const char *const sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", };
+static const char *const sel_pll0[] __initconst = { "pll0", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
+static const char *const ptp_sels[] __initconst = { "ref_xtal", "pll0", };
enum imx28_clk {
ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1,
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index ef10ad9b5daa..f07d821dd75d 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -49,7 +49,7 @@ static inline struct clk *mxs_clk_gate(const char *name,
}
static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parent_names, int num_parents)
+ u8 shift, u8 width, const char *const *parent_names, int num_parents)
{
return clk_register_mux(NULL, name, parent_names, num_parents,
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
diff --git a/drivers/clk/pistachio/clk-pll.c b/drivers/clk/pistachio/clk-pll.c
index de537560bf70..e17dada0dd21 100644
--- a/drivers/clk/pistachio/clk-pll.c
+++ b/drivers/clk/pistachio/clk-pll.c
@@ -6,9 +6,12 @@
* version 2, as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/printk.h>
#include <linux/slab.h>
#include "clk.h"
@@ -50,6 +53,18 @@
#define PLL_CTRL4 0x10
#define PLL_FRAC_CTRL4_BYPASS BIT(28)
+#define MIN_PFD 9600000UL
+#define MIN_VCO_LA 400000000UL
+#define MAX_VCO_LA 1600000000UL
+#define MIN_VCO_FRAC_INT 600000000UL
+#define MAX_VCO_FRAC_INT 1600000000UL
+#define MIN_VCO_FRAC_FRAC 600000000UL
+#define MAX_VCO_FRAC_FRAC 2400000000UL
+#define MIN_OUTPUT_LA 8000000UL
+#define MAX_OUTPUT_LA 1600000000UL
+#define MIN_OUTPUT_FRAC 12000000UL
+#define MAX_OUTPUT_FRAC 1600000000UL
+
struct pistachio_clk_pll {
struct clk_hw hw;
void __iomem *base;
@@ -67,6 +82,12 @@ static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
writel(val, pll->base + reg);
}
+static inline void pll_lock(struct pistachio_clk_pll *pll)
+{
+ while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
+ cpu_relax();
+}
+
static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
{
dividend += divisor / 2;
@@ -124,6 +145,8 @@ static int pll_gf40lp_frac_enable(struct clk_hw *hw)
val &= ~PLL_FRAC_CTRL4_BYPASS;
pll_writel(pll, val, PLL_CTRL4);
+ pll_lock(pll);
+
return 0;
}
@@ -149,16 +172,29 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
struct pistachio_pll_rate_table *params;
- bool was_enabled;
- u32 val;
+ int enabled = pll_gf40lp_frac_is_enabled(hw);
+ u32 val, vco, old_postdiv1, old_postdiv2;
+ const char *name = __clk_get_name(hw->clk);
+
+ if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
+ return -EINVAL;
params = pll_get_params(pll, parent_rate, rate);
- if (!params)
+ if (!params || !params->refdiv)
return -EINVAL;
- was_enabled = pll_gf40lp_frac_is_enabled(hw);
- if (!was_enabled)
- pll_gf40lp_frac_enable(hw);
+ vco = params->fref * params->fbdiv / params->refdiv;
+ if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
+ pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+ MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
+
+ val = params->fref / params->refdiv;
+ if (val < MIN_PFD)
+ pr_warn("%s: PFD %u is too low (min %lu)\n",
+ name, val, MIN_PFD);
+ if (val > vco / 16)
+ pr_warn("%s: PFD %u is too high (max %u)\n",
+ name, val, vco / 16);
val = pll_readl(pll, PLL_CTRL1);
val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
@@ -168,6 +204,19 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
pll_writel(pll, val, PLL_CTRL1);
val = pll_readl(pll, PLL_CTRL2);
+
+ old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
+ PLL_FRAC_CTRL2_POSTDIV1_MASK;
+ old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
+ PLL_FRAC_CTRL2_POSTDIV2_MASK;
+ if (enabled &&
+ (params->postdiv1 != old_postdiv1 ||
+ params->postdiv2 != old_postdiv2))
+ pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+ if (params->postdiv2 > params->postdiv1)
+ pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
(PLL_FRAC_CTRL2_POSTDIV1_MASK <<
PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
@@ -178,11 +227,8 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
(params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
pll_writel(pll, val, PLL_CTRL2);
- while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
- cpu_relax();
-
- if (!was_enabled)
- pll_gf40lp_frac_disable(hw);
+ if (enabled)
+ pll_lock(pll);
return 0;
}
@@ -241,6 +287,8 @@ static int pll_gf40lp_laint_enable(struct clk_hw *hw)
val &= ~PLL_INT_CTRL2_BYPASS;
pll_writel(pll, val, PLL_CTRL2);
+ pll_lock(pll);
+
return 0;
}
@@ -266,18 +314,44 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
struct pistachio_pll_rate_table *params;
- bool was_enabled;
- u32 val;
+ int enabled = pll_gf40lp_laint_is_enabled(hw);
+ u32 val, vco, old_postdiv1, old_postdiv2;
+ const char *name = __clk_get_name(hw->clk);
+
+ if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
+ return -EINVAL;
params = pll_get_params(pll, parent_rate, rate);
- if (!params)
+ if (!params || !params->refdiv)
return -EINVAL;
- was_enabled = pll_gf40lp_laint_is_enabled(hw);
- if (!was_enabled)
- pll_gf40lp_laint_enable(hw);
+ vco = params->fref * params->fbdiv / params->refdiv;
+ if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
+ pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+ MIN_VCO_LA, MAX_VCO_LA);
+
+ val = params->fref / params->refdiv;
+ if (val < MIN_PFD)
+ pr_warn("%s: PFD %u is too low (min %lu)\n",
+ name, val, MIN_PFD);
+ if (val > vco / 16)
+ pr_warn("%s: PFD %u is too high (max %u)\n",
+ name, val, vco / 16);
val = pll_readl(pll, PLL_CTRL1);
+
+ old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
+ PLL_INT_CTRL1_POSTDIV1_MASK;
+ old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
+ PLL_INT_CTRL1_POSTDIV2_MASK;
+ if (enabled &&
+ (params->postdiv1 != old_postdiv1 ||
+ params->postdiv2 != old_postdiv2))
+ pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+ if (params->postdiv2 > params->postdiv1)
+ pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
(PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
(PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
@@ -288,11 +362,8 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
(params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
pll_writel(pll, val, PLL_CTRL1);
- while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
- cpu_relax();
-
- if (!was_enabled)
- pll_gf40lp_laint_disable(hw);
+ if (enabled)
+ pll_lock(pll);
return 0;
}
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
index b04c5b9c0ea8..d1de805df867 100644
--- a/drivers/clk/pxa/clk-pxa.h
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -14,7 +14,7 @@
#define _CLK_PXA_
#define PARENTS(name) \
- static const char *name ## _parents[] __initdata
+ static const char *const name ## _parents[] __initconst
#define MUX_RO_RATE_RO_OPS(name, clk_name) \
static struct clk_hw name ## _mux_hw; \
static struct clk_hw name ## _rate_hw; \
@@ -72,7 +72,7 @@ struct desc_clk_cken {
const char *name;
const char *dev_id;
const char *con_id;
- const char **parent_names;
+ const char * const *parent_names;
struct clk_fixed_factor lp;
struct clk_fixed_factor hp;
struct clk_gate gate;
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 8539c4fd34cc..fb7721bd37e6 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -231,7 +231,7 @@ static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb,
}
struct clk *rockchip_clk_register_cpuclk(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates, void __iomem *reg_base, spinlock_t *lock)
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index c842e3b60f21..e9f8df324e7c 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -120,7 +120,7 @@ static const struct clk_ops rockchip_mmc_clk_ops = {
};
struct clk *rockchip_clk_register_mmc(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
void __iomem *reg, int shift)
{
struct clk_init_data init;
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f8d3baf275b2..76027261f7ed 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -329,10 +329,10 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
*/
struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
- const char *name, const char **parent_names, u8 num_parents,
- void __iomem *base, int con_offset, int grf_lock_offset,
- int lock_shift, int mode_offset, int mode_shift,
- struct rockchip_pll_rate_table *rate_table,
+ const char *name, const char *const *parent_names,
+ u8 num_parents, void __iomem *base, int con_offset,
+ int grf_lock_offset, int lock_shift, int mode_offset,
+ int mode_shift, struct rockchip_pll_rate_table *rate_table,
u8 clk_pll_flags, spinlock_t *lock)
{
const char *pll_parents[3];
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index 556ce041d371..e4f9d472f1ff 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -26,7 +26,7 @@ enum rk3188_plls {
apll, cpll, dpll, gpll,
};
-struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
RK3066_PLL_RATE(2208000000, 1, 92, 1),
RK3066_PLL_RATE(2184000000, 1, 91, 1),
RK3066_PLL_RATE(2160000000, 1, 90, 1),
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index d17eb4528a28..4f817ed9e6ee 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -27,7 +27,7 @@ enum rk3288_plls {
apll, dpll, cpll, gpll, npll,
};
-struct rockchip_pll_rate_table rk3288_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
RK3066_PLL_RATE(2208000000, 1, 92, 1),
RK3066_PLL_RATE(2184000000, 1, 91, 1),
RK3066_PLL_RATE(2160000000, 1, 90, 1),
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index edb5d489ae61..052b94db0ff9 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -39,7 +39,7 @@
* sometimes without one of those components.
*/
static struct clk *rockchip_clk_register_branch(const char *name,
- const char **parent_names, u8 num_parents, void __iomem *base,
+ const char *const *parent_names, u8 num_parents, void __iomem *base,
int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
u8 div_shift, u8 div_width, u8 div_flags,
struct clk_div_table *div_table, int gate_offset,
@@ -103,8 +103,8 @@ static struct clk *rockchip_clk_register_branch(const char *name,
}
static struct clk *rockchip_clk_register_frac_branch(const char *name,
- const char **parent_names, u8 num_parents, void __iomem *base,
- int muxdiv_offset, u8 div_flags,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *base, int muxdiv_offset, u8 div_flags,
int gate_offset, u8 gate_shift, u8 gate_flags,
unsigned long flags, spinlock_t *lock)
{
@@ -297,7 +297,7 @@ void __init rockchip_clk_register_branches(
}
void __init rockchip_clk_register_armclk(unsigned int lookup_id,
- const char *name, const char **parent_names,
+ const char *name, const char *const *parent_names,
u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index e63cafe893e1..6b092673048a 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -108,7 +108,7 @@ struct rockchip_pll_rate_table {
struct rockchip_pll_clock {
unsigned int id;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
int con_offset;
@@ -140,10 +140,10 @@ struct rockchip_pll_clock {
}
struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
- const char *name, const char **parent_names, u8 num_parents,
- void __iomem *base, int con_offset, int grf_lock_offset,
- int lock_shift, int reg_mode, int mode_shift,
- struct rockchip_pll_rate_table *rate_table,
+ const char *name, const char *const *parent_names,
+ u8 num_parents, void __iomem *base, int con_offset,
+ int grf_lock_offset, int lock_shift, int reg_mode,
+ int mode_shift, struct rockchip_pll_rate_table *rate_table,
u8 clk_pll_flags, spinlock_t *lock);
struct rockchip_cpuclk_clksel {
@@ -173,16 +173,16 @@ struct rockchip_cpuclk_reg_data {
};
struct clk *rockchip_clk_register_cpuclk(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates, void __iomem *reg_base, spinlock_t *lock);
struct clk *rockchip_clk_register_mmc(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
void __iomem *reg, int shift);
-#define PNAME(x) static const char *x[] __initdata
+#define PNAME(x) static const char *const x[] __initconst
enum rockchip_clk_branch_type {
branch_composite,
@@ -197,7 +197,7 @@ struct rockchip_clk_branch {
unsigned int id;
enum rockchip_clk_branch_type branch_type;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
int muxdiv_offset;
@@ -403,7 +403,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
unsigned int nr_pll, int grf_lock_offset);
void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates);
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index e2e5193d1049..06f96eb7cf93 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -94,7 +94,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
-struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static struct samsung_mux_clock aud_mux_clks[] __initdata = {
MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
MUX_SEL_AUD, 0, 1),
MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
@@ -103,7 +103,7 @@ struct samsung_mux_clock aud_mux_clks[] __initdata = {
MUX_SEL_AUD, 8, 1),
};
-struct samsung_div_clock aud_div_clks[] __initdata = {
+static struct samsung_div_clock aud_div_clks[] __initdata = {
DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
DIV_AUD0, 0, 4),
@@ -115,7 +115,7 @@ struct samsung_div_clock aud_div_clks[] __initdata = {
DIV_AUD1, 12, 4),
};
-struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static struct samsung_gate_clock aud_gate_clks[] __initdata = {
GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
@@ -135,7 +135,7 @@ struct samsung_gate_clock aud_gate_clks[] __initdata = {
static void __init exynos5260_clk_aud_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = aud_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
@@ -203,7 +203,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
-struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static struct samsung_mux_clock disp_mux_clks[] __initdata = {
MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
mout_aclk_disp_333_user_p,
MUX_SEL_DISP0, 0, 1),
@@ -272,7 +272,7 @@ struct samsung_mux_clock disp_mux_clks[] __initdata = {
MUX_SEL_DISP4, 4, 2),
};
-struct samsung_div_clock disp_div_clks[] __initdata = {
+static struct samsung_div_clock disp_div_clks[] __initdata = {
DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
"mout_aclk_disp_222_user",
DIV_DISP, 8, 4),
@@ -285,7 +285,7 @@ struct samsung_div_clock disp_div_clks[] __initdata = {
DIV_DISP, 16, 4),
};
-struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static struct samsung_gate_clock disp_gate_clks[] __initdata = {
GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
"mout_phyclk_hdmi_phy_pixel_clko_user",
EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
@@ -325,7 +325,7 @@ struct samsung_gate_clock disp_gate_clks[] __initdata = {
static void __init exynos5260_clk_disp_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = disp_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
@@ -363,13 +363,13 @@ static unsigned long egl_clk_regs[] __initdata = {
PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
-struct samsung_mux_clock egl_mux_clks[] __initdata = {
+static struct samsung_mux_clock egl_mux_clks[] __initdata = {
MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
MUX_SEL_EGL, 4, 1),
MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
};
-struct samsung_div_clock egl_div_clks[] __initdata = {
+static struct samsung_div_clock egl_div_clks[] __initdata = {
DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
@@ -389,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = {
static void __init exynos5260_clk_egl_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.pll_clks = egl_pll_clks;
cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks);
@@ -433,7 +433,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
"phyclk_usbdrd30_udrd30_phyclock"};
-struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
"mout_phyclk_usbdrd30_phyclock_user",
mout_phyclk_usbdrd30_phyclock_user_p,
@@ -456,7 +456,7 @@ struct samsung_mux_clock fsys_mux_clks[] __initdata = {
MUX_SEL_FSYS1, 16, 1),
};
-struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
"mout_phyclk_usbdrd30_phyclock_user",
EN_SCLK_FSYS, 1, 0, 0),
@@ -491,7 +491,7 @@ struct samsung_gate_clock fsys_gate_clks[] __initdata = {
static void __init exynos5260_clk_fsys_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = fsys_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
@@ -537,18 +537,18 @@ static unsigned long g2d_clk_regs[] __initdata = {
PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
-struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
mout_aclk_g2d_333_user_p,
MUX_SEL_G2D, 0, 1),
};
-struct samsung_div_clock g2d_div_clks[] __initdata = {
+static struct samsung_div_clock g2d_div_clks[] __initdata = {
DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
DIV_G2D, 0, 3),
};
-struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
EN_IP_G2D, 4, 0, 0),
GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
@@ -580,7 +580,7 @@ struct samsung_gate_clock g2d_gate_clks[] __initdata = {
static void __init exynos5260_clk_g2d_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = g2d_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
@@ -617,17 +617,17 @@ static unsigned long g3d_clk_regs[] __initdata = {
PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
-struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
MUX_SEL_G3D, 0, 1),
};
-struct samsung_div_clock g3d_div_clks[] __initdata = {
+static struct samsung_div_clock g3d_div_clks[] __initdata = {
DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
};
-struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
EN_IP_G3D, 3, 0, 0),
@@ -641,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
static void __init exynos5260_clk_g3d_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.pll_clks = g3d_pll_clks;
cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks);
@@ -694,7 +694,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
-struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
mout_aclk_gscl_333_user_p,
MUX_SEL_GSCL, 0, 1),
@@ -708,7 +708,7 @@ struct samsung_mux_clock gscl_mux_clks[] __initdata = {
MUX_SEL_GSCL, 24, 1),
};
-struct samsung_div_clock gscl_div_clks[] __initdata = {
+static struct samsung_div_clock gscl_div_clks[] __initdata = {
DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
"mout_aclk_m2m_400_user",
DIV_GSCL, 0, 3),
@@ -717,7 +717,7 @@ struct samsung_div_clock gscl_div_clks[] __initdata = {
DIV_GSCL, 4, 3),
};
-struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
@@ -776,7 +776,7 @@ struct samsung_gate_clock gscl_gate_clks[] __initdata = {
static void __init exynos5260_clk_gscl_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = gscl_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
@@ -813,14 +813,14 @@ static unsigned long isp_clk_regs[] __initdata = {
PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"};
-struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static struct samsung_mux_clock isp_mux_clks[] __initdata = {
MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
MUX_SEL_ISP0, 0, 1),
MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
MUX_SEL_ISP0, 4, 1),
};
-struct samsung_div_clock isp_div_clks[] __initdata = {
+static struct samsung_div_clock isp_div_clks[] __initdata = {
DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
DIV_ISP, 0, 3),
DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
@@ -832,7 +832,7 @@ struct samsung_div_clock isp_div_clks[] __initdata = {
DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
};
-struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static struct samsung_gate_clock isp_gate_clks[] __initdata = {
GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
EN_IP_ISP0, 15, 0, 0),
@@ -895,7 +895,7 @@ struct samsung_gate_clock isp_gate_clks[] __initdata = {
static void __init exynos5260_clk_isp_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = isp_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
@@ -934,13 +934,13 @@ static unsigned long kfc_clk_regs[] __initdata = {
PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"};
-struct samsung_mux_clock kfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
MUX_SEL_KFC0, 0, 1),
MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
};
-struct samsung_div_clock kfc_div_clks[] __initdata = {
+static struct samsung_div_clock kfc_div_clks[] __initdata = {
DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
@@ -959,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
static void __init exynos5260_clk_kfc_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.pll_clks = kfc_pll_clks;
cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks);
@@ -993,18 +993,18 @@ static unsigned long mfc_clk_regs[] __initdata = {
PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
-struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
mout_aclk_mfc_333_user_p,
MUX_SEL_MFC, 0, 1),
};
-struct samsung_div_clock mfc_div_clks[] __initdata = {
+static struct samsung_div_clock mfc_div_clks[] __initdata = {
DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
DIV_MFC, 0, 3),
};
-struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
EN_IP_MFC, 1, 0, 0),
GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
@@ -1015,7 +1015,7 @@ struct samsung_gate_clock mfc_gate_clks[] __initdata = {
static void __init exynos5260_clk_mfc_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = mfc_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
@@ -1078,7 +1078,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
-struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static struct samsung_mux_clock mif_mux_clks[] __initdata = {
MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
MUX_SEL_MIF, 0, 1),
MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
@@ -1095,7 +1095,7 @@ struct samsung_mux_clock mif_mux_clks[] __initdata = {
MUX_SEL_MIF, 24, 1),
};
-struct samsung_div_clock mif_div_clks[] __initdata = {
+static struct samsung_div_clock mif_div_clks[] __initdata = {
DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
DIV_MIF, 0, 3),
DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
@@ -1114,7 +1114,7 @@ struct samsung_div_clock mif_div_clks[] __initdata = {
DIV_MIF, 28, 4),
};
-struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static struct samsung_gate_clock mif_gate_clks[] __initdata = {
GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
@@ -1162,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = {
static void __init exynos5260_clk_mif_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.pll_clks = mif_pll_clks;
cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks);
@@ -1221,7 +1221,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
-struct samsung_mux_clock peri_mux_clks[] __initdata = {
+static struct samsung_mux_clock peri_mux_clks[] __initdata = {
MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
MUX_SEL_PERI1, 4, 2),
MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
@@ -1230,12 +1230,12 @@ struct samsung_mux_clock peri_mux_clks[] __initdata = {
MUX_SEL_PERI1, 20, 2),
};
-struct samsung_div_clock peri_div_clks[] __initdata = {
+static struct samsung_div_clock peri_div_clks[] __initdata = {
DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
};
-struct samsung_gate_clock peri_gate_clks[] __initdata = {
+static struct samsung_gate_clock peri_gate_clks[] __initdata = {
GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
CLK_SET_RATE_PARENT, 0),
GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
@@ -1370,7 +1370,7 @@ struct samsung_gate_clock peri_gate_clks[] __initdata = {
static void __init exynos5260_clk_peri_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.mux_clks = peri_mux_clks;
cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
@@ -1432,7 +1432,7 @@ static unsigned long top_clk_regs[] __initdata = {
};
/* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
CLK_IS_ROOT, 270000000),
FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
@@ -1519,7 +1519,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
"mout_mediatop_pll_user"};
-struct samsung_mux_clock top_mux_clks[] __initdata = {
+static struct samsung_mux_clock top_mux_clks[] __initdata = {
MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
mout_mediatop_pll_user_p,
MUX_SEL_TOP_PLL0, 0, 1),
@@ -1679,7 +1679,7 @@ struct samsung_mux_clock top_mux_clks[] __initdata = {
MUX_SEL_TOP_GSCL, 20, 1),
};
-struct samsung_div_clock top_div_clks[] __initdata = {
+static struct samsung_div_clock top_div_clks[] __initdata = {
DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
DIV_TOP_G2D_MFC, 0, 3),
DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
@@ -1800,7 +1800,7 @@ struct samsung_div_clock top_div_clks[] __initdata = {
};
-struct samsung_gate_clock top_gate_clks[] __initdata = {
+static struct samsung_gate_clock top_gate_clks[] __initdata = {
GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
"dout_sclk_fsys_mmc0_sdclkin_b",
EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
@@ -1826,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = {
static void __init exynos5260_clk_top_init(struct device_node *np)
{
- struct samsung_cmu_info cmu = {0};
+ struct samsung_cmu_info cmu = { NULL };
cmu.pll_clks = top_pll_clks;
cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index bea4a173eef5..a1d731ca8f48 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -504,7 +504,7 @@ static struct samsung_fixed_factor_clock
FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
};
-struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
@@ -553,7 +553,7 @@ struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
};
-struct samsung_div_clock exynos5800_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
@@ -569,14 +569,14 @@ struct samsung_div_clock exynos5800_div_clks[] __initdata = {
DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
};
-struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
GATE_BUS_TOP, 24, 0, 0),
GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
GATE_BUS_TOP, 27, 0, 0),
};
-struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
TOP_SPARE2, 4, 1),
@@ -606,7 +606,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
};
-struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
DIV_TOP0, 16, 3),
};
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 9e04ae2bb4d7..39c95649d3d0 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -835,6 +835,7 @@ static unsigned long cpif_clk_regs[] __initdata = {
MPHY_PLL_CON1,
MPHY_PLL_FREQ_DET,
MUX_SEL_CPIF0,
+ DIV_CPIF,
ENABLE_SCLK_CPIF,
};
@@ -1389,7 +1390,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
/* ENABLE_ACLK_MIF2 */
GATE(CLK_ACLK_MIFND_266, "aclk_mifnd_266", "div_aclk_mif_266",
- ENABLE_ACLK_MIF2, 20, 0, 0),
+ ENABLE_ACLK_MIF2, 20, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_PPMU_DREX1S3, "aclk_ppmu_drex1s3", "div_aclk_drex1",
ENABLE_ACLK_MIF2, 17, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_PPMU_DREX1S1, "aclk_ppmu_drex1s1", "div_aclk_drex1",
@@ -1832,39 +1833,39 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
/* ENABLE_PCLK_PERIS_SECURE_TZPC */
GATE(CLK_PCLK_TZPC12, "pclk_tzpc12", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 12, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 12, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC11, "pclk_tzpc11", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 11, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 11, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC10, "pclk_tzpc10", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 10, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 10, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC9, "pclk_tzpc9", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 9, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 9, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC8, "pclk_tzpc8", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 8, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 8, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC7, "pclk_tzpc7", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 7, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 7, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC6, "pclk_tzpc6", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 6, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 6, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC5, "pclk_tzpc5", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 5, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 5, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC4, "pclk_tzpc4", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 4, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 4, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC3, "pclk_tzpc3", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 3, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 3, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC2, "pclk_tzpc2", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 2, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 2, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC1, "pclk_tzpc1", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 1, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 1, CLK_IGNORE_UNUSED, 0),
GATE(CLK_PCLK_TZPC0, "pclk_tzpc0", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_TZPC, 0, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_TZPC, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF */
GATE(CLK_PCLK_SECKEY_APBIF, "pclk_seckey_apbif", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF */
GATE(CLK_PCLK_CHIPID_APBIF, "pclk_chipid_apbif", "aclk_peris_66",
- ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, 0, 0),
+ ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_PCLK_PERIS_SECURE_TOPRTC */
GATE(CLK_PCLK_TOPRTC, "pclk_toprtc", "aclk_peris_66",
@@ -1895,11 +1896,11 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
/* ENABLE_SCLK_PERIS_SECURE_SECKEY */
GATE(CLK_SCLK_SECKEY, "sclk_seckey", "oscclk_efuse_common",
- ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, 0, 0),
+ ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_SCLK_PERIS_SECURE_CHIPID */
GATE(CLK_SCLK_CHIPID, "sclk_chipid", "oscclk_efuse_common",
- ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0),
+ ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_SCLK_PERIS_SECURE_TOPRTC */
GATE(CLK_SCLK_TOPRTC, "sclk_toprtc", "oscclk_efuse_common",
@@ -3286,10 +3287,10 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
/* MUX_SEL_G3D */
- MUX(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
- MUX_SEL_G3D, 8, 1),
- MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
- MUX_SEL_G3D, 0, 1),
+ MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
+ MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
+ MUX_F(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
+ MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_div_clock g3d_div_clks[] __initdata = {
@@ -3298,8 +3299,8 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = {
8, 2),
DIV(CLK_DIV_PCLK_G3D, "div_pclk_g3d", "div_aclk_g3d", DIV_G3D,
4, 3),
- DIV(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
- 0, 3),
+ DIV_F(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
+ 0, 3, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
@@ -3309,9 +3310,9 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
GATE(CLK_ACLK_BTS_G3D0, "aclk_bts_g3d0", "div_aclk_g3d",
ENABLE_ACLK_G3D, 6, 0, 0),
GATE(CLK_ACLK_ASYNCAPBS_G3D, "aclk_asyncapbs_g3d", "div_pclk_g3d",
- ENABLE_ACLK_G3D, 5, 0, 0),
+ ENABLE_ACLK_G3D, 5, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_ASYNCAPBM_G3D, "aclk_asyncapbm_g3d", "div_aclk_g3d",
- ENABLE_ACLK_G3D, 4, 0, 0),
+ ENABLE_ACLK_G3D, 4, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_AHB2APB_G3DP, "aclk_ahb2apb_g3dp", "div_pclk_g3d",
ENABLE_ACLK_G3D, 3, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_G3DNP_150, "aclk_g3dnp_150", "div_pclk_g3d",
@@ -3319,7 +3320,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
GATE(CLK_ACLK_G3DND_600, "aclk_g3dnd_600", "div_aclk_g3d",
ENABLE_ACLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_G3D, "aclk_g3d", "div_aclk_g3d",
- ENABLE_ACLK_G3D, 0, 0, 0),
+ ENABLE_ACLK_G3D, 0, CLK_SET_RATE_PARENT, 0),
/* ENABLE_PCLK_G3D */
GATE(CLK_PCLK_BTS_G3D1, "pclk_bts_g3d1", "div_pclk_g3d",
@@ -3582,7 +3583,7 @@ static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
/* MUX_SEL_APOLLO0 */
MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
- MUX_SEL_APOLLO0, 0, 1, 0, CLK_MUX_READ_ONLY),
+ MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
/* MUX_SEL_APOLLO1 */
MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
@@ -3590,7 +3591,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
/* MUX_SEL_APOLLO2 */
MUX_F(CLK_MOUT_APOLLO, "mout_apollo", mout_apollo_p, MUX_SEL_APOLLO2,
- 0, 1, 0, CLK_MUX_READ_ONLY),
+ 0, 1, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_div_clock apollo_div_clks[] __initdata = {
@@ -3611,11 +3612,9 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = {
DIV_APOLLO0, 8, 3, CLK_GET_RATE_NOCACHE,
CLK_DIVIDER_READ_ONLY),
DIV_F(CLK_DIV_APOLLO2, "div_apollo2", "div_apollo1",
- DIV_APOLLO0, 4, 3, CLK_GET_RATE_NOCACHE,
- CLK_DIVIDER_READ_ONLY),
+ DIV_APOLLO0, 4, 3, CLK_SET_RATE_PARENT, 0),
DIV_F(CLK_DIV_APOLLO1, "div_apollo1", "mout_apollo",
- DIV_APOLLO0, 0, 3, CLK_GET_RATE_NOCACHE,
- CLK_DIVIDER_READ_ONLY),
+ DIV_APOLLO0, 0, 3, CLK_SET_RATE_PARENT, 0),
/* DIV_APOLLO1 */
DIV_F(CLK_DIV_SCLK_HPM_APOLLO, "div_sclk_hpm_apollo", "mout_apollo",
@@ -3666,7 +3665,8 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
- ENABLE_SCLK_APOLLO, 0, CLK_IGNORE_UNUSED, 0),
+ ENABLE_SCLK_APOLLO, 0,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
};
static struct samsung_cmu_info apollo_cmu_info __initdata = {
@@ -3775,7 +3775,7 @@ static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
/* MUX_SEL_ATLAS0 */
MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
- MUX_SEL_ATLAS0, 0, 1, 0, CLK_MUX_READ_ONLY),
+ MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
/* MUX_SEL_ATLAS1 */
MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
@@ -3783,7 +3783,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
/* MUX_SEL_ATLAS2 */
MUX_F(CLK_MOUT_ATLAS, "mout_atlas", mout_atlas_p, MUX_SEL_ATLAS2,
- 0, 1, 0, CLK_MUX_READ_ONLY),
+ 0, 1, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_div_clock atlas_div_clks[] __initdata = {
@@ -3804,11 +3804,9 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = {
DIV_ATLAS0, 8, 3, CLK_GET_RATE_NOCACHE,
CLK_DIVIDER_READ_ONLY),
DIV_F(CLK_DIV_ATLAS2, "div_atlas2", "div_atlas1",
- DIV_ATLAS0, 4, 3, CLK_GET_RATE_NOCACHE,
- CLK_DIVIDER_READ_ONLY),
+ DIV_ATLAS0, 4, 3, CLK_SET_RATE_PARENT, 0),
DIV_F(CLK_DIV_ATLAS1, "div_atlas1", "mout_atlas",
- DIV_ATLAS0, 0, 3, CLK_GET_RATE_NOCACHE,
- CLK_DIVIDER_READ_ONLY),
+ DIV_ATLAS0, 0, 3, CLK_SET_RATE_PARENT, 0),
/* DIV_ATLAS1 */
DIV_F(CLK_DIV_SCLK_HPM_ATLAS, "div_sclk_hpm_atlas", "mout_atlas",
@@ -3885,7 +3883,8 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
- ENABLE_SCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+ ENABLE_SCLK_ATLAS, 0,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
};
static struct samsung_cmu_info atlas_cmu_info __initdata = {
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9d70e5c03804..bebc61b5fce1 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1156,7 +1156,7 @@ static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
};
static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
- struct samsung_pll_clock *pll_clk,
+ const struct samsung_pll_clock *pll_clk,
void __iomem *base)
{
struct samsung_clk_pll *pll;
@@ -1303,7 +1303,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
}
void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
- struct samsung_pll_clock *pll_list,
+ const struct samsung_pll_clock *pll_list,
unsigned int nr_pll, void __iomem *base)
{
int cnt;
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index f4f29ed6bd25..e56df5064889 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -81,13 +81,13 @@ static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
return ret;
}
-const struct clk_ops s3c24xx_clkout_ops = {
+static const struct clk_ops s3c24xx_clkout_ops = {
.get_parent = s3c24xx_clkout_get_parent,
.set_parent = s3c24xx_clkout_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
-struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
+static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
const char **parent_names, u8 num_parents,
u8 shift, u32 mask)
{
@@ -404,7 +404,7 @@ static struct s3c24xx_dclk_drv_data dclk_variants[] = {
},
};
-static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
+static const struct platform_device_id s3c24xx_dclk_driver_ids[] = {
{
.name = "s3c2410-dclk",
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2410],
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index e668e479a697..cf7e8fa7b624 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -169,44 +169,44 @@ static inline void s5pv210_clk_sleep_init(void) { }
#endif
/* Mux parent lists. */
-static const char *fin_pll_p[] __initdata = {
+static const char *const fin_pll_p[] __initconst = {
"xxti",
"xusbxti"
};
-static const char *mout_apll_p[] __initdata = {
+static const char *const mout_apll_p[] __initconst = {
"fin_pll",
"fout_apll"
};
-static const char *mout_mpll_p[] __initdata = {
+static const char *const mout_mpll_p[] __initconst = {
"fin_pll",
"fout_mpll"
};
-static const char *mout_epll_p[] __initdata = {
+static const char *const mout_epll_p[] __initconst = {
"fin_pll",
"fout_epll"
};
-static const char *mout_vpllsrc_p[] __initdata = {
+static const char *const mout_vpllsrc_p[] __initconst = {
"fin_pll",
"sclk_hdmi27m"
};
-static const char *mout_vpll_p[] __initdata = {
+static const char *const mout_vpll_p[] __initconst = {
"mout_vpllsrc",
"fout_vpll"
};
-static const char *mout_group1_p[] __initdata = {
+static const char *const mout_group1_p[] __initconst = {
"dout_a2m",
"mout_mpll",
"mout_epll",
"mout_vpll"
};
-static const char *mout_group2_p[] __initdata = {
+static const char *const mout_group2_p[] __initconst = {
"xxti",
"xusbxti",
"sclk_hdmi27m",
@@ -218,7 +218,7 @@ static const char *mout_group2_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_audio0_p[] __initdata = {
+static const char *const mout_audio0_p[] __initconst = {
"xxti",
"pcmcdclk0",
"sclk_hdmi27m",
@@ -230,7 +230,7 @@ static const char *mout_audio0_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_audio1_p[] __initdata = {
+static const char *const mout_audio1_p[] __initconst = {
"i2scdclk1",
"pcmcdclk1",
"sclk_hdmi27m",
@@ -242,7 +242,7 @@ static const char *mout_audio1_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_audio2_p[] __initdata = {
+static const char *const mout_audio2_p[] __initconst = {
"i2scdclk2",
"pcmcdclk2",
"sclk_hdmi27m",
@@ -254,63 +254,63 @@ static const char *mout_audio2_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_spdif_p[] __initdata = {
+static const char *const mout_spdif_p[] __initconst = {
"dout_audio0",
"dout_audio1",
"dout_audio3",
};
-static const char *mout_group3_p[] __initdata = {
+static const char *const mout_group3_p[] __initconst = {
"mout_apll",
"mout_mpll"
};
-static const char *mout_group4_p[] __initdata = {
+static const char *const mout_group4_p[] __initconst = {
"mout_mpll",
"dout_a2m"
};
-static const char *mout_flash_p[] __initdata = {
+static const char *const mout_flash_p[] __initconst = {
"dout_hclkd",
"dout_hclkp"
};
-static const char *mout_dac_p[] __initdata = {
+static const char *const mout_dac_p[] __initconst = {
"mout_vpll",
"sclk_hdmiphy"
};
-static const char *mout_hdmi_p[] __initdata = {
+static const char *const mout_hdmi_p[] __initconst = {
"sclk_hdmiphy",
"dout_tblk"
};
-static const char *mout_mixer_p[] __initdata = {
+static const char *const mout_mixer_p[] __initconst = {
"mout_dac",
"mout_hdmi"
};
-static const char *mout_vpll_6442_p[] __initdata = {
+static const char *const mout_vpll_6442_p[] __initconst = {
"fin_pll",
"fout_vpll"
};
-static const char *mout_mixer_6442_p[] __initdata = {
+static const char *const mout_mixer_6442_p[] __initconst = {
"mout_vpll",
"dout_mixer"
};
-static const char *mout_d0sync_6442_p[] __initdata = {
+static const char *const mout_d0sync_6442_p[] __initconst = {
"mout_dsys",
"div_apll"
};
-static const char *mout_d1sync_6442_p[] __initdata = {
+static const char *const mout_d1sync_6442_p[] __initconst = {
"mout_psys",
"div_apll"
};
-static const char *mout_group2_6442_p[] __initdata = {
+static const char *const mout_group2_6442_p[] __initconst = {
"fin_pll",
"none",
"none",
@@ -322,7 +322,7 @@ static const char *mout_group2_6442_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_audio0_6442_p[] __initdata = {
+static const char *const mout_audio0_6442_p[] __initconst = {
"fin_pll",
"pcmcdclk0",
"none",
@@ -334,7 +334,7 @@ static const char *mout_audio0_6442_p[] __initdata = {
"mout_vpll",
};
-static const char *mout_audio1_6442_p[] __initdata = {
+static const char *const mout_audio1_6442_p[] __initconst = {
"i2scdclk1",
"pcmcdclk1",
"none",
@@ -347,7 +347,7 @@ static const char *mout_audio1_6442_p[] __initdata = {
"fin_pll",
};
-static const char *mout_clksel_p[] __initdata = {
+static const char *const mout_clksel_p[] __initconst = {
"fout_apll_clkout",
"fout_mpll_clkout",
"fout_epll",
@@ -370,7 +370,7 @@ static const char *mout_clksel_p[] __initdata = {
"div_dclk"
};
-static const char *mout_clksel_6442_p[] __initdata = {
+static const char *const mout_clksel_6442_p[] __initconst = {
"fout_apll_clkout",
"fout_mpll_clkout",
"fout_epll",
@@ -393,7 +393,7 @@ static const char *mout_clksel_6442_p[] __initdata = {
"div_dclk"
};
-static const char *mout_clkout_p[] __initdata = {
+static const char *const mout_clkout_p[] __initconst = {
"dout_clkout",
"none",
"xxti",
@@ -401,20 +401,20 @@ static const char *mout_clkout_p[] __initdata = {
};
/* Common fixed factor clocks. */
-static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock ffactor_clks[] __initconst = {
FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
};
/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
-static struct samsung_mux_clock early_mux_clks[] __initdata = {
+static const struct samsung_mux_clock early_mux_clks[] __initconst = {
MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
CLK_MUX_READ_ONLY, 0),
};
/* Common clock muxes. */
-static struct samsung_mux_clock mux_clks[] __initdata = {
+static const struct samsung_mux_clock mux_clks[] __initconst = {
MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
@@ -427,7 +427,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
};
/* S5PV210-specific clock muxes. */
-static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5pv210_mux_clks[] __initconst = {
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
@@ -472,7 +472,7 @@ static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
};
/* S5P6442-specific clock muxes. */
-static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5p6442_mux_clks[] __initconst = {
MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
@@ -504,7 +504,7 @@ static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
};
/* S5PV210-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initconst = {
FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
@@ -512,12 +512,12 @@ static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
};
/* S5P6442-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initconst = {
FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
};
/* Common clock dividers. */
-static struct samsung_div_clock div_clks[] __initdata = {
+static const struct samsung_div_clock div_clks[] __initconst = {
DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
@@ -549,7 +549,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
};
/* S5PV210-specific clock dividers. */
-static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+static const struct samsung_div_clock s5pv210_div_clks[] __initconst = {
DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
@@ -578,7 +578,7 @@ static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
};
/* S5P6442-specific clock dividers. */
-static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+static const struct samsung_div_clock s5p6442_div_clks[] __initconst = {
DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
@@ -586,7 +586,7 @@ static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
};
/* Common clock gates. */
-static struct samsung_gate_clock gate_clks[] __initdata = {
+static const struct samsung_gate_clock gate_clks[] __initconst = {
GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
@@ -666,7 +666,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = {
};
/* S5PV210-specific clock gates. */
-static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5pv210_gate_clks[] __initconst = {
GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -728,7 +728,7 @@ static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
};
/* S5P6442-specific clock gates. */
-static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5p6442_gate_clks[] __initconst = {
GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -748,14 +748,14 @@ static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
* Clock aliases for legacy clkdev look-up.
* NOTE: Needed only to support legacy board files.
*/
-static struct samsung_clock_alias s5pv210_aliases[] = {
+static const struct samsung_clock_alias s5pv210_aliases[] __initconst = {
ALIAS(DOUT_APLL, NULL, "armclk"),
ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
};
/* S5PV210-specific PLLs. */
-static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5pv210_pll_clks[] __initconst = {
[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, NULL),
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
@@ -767,7 +767,7 @@ static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
};
/* S5P6442-specific PLLs. */
-static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5p6442_pll_clks[] __initconst = {
[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, NULL),
[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 9e1f88c04fd4..0117238391d6 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -98,7 +98,7 @@ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
/* register a list of aliases */
void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
- struct samsung_clock_alias *list,
+ const struct samsung_clock_alias *list,
unsigned int nr_clk)
{
struct clk *clk;
@@ -132,7 +132,8 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
/* register a list of fixed clocks */
void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
- struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+ const struct samsung_fixed_rate_clock *list,
+ unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
@@ -161,7 +162,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
/* register a list of fixed factor clocks */
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
- struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+ const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx;
@@ -181,7 +182,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
/* register a list of mux clocks */
void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
- struct samsung_mux_clock *list,
+ const struct samsung_mux_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
@@ -213,7 +214,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
/* register a list of div clocks */
void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
- struct samsung_div_clock *list,
+ const struct samsung_div_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
@@ -252,7 +253,7 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
/* register a list of gate clocks */
void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
- struct samsung_gate_clock *list,
+ const struct samsung_gate_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
@@ -389,7 +390,7 @@ struct samsung_clk_provider * __init samsung_cmu_register_one(
ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
if (!ctx) {
- panic("%s: unable to alllocate ctx\n", __func__);
+ panic("%s: unable to allocate ctx\n", __func__);
return ctx;
}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4c75383cea7..b775fc29caa5 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -121,7 +121,7 @@ struct samsung_mux_clock {
unsigned int id;
const char *dev_name;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
unsigned long offset;
@@ -368,28 +368,28 @@ extern void __init samsung_clk_of_register_fixed_ext(
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk *clk, unsigned int id);
-extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
- struct samsung_clock_alias *list,
+extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
+ const struct samsung_clock_alias *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_rate(
struct samsung_clk_provider *ctx,
- struct samsung_fixed_rate_clock *clk_list,
+ const struct samsung_fixed_rate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_factor(
struct samsung_clk_provider *ctx,
- struct samsung_fixed_factor_clock *list,
+ const struct samsung_fixed_factor_clock *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
- struct samsung_mux_clock *clk_list,
+ const struct samsung_mux_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
- struct samsung_div_clock *clk_list,
+ const struct samsung_div_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
- struct samsung_gate_clock *clk_list,
+ const struct samsung_gate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
- struct samsung_pll_clock *pll_list,
+ const struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base);
extern struct samsung_clk_provider __init *samsung_cmu_register_one(
diff --git a/drivers/clk/shmobile/clk-emev2.c b/drivers/clk/shmobile/clk-emev2.c
index 6c7c929c7765..5b60beb7d0eb 100644
--- a/drivers/clk/shmobile/clk-emev2.c
+++ b/drivers/clk/shmobile/clk-emev2.c
@@ -34,7 +34,7 @@
static DEFINE_SPINLOCK(lock);
/* not pretty, but hey */
-void __iomem *smu_base;
+static void __iomem *smu_base;
static void __init emev2_smu_write(unsigned long value, int offs)
{
diff --git a/drivers/clk/sirf/Makefile b/drivers/clk/sirf/Makefile
index 36b8e203f6e7..09b4210d9124 100644
--- a/drivers/clk/sirf/Makefile
+++ b/drivers/clk/sirf/Makefile
@@ -2,4 +2,4 @@
# Makefile for sirf specific clk
#
-obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o
+obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o clk-atlas7.o
diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c
new file mode 100644
index 000000000000..db8ab691dbf6
--- /dev/null
+++ b/drivers/clk/sirf/clk-atlas7.c
@@ -0,0 +1,1632 @@
+/*
+ * Clock tree for CSR SiRFAtlas7
+ *
+ * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#define SIRFSOC_CLKC_MEMPLL_AB_FREQ 0x0000
+#define SIRFSOC_CLKC_MEMPLL_AB_SSC 0x0004
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL0 0x0008
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL1 0x000c
+#define SIRFSOC_CLKC_MEMPLL_AB_STATUS 0x0010
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_ADDR 0x0014
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_DATA 0x0018
+
+#define SIRFSOC_CLKC_CPUPLL_AB_FREQ 0x001c
+#define SIRFSOC_CLKC_CPUPLL_AB_SSC 0x0020
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL0 0x0024
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL1 0x0028
+#define SIRFSOC_CLKC_CPUPLL_AB_STATUS 0x002c
+
+#define SIRFSOC_CLKC_SYS0PLL_AB_FREQ 0x0030
+#define SIRFSOC_CLKC_SYS0PLL_AB_SSC 0x0034
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL0 0x0038
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL1 0x003c
+#define SIRFSOC_CLKC_SYS0PLL_AB_STATUS 0x0040
+
+#define SIRFSOC_CLKC_SYS1PLL_AB_FREQ 0x0044
+#define SIRFSOC_CLKC_SYS1PLL_AB_SSC 0x0048
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL0 0x004c
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL1 0x0050
+#define SIRFSOC_CLKC_SYS1PLL_AB_STATUS 0x0054
+
+#define SIRFSOC_CLKC_SYS2PLL_AB_FREQ 0x0058
+#define SIRFSOC_CLKC_SYS2PLL_AB_SSC 0x005c
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL0 0x0060
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL1 0x0064
+#define SIRFSOC_CLKC_SYS2PLL_AB_STATUS 0x0068
+
+#define SIRFSOC_CLKC_SYS3PLL_AB_FREQ 0x006c
+#define SIRFSOC_CLKC_SYS3PLL_AB_SSC 0x0070
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL0 0x0074
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL1 0x0078
+#define SIRFSOC_CLKC_SYS3PLL_AB_STATUS 0x007c
+
+#define SIRFSOC_ABPLL_CTRL0_SSEN 0x00001000
+#define SIRFSOC_ABPLL_CTRL0_BYPASS 0x00000010
+#define SIRFSOC_ABPLL_CTRL0_RESET 0x00000001
+
+#define SIRFSOC_CLKC_AUDIO_DTO_INC 0x0088
+#define SIRFSOC_CLKC_DISP0_DTO_INC 0x008c
+#define SIRFSOC_CLKC_DISP1_DTO_INC 0x0090
+
+#define SIRFSOC_CLKC_AUDIO_DTO_SRC 0x0094
+#define SIRFSOC_CLKC_AUDIO_DTO_ENA 0x0098
+#define SIRFSOC_CLKC_AUDIO_DTO_DROFF 0x009c
+
+#define SIRFSOC_CLKC_DISP0_DTO_SRC 0x00a0
+#define SIRFSOC_CLKC_DISP0_DTO_ENA 0x00a4
+#define SIRFSOC_CLKC_DISP0_DTO_DROFF 0x00a8
+
+#define SIRFSOC_CLKC_DISP1_DTO_SRC 0x00ac
+#define SIRFSOC_CLKC_DISP1_DTO_ENA 0x00b0
+#define SIRFSOC_CLKC_DISP1_DTO_DROFF 0x00b4
+
+#define SIRFSOC_CLKC_I2S_CLK_SEL 0x00b8
+#define SIRFSOC_CLKC_I2S_SEL_STAT 0x00bc
+
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_CFG 0x00c0
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_ENA 0x00c4
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL 0x00c8
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL_STAT 0x00cc
+
+#define SIRFSOC_CLKC_BTSS_CLKDIV_CFG 0x00d0
+#define SIRFSOC_CLKC_BTSS_CLKDIV_ENA 0x00d4
+#define SIRFSOC_CLKC_BTSS_CLK_SEL 0x00d8
+#define SIRFSOC_CLKC_BTSS_CLK_SEL_STAT 0x00dc
+
+#define SIRFSOC_CLKC_RGMII_CLKDIV_CFG 0x00e0
+#define SIRFSOC_CLKC_RGMII_CLKDIV_ENA 0x00e4
+#define SIRFSOC_CLKC_RGMII_CLK_SEL 0x00e8
+#define SIRFSOC_CLKC_RGMII_CLK_SEL_STAT 0x00ec
+
+#define SIRFSOC_CLKC_CPU_CLKDIV_CFG 0x00f0
+#define SIRFSOC_CLKC_CPU_CLKDIV_ENA 0x00f4
+#define SIRFSOC_CLKC_CPU_CLK_SEL 0x00f8
+#define SIRFSOC_CLKC_CPU_CLK_SEL_STAT 0x00fc
+
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG 0x0100
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA 0x0104
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL 0x0108
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL_STAT 0x010c
+
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG 0x0110
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA 0x0114
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL 0x0118
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL_STAT 0x011c
+
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG 0x0120
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA 0x0124
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL 0x0128
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL_STAT 0x012c
+
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG 0x0130
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA 0x0134
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL 0x0138
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL_STAT 0x013c
+
+#define SIRFSOC_CLKC_CAN_CLKDIV_CFG 0x0140
+#define SIRFSOC_CLKC_CAN_CLKDIV_ENA 0x0144
+#define SIRFSOC_CLKC_CAN_CLK_SEL 0x0148
+#define SIRFSOC_CLKC_CAN_CLK_SEL_STAT 0x014c
+
+#define SIRFSOC_CLKC_DEINT_CLKDIV_CFG 0x0150
+#define SIRFSOC_CLKC_DEINT_CLKDIV_ENA 0x0154
+#define SIRFSOC_CLKC_DEINT_CLK_SEL 0x0158
+#define SIRFSOC_CLKC_DEINT_CLK_SEL_STAT 0x015c
+
+#define SIRFSOC_CLKC_NAND_CLKDIV_CFG 0x0160
+#define SIRFSOC_CLKC_NAND_CLKDIV_ENA 0x0164
+#define SIRFSOC_CLKC_NAND_CLK_SEL 0x0168
+#define SIRFSOC_CLKC_NAND_CLK_SEL_STAT 0x016c
+
+#define SIRFSOC_CLKC_DISP0_CLKDIV_CFG 0x0170
+#define SIRFSOC_CLKC_DISP0_CLKDIV_ENA 0x0174
+#define SIRFSOC_CLKC_DISP0_CLK_SEL 0x0178
+#define SIRFSOC_CLKC_DISP0_CLK_SEL_STAT 0x017c
+
+#define SIRFSOC_CLKC_DISP1_CLKDIV_CFG 0x0180
+#define SIRFSOC_CLKC_DISP1_CLKDIV_ENA 0x0184
+#define SIRFSOC_CLKC_DISP1_CLK_SEL 0x0188
+#define SIRFSOC_CLKC_DISP1_CLK_SEL_STAT 0x018c
+
+#define SIRFSOC_CLKC_GPU_CLKDIV_CFG 0x0190
+#define SIRFSOC_CLKC_GPU_CLKDIV_ENA 0x0194
+#define SIRFSOC_CLKC_GPU_CLK_SEL 0x0198
+#define SIRFSOC_CLKC_GPU_CLK_SEL_STAT 0x019c
+
+#define SIRFSOC_CLKC_GNSS_CLKDIV_CFG 0x01a0
+#define SIRFSOC_CLKC_GNSS_CLKDIV_ENA 0x01a4
+#define SIRFSOC_CLKC_GNSS_CLK_SEL 0x01a8
+#define SIRFSOC_CLKC_GNSS_CLK_SEL_STAT 0x01ac
+
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG0 0x01b0
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG1 0x01b4
+#define SIRFSOC_CLKC_SHARED_DIVIDER_ENA 0x01b8
+
+#define SIRFSOC_CLKC_SYS_CLK_SEL 0x01bc
+#define SIRFSOC_CLKC_SYS_CLK_SEL_STAT 0x01c0
+#define SIRFSOC_CLKC_IO_CLK_SEL 0x01c4
+#define SIRFSOC_CLKC_IO_CLK_SEL_STAT 0x01c8
+#define SIRFSOC_CLKC_G2D_CLK_SEL 0x01cc
+#define SIRFSOC_CLKC_G2D_CLK_SEL_STAT 0x01d0
+#define SIRFSOC_CLKC_JPENC_CLK_SEL 0x01d4
+#define SIRFSOC_CLKC_JPENC_CLK_SEL_STAT 0x01d8
+#define SIRFSOC_CLKC_VDEC_CLK_SEL 0x01dc
+#define SIRFSOC_CLKC_VDEC_CLK_SEL_STAT 0x01e0
+#define SIRFSOC_CLKC_GMAC_CLK_SEL 0x01e4
+#define SIRFSOC_CLKC_GMAC_CLK_SEL_STAT 0x01e8
+#define SIRFSOC_CLKC_USB_CLK_SEL 0x01ec
+#define SIRFSOC_CLKC_USB_CLK_SEL_STAT 0x01f0
+#define SIRFSOC_CLKC_KAS_CLK_SEL 0x01f4
+#define SIRFSOC_CLKC_KAS_CLK_SEL_STAT 0x01f8
+#define SIRFSOC_CLKC_SEC_CLK_SEL 0x01fc
+#define SIRFSOC_CLKC_SEC_CLK_SEL_STAT 0x0200
+#define SIRFSOC_CLKC_SDR_CLK_SEL 0x0204
+#define SIRFSOC_CLKC_SDR_CLK_SEL_STAT 0x0208
+#define SIRFSOC_CLKC_VIP_CLK_SEL 0x020c
+#define SIRFSOC_CLKC_VIP_CLK_SEL_STAT 0x0210
+#define SIRFSOC_CLKC_NOCD_CLK_SEL 0x0214
+#define SIRFSOC_CLKC_NOCD_CLK_SEL_STAT 0x0218
+#define SIRFSOC_CLKC_NOCR_CLK_SEL 0x021c
+#define SIRFSOC_CLKC_NOCR_CLK_SEL_STAT 0x0220
+#define SIRFSOC_CLKC_TPIU_CLK_SEL 0x0224
+#define SIRFSOC_CLKC_TPIU_CLK_SEL_STAT 0x0228
+
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_SET 0x022c
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_CLR 0x0230
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_STAT 0x0234
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_SET 0x0238
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_CLR 0x023c
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_STAT 0x0240
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_SET 0x0244
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_CLR 0x0248
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_STAT 0x024c
+
+#define SIRFSOC_CLKC_RSTC_A7_SW_RST 0x0308
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN1_SET 0x04a0
+#define SIRFSOC_CLKC_LEAF_CLK_EN2_SET 0x04b8
+#define SIRFSOC_CLKC_LEAF_CLK_EN3_SET 0x04d0
+#define SIRFSOC_CLKC_LEAF_CLK_EN4_SET 0x04e8
+#define SIRFSOC_CLKC_LEAF_CLK_EN5_SET 0x0500
+#define SIRFSOC_CLKC_LEAF_CLK_EN6_SET 0x0518
+#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET 0x0530
+#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET 0x0548
+
+
+static void __iomem *sirfsoc_clk_vbase;
+static struct clk_onecell_data clk_data;
+
+static const struct clk_div_table pll_div_table[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 4 },
+ { .val = 3, .div = 8 },
+ { .val = 4, .div = 16 },
+ { .val = 5, .div = 32 },
+};
+
+struct clk_pll {
+ struct clk_hw hw;
+ u16 regofs; /* register offset */
+};
+#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct clk_dto {
+ struct clk_hw hw;
+ u16 inc_offset; /* dto increment offset */
+ u16 src_offset; /* dto src offset */
+};
+#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
+
+struct clk_unit {
+ struct clk_hw hw;
+ u16 regofs;
+ u16 bit;
+ spinlock_t *lock;
+};
+#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
+
+struct atlas7_div_init_data {
+ const char *div_name;
+ const char *parent_name;
+ const char *gate_name;
+ unsigned long flags;
+ u8 divider_flags;
+ u8 gate_flags;
+ u32 div_offset;
+ u8 shift;
+ u8 width;
+ u32 gate_offset;
+ u8 gate_bit;
+ spinlock_t *lock;
+};
+
+struct atlas7_mux_init_data {
+ const char *mux_name;
+ const char * const *parent_names;
+ u8 parent_num;
+ unsigned long flags;
+ u8 mux_flags;
+ u32 mux_offset;
+ u8 shift;
+ u8 width;
+};
+
+struct atlas7_unit_init_data {
+ u32 index;
+ const char *unit_name;
+ const char *parent_name;
+ unsigned long flags;
+ u32 regofs;
+ u8 bit;
+ spinlock_t *lock;
+};
+
+struct atlas7_reset_desc {
+ const char *name;
+ u32 clk_ofs;
+ u8 clk_bit;
+ u32 rst_ofs;
+ u8 rst_bit;
+ spinlock_t *lock;
+};
+
+static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
+static DEFINE_SPINLOCK(mempll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys1pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys2pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys3pll_ctrl1_lock);
+static DEFINE_SPINLOCK(usbphy_div_lock);
+static DEFINE_SPINLOCK(btss_div_lock);
+static DEFINE_SPINLOCK(rgmii_div_lock);
+static DEFINE_SPINLOCK(cpu_div_lock);
+static DEFINE_SPINLOCK(sdphy01_div_lock);
+static DEFINE_SPINLOCK(sdphy23_div_lock);
+static DEFINE_SPINLOCK(sdphy45_div_lock);
+static DEFINE_SPINLOCK(sdphy67_div_lock);
+static DEFINE_SPINLOCK(can_div_lock);
+static DEFINE_SPINLOCK(deint_div_lock);
+static DEFINE_SPINLOCK(nand_div_lock);
+static DEFINE_SPINLOCK(disp0_div_lock);
+static DEFINE_SPINLOCK(disp1_div_lock);
+static DEFINE_SPINLOCK(gpu_div_lock);
+static DEFINE_SPINLOCK(gnss_div_lock);
+/* gate register shared */
+static DEFINE_SPINLOCK(share_div_lock);
+static DEFINE_SPINLOCK(root0_gate_lock);
+static DEFINE_SPINLOCK(root1_gate_lock);
+static DEFINE_SPINLOCK(leaf0_gate_lock);
+static DEFINE_SPINLOCK(leaf1_gate_lock);
+static DEFINE_SPINLOCK(leaf2_gate_lock);
+static DEFINE_SPINLOCK(leaf3_gate_lock);
+static DEFINE_SPINLOCK(leaf4_gate_lock);
+static DEFINE_SPINLOCK(leaf5_gate_lock);
+static DEFINE_SPINLOCK(leaf6_gate_lock);
+static DEFINE_SPINLOCK(leaf7_gate_lock);
+static DEFINE_SPINLOCK(leaf8_gate_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+ return readl(sirfsoc_clk_vbase + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+ writel(val, sirfsoc_clk_vbase + reg);
+}
+
+/*
+* ABPLL
+* integer mode: Fvco = Fin * 2 * NF / NR
+* Spread Spectrum mode: Fvco = Fin * SSN / NR
+* SSN = 2^24 / (256 * ((ssdiv >> ssdepth) << ssdepth) + (ssmod << ssdepth))
+*/
+static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long fin = parent_rate;
+ struct clk_pll *clk = to_pllclk(hw);
+ u64 rate;
+ u32 regctrl0 = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_CTRL0 -
+ SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+ u32 regfreq = clkc_readl(clk->regofs);
+ u32 regssc = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_SSC -
+ SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+ u32 nr = (regfreq >> 16 & (BIT(3) - 1)) + 1;
+ u32 nf = (regfreq & (BIT(9) - 1)) + 1;
+ u32 ssdiv = regssc >> 8 & (BIT(12) - 1);
+ u32 ssdepth = regssc >> 20 & (BIT(2) - 1);
+ u32 ssmod = regssc & (BIT(8) - 1);
+
+ if (regctrl0 & SIRFSOC_ABPLL_CTRL0_BYPASS)
+ return fin;
+
+ if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) {
+ rate = fin;
+ rate *= 1 << 24;
+ do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth)
+ + (ssmod << ssdepth)));
+ } else {
+ rate = 2 * fin;
+ rate *= nf;
+ do_div(rate, nr);
+ }
+ return rate;
+}
+
+static const struct clk_ops ab_pll_ops = {
+ .recalc_rate = pll_clk_recalc_rate,
+};
+
+static const char * const pll_clk_parents[] = {
+ "xin",
+};
+
+static struct clk_init_data clk_cpupll_init = {
+ .name = "cpupll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_cpupll = {
+ .regofs = SIRFSOC_CLKC_CPUPLL_AB_FREQ,
+ .hw = {
+ .init = &clk_cpupll_init,
+ },
+};
+
+static struct clk_init_data clk_mempll_init = {
+ .name = "mempll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_mempll = {
+ .regofs = SIRFSOC_CLKC_MEMPLL_AB_FREQ,
+ .hw = {
+ .init = &clk_mempll_init,
+ },
+};
+
+static struct clk_init_data clk_sys0pll_init = {
+ .name = "sys0pll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys0pll = {
+ .regofs = SIRFSOC_CLKC_SYS0PLL_AB_FREQ,
+ .hw = {
+ .init = &clk_sys0pll_init,
+ },
+};
+
+static struct clk_init_data clk_sys1pll_init = {
+ .name = "sys1pll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys1pll = {
+ .regofs = SIRFSOC_CLKC_SYS1PLL_AB_FREQ,
+ .hw = {
+ .init = &clk_sys1pll_init,
+ },
+};
+
+static struct clk_init_data clk_sys2pll_init = {
+ .name = "sys2pll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys2pll = {
+ .regofs = SIRFSOC_CLKC_SYS2PLL_AB_FREQ,
+ .hw = {
+ .init = &clk_sys2pll_init,
+ },
+};
+
+static struct clk_init_data clk_sys3pll_init = {
+ .name = "sys3pll_vco",
+ .ops = &ab_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys3pll = {
+ .regofs = SIRFSOC_CLKC_SYS3PLL_AB_FREQ,
+ .hw = {
+ .init = &clk_sys3pll_init,
+ },
+};
+
+/*
+ * DTO in clkc, default enable double resolution mode
+ * double resolution mode:fout = fin * finc / 2^29
+ * normal mode:fout = fin * finc / 2^28
+ */
+static int dto_clk_is_enabled(struct clk_hw *hw)
+{
+ struct clk_dto *clk = to_dtoclk(hw);
+ int reg;
+
+ reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+ return !!(clkc_readl(reg) & BIT(0));
+}
+
+static int dto_clk_enable(struct clk_hw *hw)
+{
+ u32 val, reg;
+ struct clk_dto *clk = to_dtoclk(hw);
+
+ reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+ val = clkc_readl(reg) | BIT(0);
+ clkc_writel(val, reg);
+ return 0;
+}
+
+static void dto_clk_disable(struct clk_hw *hw)
+{
+ u32 val, reg;
+ struct clk_dto *clk = to_dtoclk(hw);
+
+ reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+ val = clkc_readl(reg) & ~BIT(0);
+ clkc_writel(val, reg);
+}
+
+static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ u64 rate = parent_rate;
+ struct clk_dto *clk = to_dtoclk(hw);
+ u32 finc = clkc_readl(clk->inc_offset);
+ u32 droff = clkc_readl(clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+
+ rate *= finc;
+ if (droff & BIT(0))
+ /* Double resolution off */
+ do_div(rate, 1 << 28);
+ else
+ do_div(rate, 1 << 29);
+
+ return rate;
+}
+
+static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u64 dividend = rate * (1 << 29);
+
+ do_div(dividend, *parent_rate);
+ dividend *= *parent_rate;
+ do_div(dividend, 1 << 29);
+
+ return dividend;
+}
+
+static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ u64 dividend = rate * (1 << 29);
+ struct clk_dto *clk = to_dtoclk(hw);
+
+ do_div(dividend, parent_rate);
+ clkc_writel(0, clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+ clkc_writel(dividend, clk->inc_offset);
+
+ return 0;
+}
+
+static u8 dto_clk_get_parent(struct clk_hw *hw)
+{
+ struct clk_dto *clk = to_dtoclk(hw);
+
+ return clkc_readl(clk->src_offset);
+}
+
+/*
+ * dto need CLK_SET_PARENT_GATE
+ */
+static int dto_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_dto *clk = to_dtoclk(hw);
+
+ clkc_writel(index, clk->src_offset);
+ return 0;
+}
+
+static const struct clk_ops dto_ops = {
+ .is_enabled = dto_clk_is_enabled,
+ .enable = dto_clk_enable,
+ .disable = dto_clk_disable,
+ .recalc_rate = dto_clk_recalc_rate,
+ .round_rate = dto_clk_round_rate,
+ .set_rate = dto_clk_set_rate,
+ .get_parent = dto_clk_get_parent,
+ .set_parent = dto_clk_set_parent,
+};
+
+/* dto parent clock as syspllvco/clk1 */
+static const char * const audiodto_clk_parents[] = {
+ "sys0pll_clk1",
+ "sys1pll_clk1",
+ "sys3pll_clk1",
+};
+
+static struct clk_init_data clk_audiodto_init = {
+ .name = "audio_dto",
+ .ops = &dto_ops,
+ .parent_names = audiodto_clk_parents,
+ .num_parents = ARRAY_SIZE(audiodto_clk_parents),
+};
+
+static struct clk_dto clk_audio_dto = {
+ .inc_offset = SIRFSOC_CLKC_AUDIO_DTO_INC,
+ .src_offset = SIRFSOC_CLKC_AUDIO_DTO_SRC,
+ .hw = {
+ .init = &clk_audiodto_init,
+ },
+};
+
+static const char * const disp0dto_clk_parents[] = {
+ "sys0pll_clk1",
+ "sys1pll_clk1",
+ "sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp0dto_init = {
+ .name = "disp0_dto",
+ .ops = &dto_ops,
+ .parent_names = disp0dto_clk_parents,
+ .num_parents = ARRAY_SIZE(disp0dto_clk_parents),
+};
+
+static struct clk_dto clk_disp0_dto = {
+ .inc_offset = SIRFSOC_CLKC_DISP0_DTO_INC,
+ .src_offset = SIRFSOC_CLKC_DISP0_DTO_SRC,
+ .hw = {
+ .init = &clk_disp0dto_init,
+ },
+};
+
+static const char * const disp1dto_clk_parents[] = {
+ "sys0pll_clk1",
+ "sys1pll_clk1",
+ "sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp1dto_init = {
+ .name = "disp1_dto",
+ .ops = &dto_ops,
+ .parent_names = disp1dto_clk_parents,
+ .num_parents = ARRAY_SIZE(disp1dto_clk_parents),
+};
+
+static struct clk_dto clk_disp1_dto = {
+ .inc_offset = SIRFSOC_CLKC_DISP1_DTO_INC,
+ .src_offset = SIRFSOC_CLKC_DISP1_DTO_SRC,
+ .hw = {
+ .init = &clk_disp1dto_init,
+ },
+};
+
+static struct atlas7_div_init_data divider_list[] __initdata = {
+ /* div_name, parent_name, gate_name, clk_flag, divider_flag, gate_flag, div_offset, shift, wdith, gate_offset, bit_enable, lock */
+ { "sys0pll_qa1", "sys0pll_fixdiv", "sys0pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 0, &usbphy_div_lock },
+ { "sys1pll_qa1", "sys1pll_fixdiv", "sys1pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 4, &usbphy_div_lock },
+ { "sys2pll_qa1", "sys2pll_fixdiv", "sys2pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 8, &usbphy_div_lock },
+ { "sys3pll_qa1", "sys3pll_fixdiv", "sys3pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 12, &usbphy_div_lock },
+ { "sys0pll_qa2", "sys0pll_fixdiv", "sys0pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 0, &btss_div_lock },
+ { "sys1pll_qa2", "sys1pll_fixdiv", "sys1pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 4, &btss_div_lock },
+ { "sys2pll_qa2", "sys2pll_fixdiv", "sys2pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 8, &btss_div_lock },
+ { "sys3pll_qa2", "sys3pll_fixdiv", "sys3pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 12, &btss_div_lock },
+ { "sys0pll_qa3", "sys0pll_fixdiv", "sys0pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 0, &rgmii_div_lock },
+ { "sys1pll_qa3", "sys1pll_fixdiv", "sys1pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 4, &rgmii_div_lock },
+ { "sys2pll_qa3", "sys2pll_fixdiv", "sys2pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 8, &rgmii_div_lock },
+ { "sys3pll_qa3", "sys3pll_fixdiv", "sys3pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 12, &rgmii_div_lock },
+ { "sys0pll_qa4", "sys0pll_fixdiv", "sys0pll_a4", 0, 0, 0, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 0, &cpu_div_lock },
+ { "sys1pll_qa4", "sys1pll_fixdiv", "sys1pll_a4", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 4, &cpu_div_lock },
+ { "sys0pll_qa5", "sys0pll_fixdiv", "sys0pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 0, &sdphy01_div_lock },
+ { "sys1pll_qa5", "sys1pll_fixdiv", "sys1pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 4, &sdphy01_div_lock },
+ { "sys2pll_qa5", "sys2pll_fixdiv", "sys2pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 8, &sdphy01_div_lock },
+ { "sys3pll_qa5", "sys3pll_fixdiv", "sys3pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 12, &sdphy01_div_lock },
+ { "sys0pll_qa6", "sys0pll_fixdiv", "sys0pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 0, &sdphy23_div_lock },
+ { "sys1pll_qa6", "sys1pll_fixdiv", "sys1pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 4, &sdphy23_div_lock },
+ { "sys2pll_qa6", "sys2pll_fixdiv", "sys2pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 8, &sdphy23_div_lock },
+ { "sys3pll_qa6", "sys3pll_fixdiv", "sys3pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 12, &sdphy23_div_lock },
+ { "sys0pll_qa7", "sys0pll_fixdiv", "sys0pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 0, &sdphy45_div_lock },
+ { "sys1pll_qa7", "sys1pll_fixdiv", "sys1pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 4, &sdphy45_div_lock },
+ { "sys2pll_qa7", "sys2pll_fixdiv", "sys2pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 8, &sdphy45_div_lock },
+ { "sys3pll_qa7", "sys3pll_fixdiv", "sys3pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 12, &sdphy45_div_lock },
+ { "sys0pll_qa8", "sys0pll_fixdiv", "sys0pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 0, &sdphy67_div_lock },
+ { "sys1pll_qa8", "sys1pll_fixdiv", "sys1pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 4, &sdphy67_div_lock },
+ { "sys2pll_qa8", "sys2pll_fixdiv", "sys2pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 8, &sdphy67_div_lock },
+ { "sys3pll_qa8", "sys3pll_fixdiv", "sys3pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 12, &sdphy67_div_lock },
+ { "sys0pll_qa9", "sys0pll_fixdiv", "sys0pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 0, &can_div_lock },
+ { "sys1pll_qa9", "sys1pll_fixdiv", "sys1pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 4, &can_div_lock },
+ { "sys2pll_qa9", "sys2pll_fixdiv", "sys2pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 8, &can_div_lock },
+ { "sys3pll_qa9", "sys3pll_fixdiv", "sys3pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 12, &can_div_lock },
+ { "sys0pll_qa10", "sys0pll_fixdiv", "sys0pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 0, &deint_div_lock },
+ { "sys1pll_qa10", "sys1pll_fixdiv", "sys1pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 4, &deint_div_lock },
+ { "sys2pll_qa10", "sys2pll_fixdiv", "sys2pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 8, &deint_div_lock },
+ { "sys3pll_qa10", "sys3pll_fixdiv", "sys3pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 12, &deint_div_lock },
+ { "sys0pll_qa11", "sys0pll_fixdiv", "sys0pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 0, &nand_div_lock },
+ { "sys1pll_qa11", "sys1pll_fixdiv", "sys1pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 4, &nand_div_lock },
+ { "sys2pll_qa11", "sys2pll_fixdiv", "sys2pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 8, &nand_div_lock },
+ { "sys3pll_qa11", "sys3pll_fixdiv", "sys3pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 12, &nand_div_lock },
+ { "sys0pll_qa12", "sys0pll_fixdiv", "sys0pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 0, &disp0_div_lock },
+ { "sys1pll_qa12", "sys1pll_fixdiv", "sys1pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 4, &disp0_div_lock },
+ { "sys2pll_qa12", "sys2pll_fixdiv", "sys2pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 8, &disp0_div_lock },
+ { "sys3pll_qa12", "sys3pll_fixdiv", "sys3pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 12, &disp0_div_lock },
+ { "sys0pll_qa13", "sys0pll_fixdiv", "sys0pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 0, &disp1_div_lock },
+ { "sys1pll_qa13", "sys1pll_fixdiv", "sys1pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 4, &disp1_div_lock },
+ { "sys2pll_qa13", "sys2pll_fixdiv", "sys2pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 8, &disp1_div_lock },
+ { "sys3pll_qa13", "sys3pll_fixdiv", "sys3pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 12, &disp1_div_lock },
+ { "sys0pll_qa14", "sys0pll_fixdiv", "sys0pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 0, &gpu_div_lock },
+ { "sys1pll_qa14", "sys1pll_fixdiv", "sys1pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 4, &gpu_div_lock },
+ { "sys2pll_qa14", "sys2pll_fixdiv", "sys2pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 8, &gpu_div_lock },
+ { "sys3pll_qa14", "sys3pll_fixdiv", "sys3pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 12, &gpu_div_lock },
+ { "sys0pll_qa15", "sys0pll_fixdiv", "sys0pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 0, &gnss_div_lock },
+ { "sys1pll_qa15", "sys1pll_fixdiv", "sys1pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 4, &gnss_div_lock },
+ { "sys2pll_qa15", "sys2pll_fixdiv", "sys2pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 8, &gnss_div_lock },
+ { "sys3pll_qa15", "sys3pll_fixdiv", "sys3pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 12, &gnss_div_lock },
+ { "sys1pll_qa18", "sys1pll_fixdiv", "sys1pll_a18", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 24, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 12, &share_div_lock },
+ { "sys1pll_qa19", "sys1pll_fixdiv", "sys1pll_a19", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 16, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 8, &share_div_lock },
+ { "sys1pll_qa20", "sys1pll_fixdiv", "sys1pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 4, &share_div_lock },
+ { "sys2pll_qa20", "sys2pll_fixdiv", "sys2pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 0, &share_div_lock },
+ { "sys1pll_qa17", "sys1pll_fixdiv", "sys1pll_a17", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 20, &share_div_lock },
+ { "sys0pll_qa20", "sys0pll_fixdiv", "sys0pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 16, &share_div_lock },
+};
+
+static const char * const i2s_clk_parents[] = {
+ "xin",
+ "xinw",
+ "audio_dto",
+ /* "pwm_i2s01" */
+};
+
+static const char * const usbphy_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a1",
+ "sys1pll_a1",
+ "sys2pll_a1",
+ "sys3pll_a1",
+};
+
+static const char * const btss_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a2",
+ "sys1pll_a2",
+ "sys2pll_a2",
+ "sys3pll_a2",
+};
+
+static const char * const rgmii_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a3",
+ "sys1pll_a3",
+ "sys2pll_a3",
+ "sys3pll_a3",
+};
+
+static const char * const cpu_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a4",
+ "sys1pll_a4",
+ "cpupll_clk1",
+};
+
+static const char * const sdphy01_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a5",
+ "sys1pll_a5",
+ "sys2pll_a5",
+ "sys3pll_a5",
+};
+
+static const char * const sdphy23_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a6",
+ "sys1pll_a6",
+ "sys2pll_a6",
+ "sys3pll_a6",
+};
+
+static const char * const sdphy45_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a7",
+ "sys1pll_a7",
+ "sys2pll_a7",
+ "sys3pll_a7",
+};
+
+static const char * const sdphy67_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a8",
+ "sys1pll_a8",
+ "sys2pll_a8",
+ "sys3pll_a8",
+};
+
+static const char * const can_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a9",
+ "sys1pll_a9",
+ "sys2pll_a9",
+ "sys3pll_a9",
+};
+
+static const char * const deint_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a10",
+ "sys1pll_a10",
+ "sys2pll_a10",
+ "sys3pll_a10",
+};
+
+static const char * const nand_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a11",
+ "sys1pll_a11",
+ "sys2pll_a11",
+ "sys3pll_a11",
+};
+
+static const char * const disp0_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a12",
+ "sys1pll_a12",
+ "sys2pll_a12",
+ "sys3pll_a12",
+ "disp0_dto",
+};
+
+static const char * const disp1_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a13",
+ "sys1pll_a13",
+ "sys2pll_a13",
+ "sys3pll_a13",
+ "disp1_dto",
+};
+
+static const char * const gpu_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a14",
+ "sys1pll_a14",
+ "sys2pll_a14",
+ "sys3pll_a14",
+};
+
+static const char * const gnss_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys0pll_a15",
+ "sys1pll_a15",
+ "sys2pll_a15",
+ "sys3pll_a15",
+};
+
+static const char * const sys_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const io_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const g2d_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const jpenc_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const vdec_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const gmac_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const usb_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const kas_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const sec_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const sdr_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const vip_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const nocd_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const nocr_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static const char * const tpiu_clk_parents[] = {
+ "xin",
+ "xinw",
+ "sys2pll_a20",
+ "sys1pll_a20",
+ "sys1pll_a19",
+ "sys1pll_a18",
+ "sys0pll_a20",
+ "sys1pll_a17",
+};
+
+static struct atlas7_mux_init_data mux_list[] __initdata = {
+ /* mux_name, parent_names, parent_num, flags, mux_flags, mux_offset, shift, width */
+ { "i2s_mux", i2s_clk_parents, ARRAY_SIZE(i2s_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 2 },
+ { "usbphy_mux", usbphy_clk_parents, ARRAY_SIZE(usbphy_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 3 },
+ { "btss_mux", btss_clk_parents, ARRAY_SIZE(btss_clk_parents), 0, 0, SIRFSOC_CLKC_BTSS_CLK_SEL, 0, 3 },
+ { "rgmii_mux", rgmii_clk_parents, ARRAY_SIZE(rgmii_clk_parents), 0, 0, SIRFSOC_CLKC_RGMII_CLK_SEL, 0, 3 },
+ { "cpu_mux", cpu_clk_parents, ARRAY_SIZE(cpu_clk_parents), 0, 0, SIRFSOC_CLKC_CPU_CLK_SEL, 0, 3 },
+ { "sdphy01_mux", sdphy01_clk_parents, ARRAY_SIZE(sdphy01_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY01_CLK_SEL, 0, 3 },
+ { "sdphy23_mux", sdphy23_clk_parents, ARRAY_SIZE(sdphy23_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY23_CLK_SEL, 0, 3 },
+ { "sdphy45_mux", sdphy45_clk_parents, ARRAY_SIZE(sdphy45_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY45_CLK_SEL, 0, 3 },
+ { "sdphy67_mux", sdphy67_clk_parents, ARRAY_SIZE(sdphy67_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY67_CLK_SEL, 0, 3 },
+ { "can_mux", can_clk_parents, ARRAY_SIZE(can_clk_parents), 0, 0, SIRFSOC_CLKC_CAN_CLK_SEL, 0, 3 },
+ { "deint_mux", deint_clk_parents, ARRAY_SIZE(deint_clk_parents), 0, 0, SIRFSOC_CLKC_DEINT_CLK_SEL, 0, 3 },
+ { "nand_mux", nand_clk_parents, ARRAY_SIZE(nand_clk_parents), 0, 0, SIRFSOC_CLKC_NAND_CLK_SEL, 0, 3 },
+ { "disp0_mux", disp0_clk_parents, ARRAY_SIZE(disp0_clk_parents), 0, 0, SIRFSOC_CLKC_DISP0_CLK_SEL, 0, 3 },
+ { "disp1_mux", disp1_clk_parents, ARRAY_SIZE(disp1_clk_parents), 0, 0, SIRFSOC_CLKC_DISP1_CLK_SEL, 0, 3 },
+ { "gpu_mux", gpu_clk_parents, ARRAY_SIZE(gpu_clk_parents), 0, 0, SIRFSOC_CLKC_GPU_CLK_SEL, 0, 3 },
+ { "gnss_mux", gnss_clk_parents, ARRAY_SIZE(gnss_clk_parents), 0, 0, SIRFSOC_CLKC_GNSS_CLK_SEL, 0, 3 },
+ { "sys_mux", sys_clk_parents, ARRAY_SIZE(sys_clk_parents), 0, 0, SIRFSOC_CLKC_SYS_CLK_SEL, 0, 3 },
+ { "io_mux", io_clk_parents, ARRAY_SIZE(io_clk_parents), 0, 0, SIRFSOC_CLKC_IO_CLK_SEL, 0, 3 },
+ { "g2d_mux", g2d_clk_parents, ARRAY_SIZE(g2d_clk_parents), 0, 0, SIRFSOC_CLKC_G2D_CLK_SEL, 0, 3 },
+ { "jpenc_mux", jpenc_clk_parents, ARRAY_SIZE(jpenc_clk_parents), 0, 0, SIRFSOC_CLKC_JPENC_CLK_SEL, 0, 3 },
+ { "vdec_mux", vdec_clk_parents, ARRAY_SIZE(vdec_clk_parents), 0, 0, SIRFSOC_CLKC_VDEC_CLK_SEL, 0, 3 },
+ { "gmac_mux", gmac_clk_parents, ARRAY_SIZE(gmac_clk_parents), 0, 0, SIRFSOC_CLKC_GMAC_CLK_SEL, 0, 3 },
+ { "usb_mux", usb_clk_parents, ARRAY_SIZE(usb_clk_parents), 0, 0, SIRFSOC_CLKC_USB_CLK_SEL, 0, 3 },
+ { "kas_mux", kas_clk_parents, ARRAY_SIZE(kas_clk_parents), 0, 0, SIRFSOC_CLKC_KAS_CLK_SEL, 0, 3 },
+ { "sec_mux", sec_clk_parents, ARRAY_SIZE(sec_clk_parents), 0, 0, SIRFSOC_CLKC_SEC_CLK_SEL, 0, 3 },
+ { "sdr_mux", sdr_clk_parents, ARRAY_SIZE(sdr_clk_parents), 0, 0, SIRFSOC_CLKC_SDR_CLK_SEL, 0, 3 },
+ { "vip_mux", vip_clk_parents, ARRAY_SIZE(vip_clk_parents), 0, 0, SIRFSOC_CLKC_VIP_CLK_SEL, 0, 3 },
+ { "nocd_mux", nocd_clk_parents, ARRAY_SIZE(nocd_clk_parents), 0, 0, SIRFSOC_CLKC_NOCD_CLK_SEL, 0, 3 },
+ { "nocr_mux", nocr_clk_parents, ARRAY_SIZE(nocr_clk_parents), 0, 0, SIRFSOC_CLKC_NOCR_CLK_SEL, 0, 3 },
+ { "tpiu_mux", tpiu_clk_parents, ARRAY_SIZE(tpiu_clk_parents), 0, 0, SIRFSOC_CLKC_TPIU_CLK_SEL, 0, 3 },
+};
+
+ /* new unit should add start from the tail of list */
+static struct atlas7_unit_init_data unit_list[] __initdata = {
+ /* unit_name, parent_name, flags, regofs, bit, lock */
+ { 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, &root0_gate_lock },
+ { 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, &root0_gate_lock },
+ { 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, &root0_gate_lock },
+ { 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, &root0_gate_lock },
+ { 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, &root0_gate_lock },
+ { 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, &root0_gate_lock },
+ { 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, &root0_gate_lock },
+ { 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, &root0_gate_lock },
+ { 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, &root0_gate_lock },
+ { 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, &root0_gate_lock },
+ { 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, &root0_gate_lock },
+ { 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, &root0_gate_lock },
+ { 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, &root0_gate_lock },
+ { 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, &root0_gate_lock },
+ { 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, &root0_gate_lock },
+ { 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, &root0_gate_lock },
+ { 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, &root0_gate_lock },
+ { 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, &root0_gate_lock },
+ { 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, &root0_gate_lock },
+ { 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, &root0_gate_lock },
+ { 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, &root0_gate_lock },
+ { 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, &root0_gate_lock },
+ { 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, &root0_gate_lock },
+ { 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, &root1_gate_lock },
+ { 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, &root1_gate_lock },
+ { 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, &root1_gate_lock },
+ { 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, &root1_gate_lock },
+ { 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, &root1_gate_lock },
+ { 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, &root1_gate_lock },
+ { 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, &root1_gate_lock },
+ { 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, &root1_gate_lock },
+ { 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, &root1_gate_lock },
+ { 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, &root1_gate_lock },
+ { 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, &root1_gate_lock },
+ { 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, &root1_gate_lock },
+ { 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, &root1_gate_lock },
+ { 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, &root1_gate_lock },
+ { 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, &root1_gate_lock },
+ { 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, &root1_gate_lock },
+ { 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, &root1_gate_lock },
+ { 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, &root1_gate_lock },
+ { 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, &root1_gate_lock },
+ { 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, &root1_gate_lock },
+ { 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, &root1_gate_lock },
+ { 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, &root1_gate_lock },
+ { 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, &root1_gate_lock },
+ { 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, &leaf1_gate_lock },
+ { 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, &leaf1_gate_lock },
+ { 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, &leaf1_gate_lock },
+ { 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, &leaf1_gate_lock },
+ { 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, &leaf1_gate_lock },
+ { 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, &leaf1_gate_lock },
+ { 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, &leaf1_gate_lock },
+ { 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, &leaf1_gate_lock },
+ { 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, &leaf1_gate_lock },
+ { 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, &leaf1_gate_lock },
+ { 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, &leaf1_gate_lock },
+ { 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, &leaf1_gate_lock },
+ { 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, &leaf1_gate_lock },
+ { 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, &leaf1_gate_lock },
+ { 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, &leaf1_gate_lock },
+ { 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, &leaf1_gate_lock },
+ { 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, &leaf1_gate_lock },
+ { 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, &leaf1_gate_lock },
+ { 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, &leaf1_gate_lock },
+ { 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, &leaf1_gate_lock },
+ { 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, &leaf2_gate_lock },
+ { 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, &leaf2_gate_lock },
+ { 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, &leaf2_gate_lock },
+ { 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, &leaf2_gate_lock },
+ { 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, &leaf2_gate_lock },
+ { 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, &leaf2_gate_lock },
+ { 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, &leaf2_gate_lock },
+ { 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, &leaf2_gate_lock },
+ { 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, &leaf2_gate_lock },
+ { 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, &leaf2_gate_lock },
+ { 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, &leaf2_gate_lock },
+ { 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, &leaf2_gate_lock },
+ { 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, &leaf2_gate_lock },
+ { 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, &leaf2_gate_lock },
+ { 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, &leaf2_gate_lock },
+ { 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, &leaf2_gate_lock },
+ { 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, &leaf2_gate_lock },
+ { 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, &leaf2_gate_lock },
+ { 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, &leaf2_gate_lock },
+ { 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, &leaf2_gate_lock },
+ { 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, &leaf3_gate_lock },
+ { 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, &leaf3_gate_lock },
+ { 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, &leaf3_gate_lock },
+ { 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, &leaf3_gate_lock },
+ { 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, &leaf3_gate_lock },
+ { 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, &leaf3_gate_lock },
+ { 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, &leaf3_gate_lock },
+ { 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, &leaf3_gate_lock },
+ { 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, &leaf3_gate_lock },
+ { 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, &leaf3_gate_lock },
+ { 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, &leaf3_gate_lock },
+ { 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, &leaf3_gate_lock },
+ { 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, &leaf3_gate_lock },
+ { 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, &leaf3_gate_lock },
+ { 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, &leaf3_gate_lock },
+ { 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, &leaf3_gate_lock },
+ { 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, &leaf4_gate_lock },
+ { 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, &leaf4_gate_lock },
+ { 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, &leaf4_gate_lock },
+ { 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, &leaf4_gate_lock },
+ { 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, &leaf4_gate_lock },
+ { 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, &leaf4_gate_lock },
+ { 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, &leaf4_gate_lock },
+ { 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, &leaf4_gate_lock },
+ { 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, &leaf4_gate_lock },
+ { 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, &leaf4_gate_lock },
+ { 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, &leaf4_gate_lock },
+ { 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, &leaf4_gate_lock },
+ { 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, &leaf4_gate_lock },
+ { 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, &leaf4_gate_lock },
+ { 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, &leaf4_gate_lock },
+ { 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, &leaf4_gate_lock },
+ { 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, &leaf5_gate_lock },
+ { 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, &leaf5_gate_lock },
+ { 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, &leaf5_gate_lock },
+ { 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, &leaf5_gate_lock },
+ { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
+ { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
+ { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
+ { 125, "thcpum_cpudiv4", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
+ { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
+ { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
+ { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
+ { 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, &leaf8_gate_lock },
+ { 130, "dmac4_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, &leaf8_gate_lock },
+ { 131, "uart6_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, &leaf8_gate_lock },
+ { 132, "usp3_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, &leaf8_gate_lock },
+ { 133, "a7ca_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, &leaf8_gate_lock },
+ { 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, &leaf8_gate_lock },
+ { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
+ { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
+ { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
+};
+
+static struct clk *atlas7_clks[ARRAY_SIZE(unit_list)];
+
+static int unit_clk_is_enabled(struct clk_hw *hw)
+{
+ struct clk_unit *clk = to_unitclk(hw);
+ u32 reg;
+
+ reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_STAT - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+ return !!(clkc_readl(reg) & BIT(clk->bit));
+}
+
+static int unit_clk_enable(struct clk_hw *hw)
+{
+ u32 reg;
+ struct clk_unit *clk = to_unitclk(hw);
+ unsigned long flags;
+
+ reg = clk->regofs;
+
+ spin_lock_irqsave(clk->lock, flags);
+ clkc_writel(BIT(clk->bit), reg);
+ spin_unlock_irqrestore(clk->lock, flags);
+ return 0;
+}
+
+static void unit_clk_disable(struct clk_hw *hw)
+{
+ u32 reg;
+ struct clk_unit *clk = to_unitclk(hw);
+ unsigned long flags;
+
+ reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+ spin_lock_irqsave(clk->lock, flags);
+ clkc_writel(BIT(clk->bit), reg);
+ spin_unlock_irqrestore(clk->lock, flags);
+}
+
+static const struct clk_ops unit_clk_ops = {
+ .is_enabled = unit_clk_is_enabled,
+ .enable = unit_clk_enable,
+ .disable = unit_clk_disable,
+};
+
+static struct clk * __init
+atlas7_unit_clk_register(struct device *dev, const char *name,
+ const char * const parent_name, unsigned long flags,
+ u32 regofs, u8 bit, spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_unit *unit;
+ struct clk_init_data init;
+
+ unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+ if (!unit)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.ops = &unit_clk_ops;
+ init.flags = flags;
+
+ unit->hw.init = &init;
+ unit->regofs = regofs;
+ unit->bit = bit;
+ unit->lock = lock;
+
+ clk = clk_register(dev, &unit->hw);
+ if (IS_ERR(clk))
+ kfree(unit);
+
+ return clk;
+}
+
+static struct atlas7_reset_desc atlas7_reset_unit[] = {
+ { "PWM", 0x0244, 0, 0x0320, 0, &leaf0_gate_lock }, /* 0-5 */
+ { "THCGUM", 0x0244, 3, 0x0320, 1, &leaf0_gate_lock },
+ { "CVD", 0x04A0, 0, 0x032C, 0, &leaf1_gate_lock },
+ { "TIMER", 0x04A0, 1, 0x032C, 1, &leaf1_gate_lock },
+ { "PULSEC", 0x04A0, 2, 0x032C, 2, &leaf1_gate_lock },
+ { "TSC", 0x04A0, 3, 0x032C, 3, &leaf1_gate_lock },
+ { "IOCTOP", 0x04A0, 4, 0x032C, 4, &leaf1_gate_lock }, /* 6-10 */
+ { "RSC", 0x04A0, 5, 0x032C, 5, &leaf1_gate_lock },
+ { "DVM", 0x04A0, 6, 0x032C, 6, &leaf1_gate_lock },
+ { "LVDS", 0x04A0, 7, 0x032C, 7, &leaf1_gate_lock },
+ { "KAS", 0x04A0, 8, 0x032C, 8, &leaf1_gate_lock },
+ { "AC97", 0x04A0, 9, 0x032C, 9, &leaf1_gate_lock }, /* 11-15 */
+ { "USP0", 0x04A0, 10, 0x032C, 10, &leaf1_gate_lock },
+ { "USP1", 0x04A0, 11, 0x032C, 11, &leaf1_gate_lock },
+ { "USP2", 0x04A0, 12, 0x032C, 12, &leaf1_gate_lock },
+ { "DMAC2", 0x04A0, 13, 0x032C, 13, &leaf1_gate_lock },
+ { "DMAC3", 0x04A0, 14, 0x032C, 14, &leaf1_gate_lock }, /* 16-20 */
+ { "AUDIO", 0x04A0, 15, 0x032C, 15, &leaf1_gate_lock },
+ { "I2S1", 0x04A0, 17, 0x032C, 16, &leaf1_gate_lock },
+ { "PMU_AUDIO", 0x04A0, 22, 0x032C, 17, &leaf1_gate_lock },
+ { "THAUDMSCM", 0x04A0, 23, 0x032C, 18, &leaf1_gate_lock },
+ { "SYS2PCI", 0x04B8, 0, 0x0338, 0, &leaf2_gate_lock }, /* 21-25 */
+ { "PCIARB", 0x04B8, 1, 0x0338, 1, &leaf2_gate_lock },
+ { "PCICOPY", 0x04B8, 2, 0x0338, 2, &leaf2_gate_lock },
+ { "ROM", 0x04B8, 3, 0x0338, 3, &leaf2_gate_lock },
+ { "SDIO23", 0x04B8, 4, 0x0338, 4, &leaf2_gate_lock },
+ { "SDIO45", 0x04B8, 5, 0x0338, 5, &leaf2_gate_lock }, /* 26-30 */
+ { "SDIO67", 0x04B8, 6, 0x0338, 6, &leaf2_gate_lock },
+ { "VIP1", 0x04B8, 7, 0x0338, 7, &leaf2_gate_lock },
+ { "VPP0", 0x04B8, 11, 0x0338, 8, &leaf2_gate_lock },
+ { "LCD0", 0x04B8, 12, 0x0338, 9, &leaf2_gate_lock },
+ { "VPP1", 0x04B8, 13, 0x0338, 10, &leaf2_gate_lock }, /* 31-35 */
+ { "LCD1", 0x04B8, 14, 0x0338, 11, &leaf2_gate_lock },
+ { "DCU", 0x04B8, 15, 0x0338, 12, &leaf2_gate_lock },
+ { "GPIO", 0x04B8, 18, 0x0338, 13, &leaf2_gate_lock },
+ { "DAPA_VDIFM", 0x04B8, 17, 0x0338, 15, &leaf2_gate_lock },
+ { "THVDIFM", 0x04B8, 19, 0x0338, 16, &leaf2_gate_lock }, /* 36-40 */
+ { "RGMII", 0x04D0, 0, 0x0344, 0, &leaf3_gate_lock },
+ { "GMAC", 0x04D0, 1, 0x0344, 1, &leaf3_gate_lock },
+ { "UART1", 0x04D0, 2, 0x0344, 2, &leaf3_gate_lock },
+ { "DMAC0", 0x04D0, 3, 0x0344, 3, &leaf3_gate_lock },
+ { "UART0", 0x04D0, 4, 0x0344, 4, &leaf3_gate_lock }, /* 41-45 */
+ { "UART2", 0x04D0, 5, 0x0344, 5, &leaf3_gate_lock },
+ { "UART3", 0x04D0, 6, 0x0344, 6, &leaf3_gate_lock },
+ { "UART4", 0x04D0, 7, 0x0344, 7, &leaf3_gate_lock },
+ { "UART5", 0x04D0, 8, 0x0344, 8, &leaf3_gate_lock },
+ { "SPI1", 0x04D0, 9, 0x0344, 9, &leaf3_gate_lock }, /* 46-50 */
+ { "GNSS_SYS_M0", 0x04D0, 10, 0x0344, 10, &leaf3_gate_lock },
+ { "CANBUS1", 0x04D0, 12, 0x0344, 11, &leaf3_gate_lock },
+ { "CCSEC", 0x04D0, 15, 0x0344, 12, &leaf3_gate_lock },
+ { "CCPUB", 0x04D0, 16, 0x0344, 13, &leaf3_gate_lock },
+ { "DAPA_GNSSM", 0x04D0, 13, 0x0344, 14, &leaf3_gate_lock }, /* 51-55 */
+ { "THGNSSM", 0x04D0, 14, 0x0344, 15, &leaf3_gate_lock },
+ { "VDEC", 0x04E8, 0, 0x0350, 0, &leaf4_gate_lock },
+ { "JPENC", 0x04E8, 1, 0x0350, 1, &leaf4_gate_lock },
+ { "G2D", 0x04E8, 2, 0x0350, 2, &leaf4_gate_lock },
+ { "I2C0", 0x04E8, 3, 0x0350, 3, &leaf4_gate_lock }, /* 56-60 */
+ { "I2C1", 0x04E8, 4, 0x0350, 4, &leaf4_gate_lock },
+ { "GPIO0", 0x04E8, 5, 0x0350, 5, &leaf4_gate_lock },
+ { "NAND", 0x04E8, 6, 0x0350, 6, &leaf4_gate_lock },
+ { "SDIO01", 0x04E8, 7, 0x0350, 7, &leaf4_gate_lock },
+ { "SYS2PCI2", 0x04E8, 8, 0x0350, 8, &leaf4_gate_lock }, /* 61-65 */
+ { "USB0", 0x04E8, 11, 0x0350, 9, &leaf4_gate_lock },
+ { "USB1", 0x04E8, 12, 0x0350, 10, &leaf4_gate_lock },
+ { "THMEDIAM", 0x04E8, 15, 0x0350, 11, &leaf4_gate_lock },
+ { "MEMC_DDRPHY", 0x0500, 0, 0x035C, 0, &leaf5_gate_lock },
+ { "MEMC_UPCTL", 0x0500, 0, 0x035C, 1, &leaf5_gate_lock }, /* 66-70 */
+ { "DAPA_MEM", 0x0500, 1, 0x035C, 2, &leaf5_gate_lock },
+ { "MEMC_MEMDIV", 0x0500, 0, 0x035C, 3, &leaf5_gate_lock },
+ { "THDDRM", 0x0500, 3, 0x035C, 4, &leaf5_gate_lock },
+ { "CORESIGHT", 0x0518, 3, 0x0368, 13, &leaf6_gate_lock },
+ { "THCPUM", 0x0518, 4, 0x0368, 17, &leaf6_gate_lock }, /* 71-75 */
+ { "GRAPHIC", 0x0530, 0, 0x0374, 0, &leaf7_gate_lock },
+ { "VSS_SDR", 0x0530, 1, 0x0374, 1, &leaf7_gate_lock },
+ { "THGPUM", 0x0530, 2, 0x0374, 2, &leaf7_gate_lock },
+ { "DMAC4", 0x0548, 2, 0x0380, 1, &leaf8_gate_lock },
+ { "UART6", 0x0548, 3, 0x0380, 2, &leaf8_gate_lock }, /* 76- */
+ { "USP3", 0x0548, 4, 0x0380, 3, &leaf8_gate_lock },
+ { "THBTM", 0x0548, 5, 0x0380, 5, &leaf8_gate_lock },
+ { "A7CA", 0x0548, 1, 0x0380, 0, &leaf8_gate_lock },
+ { "A7CA_APB", 0x0548, 5, 0x0380, 4, &leaf8_gate_lock },
+};
+
+static int atlas7_reset_module(struct reset_controller_dev *rcdev,
+ unsigned long reset_idx)
+{
+ struct atlas7_reset_desc *reset = &atlas7_reset_unit[reset_idx];
+ unsigned long flags;
+
+ /*
+ * HW suggest unit reset sequence:
+ * assert sw reset (0)
+ * setting sw clk_en to if the clock was disabled before reset
+ * delay 16 clocks
+ * disable clock (sw clk_en = 0)
+ * de-assert reset (1)
+ * after this sequence, restore clock or not is decided by SW
+ */
+
+ spin_lock_irqsave(reset->lock, flags);
+ /* clock enable or not */
+ if (clkc_readl(reset->clk_ofs + 8) & (1 << reset->clk_bit)) {
+ clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+ udelay(2);
+ clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+ clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+ /* restore clock enable */
+ clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+ } else {
+ clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+ clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+ udelay(2);
+ clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+ clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+ }
+ spin_unlock_irqrestore(reset->lock, flags);
+
+ return 0;
+}
+
+static struct reset_control_ops atlas7_rst_ops = {
+ .reset = atlas7_reset_module,
+};
+
+static struct reset_controller_dev atlas7_rst_ctlr = {
+ .ops = &atlas7_rst_ops,
+ .owner = THIS_MODULE,
+ .of_reset_n_cells = 1,
+};
+
+static void __init atlas7_clk_init(struct device_node *np)
+{
+ struct clk *clk;
+ struct atlas7_div_init_data *div;
+ struct atlas7_mux_init_data *mux;
+ struct atlas7_unit_init_data *unit;
+ int i;
+ int ret;
+
+ sirfsoc_clk_vbase = of_iomap(np, 0);
+ if (!sirfsoc_clk_vbase)
+ panic("unable to map clkc registers\n");
+
+ of_node_put(np);
+
+ clk = clk_register(NULL, &clk_cpupll.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_mempll.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_sys0pll.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_sys1pll.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_sys2pll.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_sys3pll.hw);
+ BUG_ON(!clk);
+
+ clk = clk_register_divider_table(NULL, "cpupll_div1", "cpupll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "cpupll_div2", "cpupll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "cpupll_div3", "cpupll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_divider_table(NULL, "mempll_div1", "mempll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "mempll_div2", "mempll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "mempll_div3", "mempll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_divider_table(NULL, "sys0pll_div1", "sys0pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys0pll_div2", "sys0pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys0pll_div3", "sys0pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_fixed_factor(NULL, "sys0pll_fixdiv", "sys0pll_vco",
+ CLK_SET_RATE_PARENT, 1, 2);
+
+ clk = clk_register_divider_table(NULL, "sys1pll_div1", "sys1pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys1pll_div2", "sys1pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys1pll_div3", "sys1pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_fixed_factor(NULL, "sys1pll_fixdiv", "sys1pll_vco",
+ CLK_SET_RATE_PARENT, 1, 2);
+
+ clk = clk_register_divider_table(NULL, "sys2pll_div1", "sys2pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys2pll_div2", "sys2pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys2pll_div3", "sys2pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_fixed_factor(NULL, "sys2pll_fixdiv", "sys2pll_vco",
+ CLK_SET_RATE_PARENT, 1, 2);
+
+ clk = clk_register_divider_table(NULL, "sys3pll_div1", "sys3pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 0, 3, 0,
+ pll_div_table, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys3pll_div2", "sys3pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 4, 3, 0,
+ pll_div_table, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_divider_table(NULL, "sys3pll_div3", "sys3pll_vco", 0,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 8, 3, 0,
+ pll_div_table, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_fixed_factor(NULL, "sys3pll_fixdiv", "sys3pll_vco",
+ CLK_SET_RATE_PARENT, 1, 2);
+
+ BUG_ON(!clk);
+ clk = clk_register_fixed_factor(NULL, "xinw_fixdiv_btslow", "xinw",
+ CLK_SET_RATE_PARENT, 1, 4);
+
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "cpupll_clk1", "cpupll_div1",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+ 12, 0, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "cpupll_clk2", "cpupll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+ 13, 0, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "cpupll_clk3", "cpupll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+ 14, 0, &cpupll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_gate(NULL, "mempll_clk1", "mempll_div1",
+ CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+ 12, 0, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "mempll_clk2", "mempll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+ 13, 0, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "mempll_clk3", "mempll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+ 14, 0, &mempll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_gate(NULL, "sys0pll_clk1", "sys0pll_div1",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+ 12, 0, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys0pll_clk2", "sys0pll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+ 13, 0, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys0pll_clk3", "sys0pll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+ 14, 0, &sys0pll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_gate(NULL, "sys1pll_clk1", "sys1pll_div1",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+ 12, 0, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys1pll_clk2", "sys1pll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+ 13, 0, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys1pll_clk3", "sys1pll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+ 14, 0, &sys1pll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_gate(NULL, "sys2pll_clk1", "sys2pll_div1",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+ 12, 0, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys2pll_clk2", "sys2pll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+ 13, 0, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys2pll_clk3", "sys2pll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+ 14, 0, &sys2pll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register_gate(NULL, "sys3pll_clk1", "sys3pll_div1",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+ 12, 0, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys3pll_clk2", "sys3pll_div2",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+ 13, 0, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, "sys3pll_clk3", "sys3pll_div3",
+ CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+ 14, 0, &sys3pll_ctrl1_lock);
+ BUG_ON(!clk);
+
+ clk = clk_register(NULL, &clk_audio_dto.hw);
+ BUG_ON(!clk);
+
+ clk = clk_register(NULL, &clk_disp0_dto.hw);
+ BUG_ON(!clk);
+
+ clk = clk_register(NULL, &clk_disp1_dto.hw);
+ BUG_ON(!clk);
+
+ for (i = 0; i < ARRAY_SIZE(divider_list); i++) {
+ div = &divider_list[i];
+ clk = clk_register_divider(NULL, div->div_name,
+ div->parent_name, div->divider_flags, sirfsoc_clk_vbase + div->div_offset,
+ div->shift, div->width, 0, div->lock);
+ BUG_ON(!clk);
+ clk = clk_register_gate(NULL, div->gate_name, div->div_name,
+ div->gate_flags, sirfsoc_clk_vbase + div->gate_offset,
+ div->gate_bit, 0, div->lock);
+ BUG_ON(!clk);
+ }
+ /* ignore selector status register check */
+ for (i = 0; i < ARRAY_SIZE(mux_list); i++) {
+ mux = &mux_list[i];
+ clk = clk_register_mux(NULL, mux->mux_name, mux->parent_names,
+ mux->parent_num, mux->flags,
+ sirfsoc_clk_vbase + mux->mux_offset,
+ mux->shift, mux->width,
+ mux->mux_flags, NULL);
+ BUG_ON(!clk);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
+ unit = &unit_list[i];
+ atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
+ unit->flags, unit->regofs, unit->bit, unit->lock);
+ BUG_ON(!atlas7_clks[i]);
+ }
+
+ clk_data.clks = atlas7_clks;
+ clk_data.clk_num = ARRAY_SIZE(unit_list);
+
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ BUG_ON(ret);
+
+ atlas7_rst_ctlr.of_node = np;
+ atlas7_rst_ctlr.nr_resets = ARRAY_SIZE(atlas7_reset_unit);
+ reset_controller_register(&atlas7_rst_ctlr);
+}
+CLK_OF_DECLARE(atlas7_clk, "sirf,atlas7-car", atlas7_clk_init);
diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c
index 37af51c5f213..9fc285d784d3 100644
--- a/drivers/clk/sirf/clk-common.c
+++ b/drivers/clk/sirf/clk-common.c
@@ -10,8 +10,8 @@
#define KHZ 1000
#define MHZ (KHZ * KHZ)
-static void *sirfsoc_clk_vbase;
-static void *sirfsoc_rsc_vbase;
+static void __iomem *sirfsoc_clk_vbase;
+static void __iomem *sirfsoc_rsc_vbase;
static struct clk_onecell_data clk_data;
/*
@@ -188,7 +188,7 @@ static struct clk_ops std_pll_ops = {
.set_rate = pll_clk_set_rate,
};
-static const char *pll_clk_parents[] = {
+static const char * const pll_clk_parents[] = {
"osc",
};
@@ -284,7 +284,7 @@ static struct clk_hw usb_pll_clk_hw = {
* clock domains - cpu, mem, sys/io, dsp, gfx
*/
-static const char *dmn_clk_parents[] = {
+static const char * const dmn_clk_parents[] = {
"rtc",
"osc",
"pll1",
@@ -673,7 +673,7 @@ static void std_clk_disable(struct clk_hw *hw)
clkc_writel(val, reg);
}
-static const char *std_clk_io_parents[] = {
+static const char * const std_clk_io_parents[] = {
"io",
};
@@ -949,7 +949,7 @@ static struct clk_std clk_pulse = {
},
};
-static const char *std_clk_dsp_parents[] = {
+static const char * const std_clk_dsp_parents[] = {
"dsp",
};
@@ -981,7 +981,7 @@ static struct clk_std clk_mf = {
},
};
-static const char *std_clk_sys_parents[] = {
+static const char * const std_clk_sys_parents[] = {
"sys",
};
@@ -999,7 +999,7 @@ static struct clk_std clk_security = {
},
};
-static const char *std_clk_usb_parents[] = {
+static const char * const std_clk_usb_parents[] = {
"usb_pll",
};
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 7e2d15a0c7b8..d8bb239753a4 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -2,3 +2,4 @@ obj-y += clk.o
obj-y += clk-gate.o
obj-y += clk-pll.o
obj-y += clk-periph.o
+obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
new file mode 100644
index 000000000000..83c6780ff4b2
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 Altera 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/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#include "clk.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+/* SDMMC Group for System Manager defines */
+#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 div = 1, val;
+
+ if (socfpgaclk->fixed_div)
+ div = socfpgaclk->fixed_div;
+ else if (socfpgaclk->div_reg) {
+ val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+ val &= div_mask(socfpgaclk->width);
+ div = (1 << val);
+ }
+
+ return parent_rate / div;
+}
+
+static int socfpga_clk_prepare(struct clk_hw *hwclk)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ int i;
+ u32 hs_timing;
+ u32 clk_phase[2];
+
+ if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
+ for (i = 0; i < ARRAY_SIZE(clk_phase); i++) {
+ switch (socfpgaclk->clk_phase[i]) {
+ case 0:
+ clk_phase[i] = 0;
+ break;
+ case 45:
+ clk_phase[i] = 1;
+ break;
+ case 90:
+ clk_phase[i] = 2;
+ break;
+ case 135:
+ clk_phase[i] = 3;
+ break;
+ case 180:
+ clk_phase[i] = 4;
+ break;
+ case 225:
+ clk_phase[i] = 5;
+ break;
+ case 270:
+ clk_phase[i] = 6;
+ break;
+ case 315:
+ clk_phase[i] = 7;
+ break;
+ default:
+ clk_phase[i] = 0;
+ break;
+ }
+ }
+
+ hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+ if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
+ regmap_write(socfpgaclk->sys_mgr_base_addr,
+ SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);
+ else
+ pr_err("%s: cannot set clk_phase because sys_mgr_base_addr is not available!\n",
+ __func__);
+ }
+ return 0;
+}
+
+static struct clk_ops gateclk_ops = {
+ .prepare = socfpga_clk_prepare,
+ .recalc_rate = socfpga_gate_clk_recalc_rate,
+};
+
+static void __init __socfpga_gate_init(struct device_node *node,
+ const struct clk_ops *ops)
+{
+ u32 clk_gate[2];
+ u32 div_reg[3];
+ u32 clk_phase[2];
+ u32 fixed_div;
+ struct clk *clk;
+ struct socfpga_gate_clk *socfpga_clk;
+ const char *clk_name = node->name;
+ const char *parent_name[SOCFPGA_MAX_PARENTS];
+ struct clk_init_data init;
+ int rc;
+ int i = 0;
+
+ socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+ if (WARN_ON(!socfpga_clk))
+ return;
+
+ rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
+ if (rc)
+ clk_gate[0] = 0;
+
+ if (clk_gate[0]) {
+ socfpga_clk->hw.reg = clk_mgr_a10_base_addr + clk_gate[0];
+ socfpga_clk->hw.bit_idx = clk_gate[1];
+
+ gateclk_ops.enable = clk_gate_ops.enable;
+ gateclk_ops.disable = clk_gate_ops.disable;
+ }
+
+ rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+ if (rc)
+ socfpga_clk->fixed_div = 0;
+ else
+ socfpga_clk->fixed_div = fixed_div;
+
+ rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+ if (!rc) {
+ socfpga_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+ socfpga_clk->shift = div_reg[1];
+ socfpga_clk->width = div_reg[2];
+ } else {
+ socfpga_clk->div_reg = NULL;
+ }
+
+ rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
+ if (!rc) {
+ socfpga_clk->clk_phase[0] = clk_phase[0];
+ socfpga_clk->clk_phase[1] = clk_phase[1];
+
+ socfpga_clk->sys_mgr_base_addr =
+ syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+ if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
+ pr_err("%s: failed to find altr,sys-mgr regmap!\n",
+ __func__);
+ return;
+ }
+ }
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ init.name = clk_name;
+ init.ops = ops;
+ init.flags = 0;
+ while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
+ of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+ init.parent_names = parent_name;
+ init.num_parents = i;
+ socfpga_clk->hw.hw.init = &init;
+
+ clk = clk_register(NULL, &socfpga_clk->hw.hw);
+ if (WARN_ON(IS_ERR(clk))) {
+ kfree(socfpga_clk);
+ return;
+ }
+ rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ if (WARN_ON(rc))
+ return;
+}
+
+void __init socfpga_a10_gate_init(struct device_node *node)
+{
+ __socfpga_gate_init(node, &gateclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index dd3a78c64795..82449cd76fd7 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -32,14 +32,10 @@
#define SOCFPGA_MMC_CLK "sdmmc_clk"
#define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
/* SDMMC Group for System Manager defines */
#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108
-#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
- ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
{
@@ -194,7 +190,6 @@ static void __init __socfpga_gate_init(struct device_node *node,
const char *parent_name[SOCFPGA_MAX_PARENTS];
struct clk_init_data init;
int rc;
- int i = 0;
socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
if (WARN_ON(!socfpga_clk))
@@ -224,7 +219,7 @@ static void __init __socfpga_gate_init(struct device_node *node,
socfpga_clk->shift = div_reg[1];
socfpga_clk->width = div_reg[2];
} else {
- socfpga_clk->div_reg = 0;
+ socfpga_clk->div_reg = NULL;
}
rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
@@ -238,12 +233,9 @@ static void __init __socfpga_gate_init(struct device_node *node,
init.name = clk_name;
init.ops = ops;
init.flags = 0;
- while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
- of_clk_get_parent_name(node, i)) != NULL)
- i++;
+ init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
init.parent_names = parent_name;
- init.num_parents = i;
socfpga_clk->hw.hw.init = &init;
clk = clk_register(NULL, &socfpga_clk->hw.hw);
diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c
new file mode 100644
index 000000000000..9d0181b5a6a4
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-a10.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Altera 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/io.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT 16
+#define CLK_MGR_FREE_MASK 0x7
+
+#define SOCFPGA_MPU_FREE_CLK "mpu_free_clk"
+#define SOCFPGA_NOC_FREE_CLK "noc_free_clk"
+#define SOCFPGA_SDMMC_FREE_CLK "sdmmc_free_clk"
+#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+ u32 div;
+
+ if (socfpgaclk->fixed_div) {
+ div = socfpgaclk->fixed_div;
+ } else if (socfpgaclk->div_reg) {
+ div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+ div &= div_mask(socfpgaclk->width);
+ div += 1;
+ } else {
+ div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+ }
+
+ return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+ u32 clk_src;
+
+ clk_src = readl(socfpgaclk->hw.reg);
+ if (streq(hwclk->init->name, SOCFPGA_MPU_FREE_CLK) ||
+ streq(hwclk->init->name, SOCFPGA_NOC_FREE_CLK) ||
+ streq(hwclk->init->name, SOCFPGA_SDMMC_FREE_CLK))
+ return (clk_src >> CLK_MGR_FREE_SHIFT) &
+ CLK_MGR_FREE_MASK;
+ else
+ return 0;
+}
+
+static const struct clk_ops periclk_ops = {
+ .recalc_rate = clk_periclk_recalc_rate,
+ .get_parent = clk_periclk_get_parent,
+};
+
+static __init void __socfpga_periph_init(struct device_node *node,
+ const struct clk_ops *ops)
+{
+ u32 reg;
+ struct clk *clk;
+ struct socfpga_periph_clk *periph_clk;
+ const char *clk_name = node->name;
+ const char *parent_name;
+ struct clk_init_data init;
+ int rc;
+ u32 fixed_div;
+ u32 div_reg[3];
+
+ of_property_read_u32(node, "reg", &reg);
+
+ periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+ if (WARN_ON(!periph_clk))
+ return;
+
+ periph_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+ rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+ if (!rc) {
+ periph_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+ periph_clk->shift = div_reg[1];
+ periph_clk->width = div_reg[2];
+ } else {
+ periph_clk->div_reg = NULL;
+ }
+
+ rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+ if (rc)
+ periph_clk->fixed_div = 0;
+ else
+ periph_clk->fixed_div = fixed_div;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ init.name = clk_name;
+ init.ops = ops;
+ init.flags = 0;
+
+ parent_name = of_clk_get_parent_name(node, 0);
+ init.num_parents = 1;
+ init.parent_names = &parent_name;
+
+ periph_clk->hw.hw.init = &init;
+
+ clk = clk_register(NULL, &periph_clk->hw.hw);
+ if (WARN_ON(IS_ERR(clk))) {
+ kfree(periph_clk);
+ return;
+ }
+ rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ if (rc < 0) {
+ pr_err("Could not register clock provider for node:%s\n",
+ clk_name);
+ goto err_clk;
+ }
+
+ return;
+
+err_clk:
+ clk_unregister(clk);
+}
+
+void __init socfpga_a10_periph_init(struct device_node *node)
+{
+ __socfpga_periph_init(node, &periclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
index 46531c34ec9b..83aeaa219d14 100644
--- a/drivers/clk/socfpga/clk-periph.c
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -76,7 +76,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
periph_clk->shift = div_reg[1];
periph_clk->width = div_reg[2];
} else {
- periph_clk->div_reg = 0;
+ periph_clk->div_reg = NULL;
}
rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c
new file mode 100644
index 000000000000..1178b11babca
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-a10.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 Altera 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/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT 8
+#define CLK_MGR_PLL_CLK_SRC_MASK 0x3
+
+/* Clock bypass bits */
+#define SOCFPGA_PLL_BG_PWRDWN 0
+#define SOCFPGA_PLL_PWR_DOWN 1
+#define SOCFPGA_PLL_EXT_ENA 2
+#define SOCFPGA_PLL_DIVF_MASK 0x00001FFF
+#define SOCFPGA_PLL_DIVF_SHIFT 0
+#define SOCFPGA_PLL_DIVQ_MASK 0x003F0000
+#define SOCFPGA_PLL_DIVQ_SHIFT 16
+#define SOCFGPA_MAX_PARENTS 5
+
+#define SOCFPGA_MAIN_PLL_CLK "main_pll"
+#define SOCFPGA_PERIP_PLL_CLK "periph_pll"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+void __iomem *clk_mgr_a10_base_addr;
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ unsigned long divf, divq, reg;
+ unsigned long long vco_freq;
+
+ /* read VCO1 reg for numerator and denominator */
+ reg = readl(socfpgaclk->hw.reg + 0x4);
+ divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
+ divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
+ vco_freq = (unsigned long long)parent_rate * (divf + 1);
+ do_div(vco_freq, (1 + divq));
+ return (unsigned long)vco_freq;
+}
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ u32 pll_src;
+
+ pll_src = readl(socfpgaclk->hw.reg);
+
+ return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+ CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static struct clk_ops clk_pll_ops = {
+ .recalc_rate = clk_pll_recalc_rate,
+ .get_parent = clk_pll_get_parent,
+};
+
+static struct __init clk * __socfpga_pll_init(struct device_node *node,
+ const struct clk_ops *ops)
+{
+ u32 reg;
+ struct clk *clk;
+ struct socfpga_pll *pll_clk;
+ const char *clk_name = node->name;
+ const char *parent_name[SOCFGPA_MAX_PARENTS];
+ struct clk_init_data init;
+ struct device_node *clkmgr_np;
+ int rc;
+ int i = 0;
+
+ of_property_read_u32(node, "reg", &reg);
+
+ pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+ if (WARN_ON(!pll_clk))
+ return NULL;
+
+ clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
+ clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0);
+ BUG_ON(!clk_mgr_a10_base_addr);
+ pll_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ init.name = clk_name;
+ init.ops = ops;
+ init.flags = 0;
+
+ while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
+ of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+ init.num_parents = i;
+ init.parent_names = parent_name;
+ pll_clk->hw.hw.init = &init;
+
+ pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
+ clk_pll_ops.enable = clk_gate_ops.enable;
+ clk_pll_ops.disable = clk_gate_ops.disable;
+
+ clk = clk_register(NULL, &pll_clk->hw.hw);
+ if (WARN_ON(IS_ERR(clk))) {
+ kfree(pll_clk);
+ return NULL;
+ }
+ rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ return clk;
+}
+
+void __init socfpga_a10_pll_init(struct device_node *node)
+{
+ __socfpga_pll_init(node, &clk_pll_ops);
+}
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
index de6da957a09d..8f26b5234947 100644
--- a/drivers/clk/socfpga/clk-pll.c
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -92,7 +92,6 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
struct clk_init_data init;
struct device_node *clkmgr_np;
int rc;
- int i = 0;
of_property_read_u32(node, "reg", &reg);
@@ -111,11 +110,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
init.ops = ops;
init.flags = 0;
- while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
- of_clk_get_parent_name(node, i)) != NULL)
- i++;
-
- init.num_parents = i;
+ init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
init.parent_names = parent_name;
pll_clk->hw.hw.init = &init;
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 43db947e5f0e..7564d2e35f32 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -24,4 +24,9 @@
CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init);
CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init);
CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init);
-
+CLK_OF_DECLARE(socfpga_a10_pll_clk, "altr,socfpga-a10-pll-clock",
+ socfpga_a10_pll_init);
+CLK_OF_DECLARE(socfpga_a10_perip_clk, "altr,socfpga-a10-perip-clk",
+ socfpga_a10_periph_init);
+CLK_OF_DECLARE(socfpga_a10_gate_clk, "altr,socfpga-a10-gate-clk",
+ socfpga_a10_gate_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index d291f60c46e1..603973ab7e29 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -26,14 +26,22 @@
#define CLKMGR_L4SRC 0x70
#define CLKMGR_PERPLL_SRC 0xAC
-#define SOCFPGA_MAX_PARENTS 3
+#define SOCFPGA_MAX_PARENTS 5
#define div_mask(width) ((1 << (width)) - 1)
+#define streq(a, b) (strcmp((a), (b)) == 0)
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+ ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
+
extern void __iomem *clk_mgr_base_addr;
+extern void __iomem *clk_mgr_a10_base_addr;
void __init socfpga_pll_init(struct device_node *node);
void __init socfpga_periph_init(struct device_node *node);
void __init socfpga_gate_init(struct device_node *node);
+void socfpga_a10_pll_init(struct device_node *node);
+void socfpga_a10_periph_init(struct device_node *node);
+void socfpga_a10_gate_init(struct device_node *node);
struct socfpga_pll {
struct clk_gate hw;
@@ -44,6 +52,7 @@ struct socfpga_gate_clk {
char *parent_name;
u32 fixed_div;
void __iomem *div_reg;
+ struct regmap *sys_mgr_base_addr;
u32 width; /* only valid if div_reg != 0 */
u32 shift; /* only valid if div_reg != 0 */
u32 clk_phase[2];
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index bf12a25eb3a2..657ca14ba709 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -116,7 +116,7 @@ static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
return *prate / div;
}
-unsigned long flexgen_recalc_rate(struct clk_hw *hw,
+static unsigned long flexgen_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct flexgen *flexgen = to_flexgen(hw);
@@ -174,7 +174,7 @@ static const struct clk_ops flexgen_ops = {
.set_rate = flexgen_set_rate,
};
-struct clk *clk_register_flexgen(const char *name,
+static struct clk *clk_register_flexgen(const char *name,
const char **parent_names, u8 num_parents,
void __iomem *reg, spinlock_t *lock, u32 idx,
unsigned long flexgen_flags) {
@@ -245,7 +245,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
const char **parents;
int nparents, i;
- nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ nparents = of_clk_get_parent_count(np);
if (WARN_ON(nparents <= 0))
return NULL;
@@ -260,7 +260,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
return parents;
}
-void __init st_of_flexgen_setup(struct device_node *np)
+static void __init st_of_flexgen_setup(struct device_node *np)
{
struct device_node *pnode;
void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index a917c4c7eaa9..e94197f04b0b 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -492,7 +492,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw)
return !!npda;
}
-int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
unsigned long *rate)
{
unsigned long nd = fs->ndiv + 16; /* ndiv value */
@@ -519,7 +519,7 @@ static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
return rate;
}
-int clk_fs660c32_vco_get_params(unsigned long input,
+static int clk_fs660c32_vco_get_params(unsigned long input,
unsigned long output, struct stm_fs *fs)
{
/* Formula
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index fdcff10f6d30..4fbe6e099587 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -26,7 +26,7 @@ static const char ** __init clkgen_mux_get_parents(struct device_node *np,
const char **parents;
int nparents, i;
- nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ nparents = of_clk_get_parent_count(np);
if (WARN_ON(nparents <= 0))
return ERR_PTR(-EINVAL);
@@ -131,7 +131,7 @@ static int clkgena_divmux_is_enabled(struct clk_hw *hw)
return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
}
-u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
{
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
@@ -168,7 +168,7 @@ static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
return 0;
}
-unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+static unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
@@ -215,7 +215,7 @@ static const struct clk_ops clkgena_divmux_ops = {
/**
* clk_register_genamux - register a genamux clock with the clock framework
*/
-struct clk *clk_register_genamux(const char *name,
+static struct clk *clk_register_genamux(const char *name,
const char **parent_names, u8 num_parents,
void __iomem *reg,
const struct clkgena_divmux_data *muxdata,
@@ -385,7 +385,7 @@ static void __iomem * __init clkgen_get_register_base(
return reg;
}
-void __init st_of_clkgena_divmux_setup(struct device_node *np)
+static void __init st_of_clkgena_divmux_setup(struct device_node *np)
{
const struct of_device_id *match;
const struct clkgena_divmux_data *data;
@@ -485,7 +485,7 @@ static const struct of_device_id clkgena_prediv_of_match[] = {
{}
};
-void __init st_of_clkgena_prediv_setup(struct device_node *np)
+static void __init st_of_clkgena_prediv_setup(struct device_node *np)
{
const struct of_device_id *match;
void __iomem *reg;
@@ -622,7 +622,7 @@ static const struct of_device_id mux_of_match[] = {
{}
};
-void __init st_of_clkgen_mux_setup(struct device_node *np)
+static void __init st_of_clkgen_mux_setup(struct device_node *np)
{
const struct of_device_id *match;
struct clk *clk;
@@ -699,7 +699,7 @@ static const struct of_device_id vcc_of_match[] = {
{}
};
-void __init st_of_clkgen_vcc_setup(struct device_node *np)
+static void __init st_of_clkgen_vcc_setup(struct device_node *np)
{
const struct of_device_id *match;
void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index d204ba85db3a..106532207213 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -270,7 +270,7 @@ static int clkgen_pll_is_enabled(struct clk_hw *hw)
return !poweroff;
}
-unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -297,7 +297,7 @@ unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
}
-unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -321,7 +321,7 @@ unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
return rate;
}
-unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -343,7 +343,7 @@ unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
return rate;
}
-unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -544,7 +544,7 @@ CLK_OF_DECLARE(clkgena_c65_plls,
"st,clkgena-plls-c65", clkgena_c65_pll_setup);
static struct clk * __init clkgen_odf_register(const char *parent_name,
- void * __iomem reg,
+ void __iomem *reg,
struct clkgen_pll_data *pll_data,
int odf,
spinlock_t *odf_lock,
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index d86bc46b93bd..19e543a32e2b 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -155,7 +155,7 @@ static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-const struct clk_ops atl_clk_ops = {
+static const struct clk_ops atl_clk_ops = {
.enable = atl_clk_enable,
.disable = atl_clk_disable,
.is_enabled = atl_clk_is_enabled,
@@ -167,7 +167,7 @@ const struct clk_ops atl_clk_ops = {
static void __init of_dra7_atl_clock_setup(struct device_node *node)
{
struct dra7_atl_desc *clk_hw = NULL;
- struct clk_init_data init = { 0 };
+ struct clk_init_data init = { NULL };
const char **parent_names = NULL;
struct clk *clk;
@@ -252,6 +252,11 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
}
clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to get atl clock %d from provider\n",
+ __func__, i);
+ return PTR_ERR(clk);
+ }
cdesc = to_atl_desc(__clk_get_hw(clk));
cdesc->cinfo = cinfo;
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 0ebe5c51062b..64bb5e8a3b8c 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -122,14 +122,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
if (i == CLK_MAX_MEMMAPS) {
pr_err("clk-provider not found for %s!\n", node->name);
- return ERR_PTR(-ENOENT);
+ return IOMEM_ERR_PTR(-ENOENT);
}
reg->index = i;
if (of_property_read_u32_index(node, "reg", index, &val)) {
pr_err("%s must have reg[%d]!\n", node->name, index);
- return ERR_PTR(-EINVAL);
+ return IOMEM_ERR_PTR(-EINVAL);
}
reg->offset = val;
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index 35fe1085480c..b82ef07f3403 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -32,7 +32,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
int i;
int num_clks;
- num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+ num_clks = of_clk_get_parent_count(node);
for (i = 0; i < num_clks; i++) {
clk = of_clk_get(node, i);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 11478a501c30..2aacf7a3bcae 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -177,7 +177,7 @@ cleanup:
}
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
-void __iomem *_get_reg(u8 module, u16 offset)
+static void __iomem *_get_reg(u8 module, u16 offset)
{
u32 reg;
struct clk_omap_reg *reg_setup;
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index ffcd8e09e85b..730aa62454a2 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -621,13 +621,13 @@ static void __init ti_fapll_setup(struct device_node *node)
/* Check for hardwired audio_pll_clk1 */
if (is_audio_pll_clk1(freq)) {
- freq = 0;
- div = 0;
+ freq = NULL;
+ div = NULL;
} else {
/* Does the synthesizer have a FREQ register? */
v = readl_relaxed(freq);
if (!v)
- freq = 0;
+ freq = NULL;
}
synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
output_name, node->name,
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index 80069c370a47..4626b97b7d83 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -116,11 +116,12 @@ void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
clk_register_clkdev(clk, NULL, "hdmi");
clk_register_clkdev(clk, "hdmi", "mcde");
- clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+ clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
clk_register_clkdev(clk, NULL, "apeat");
- clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
- CLK_IS_ROOT);
+ clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
clk_register_clkdev(clk, NULL, "apetrace");
clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 7b55ef89baa5..e319ef912dc6 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -166,8 +166,8 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
prcmu_clk[PRCMU_APEATCLK] = clk;
- clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
- CLK_IS_ROOT);
+ clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
prcmu_clk[PRCMU_APETRACECLK] = clk;
clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c
index c6e86a9a2aa3..a96dd8e53fdb 100644
--- a/drivers/clk/versatile/clk-sp810.c
+++ b/drivers/clk/versatile/clk-sp810.c
@@ -135,7 +135,7 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec,
return sp810->timerclken[clkspec->args[0]].clk;
}
-void __init clk_sp810_of_setup(struct device_node *node)
+static void __init clk_sp810_of_setup(struct device_node *node)
{
struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL);
const char *parent_names[2];
@@ -156,7 +156,7 @@ void __init clk_sp810_of_setup(struct device_node *node)
"timclk");
parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index);
- if (parent_names[0] <= 0 || parent_names[1] <= 0) {
+ if (!parent_names[0] || !parent_names[1]) {
pr_warn("Failed to obtain parent clocks for SP810!\n");
return;
}
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 40cb113be6af..de614384bb44 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -85,22 +85,29 @@ static DEFINE_SPINLOCK(canmioclk_lock);
static DEFINE_SPINLOCK(dbgclk_lock);
static DEFINE_SPINLOCK(aperclk_lock);
-static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"};
-static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"};
-static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"};
+static const char *const armpll_parents[] __initconst = {"armpll_int",
+ "ps_clk"};
+static const char *const ddrpll_parents[] __initconst = {"ddrpll_int",
+ "ps_clk"};
+static const char *const iopll_parents[] __initconst = {"iopll_int",
+ "ps_clk"};
static const char *gem0_mux_parents[] __initdata = {"gem0_div1", "dummy_name"};
static const char *gem1_mux_parents[] __initdata = {"gem1_div1", "dummy_name"};
-static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
+static const char *const can0_mio_mux2_parents[] __initconst = {"can0_gate",
"can0_mio_mux"};
-static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate",
+static const char *const can1_mio_mux2_parents[] __initconst = {"can1_gate",
"can1_mio_mux"};
static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div",
"dummy_name"};
-static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"};
-static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"};
-static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"};
-static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"};
+static const char *const dbgtrc_emio_input_names[] __initconst = {
+ "trace_emio_clk"};
+static const char *const gem0_emio_input_names[] __initconst = {
+ "gem0_emio_clk"};
+static const char *const gem1_emio_input_names[] __initconst = {
+ "gem1_emio_clk"};
+static const char *const swdt_ext_clk_input_names[] __initconst = {
+ "swdt_ext_clk"};
static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
const char *clk_name, void __iomem *fclk_ctrl_reg,
diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
index 9b84def7a353..f42f71e37e73 100644
--- a/drivers/dma/hsu/hsu.c
+++ b/drivers/dma/hsu/hsu.c
@@ -384,7 +384,10 @@ static int hsu_dma_terminate_all(struct dma_chan *chan)
spin_lock_irqsave(&hsuc->vchan.lock, flags);
hsu_dma_stop_channel(hsuc);
- hsuc->desc = NULL;
+ if (hsuc->desc) {
+ hsu_dma_desc_free(&hsuc->desc->vdesc);
+ hsuc->desc = NULL;
+ }
vchan_get_all_descriptors(&hsuc->vchan, &head);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index a7d9d3029b14..340f9e607cd8 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2127,6 +2127,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
struct pl330_dmac *pl330 = pch->dmac;
LIST_HEAD(list);
+ pm_runtime_get_sync(pl330->ddma.dev);
spin_lock_irqsave(&pch->lock, flags);
spin_lock(&pl330->lock);
_stop(pch->thread);
@@ -2151,6 +2152,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
spin_unlock_irqrestore(&pch->lock, flags);
+ pm_runtime_mark_last_busy(pl330->ddma.dev);
+ pm_runtime_put_autosuspend(pl330->ddma.dev);
return 0;
}
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 071c2c969eec..72791232e46b 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -186,8 +186,20 @@ struct ibft_kobject {
static struct iscsi_boot_kset *boot_kset;
+/* fully null address */
static const char nulls[16];
+/* IPv4-mapped IPv6 ::ffff:0.0.0.0 */
+static const char mapped_nulls[16] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00 };
+
+static int address_not_null(u8 *ip)
+{
+ return (memcmp(ip, nulls, 16) && memcmp(ip, mapped_nulls, 16));
+}
+
/*
* Helper functions to parse data properly.
*/
@@ -445,7 +457,7 @@ static umode_t ibft_check_nic_for(void *data, int type)
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_IP_ADDR:
- if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
+ if (address_not_null(nic->ip_addr))
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_SUBNET_MASK:
@@ -456,21 +468,19 @@ static umode_t ibft_check_nic_for(void *data, int type)
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_GATEWAY:
- if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
+ if (address_not_null(nic->gateway))
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_PRIMARY_DNS:
- if (memcmp(nic->primary_dns, nulls,
- sizeof(nic->primary_dns)))
+ if (address_not_null(nic->primary_dns))
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_SECONDARY_DNS:
- if (memcmp(nic->secondary_dns, nulls,
- sizeof(nic->secondary_dns)))
+ if (address_not_null(nic->secondary_dns))
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_DHCP:
- if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+ if (address_not_null(nic->dhcp))
rc = S_IRUGO;
break;
case ISCSI_BOOT_ETH_VLAN:
@@ -536,23 +546,19 @@ static umode_t __init ibft_check_initiator_for(void *data, int type)
rc = S_IRUGO;
break;
case ISCSI_BOOT_INI_ISNS_SERVER:
- if (memcmp(init->isns_server, nulls,
- sizeof(init->isns_server)))
+ if (address_not_null(init->isns_server))
rc = S_IRUGO;
break;
case ISCSI_BOOT_INI_SLP_SERVER:
- if (memcmp(init->slp_server, nulls,
- sizeof(init->slp_server)))
+ if (address_not_null(init->slp_server))
rc = S_IRUGO;
break;
case ISCSI_BOOT_INI_PRI_RADIUS_SERVER:
- if (memcmp(init->pri_radius_server, nulls,
- sizeof(init->pri_radius_server)))
+ if (address_not_null(init->pri_radius_server))
rc = S_IRUGO;
break;
case ISCSI_BOOT_INI_SEC_RADIUS_SERVER:
- if (memcmp(init->sec_radius_server, nulls,
- sizeof(init->sec_radius_server)))
+ if (address_not_null(init->sec_radius_server))
rc = S_IRUGO;
break;
case ISCSI_BOOT_INI_INITIATOR_NAME:
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index e469c4b2e8cc..c25728bc388a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -684,8 +684,6 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
dev->node_props.cpu_core_id_base);
sysfs_show_32bit_prop(buffer, "simd_id_base",
dev->node_props.simd_id_base);
- sysfs_show_32bit_prop(buffer, "capability",
- dev->node_props.capability);
sysfs_show_32bit_prop(buffer, "max_waves_per_simd",
dev->node_props.max_waves_per_simd);
sysfs_show_32bit_prop(buffer, "lds_size_in_kb",
@@ -736,6 +734,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
dev->gpu->kfd2kgd->get_fw_version(
dev->gpu->kgd,
KGD_ENGINE_MEC1));
+ sysfs_show_32bit_prop(buffer, "capability",
+ dev->node_props.capability);
}
return sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute",
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index ffc305fc2076..eb7e61078a5b 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -217,7 +217,7 @@ static ssize_t status_store(struct device *device,
mutex_unlock(&dev->mode_config.mutex);
- return ret;
+ return ret ? ret : count;
}
static ssize_t status_show(struct device *device,
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 007c7d7d8295..dc55c51964ab 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1667,12 +1667,15 @@ static int i915_sr_status(struct seq_file *m, void *unused)
if (HAS_PCH_SPLIT(dev))
sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
- else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev))
+ else if (IS_CRESTLINE(dev) || IS_G4X(dev) ||
+ IS_I945G(dev) || IS_I945GM(dev))
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (IS_I915GM(dev))
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
else if (IS_PINEVIEW(dev))
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
+ else if (IS_VALLEYVIEW(dev))
+ sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 53394f998a1f..851b585987f9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2656,9 +2656,6 @@ void i915_gem_reset(struct drm_device *dev)
void
i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
{
- if (list_empty(&ring->request_list))
- return;
-
WARN_ON(i915_verify_lists(ring->dev));
/* Retire requests first as we use it above for the early return.
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f27346e907b1..d714a4b5711e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -880,10 +880,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
DP_AUX_CH_CTL_RECEIVE_ERROR))
continue;
if (status & DP_AUX_CH_CTL_DONE)
- break;
+ goto done;
}
- if (status & DP_AUX_CH_CTL_DONE)
- break;
}
if ((status & DP_AUX_CH_CTL_DONE) == 0) {
@@ -892,6 +890,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
goto out;
}
+done:
/* Check for timeout or receive error.
* Timeouts occur when the sink is not connected
*/
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 09df74b8e917..424e62197787 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1134,6 +1134,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
+ if (ring->status_page.obj) {
+ I915_WRITE(RING_HWS_PGA(ring->mmio_base),
+ (u32)ring->status_page.gfx_addr);
+ POSTING_READ(RING_HWS_PGA(ring->mmio_base));
+ }
+
I915_WRITE(RING_MODE_GEN7(ring),
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 441e2502b889..005b5e04de4d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -901,13 +901,6 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
GEN6_WIZ_HASHING_MASK,
GEN6_WIZ_HASHING_16x4);
- if (INTEL_REVID(dev) == SKL_REVID_C0 ||
- INTEL_REVID(dev) == SKL_REVID_D0)
- /* WaBarrierPerformanceFixDisable:skl */
- WA_SET_BIT_MASKED(HDC_CHICKEN0,
- HDC_FENCE_DEST_SLM_DISABLE |
- HDC_BARRIER_PERFORMANCE_DISABLE);
-
return 0;
}
@@ -1024,6 +1017,13 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
WA_SET_BIT_MASKED(HIZ_CHICKEN,
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
+ if (INTEL_REVID(dev) == SKL_REVID_C0 ||
+ INTEL_REVID(dev) == SKL_REVID_D0)
+ /* WaBarrierPerformanceFixDisable:skl */
+ WA_SET_BIT_MASKED(HDC_CHICKEN0,
+ HDC_FENCE_DEST_SLM_DISABLE |
+ HDC_BARRIER_PERFORMANCE_DISABLE);
+
return skl_tune_iz_hashing(ring);
}
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
index f04205170b8a..cfa3a84a2af0 100644
--- a/drivers/gpu/drm/radeon/dce3_1_afmt.c
+++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
@@ -173,7 +173,7 @@ void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset,
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
- WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
+ WREG32(DCE3_HDMI0_ACR_PACKET_CONTROL + offset,
HDMI0_ACR_SOURCE | /* select SW CTS value */
HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index 8fe78d08e01c..7c6966434ee7 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -554,4 +554,4 @@ module_platform_driver(hix5hd2_i2c_driver);
MODULE_DESCRIPTION("Hix5hd2 I2C Bus driver");
MODULE_AUTHOR("Wei Yan <sledge.yanwei@huawei.com>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:i2c-hix5hd2");
+MODULE_ALIAS("platform:hix5hd2-i2c");
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 958c8db4ec30..297e9c9ac943 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1143,6 +1143,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return -ENOMEM;
i2c->quirks = s3c24xx_get_device_quirks(pdev);
+ i2c->sysreg = ERR_PTR(-ENOENT);
if (pdata)
memcpy(i2c->pdata, pdata, sizeof(*pdata));
else
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 89d8aa1d2818..df12c57e6ce0 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -1001,7 +1001,7 @@ static struct platform_driver twl6030_gpadc_driver = {
module_platform_driver(twl6030_gpadc_driver);
-MODULE_ALIAS("platform: " DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
MODULE_AUTHOR("Balaji T K <balajitk@ti.com>");
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
MODULE_AUTHOR("Oleksandr Kozaruk <oleksandr.kozaruk@ti.com");
diff --git a/drivers/iio/imu/adis16400.h b/drivers/iio/imu/adis16400.h
index 0916bf6b6c31..73b189c1c0fb 100644
--- a/drivers/iio/imu/adis16400.h
+++ b/drivers/iio/imu/adis16400.h
@@ -139,6 +139,7 @@
#define ADIS16400_NO_BURST BIT(1)
#define ADIS16400_HAS_SLOW_MODE BIT(2)
#define ADIS16400_HAS_SERIAL_NUMBER BIT(3)
+#define ADIS16400_BURST_DIAG_STAT BIT(4)
struct adis16400_state;
@@ -165,6 +166,7 @@ struct adis16400_state {
int filt_int;
struct adis adis;
+ unsigned long avail_scan_mask[2];
};
/* At the moment triggers are only used for ring buffer
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index 6e727ffe5262..90c24a23c679 100644
--- a/drivers/iio/imu/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -18,7 +18,8 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
{
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
- uint16_t *tx;
+ unsigned int burst_length;
+ u8 *tx;
if (st->variant->flags & ADIS16400_NO_BURST)
return adis_update_scan_mode(indio_dev, scan_mask);
@@ -26,26 +27,29 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
kfree(adis->xfer);
kfree(adis->buffer);
+ /* All but the timestamp channel */
+ burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
+ if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
+ burst_length += sizeof(u16);
+
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
- adis->buffer = kzalloc(indio_dev->scan_bytes + sizeof(u16),
- GFP_KERNEL);
+ adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;
- tx = adis->buffer + indio_dev->scan_bytes;
-
+ tx = adis->buffer + burst_length;
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
tx[1] = 0;
adis->xfer[0].tx_buf = tx;
adis->xfer[0].bits_per_word = 8;
adis->xfer[0].len = 2;
- adis->xfer[1].tx_buf = tx;
+ adis->xfer[1].rx_buf = adis->buffer;
adis->xfer[1].bits_per_word = 8;
- adis->xfer[1].len = indio_dev->scan_bytes;
+ adis->xfer[1].len = burst_length;
spi_message_init(&adis->msg);
spi_message_add_tail(&adis->xfer[0], &adis->msg);
@@ -61,6 +65,7 @@ irqreturn_t adis16400_trigger_handler(int irq, void *p)
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
u32 old_speed_hz = st->adis.spi->max_speed_hz;
+ void *buffer;
int ret;
if (!adis->buffer)
@@ -81,7 +86,12 @@ irqreturn_t adis16400_trigger_handler(int irq, void *p)
spi_setup(st->adis.spi);
}
- iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
+ if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
+ buffer = adis->buffer + sizeof(u16);
+ else
+ buffer = adis->buffer;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, buffer,
pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index fa795dcd5f75..2fd68f2219a7 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -405,6 +405,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val = st->variant->temp_scale_nano / 1000000;
*val2 = (st->variant->temp_scale_nano % 1000000);
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_PRESSURE:
+ /* 20 uBar = 0.002kPascal */
+ *val = 0;
+ *val2 = 2000;
+ return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@@ -454,10 +459,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
}
}
-#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si) { \
+#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
- .channel = 0, \
+ .channel = chn, \
.extend_name = name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
@@ -474,10 +479,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
}
#define ADIS16400_SUPPLY_CHAN(addr, bits) \
- ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY)
+ ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0)
#define ADIS16400_AUX_ADC_CHAN(addr, bits) \
- ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC)
+ ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1)
#define ADIS16400_GYRO_CHAN(mod, addr, bits) { \
.type = IIO_ANGL_VEL, \
@@ -773,7 +778,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16448_channels,
.num_channels = ARRAY_SIZE(adis16448_channels),
.flags = ADIS16400_HAS_PROD_ID |
- ADIS16400_HAS_SERIAL_NUMBER,
+ ADIS16400_HAS_SERIAL_NUMBER |
+ ADIS16400_BURST_DIAG_STAT,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
.temp_scale_nano = 73860000, /* 0.07386 C */
@@ -791,11 +797,6 @@ static const struct iio_info adis16400_info = {
.debugfs_reg_access = adis_debugfs_reg_access,
};
-static const unsigned long adis16400_burst_scan_mask[] = {
- ~0UL,
- 0,
-};
-
static const char * const adis16400_status_error_msgs[] = {
[ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
@@ -843,6 +844,20 @@ static const struct adis_data adis16400_data = {
BIT(ADIS16400_DIAG_STAT_POWER_LOW),
};
+static void adis16400_setup_chan_mask(struct adis16400_state *st)
+{
+ const struct adis16400_chip_info *chip_info = st->variant;
+ unsigned i;
+
+ for (i = 0; i < chip_info->num_channels; i++) {
+ const struct iio_chan_spec *ch = &chip_info->channels[i];
+
+ if (ch->scan_index >= 0 &&
+ ch->scan_index != ADIS16400_SCAN_TIMESTAMP)
+ st->avail_scan_mask[0] |= BIT(ch->scan_index);
+ }
+}
+
static int adis16400_probe(struct spi_device *spi)
{
struct adis16400_state *st;
@@ -866,8 +881,10 @@ static int adis16400_probe(struct spi_device *spi)
indio_dev->info = &adis16400_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- if (!(st->variant->flags & ADIS16400_NO_BURST))
- indio_dev->available_scan_masks = adis16400_burst_scan_mask;
+ if (!(st->variant->flags & ADIS16400_NO_BURST)) {
+ adis16400_setup_chan_mask(st);
+ indio_dev->available_scan_masks = st->avail_scan_mask;
+ }
ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
if (ret)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 7752bd59d4b7..a353b7de6d22 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1063,9 +1063,8 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
right = (packet[1] & 0x02) >> 1;
middle = (packet[1] & 0x04) >> 2;
- /* Divide 2 since trackpoint's speed is too fast */
- input_report_rel(dev2, REL_X, (char)x / 2);
- input_report_rel(dev2, REL_Y, -((char)y / 2));
+ input_report_rel(dev2, REL_X, (char)x);
+ input_report_rel(dev2, REL_Y, -((char)y));
input_report_key(dev2, BTN_LEFT, left);
input_report_key(dev2, BTN_RIGHT, right);
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 79363b687195..ce3d40004458 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1376,10 +1376,11 @@ static bool elantech_is_signature_valid(const unsigned char *param)
return true;
/*
- * Some models have a revision higher then 20. Meaning param[2] may
- * be 10 or 20, skip the rates check for these.
+ * Some hw_version >= 4 models have a revision higher then 20. Meaning
+ * that param[2] may be 10 or 20, skip the rates check for these.
*/
- if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
+ if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f &&
+ param[2] < 40)
return true;
for (i = 0; i < ARRAY_SIZE(rates); i++)
@@ -1555,6 +1556,7 @@ static int elantech_set_properties(struct elantech_data *etd)
case 9:
case 10:
case 13:
+ case 14:
etd->hw_version = 4;
break;
default:
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index e43d48956dea..e1c7e9e51045 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2930,6 +2930,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
size = PAGE_ALIGN(size);
dma_mask = dev->coherent_dma_mask;
flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+ flag |= __GFP_ZERO;
page = alloc_pages(flag | __GFP_NOWARN, get_order(size));
if (!page) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index a3b0f7a0c61e..1f82a04ce01a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1774,7 +1774,7 @@ struct bnx2x {
int stats_state;
/* used for synchronization of concurrent threads statistics handling */
- struct mutex stats_lock;
+ struct semaphore stats_lock;
/* used by dmae command loader */
struct dmae_command stats_dmae;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index fd52ce95127e..33501bcddc48 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12054,7 +12054,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
mutex_init(&bp->fw_mb_mutex);
mutex_init(&bp->drv_info_mutex);
- mutex_init(&bp->stats_lock);
+ sema_init(&bp->stats_lock, 1);
bp->drv_info_mng_owner = false;
INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
@@ -13690,9 +13690,10 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
cancel_delayed_work_sync(&bp->sp_task);
cancel_delayed_work_sync(&bp->period_task);
- mutex_lock(&bp->stats_lock);
- bp->stats_state = STATS_STATE_DISABLED;
- mutex_unlock(&bp->stats_lock);
+ if (!down_timeout(&bp->stats_lock, HZ / 10)) {
+ bp->stats_state = STATS_STATE_DISABLED;
+ up(&bp->stats_lock);
+ }
bnx2x_save_statistics(bp);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 266b055c2360..69d699f0730a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1372,19 +1372,23 @@ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
* that context in case someone is in the middle of a transition.
* For other events, wait a bit until lock is taken.
*/
- if (!mutex_trylock(&bp->stats_lock)) {
+ if (down_trylock(&bp->stats_lock)) {
if (event == STATS_EVENT_UPDATE)
return;
DP(BNX2X_MSG_STATS,
"Unlikely stats' lock contention [event %d]\n", event);
- mutex_lock(&bp->stats_lock);
+ if (unlikely(down_timeout(&bp->stats_lock, HZ / 10))) {
+ BNX2X_ERR("Failed to take stats lock [event %d]\n",
+ event);
+ return;
+ }
}
bnx2x_stats_stm[state][event].action(bp);
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
- mutex_unlock(&bp->stats_lock);
+ up(&bp->stats_lock);
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
@@ -1970,7 +1974,11 @@ int bnx2x_stats_safe_exec(struct bnx2x *bp,
/* Wait for statistics to end [while blocking further requests],
* then run supplied function 'safely'.
*/
- mutex_lock(&bp->stats_lock);
+ rc = down_timeout(&bp->stats_lock, HZ / 10);
+ if (unlikely(rc)) {
+ BNX2X_ERR("Failed to take statistics lock for safe execution\n");
+ goto out_no_lock;
+ }
bnx2x_stats_comp(bp);
while (bp->stats_pending && cnt--)
@@ -1988,7 +1996,7 @@ out:
/* No need to restart statistics - if they're enabled, the timer
* will restart the statistics.
*/
- mutex_unlock(&bp->stats_lock);
-
+ up(&bp->stats_lock);
+out_no_lock:
return rc;
}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 594a2ab36d31..68f3c13c9ef6 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -2414,7 +2414,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
if (status == BFA_STATUS_OK)
bfa_ioc_lpu_start(ioc);
else
- bfa_nw_iocpf_timeout(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
return status;
}
@@ -3029,7 +3029,7 @@ bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
}
if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {
- bfa_nw_iocpf_timeout(ioc);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
} else {
ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
mod_timer(&ioc->iocpf_timer, jiffies +
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 37072a83f9d6..caae6cb2bc1a 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3701,10 +3701,6 @@ bnad_pci_probe(struct pci_dev *pdev,
setup_timer(&bnad->bna.ioceth.ioc.sem_timer, bnad_iocpf_sem_timeout,
((unsigned long)bnad));
- /* Now start the timer before calling IOC */
- mod_timer(&bnad->bna.ioceth.ioc.iocpf_timer,
- jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
-
/*
* Start the chip
* If the call back comes with error, we bail out.
diff --git a/drivers/net/ethernet/brocade/bna/cna_fwimg.c b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
index ebf462d8082f..badea368bdc8 100644
--- a/drivers/net/ethernet/brocade/bna/cna_fwimg.c
+++ b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
@@ -30,6 +30,7 @@ cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
u32 *bfi_image_size, char *fw_name)
{
const struct firmware *fw;
+ u32 n;
if (request_firmware(&fw, fw_name, &pdev->dev)) {
pr_alert("Can't locate firmware %s\n", fw_name);
@@ -40,6 +41,12 @@ cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
*bfi_image_size = fw->size/sizeof(u32);
bfi_fw = fw;
+ /* Convert loaded firmware to host order as it is stored in file
+ * as sequence of LE32 integers.
+ */
+ for (n = 0; n < *bfi_image_size; n++)
+ le32_to_cpus(*bfi_image + n);
+
return *bfi_image;
error:
return NULL;
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index c0ad95d2f63d..809ea4610a77 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -224,12 +224,17 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx,
}
}
-static void efx_free_rx_buffer(struct efx_rx_buffer *rx_buf)
+static void efx_free_rx_buffers(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf,
+ unsigned int num_bufs)
{
- if (rx_buf->page) {
- put_page(rx_buf->page);
- rx_buf->page = NULL;
- }
+ do {
+ if (rx_buf->page) {
+ put_page(rx_buf->page);
+ rx_buf->page = NULL;
+ }
+ rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
+ } while (--num_bufs);
}
/* Attempt to recycle the page if there is an RX recycle ring; the page can
@@ -278,7 +283,7 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
/* If this is the last buffer in a page, unmap and free it. */
if (rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE) {
efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
- efx_free_rx_buffer(rx_buf);
+ efx_free_rx_buffers(rx_queue, rx_buf, 1);
}
rx_buf->page = NULL;
}
@@ -304,10 +309,7 @@ static void efx_discard_rx_packet(struct efx_channel *channel,
efx_recycle_rx_pages(channel, rx_buf, n_frags);
- do {
- efx_free_rx_buffer(rx_buf);
- rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
- } while (--n_frags);
+ efx_free_rx_buffers(rx_queue, rx_buf, n_frags);
}
/**
@@ -431,11 +433,10 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
skb = napi_get_frags(napi);
if (unlikely(!skb)) {
- while (n_frags--) {
- put_page(rx_buf->page);
- rx_buf->page = NULL;
- rx_buf = efx_rx_buf_next(&channel->rx_queue, rx_buf);
- }
+ struct efx_rx_queue *rx_queue;
+
+ rx_queue = efx_channel_get_rx_queue(channel);
+ efx_free_rx_buffers(rx_queue, rx_buf, n_frags);
return;
}
@@ -622,7 +623,10 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh,
skb = efx_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len);
if (unlikely(skb == NULL)) {
- efx_free_rx_buffer(rx_buf);
+ struct efx_rx_queue *rx_queue;
+
+ rx_queue = efx_channel_get_rx_queue(channel);
+ efx_free_rx_buffers(rx_queue, rx_buf, n_frags);
return;
}
skb_record_rx_queue(skb, channel->rx_queue.core_index);
@@ -661,8 +665,12 @@ void __efx_rx_packet(struct efx_channel *channel)
* loopback layer, and free the rx_buf here
*/
if (unlikely(efx->loopback_selftest)) {
+ struct efx_rx_queue *rx_queue;
+
efx_loopback_rx_packet(efx, eh, rx_buf->len);
- efx_free_rx_buffer(rx_buf);
+ rx_queue = efx_channel_get_rx_queue(channel);
+ efx_free_rx_buffers(rx_queue, rx_buf,
+ channel->rx_pkt_n_frags);
goto out;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 4ec9811f49c8..65efb1468988 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -511,11 +511,9 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
msgbuf->rx_pktids,
msgbuf->ioctl_resp_pktid);
if (msgbuf->ioctl_resp_ret_len != 0) {
- if (!skb) {
- brcmf_err("Invalid packet id idx recv'd %d\n",
- msgbuf->ioctl_resp_pktid);
+ if (!skb)
return -EBADF;
- }
+
memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
len : msgbuf->ioctl_resp_ret_len);
}
@@ -874,10 +872,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->tx_pktids, idx);
- if (!skb) {
- brcmf_err("Invalid packet id idx recv'd %d\n", idx);
+ if (!skb)
return;
- }
set_bit(flowid, msgbuf->txstatus_done_map);
commonring = msgbuf->flowrings[flowid];
@@ -1156,6 +1152,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->rx_pktids, idx);
+ if (!skb)
+ return;
if (data_offset)
skb_pull(skb, data_offset);
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 75e96db6626b..8e604a3931ca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -471,7 +471,7 @@ static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
return le16_to_cpup(nvm_sw + RADIO_CFG);
- return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
+ return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_8000));
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 01996c9d98a7..376b84e54ad7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -320,7 +320,7 @@ struct iwl_trans_pcie {
/*protect hw register */
spinlock_t reg_lock;
- bool cmd_in_flight;
+ bool cmd_hold_nic_awake;
bool ref_cmd_in_flight;
/* protect ref counter */
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index d6f6515fe663..dc179094e6a0 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1372,7 +1372,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,
spin_lock_irqsave(&trans_pcie->reg_lock, *flags);
- if (trans_pcie->cmd_in_flight)
+ if (trans_pcie->cmd_hold_nic_awake)
goto out;
/* this bit wakes up the NIC */
@@ -1438,7 +1438,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
*/
__acquire(&trans_pcie->reg_lock);
- if (trans_pcie->cmd_in_flight)
+ if (trans_pcie->cmd_hold_nic_awake)
goto out;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 06952aadfd7b..5ef8044c2ea3 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1039,18 +1039,14 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
iwl_trans_pcie_ref(trans);
}
- if (trans_pcie->cmd_in_flight)
- return 0;
-
- trans_pcie->cmd_in_flight = true;
-
/*
* wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set.
*/
- if (trans->cfg->base_params->apmg_wake_up_wa) {
+ if (trans->cfg->base_params->apmg_wake_up_wa &&
+ !trans_pcie->cmd_hold_nic_awake) {
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
@@ -1064,10 +1060,10 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- trans_pcie->cmd_in_flight = false;
IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
return -EIO;
}
+ trans_pcie->cmd_hold_nic_awake = true;
}
return 0;
@@ -1085,15 +1081,14 @@ static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
iwl_trans_pcie_unref(trans);
}
- if (WARN_ON(!trans_pcie->cmd_in_flight))
- return 0;
-
- trans_pcie->cmd_in_flight = false;
+ if (trans->cfg->base_params->apmg_wake_up_wa) {
+ if (WARN_ON(!trans_pcie->cmd_hold_nic_awake))
+ return 0;
- if (trans->cfg->base_params->apmg_wake_up_wa)
+ trans_pcie->cmd_hold_nic_awake = false;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ }
return 0;
}
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 4de46aa61d95..0d2594395ffb 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1250,7 +1250,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
netdev_err(queue->vif->dev,
"txreq.offset: %x, size: %u, end: %lu\n",
txreq.offset, txreq.size,
- (txreq.offset&~PAGE_MASK) + txreq.size);
+ (unsigned long)(txreq.offset&~PAGE_MASK) + txreq.size);
xenvif_fatal_tx_err(queue->vif);
break;
}
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index fee02414529e..968787abf78d 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -34,6 +34,8 @@ struct backend_info {
enum xenbus_state frontend_state;
struct xenbus_watch hotplug_status_watch;
u8 have_hotplug_status_watch:1;
+
+ const char *hotplug_script;
};
static int connect_rings(struct backend_info *be, struct xenvif_queue *queue);
@@ -238,6 +240,7 @@ static int netback_remove(struct xenbus_device *dev)
xenvif_free(be->vif);
be->vif = NULL;
}
+ kfree(be->hotplug_script);
kfree(be);
dev_set_drvdata(&dev->dev, NULL);
return 0;
@@ -255,6 +258,7 @@ static int netback_probe(struct xenbus_device *dev,
struct xenbus_transaction xbt;
int err;
int sg;
+ const char *script;
struct backend_info *be = kzalloc(sizeof(struct backend_info),
GFP_KERNEL);
if (!be) {
@@ -347,6 +351,15 @@ static int netback_probe(struct xenbus_device *dev,
if (err)
pr_debug("Error writing multi-queue-max-queues\n");
+ script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL);
+ if (IS_ERR(script)) {
+ err = PTR_ERR(script);
+ xenbus_dev_fatal(dev, err, "reading script");
+ goto fail;
+ }
+
+ be->hotplug_script = script;
+
err = xenbus_switch_state(dev, XenbusStateInitWait);
if (err)
goto fail;
@@ -379,22 +392,14 @@ static int netback_uevent(struct xenbus_device *xdev,
struct kobj_uevent_env *env)
{
struct backend_info *be = dev_get_drvdata(&xdev->dev);
- char *val;
- val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
- if (IS_ERR(val)) {
- int err = PTR_ERR(val);
- xenbus_dev_fatal(xdev, err, "reading script");
- return err;
- } else {
- if (add_uevent_var(env, "script=%s", val)) {
- kfree(val);
- return -ENOMEM;
- }
- kfree(val);
- }
+ if (!be)
+ return 0;
+
+ if (add_uevent_var(env, "script=%s", be->hotplug_script))
+ return -ENOMEM;
- if (!be || !be->vif)
+ if (!be->vif)
return 0;
return add_uevent_var(env, "vif=%s", be->vif->dev->name);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 99764db0875a..f0650265febf 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -189,7 +189,7 @@ int __of_attach_node_sysfs(struct device_node *np)
return 0;
}
-static int __init of_init(void)
+void __init of_core_init(void)
{
struct device_node *np;
@@ -198,7 +198,8 @@ static int __init of_init(void)
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
if (!of_kset) {
mutex_unlock(&of_mutex);
- return -ENOMEM;
+ pr_err("devicetree: failed to register existing nodes\n");
+ return;
}
for_each_of_allnodes(np)
__of_attach_node_sysfs(np);
@@ -207,10 +208,7 @@ static int __init of_init(void)
/* Symlink in /proc as required by userspace ABI */
if (of_root)
proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
-
- return 0;
}
-core_initcall(of_init);
static struct property *__of_find_property(const struct device_node *np,
const char *name, int *lenp)
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 3351ef408125..53826b84e0ec 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -225,7 +225,7 @@ void __of_attach_node(struct device_node *np)
phandle = __of_get_property(np, "phandle", &sz);
if (!phandle)
phandle = __of_get_property(np, "linux,phandle", &sz);
- if (IS_ENABLED(PPC_PSERIES) && !phandle)
+ if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
phandle = __of_get_property(np, "ibm,phandle", &sz);
np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 4fd0cacf7ca0..508cc56130e3 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -428,16 +428,19 @@ static void __assign_resources_sorted(struct list_head *head,
* consistent.
*/
if (add_align > dev_res->res->start) {
+ resource_size_t r_size = resource_size(dev_res->res);
+
dev_res->res->start = add_align;
- dev_res->res->end = add_align +
- resource_size(dev_res->res);
+ dev_res->res->end = add_align + r_size - 1;
list_for_each_entry(dev_res2, head, list) {
align = pci_resource_alignment(dev_res2->dev,
dev_res2->res);
- if (add_align > align)
+ if (add_align > align) {
list_move_tail(&dev_res->list,
&dev_res2->list);
+ break;
+ }
}
}
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index a53bd5b52df9..fc9b9f0ea91e 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -38,7 +38,9 @@ config ARMADA375_USBCLUSTER_PHY
config PHY_DM816X_USB
tristate "TI dm816x USB PHY driver"
depends on ARCH_OMAP2PLUS
+ depends on USB_SUPPORT
select GENERIC_PHY
+ select USB_PHY
help
Enable this for dm816x USB to work.
@@ -97,8 +99,9 @@ config OMAP_CONTROL_PHY
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
- depends on USB_PHY
+ depends on USB_SUPPORT
select GENERIC_PHY
+ select USB_PHY
select OMAP_CONTROL_PHY
depends on OMAP_OCP2SCP
help
@@ -122,8 +125,9 @@ config TI_PIPE3
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
- depends on USB_PHY
+ depends on USB_SUPPORT
select GENERIC_PHY
+ select USB_PHY
help
Enable this to support the USB OTG transceiver on TWL4030
family chips (including the TWL5030 and TPS659x0 devices).
@@ -304,7 +308,7 @@ config PHY_STIH41X_USB
config PHY_QCOM_UFS
tristate "Qualcomm UFS PHY driver"
- depends on OF && ARCH_MSM
+ depends on OF && ARCH_QCOM
select GENERIC_PHY
help
Support for UFS PHY on QCOM chipsets.
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 3791838f4bd4..63bc12d7a73e 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -530,7 +530,7 @@ struct phy *phy_optional_get(struct device *dev, const char *string)
{
struct phy *phy = phy_get(dev, string);
- if (PTR_ERR(phy) == -ENODEV)
+ if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
phy = NULL;
return phy;
@@ -584,7 +584,7 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string)
{
struct phy *phy = devm_phy_get(dev, string);
- if (PTR_ERR(phy) == -ENODEV)
+ if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
phy = NULL;
return phy;
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 183ef4368101..c1a468686bdc 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -275,6 +275,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+ pm_runtime_disable(phy->dev);
return PTR_ERR(phy->wkupclk);
} else {
dev_warn(&pdev->dev,
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index 778276aba3aa..97d45f47d1ad 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -23,7 +23,7 @@
#define USBHS_LPSTS 0x02
#define USBHS_UGCTRL 0x80
#define USBHS_UGCTRL2 0x84
-#define USBHS_UGSTS 0x88 /* The manuals have 0x90 */
+#define USBHS_UGSTS 0x88 /* From technical update */
/* Low Power Status register (LPSTS) */
#define USBHS_LPSTS_SUSPM 0x4000
@@ -41,7 +41,7 @@
#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030
/* USB General status register (UGSTS) */
-#define USBHS_UGSTS_LOCK 0x00000300 /* The manuals have 0x3 */
+#define USBHS_UGSTS_LOCK 0x00000100 /* From technical update */
#define PHYS_PER_CHANNEL 2
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index 5ff4716b72c3..784b5ecfa849 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -746,8 +746,8 @@ void oz_hcd_pd_reset(void *hpd, void *hport)
/*
* Context: softirq
*/
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
- int length, int offset, int total_size)
+void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, const u8 *desc,
+ u8 length, u16 offset, u16 total_size)
{
struct oz_port *port = hport;
struct urb *urb;
@@ -759,8 +759,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
if (!urb)
return;
if (status == 0) {
- int copy_len;
- int required_size = urb->transfer_buffer_length;
+ unsigned int copy_len;
+ unsigned int required_size = urb->transfer_buffer_length;
if (required_size > total_size)
required_size = total_size;
diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h
index 4249fa374012..d2a6085345be 100644
--- a/drivers/staging/ozwpan/ozusbif.h
+++ b/drivers/staging/ozwpan/ozusbif.h
@@ -29,8 +29,8 @@ void oz_usb_request_heartbeat(void *hpd);
/* Confirmation functions.
*/
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status,
- const u8 *desc, int length, int offset, int total_size);
+void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status,
+ const u8 *desc, u8 length, u16 offset, u16 total_size);
void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode,
const u8 *data, int data_len);
diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c
index d434d8c6fff6..f660bb198c65 100644
--- a/drivers/staging/ozwpan/ozusbsvc1.c
+++ b/drivers/staging/ozwpan/ozusbsvc1.c
@@ -326,7 +326,11 @@ static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx,
struct oz_multiple_fixed *body =
(struct oz_multiple_fixed *)data_hdr;
u8 *data = body->data;
- int n = (len - sizeof(struct oz_multiple_fixed)+1)
+ unsigned int n;
+ if (!body->unit_size ||
+ len < sizeof(struct oz_multiple_fixed) - 1)
+ break;
+ n = (len - (sizeof(struct oz_multiple_fixed) - 1))
/ body->unit_size;
while (n--) {
oz_hcd_data_ind(usb_ctx->hport, body->endpoint,
@@ -390,10 +394,15 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
case OZ_GET_DESC_RSP: {
struct oz_get_desc_rsp *body =
(struct oz_get_desc_rsp *)usb_hdr;
- int data_len = elt->length -
- sizeof(struct oz_get_desc_rsp) + 1;
- u16 offs = le16_to_cpu(get_unaligned(&body->offset));
- u16 total_size =
+ u16 offs, total_size;
+ u8 data_len;
+
+ if (elt->length < sizeof(struct oz_get_desc_rsp) - 1)
+ break;
+ data_len = elt->length -
+ (sizeof(struct oz_get_desc_rsp) - 1);
+ offs = le16_to_cpu(get_unaligned(&body->offset));
+ total_size =
le16_to_cpu(get_unaligned(&body->total_size));
oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
index f1d47a0676c3..ada8d5dafd49 100644
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ b/drivers/staging/rtl8712/rtl8712_led.c
@@ -898,11 +898,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -921,11 +921,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedLinkBlinkInProgress = true;
@@ -946,15 +946,15 @@ static void SwLedControlMode1(struct _adapter *padapter,
if (IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedScanBlinkInProgress = true;
@@ -975,11 +975,11 @@ static void SwLedControlMode1(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
pLed->bLedBlinkInProgress = true;
@@ -998,19 +998,19 @@ static void SwLedControlMode1(struct _adapter *padapter,
case LED_CTL_START_WPS_BOTTON:
if (pLed->bLedWPSBlinkInProgress == false) {
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
pLed->bLedWPSBlinkInProgress = true;
@@ -1025,23 +1025,23 @@ static void SwLedControlMode1(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS:
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress)
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
else
pLed->bLedWPSBlinkInProgress = true;
pLed->CurrLedState = LED_BLINK_WPS_STOP;
@@ -1057,7 +1057,7 @@ static void SwLedControlMode1(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS_FAIL:
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -1073,23 +1073,23 @@ static void SwLedControlMode1(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
mod_timer(&pLed->BlinkTimer,
@@ -1116,7 +1116,7 @@ static void SwLedControlMode2(struct _adapter *padapter,
return;
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedScanBlinkInProgress = true;
@@ -1154,11 +1154,11 @@ static void SwLedControlMode2(struct _adapter *padapter,
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
@@ -1170,11 +1170,11 @@ static void SwLedControlMode2(struct _adapter *padapter,
case LED_CTL_START_WPS_BOTTON:
if (pLed->bLedWPSBlinkInProgress == false) {
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
pLed->bLedWPSBlinkInProgress = true;
@@ -1214,15 +1214,15 @@ static void SwLedControlMode2(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
mod_timer(&pLed->BlinkTimer,
@@ -1248,7 +1248,7 @@ static void SwLedControlMode3(struct _adapter *padapter,
if (IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedScanBlinkInProgress = true;
@@ -1286,11 +1286,11 @@ static void SwLedControlMode3(struct _adapter *padapter,
pLed->CurrLedState = LED_ON;
pLed->BlinkingLedState = LED_ON;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
mod_timer(&pLed->BlinkTimer,
@@ -1300,11 +1300,11 @@ static void SwLedControlMode3(struct _adapter *padapter,
case LED_CTL_START_WPS_BOTTON:
if (pLed->bLedWPSBlinkInProgress == false) {
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
pLed->bLedWPSBlinkInProgress = true;
@@ -1319,7 +1319,7 @@ static void SwLedControlMode3(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS:
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&(pLed->BlinkTimer));
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
} else
pLed->bLedWPSBlinkInProgress = true;
@@ -1336,7 +1336,7 @@ static void SwLedControlMode3(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS_FAIL:
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->CurrLedState = LED_OFF;
@@ -1357,15 +1357,15 @@ static void SwLedControlMode3(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
mod_timer(&pLed->BlinkTimer,
@@ -1388,7 +1388,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
case LED_CTL_START_TO_LINK:
if (pLed1->bLedWPSBlinkInProgress) {
pLed1->bLedWPSBlinkInProgress = false;
- del_timer_sync(&pLed1->BlinkTimer);
+ del_timer(&pLed1->BlinkTimer);
pLed1->BlinkingLedState = LED_OFF;
pLed1->CurrLedState = LED_OFF;
if (pLed1->bLedOn)
@@ -1400,11 +1400,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
pLed->bLedStartToLinkBlinkInProgress = true;
@@ -1426,7 +1426,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
if (LedAction == LED_CTL_LINK) {
if (pLed1->bLedWPSBlinkInProgress) {
pLed1->bLedWPSBlinkInProgress = false;
- del_timer_sync(&pLed1->BlinkTimer);
+ del_timer(&pLed1->BlinkTimer);
pLed1->BlinkingLedState = LED_OFF;
pLed1->CurrLedState = LED_OFF;
if (pLed1->bLedOn)
@@ -1439,7 +1439,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -1460,11 +1460,11 @@ static void SwLedControlMode4(struct _adapter *padapter,
if (IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedScanBlinkInProgress = true;
@@ -1485,7 +1485,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
IS_LED_WPS_BLINKING(pLed))
return;
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
pLed->bLedBlinkInProgress = true;
@@ -1503,7 +1503,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
case LED_CTL_START_WPS_BOTTON:
if (pLed1->bLedWPSBlinkInProgress) {
pLed1->bLedWPSBlinkInProgress = false;
- del_timer_sync(&(pLed1->BlinkTimer));
+ del_timer(&pLed1->BlinkTimer);
pLed1->BlinkingLedState = LED_OFF;
pLed1->CurrLedState = LED_OFF;
if (pLed1->bLedOn)
@@ -1512,15 +1512,15 @@ static void SwLedControlMode4(struct _adapter *padapter,
}
if (pLed->bLedWPSBlinkInProgress == false) {
if (pLed->bLedNoLinkBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
pLed->bLedWPSBlinkInProgress = true;
@@ -1538,7 +1538,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS: /*WPS connect success*/
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -1552,7 +1552,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS_FAIL: /*WPS authentication fail*/
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -1565,7 +1565,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
/*LED1 settings*/
if (pLed1->bLedWPSBlinkInProgress)
- del_timer_sync(&pLed1->BlinkTimer);
+ del_timer(&pLed1->BlinkTimer);
else
pLed1->bLedWPSBlinkInProgress = true;
pLed1->CurrLedState = LED_BLINK_WPS_STOP;
@@ -1578,7 +1578,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
break;
case LED_CTL_STOP_WPS_FAIL_OVERLAP: /*WPS session overlap*/
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->bLedNoLinkBlinkInProgress = true;
@@ -1591,7 +1591,7 @@ static void SwLedControlMode4(struct _adapter *padapter,
msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
/*LED1 settings*/
if (pLed1->bLedWPSBlinkInProgress)
- del_timer_sync(&pLed1->BlinkTimer);
+ del_timer(&pLed1->BlinkTimer);
else
pLed1->bLedWPSBlinkInProgress = true;
pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
@@ -1607,31 +1607,31 @@ static void SwLedControlMode4(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedNoLinkBlinkInProgress = false;
}
if (pLed->bLedLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedLinkBlinkInProgress = false;
}
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
if (pLed->bLedScanBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedScanBlinkInProgress = false;
}
if (pLed->bLedStartToLinkBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedStartToLinkBlinkInProgress = false;
}
if (pLed1->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed1->BlinkTimer);
+ del_timer(&pLed1->BlinkTimer);
pLed1->bLedWPSBlinkInProgress = false;
}
pLed1->BlinkingLedState = LED_UNKNOWN;
@@ -1671,7 +1671,7 @@ static void SwLedControlMode5(struct _adapter *padapter,
; /* dummy branch */
else if (pLed->bLedScanBlinkInProgress == false) {
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedScanBlinkInProgress = true;
@@ -1705,7 +1705,7 @@ static void SwLedControlMode5(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
SwLedOff(padapter, pLed);
@@ -1756,7 +1756,7 @@ static void SwLedControlMode6(struct _adapter *padapter,
case LED_CTL_START_WPS_BOTTON:
if (pLed->bLedWPSBlinkInProgress == false) {
if (pLed->bLedBlinkInProgress == true) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
pLed->bLedWPSBlinkInProgress = true;
@@ -1772,7 +1772,7 @@ static void SwLedControlMode6(struct _adapter *padapter,
case LED_CTL_STOP_WPS_FAIL:
case LED_CTL_STOP_WPS:
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
pLed->CurrLedState = LED_ON;
@@ -1784,11 +1784,11 @@ static void SwLedControlMode6(struct _adapter *padapter,
pLed->CurrLedState = LED_OFF;
pLed->BlinkingLedState = LED_OFF;
if (pLed->bLedBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedBlinkInProgress = false;
}
if (pLed->bLedWPSBlinkInProgress) {
- del_timer_sync(&pLed->BlinkTimer);
+ del_timer(&pLed->BlinkTimer);
pLed->bLedWPSBlinkInProgress = false;
}
SwLedOff(padapter, pLed);
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index 1a1c38f885d6..e35854d28f90 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -910,7 +910,7 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
if (pcmd->res != H2C_SUCCESS)
mod_timer(&pmlmepriv->assoc_timer,
jiffies + msecs_to_jiffies(1));
- del_timer_sync(&pmlmepriv->assoc_timer);
+ del_timer(&pmlmepriv->assoc_timer);
#ifdef __BIG_ENDIAN
/* endian_convert */
pnetwork->Length = le32_to_cpu(pnetwork->Length);
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index fb2b195b90af..c044b0e55ba9 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -582,7 +582,7 @@ void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
spin_lock_irqsave(&pmlmepriv->lock, irqL);
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
- del_timer_sync(&pmlmepriv->scan_to_timer);
+ del_timer(&pmlmepriv->scan_to_timer);
_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
}
@@ -696,7 +696,7 @@ void r8712_ind_disconnect(struct _adapter *padapter)
}
if (padapter->pwrctrlpriv.pwr_mode !=
padapter->registrypriv.power_mgnt) {
- del_timer_sync(&pmlmepriv->dhcp_timer);
+ del_timer(&pmlmepriv->dhcp_timer);
r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
padapter->registrypriv.smart_ps);
}
@@ -910,7 +910,7 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
== true)
r8712_indicate_connect(adapter);
- del_timer_sync(&pmlmepriv->assoc_timer);
+ del_timer(&pmlmepriv->assoc_timer);
} else
goto ignore_joinbss_callback;
} else {
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
index aaa584435c87..9bc04f474d18 100644
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c
+++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
@@ -103,7 +103,7 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter,
if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80))
return;
- del_timer_sync(&padapter->pwrctrlpriv.rpwm_check_timer);
+ del_timer(&padapter->pwrctrlpriv.rpwm_check_timer);
_enter_pwrlock(&pwrpriv->lock);
pwrpriv->cpwm = (preportpwrstate->state) & 0xf;
if (pwrpriv->cpwm >= PS_STATE_S2) {
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 7bb96c47f188..a9b93d0f6f56 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -198,7 +198,7 @@ void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
* cancel reordering_ctrl_timer */
for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ del_timer(&preorder_ctrl->reordering_ctrl_timer);
}
spin_lock(&(pfree_sta_queue->lock));
/* insert into free_sta_queue; 20061114 */
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index cc57a3a6b02b..396344cb011f 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -162,6 +162,17 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
return put_user(x, ptr);
}
+static inline int tty_copy_to_user(struct tty_struct *tty,
+ void __user *to,
+ const void *from,
+ unsigned long n)
+{
+ struct n_tty_data *ldata = tty->disc_data;
+
+ tty_audit_add_data(tty, to, n, ldata->icanon);
+ return copy_to_user(to, from, n);
+}
+
/**
* n_tty_kick_worker - start input worker (if required)
* @tty: terminal
@@ -2070,8 +2081,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
size = N_TTY_BUF_SIZE - tail;
n = eol - tail;
- if (n > 4096)
- n += 4096;
+ if (n > N_TTY_BUF_SIZE)
+ n += N_TTY_BUF_SIZE;
n += found;
c = n;
@@ -2084,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
__func__, eol, found, n, c, size, more);
if (n > size) {
- ret = copy_to_user(*b, read_buf_addr(ldata, tail), size);
+ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size);
if (ret)
return -EFAULT;
- ret = copy_to_user(*b + size, ldata->read_buf, n - size);
+ ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size);
} else
- ret = copy_to_user(*b, read_buf_addr(ldata, tail), n);
+ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n);
if (ret)
return -EFAULT;
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 9289999cb7c6..dce1a23706e8 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -562,12 +562,36 @@ static irqreturn_t omap_wake_irq(int irq, void *dev_id)
return IRQ_NONE;
}
+#ifdef CONFIG_SERIAL_8250_DMA
+static int omap_8250_dma_handle_irq(struct uart_port *port);
+#endif
+
+static irqreturn_t omap8250_irq(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int iir;
+ int ret;
+
+#ifdef CONFIG_SERIAL_8250_DMA
+ if (up->dma) {
+ ret = omap_8250_dma_handle_irq(port);
+ return IRQ_RETVAL(ret);
+ }
+#endif
+
+ serial8250_rpm_get(up);
+ iir = serial_port_in(port, UART_IIR);
+ ret = serial8250_handle_irq(port, iir);
+ serial8250_rpm_put(up);
+
+ return IRQ_RETVAL(ret);
+}
+
static int omap_8250_startup(struct uart_port *port)
{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
+ struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = port->private_data;
-
int ret;
if (priv->wakeirq) {
@@ -580,10 +604,31 @@ static int omap_8250_startup(struct uart_port *port)
pm_runtime_get_sync(port->dev);
- ret = serial8250_do_startup(port);
- if (ret)
+ up->mcr = 0;
+ serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+ up->lsr_saved_flags = 0;
+ up->msr_saved_flags = 0;
+
+ if (up->dma) {
+ ret = serial8250_request_dma(up);
+ if (ret) {
+ dev_warn_ratelimited(port->dev,
+ "failed to request DMA\n");
+ up->dma = NULL;
+ }
+ }
+
+ ret = request_irq(port->irq, omap8250_irq, IRQF_SHARED,
+ dev_name(port->dev), port);
+ if (ret < 0)
goto err;
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+
#ifdef CONFIG_PM
up->capabilities |= UART_CAP_RPM;
#endif
@@ -610,8 +655,7 @@ err:
static void omap_8250_shutdown(struct uart_port *port)
{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
+ struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = port->private_data;
flush_work(&priv->qos_work);
@@ -621,11 +665,24 @@ static void omap_8250_shutdown(struct uart_port *port)
pm_runtime_get_sync(port->dev);
serial_out(up, UART_OMAP_WER, 0);
- serial8250_do_shutdown(port);
+
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
+ if (up->dma)
+ serial8250_release_dma(up);
+
+ /*
+ * Disable break condition and FIFOs
+ */
+ if (up->lcr & UART_LCR_SBC)
+ serial_out(up, UART_LCR, up->lcr & ~UART_LCR_SBC);
+ serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
pm_runtime_mark_last_busy(port->dev);
pm_runtime_put_autosuspend(port->dev);
+ free_irq(port->irq, port);
if (priv->wakeirq)
free_irq(priv->wakeirq, port);
}
@@ -974,6 +1031,13 @@ static inline int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
}
#endif
+static int omap8250_no_handle_irq(struct uart_port *port)
+{
+ /* IRQ has not been requested but handling irq? */
+ WARN_ONCE(1, "Unexpected irq handling before port startup\n");
+ return 0;
+}
+
static int omap8250_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1075,6 +1139,7 @@ static int omap8250_probe(struct platform_device *pdev)
pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(&up, priv);
+ up.port.handle_irq = omap8250_no_handle_irq;
#ifdef CONFIG_SERIAL_8250_DMA
if (pdev->dev.of_node) {
/*
@@ -1088,7 +1153,6 @@ static int omap8250_probe(struct platform_device *pdev)
ret = of_property_count_strings(pdev->dev.of_node, "dma-names");
if (ret == 2) {
up.dma = &priv->omap8250_dma;
- up.port.handle_irq = omap_8250_dma_handle_irq;
priv->omap8250_dma.fn = the_no_dma_filter_fn;
priv->omap8250_dma.tx_dma = omap_8250_tx_dma;
priv->omap8250_dma.rx_dma = omap_8250_rx_dma;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6f5a0720a8c8..763eb20fe321 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1249,20 +1249,19 @@ __acquires(&uap->port.lock)
/*
* Transmit a character
- * There must be at least one free entry in the TX FIFO to accept the char.
*
- * Returns true if the FIFO might have space in it afterwards;
- * returns false if the FIFO definitely became full.
+ * Returns true if the character was successfully queued to the FIFO.
+ * Returns false otherwise.
*/
static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
{
+ if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+ return false; /* unable to transmit character */
+
writew(c, uap->port.membase + UART01x_DR);
uap->port.icount.tx++;
- if (likely(uap->tx_irq_seen > 1))
- return true;
-
- return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
+ return true;
}
static bool pl011_tx_chars(struct uart_amba_port *uap)
@@ -1296,7 +1295,8 @@ static bool pl011_tx_chars(struct uart_amba_port *uap)
return false;
if (uap->port.x_char) {
- pl011_tx_char(uap, uap->port.x_char);
+ if (!pl011_tx_char(uap, uap->port.x_char))
+ goto done;
uap->port.x_char = 0;
--count;
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index c8cfa0637128..88250395b0ce 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -911,6 +911,14 @@ static void dma_rx_callback(void *data)
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue;
+
+ if (readl(sport->port.membase + USR2) & USR2_IDLE) {
+ /* In condition [3] the SDMA counted up too early */
+ count--;
+
+ writel(USR2_IDLE, sport->port.membase + USR2);
+ }
+
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) {
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index fdab715a0631..c0eafa6fd403 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -339,7 +339,7 @@
#define DWC3_DGCMD_SET_ENDPOINT_NRDY 0x0c
#define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10
-#define DWC3_DGCMD_STATUS(n) (((n) >> 15) & 1)
+#define DWC3_DGCMD_STATUS(n) (((n) >> 12) & 0x0F)
#define DWC3_DGCMD_CMDACT (1 << 10)
#define DWC3_DGCMD_CMDIOC (1 << 8)
@@ -355,7 +355,7 @@
#define DWC3_DEPCMD_PARAM_SHIFT 16
#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT)
#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
-#define DWC3_DEPCMD_STATUS(x) (((x) >> 15) & 1)
+#define DWC3_DEPCMD_STATUS(x) (((x) >> 12) & 0x0F)
#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11)
#define DWC3_DEPCMD_CMDACT (1 << 10)
#define DWC3_DEPCMD_CMDIOC (1 << 8)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 6bdb57069044..3507f880eb74 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -315,7 +315,6 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
return ret;
}
- set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
return len;
}
break;
@@ -847,7 +846,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
ret = ep->status;
if (io_data->read && ret > 0) {
ret = copy_to_iter(data, ret, &io_data->data);
- if (unlikely(iov_iter_count(&io_data->data)))
+ if (!ret)
ret = -EFAULT;
}
}
@@ -1463,8 +1462,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
{
ENTER();
- if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
- ffs_closed(ffs);
+ ffs_closed(ffs);
BUG_ON(ffs->gadget);
@@ -3422,9 +3420,13 @@ static int ffs_ready(struct ffs_data *ffs)
ffs_obj->desc_ready = true;
ffs_obj->ffs_data = ffs;
- if (ffs_obj->ffs_ready_callback)
+ if (ffs_obj->ffs_ready_callback) {
ret = ffs_obj->ffs_ready_callback(ffs);
+ if (ret)
+ goto done;
+ }
+ set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags);
done:
ffs_dev_unlock();
return ret;
@@ -3443,7 +3445,8 @@ static void ffs_closed(struct ffs_data *ffs)
ffs_obj->desc_ready = false;
- if (ffs_obj->ffs_closed_callback)
+ if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) &&
+ ffs_obj->ffs_closed_callback)
ffs_obj->ffs_closed_callback(ffs);
if (!ffs_obj->opts || ffs_obj->opts->no_configfs
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 259b656c0b3e..6316aa5b1c49 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -973,7 +973,13 @@ static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
int result;
mutex_lock(&opts->lock);
- result = strlcpy(page, opts->id, PAGE_SIZE);
+ if (opts->id) {
+ result = strlcpy(page, opts->id, PAGE_SIZE);
+ } else {
+ page[0] = 0;
+ result = 0;
+ }
+
mutex_unlock(&opts->lock);
return result;
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 9719abfb6145..7856b3394494 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -588,7 +588,10 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (intf == 1) {
if (alt == 1) {
- config_ep_by_speed(cdev->gadget, f, out_ep);
+ err = config_ep_by_speed(cdev->gadget, f, out_ep);
+ if (err)
+ return err;
+
usb_ep_enable(out_ep);
out_ep->driver_data = audio;
audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index 7b9ef7e257d2..e821931c965c 100644
--- a/drivers/usb/gadget/legacy/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -304,8 +304,10 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
gfs_registered = true;
ret = usb_composite_probe(&gfs_driver);
- if (unlikely(ret < 0))
+ if (unlikely(ret < 0)) {
+ ++missing_funcs;
gfs_registered = false;
+ }
return ret;
}
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index b808951491cc..99fd9a5667df 100644
--- a/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1487,7 +1487,7 @@ static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
dprintk(DEBUG_NORMAL, "%s()\n", __func__);
- s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
+ s3c2410_udc_set_pullup(udc, is_on);
return 0;
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ec8ac1674854..36bf089b708f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3682,18 +3682,21 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned long flags;
- int ret;
+ int ret, slot_id;
struct xhci_command *command;
command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
if (!command)
return 0;
+ /* xhci->slot_id and xhci->addr_dev are not thread-safe */
+ mutex_lock(&xhci->mutex);
spin_lock_irqsave(&xhci->lock, flags);
command->completion = &xhci->addr_dev;
ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
+ mutex_unlock(&xhci->mutex);
xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
kfree(command);
return 0;
@@ -3702,8 +3705,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
spin_unlock_irqrestore(&xhci->lock, flags);
wait_for_completion(command->completion);
+ slot_id = xhci->slot_id;
+ mutex_unlock(&xhci->mutex);
- if (!xhci->slot_id || command->status != COMP_SUCCESS) {
+ if (!slot_id || command->status != COMP_SUCCESS) {
xhci_err(xhci, "Error while assigning device slot ID\n");
xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n",
HCS_MAX_SLOTS(
@@ -3728,11 +3733,11 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
* xhci_discover_or_reset_device(), which may be called as part of
* mass storage driver error handling.
*/
- if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) {
+ if (!xhci_alloc_virt_device(xhci, slot_id, udev, GFP_NOIO)) {
xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
goto disable_slot;
}
- udev->slot_id = xhci->slot_id;
+ udev->slot_id = slot_id;
#ifndef CONFIG_USB_DEFAULT_PERSIST
/*
@@ -3778,12 +3783,15 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_slot_ctx *slot_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
u64 temp_64;
- struct xhci_command *command;
+ struct xhci_command *command = NULL;
+
+ mutex_lock(&xhci->mutex);
if (!udev->slot_id) {
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Bad Slot ID %d", udev->slot_id);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
virt_dev = xhci->devs[udev->slot_id];
@@ -3796,7 +3804,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
*/
xhci_warn(xhci, "Virt dev invalid for slot_id 0x%x!\n",
udev->slot_id);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (setup == SETUP_CONTEXT_ONLY) {
@@ -3804,13 +3813,15 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
SLOT_STATE_DEFAULT) {
xhci_dbg(xhci, "Slot already in default state\n");
- return 0;
+ goto out;
}
}
command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
- if (!command)
- return -ENOMEM;
+ if (!command) {
+ ret = -ENOMEM;
+ goto out;
+ }
command->in_ctx = virt_dev->in_ctx;
command->completion = &xhci->addr_dev;
@@ -3820,8 +3831,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
if (!ctrl_ctx) {
xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
__func__);
- kfree(command);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/*
* If this is the first Set Address since device plug-in or
@@ -3848,8 +3859,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"FIXME: allocate a command ring segment");
- kfree(command);
- return ret;
+ goto out;
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -3896,10 +3906,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
ret = -EINVAL;
break;
}
- if (ret) {
- kfree(command);
- return ret;
- }
+ if (ret)
+ goto out;
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Op regs DCBAA ptr = %#016llx", temp_64);
@@ -3932,8 +3940,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Internal device address = %d",
le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
+out:
+ mutex_unlock(&xhci->mutex);
kfree(command);
- return 0;
+ return ret;
}
int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
@@ -4855,6 +4865,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
return 0;
}
+ mutex_init(&xhci->mutex);
xhci->cap_regs = hcd->regs;
xhci->op_regs = hcd->regs +
HC_LENGTH(readl(&xhci->cap_regs->hc_capbase));
@@ -5011,4 +5022,12 @@ static int __init xhci_hcd_init(void)
BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
return 0;
}
+
+/*
+ * If an init function is provided, an exit function must also be provided
+ * to allow module unload.
+ */
+static void __exit xhci_hcd_fini(void) { }
+
module_init(xhci_hcd_init);
+module_exit(xhci_hcd_fini);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index ea75e8ccd3c1..6977f8491fa7 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1497,6 +1497,8 @@ struct xhci_hcd {
struct list_head lpm_failed_devs;
/* slot enabling and address device helpers */
+ /* these are not thread safe so use mutex */
+ struct mutex mutex;
struct completion addr_dev;
int slot_id;
/* For USB 3.0 LPM enable/disable. */
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 3789b08ef67b..6dca3d794ced 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2021,13 +2021,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
if (musb->ops->quirks)
musb->io.quirks = musb->ops->quirks;
- /* At least tusb6010 has it's own offsets.. */
- if (musb->ops->ep_offset)
- musb->io.ep_offset = musb->ops->ep_offset;
- if (musb->ops->ep_select)
- musb->io.ep_select = musb->ops->ep_select;
-
- /* ..and some devices use indexed offset or flat offset */
+ /* Most devices use indexed offset or flat offset */
if (musb->io.quirks & MUSB_INDEXED_EP) {
musb->io.ep_offset = musb_indexed_ep_offset;
musb->io.ep_select = musb_indexed_ep_select;
@@ -2036,6 +2030,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->io.ep_select = musb_flat_ep_select;
}
+ /* At least tusb6010 has its own offsets */
+ if (musb->ops->ep_offset)
+ musb->io.ep_offset = musb->ops->ep_offset;
+ if (musb->ops->ep_select)
+ musb->io.ep_select = musb->ops->ep_select;
+
if (musb->ops->fifo_mode)
fifo_mode = musb->ops->fifo_mode;
else
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 7225d526df04..03ab0c699f74 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -1179,7 +1179,7 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev,
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
ab8500_usb_link_status_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
+ IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT,
"usb-link-status", ab);
if (err < 0) {
dev_err(ab->dev, "request_irq failed for link status irq\n");
@@ -1195,7 +1195,7 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev,
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
ab8500_usb_disconnect_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
+ IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT,
"usb-id-fall", ab);
if (err < 0) {
dev_err(ab->dev, "request_irq failed for ID fall irq\n");
@@ -1211,7 +1211,7 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev,
}
err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
ab8500_usb_disconnect_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
+ IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT,
"usb-vbus-fall", ab);
if (err < 0) {
dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index 845f658276b1..2b28443d07b9 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -401,7 +401,8 @@ static int tahvo_usb_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, tu);
tu->irq = platform_get_irq(pdev, 0);
- ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, 0,
+ ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt,
+ IRQF_ONESHOT,
"tahvo-vbus", tu);
if (ret) {
dev_err(&pdev->dev, "could not register tahvo-vbus irq: %d\n",
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 8597cf9cfceb..c0f5c652d272 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -611,6 +611,8 @@ struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
{
struct usbhs_pipe *pipe = pkt->pipe;
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+ struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv);
if (usbhs_pipe_is_busy(pipe))
return 0;
@@ -624,6 +626,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_data_sequence(pipe, pkt->sequence);
pkt->sequence = -1; /* -1 sequence will be ignored */
+ if (usbhs_pipe_is_dcp(pipe))
+ usbhsf_fifo_clear(pipe, fifo);
+
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
usbhs_pipe_enable(pipe);
usbhs_pipe_running(pipe, 1);
@@ -673,7 +678,14 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
*is_done = 1;
usbhsf_rx_irq_ctrl(pipe, 0);
usbhs_pipe_running(pipe, 0);
- usbhs_pipe_disable(pipe); /* disable pipe first */
+ /*
+ * If function mode, since this controller is possible to enter
+ * Control Write status stage at this timing, this driver
+ * should not disable the pipe. If such a case happens, this
+ * controller is not able to complete the status stage.
+ */
+ if (!usbhs_mod_is_host(priv) && !usbhs_pipe_is_dcp(pipe))
+ usbhs_pipe_disable(pipe); /* disable pipe first */
}
/*
@@ -1227,15 +1239,21 @@ static void usbhsf_dma_init_dt(struct device *dev, struct usbhs_fifo *fifo,
{
char name[16];
- snprintf(name, sizeof(name), "tx%d", channel);
- fifo->tx_chan = dma_request_slave_channel_reason(dev, name);
- if (IS_ERR(fifo->tx_chan))
- fifo->tx_chan = NULL;
-
- snprintf(name, sizeof(name), "rx%d", channel);
- fifo->rx_chan = dma_request_slave_channel_reason(dev, name);
- if (IS_ERR(fifo->rx_chan))
- fifo->rx_chan = NULL;
+ /*
+ * To avoid complex handing for DnFIFOs, the driver uses each
+ * DnFIFO as TX or RX direction (not bi-direction).
+ * So, the driver uses odd channels for TX, even channels for RX.
+ */
+ snprintf(name, sizeof(name), "ch%d", channel);
+ if (channel & 1) {
+ fifo->tx_chan = dma_request_slave_channel_reason(dev, name);
+ if (IS_ERR(fifo->tx_chan))
+ fifo->tx_chan = NULL;
+ } else {
+ fifo->rx_chan = dma_request_slave_channel_reason(dev, name);
+ if (IS_ERR(fifo->rx_chan))
+ fifo->rx_chan = NULL;
+ }
}
static void usbhsf_dma_init(struct usbhs_priv *priv, struct usbhs_fifo *fifo,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 9031750e7404..ffd739e31bfc 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -128,6 +128,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
{ USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */
{ USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
+ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8eb68a31cab6..4c8b3b82103d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -699,6 +699,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
+ { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 4e4f46f3c89c..792e054126de 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -155,6 +155,7 @@
#define XSENS_AWINDA_STATION_PID 0x0101
#define XSENS_AWINDA_DONGLE_PID 0x0102
#define XSENS_MTW_PID 0x0200 /* Xsens MTw */
+#define XSENS_MTDEVBOARD_PID 0x0300 /* Motion Tracker Development Board */
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */
/* Xsens devices using FTDI VID */
diff --git a/fs/fhandle.c b/fs/fhandle.c
index 999ff5c3cab0..d59712dfa3e7 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -195,8 +195,9 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
goto out_err;
}
/* copy the full handle */
- if (copy_from_user(handle, ufh,
- sizeof(struct file_handle) +
+ *handle = f_handle;
+ if (copy_from_user(&handle->f_handle,
+ &ufh->f_handle,
f_handle.handle_bytes)) {
retval = -EFAULT;
goto out_handle;
diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 000000000000..70ee3833a7a0
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * 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 __DT_BINDINGS_CLOCK_HI6220_H
+#define __DT_BINDINGS_CLOCK_HI6220_H
+
+/* clk in Hi6220 AO (always on) controller */
+#define HI6220_NONE_CLOCK 0
+
+/* fixed rate clocks */
+#define HI6220_REF32K 1
+#define HI6220_CLK_TCXO 2
+#define HI6220_MMC1_PAD 3
+#define HI6220_MMC2_PAD 4
+#define HI6220_MMC0_PAD 5
+#define HI6220_PLL_BBP 6
+#define HI6220_PLL_GPU 7
+#define HI6220_PLL1_DDR 8
+#define HI6220_PLL_SYS 9
+#define HI6220_PLL_SYS_MEDIA 10
+#define HI6220_DDR_SRC 11
+#define HI6220_PLL_MEDIA 12
+#define HI6220_PLL_DDR 13
+
+/* fixed factor clocks */
+#define HI6220_300M 14
+#define HI6220_150M 15
+#define HI6220_PICOPHY_SRC 16
+#define HI6220_MMC0_SRC_SEL 17
+#define HI6220_MMC1_SRC_SEL 18
+#define HI6220_MMC2_SRC_SEL 19
+#define HI6220_VPU_CODEC 20
+#define HI6220_MMC0_SMP 21
+#define HI6220_MMC1_SMP 22
+#define HI6220_MMC2_SMP 23
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK 24
+#define HI6220_WDT1_PCLK 25
+#define HI6220_WDT2_PCLK 26
+#define HI6220_TIMER0_PCLK 27
+#define HI6220_TIMER1_PCLK 28
+#define HI6220_TIMER2_PCLK 29
+#define HI6220_TIMER3_PCLK 30
+#define HI6220_TIMER4_PCLK 31
+#define HI6220_TIMER5_PCLK 32
+#define HI6220_TIMER6_PCLK 33
+#define HI6220_TIMER7_PCLK 34
+#define HI6220_TIMER8_PCLK 35
+#define HI6220_UART0_PCLK 36
+
+#define HI6220_AO_NR_CLKS 37
+
+/* clk in Hi6220 systrl */
+/* gate clock */
+#define HI6220_MMC0_CLK 1
+#define HI6220_MMC0_CIUCLK 2
+#define HI6220_MMC1_CLK 3
+#define HI6220_MMC1_CIUCLK 4
+#define HI6220_MMC2_CLK 5
+#define HI6220_MMC2_CIUCLK 6
+#define HI6220_USBOTG_HCLK 7
+#define HI6220_CLK_PICOPHY 8
+#define HI6220_HIFI 9
+#define HI6220_DACODEC_PCLK 10
+#define HI6220_EDMAC_ACLK 11
+#define HI6220_CS_ATB 12
+#define HI6220_I2C0_CLK 13
+#define HI6220_I2C1_CLK 14
+#define HI6220_I2C2_CLK 15
+#define HI6220_I2C3_CLK 16
+#define HI6220_UART1_PCLK 17
+#define HI6220_UART2_PCLK 18
+#define HI6220_UART3_PCLK 19
+#define HI6220_UART4_PCLK 20
+#define HI6220_SPI_CLK 21
+#define HI6220_TSENSOR_CLK 22
+#define HI6220_MMU_CLK 23
+#define HI6220_HIFI_SEL 24
+#define HI6220_MMC0_SYSPLL 25
+#define HI6220_MMC1_SYSPLL 26
+#define HI6220_MMC2_SYSPLL 27
+#define HI6220_MMC0_SEL 28
+#define HI6220_MMC1_SEL 29
+#define HI6220_BBPPLL_SEL 30
+#define HI6220_MEDIA_PLL_SRC 31
+#define HI6220_MMC2_SEL 32
+#define HI6220_CS_ATB_SYSPLL 33
+
+/* mux clocks */
+#define HI6220_MMC0_SRC 34
+#define HI6220_MMC0_SMP_IN 35
+#define HI6220_MMC1_SRC 36
+#define HI6220_MMC1_SMP_IN 37
+#define HI6220_MMC2_SRC 38
+#define HI6220_MMC2_SMP_IN 39
+#define HI6220_HIFI_SRC 40
+#define HI6220_UART1_SRC 41
+#define HI6220_UART2_SRC 42
+#define HI6220_UART3_SRC 43
+#define HI6220_UART4_SRC 44
+#define HI6220_MMC0_MUX0 45
+#define HI6220_MMC1_MUX0 46
+#define HI6220_MMC2_MUX0 47
+#define HI6220_MMC0_MUX1 48
+#define HI6220_MMC1_MUX1 49
+#define HI6220_MMC2_MUX1 50
+
+/* divider clocks */
+#define HI6220_CLK_BUS 51
+#define HI6220_MMC0_DIV 52
+#define HI6220_MMC1_DIV 53
+#define HI6220_MMC2_DIV 54
+#define HI6220_HIFI_DIV 55
+#define HI6220_BBPPLL0_DIV 56
+#define HI6220_CS_DAPB 57
+#define HI6220_CS_ATB_DIV 58
+
+#define HI6220_SYS_NR_CLKS 59
+
+/* clk in Hi6220 media controller */
+/* gate clocks */
+#define HI6220_DSI_PCLK 1
+#define HI6220_G3D_PCLK 2
+#define HI6220_ACLK_CODEC_VPU 3
+#define HI6220_ISP_SCLK 4
+#define HI6220_ADE_CORE 5
+#define HI6220_MED_MMU 6
+#define HI6220_CFG_CSI4PHY 7
+#define HI6220_CFG_CSI2PHY 8
+#define HI6220_ISP_SCLK_GATE 9
+#define HI6220_ISP_SCLK_GATE1 10
+#define HI6220_ADE_CORE_GATE 11
+#define HI6220_CODEC_VPU_GATE 12
+#define HI6220_MED_SYSPLL 13
+
+/* mux clocks */
+#define HI6220_1440_1200 14
+#define HI6220_1000_1200 15
+#define HI6220_1000_1440 16
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG 17
+#define HI6220_ISP_SCLK_SRC 18
+#define HI6220_ISP_SCLK1 19
+#define HI6220_ADE_CORE_SRC 20
+#define HI6220_ADE_PIX_SRC 21
+#define HI6220_G3D_CLK 22
+#define HI6220_CODEC_VPU_SRC 23
+
+#define HI6220_MEDIA_NR_CLKS 24
+
+/* clk in Hi6220 power controller */
+/* gate clocks */
+#define HI6220_PLL_GPU_GATE 1
+#define HI6220_PLL1_DDR_GATE 2
+#define HI6220_PLL_DDR_GATE 3
+#define HI6220_PLL_MEDIA_GATE 4
+#define HI6220_PLL0_BBP_GATE 5
+
+/* divider clocks */
+#define HI6220_DDRC_SRC 6
+#define HI6220_DDRC_AXI1 7
+
+#define HI6220_POWER_NR_CLKS 8
+#endif
diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h
index 591f7fba89e2..7a510384a82a 100644
--- a/include/dt-bindings/clock/marvell,mmp2.h
+++ b/include/dt-bindings/clock/marvell,mmp2.h
@@ -48,6 +48,7 @@
#define MMP2_CLK_SSP1 78
#define MMP2_CLK_SSP2 79
#define MMP2_CLK_SSP3 80
+#define MMP2_CLK_TIMER 81
/* axi periphrals */
#define MMP2_CLK_SDH0 101
diff --git a/include/dt-bindings/clock/marvell,pxa168.h b/include/dt-bindings/clock/marvell,pxa168.h
index 79630b9d74b8..3e45bdfe1aa4 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -18,7 +18,9 @@
#define PXA168_CLK_PLL1_13_1_5 18
#define PXA168_CLK_PLL1_2_1_5 19
#define PXA168_CLK_PLL1_3_16 20
+#define PXA168_CLK_PLL1_192 21
#define PXA168_CLK_UART_PLL 27
+#define PXA168_CLK_USB_PLL 28
/* apb periphrals */
#define PXA168_CLK_TWSI0 60
@@ -40,6 +42,7 @@
#define PXA168_CLK_SSP2 76
#define PXA168_CLK_SSP3 77
#define PXA168_CLK_SSP4 78
+#define PXA168_CLK_TIMER 79
/* axi periphrals */
#define PXA168_CLK_DFC 100
diff --git a/include/dt-bindings/clock/marvell,pxa1928.h b/include/dt-bindings/clock/marvell,pxa1928.h
new file mode 100644
index 000000000000..d4f2e18919ff
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,pxa1928.h
@@ -0,0 +1,57 @@
+#ifndef __DTS_MARVELL_PXA1928_CLOCK_H
+#define __DTS_MARVELL_PXA1928_CLOCK_H
+
+/*
+ * Clock ID values here correspond to the control register offset/4.
+ */
+
+/* apb peripherals */
+#define PXA1928_CLK_RTC 0x00
+#define PXA1928_CLK_TWSI0 0x01
+#define PXA1928_CLK_TWSI1 0x02
+#define PXA1928_CLK_TWSI2 0x03
+#define PXA1928_CLK_TWSI3 0x04
+#define PXA1928_CLK_OWIRE 0x05
+#define PXA1928_CLK_KPC 0x06
+#define PXA1928_CLK_TB_ROTARY 0x07
+#define PXA1928_CLK_SW_JTAG 0x08
+#define PXA1928_CLK_TIMER1 0x09
+#define PXA1928_CLK_UART0 0x0b
+#define PXA1928_CLK_UART1 0x0c
+#define PXA1928_CLK_UART2 0x0d
+#define PXA1928_CLK_GPIO 0x0e
+#define PXA1928_CLK_PWM0 0x0f
+#define PXA1928_CLK_PWM1 0x10
+#define PXA1928_CLK_PWM2 0x11
+#define PXA1928_CLK_PWM3 0x12
+#define PXA1928_CLK_SSP0 0x13
+#define PXA1928_CLK_SSP1 0x14
+#define PXA1928_CLK_SSP2 0x15
+
+#define PXA1928_CLK_TWSI4 0x1f
+#define PXA1928_CLK_TWSI5 0x20
+#define PXA1928_CLK_UART3 0x22
+#define PXA1928_CLK_THSENS_GLOB 0x24
+#define PXA1928_CLK_THSENS_CPU 0x26
+#define PXA1928_CLK_THSENS_VPU 0x27
+#define PXA1928_CLK_THSENS_GC 0x28
+#define PXA1928_APBC_NR_CLKS 0x30
+
+
+/* axi peripherals */
+#define PXA1928_CLK_SDH0 0x15
+#define PXA1928_CLK_SDH1 0x16
+#define PXA1928_CLK_USB 0x17
+#define PXA1928_CLK_NAND 0x18
+#define PXA1928_CLK_DMA 0x19
+
+#define PXA1928_CLK_SDH2 0x3a
+#define PXA1928_CLK_SDH3 0x3b
+#define PXA1928_CLK_HSIC 0x3e
+#define PXA1928_CLK_SDH4 0x57
+#define PXA1928_CLK_GC3D 0x5d
+#define PXA1928_CLK_GC2D 0x5f
+
+#define PXA1928_APMU_NR_CLKS 0x60
+
+#endif
diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h
index 719cffb2bea2..135082a0b62f 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -18,7 +18,9 @@
#define PXA910_CLK_PLL1_13_1_5 18
#define PXA910_CLK_PLL1_2_1_5 19
#define PXA910_CLK_PLL1_3_16 20
+#define PXA910_CLK_PLL1_192 21
#define PXA910_CLK_UART_PLL 27
+#define PXA910_CLK_USB_PLL 28
/* apb periphrals */
#define PXA910_CLK_TWSI0 60
@@ -37,6 +39,8 @@
#define PXA910_CLK_UART2 73
#define PXA910_CLK_SSP0 74
#define PXA910_CLK_SSP1 75
+#define PXA910_CLK_TIMER0 76
+#define PXA910_CLK_TIMER1 77
/* axi periphrals */
#define PXA910_CLK_DFC 100
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
new file mode 100644
index 000000000000..bd2720d58e0c
--- /dev/null
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -0,0 +1,25 @@
+/*
+ * Meson8b clock tree IDs
+ */
+
+#ifndef __MESON8B_CLKC_H
+#define __MESON8B_CLKC_H
+
+#define CLKID_UNUSED 0
+#define CLKID_XTAL 1
+#define CLKID_PLL_FIXED 2
+#define CLKID_PLL_VID 3
+#define CLKID_PLL_SYS 4
+#define CLKID_FCLK_DIV2 5
+#define CLKID_FCLK_DIV3 6
+#define CLKID_FCLK_DIV4 7
+#define CLKID_FCLK_DIV5 8
+#define CLKID_FCLK_DIV7 9
+#define CLKID_CLK81 10
+#define CLKID_MALI 11
+#define CLKID_CPUCLK 12
+#define CLKID_ZERO 13
+
+#define CLK_NR_CLKS (CLKID_ZERO + 1)
+
+#endif /* __MESON8B_CLKC_H */
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 000000000000..6dac6c091dd2
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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 _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_DSI0_LNTC_DSICLK 1
+#define CLK_TOP_HDMITX_CLKDIG_CTS 2
+#define CLK_TOP_CLKPH_MCK 3
+#define CLK_TOP_CPUM_TCK_IN 4
+#define CLK_TOP_MAINPLL_806M 5
+#define CLK_TOP_MAINPLL_537P3M 6
+#define CLK_TOP_MAINPLL_322P4M 7
+#define CLK_TOP_MAINPLL_230P3M 8
+#define CLK_TOP_UNIVPLL_624M 9
+#define CLK_TOP_UNIVPLL_416M 10
+#define CLK_TOP_UNIVPLL_249P6M 11
+#define CLK_TOP_UNIVPLL_178P3M 12
+#define CLK_TOP_UNIVPLL_48M 13
+#define CLK_TOP_MMPLL_D2 14
+#define CLK_TOP_MMPLL_D3 15
+#define CLK_TOP_MMPLL_D5 16
+#define CLK_TOP_MMPLL_D7 17
+#define CLK_TOP_MMPLL_D4 18
+#define CLK_TOP_MMPLL_D6 19
+#define CLK_TOP_SYSPLL_D2 20
+#define CLK_TOP_SYSPLL_D4 21
+#define CLK_TOP_SYSPLL_D6 22
+#define CLK_TOP_SYSPLL_D8 23
+#define CLK_TOP_SYSPLL_D10 24
+#define CLK_TOP_SYSPLL_D12 25
+#define CLK_TOP_SYSPLL_D16 26
+#define CLK_TOP_SYSPLL_D24 27
+#define CLK_TOP_SYSPLL_D3 28
+#define CLK_TOP_SYSPLL_D2P5 29
+#define CLK_TOP_SYSPLL_D5 30
+#define CLK_TOP_SYSPLL_D3P5 31
+#define CLK_TOP_UNIVPLL1_D2 32
+#define CLK_TOP_UNIVPLL1_D4 33
+#define CLK_TOP_UNIVPLL1_D6 34
+#define CLK_TOP_UNIVPLL1_D8 35
+#define CLK_TOP_UNIVPLL1_D10 36
+#define CLK_TOP_UNIVPLL2_D2 37
+#define CLK_TOP_UNIVPLL2_D4 38
+#define CLK_TOP_UNIVPLL2_D6 39
+#define CLK_TOP_UNIVPLL2_D8 40
+#define CLK_TOP_UNIVPLL_D3 41
+#define CLK_TOP_UNIVPLL_D5 42
+#define CLK_TOP_UNIVPLL_D7 43
+#define CLK_TOP_UNIVPLL_D10 44
+#define CLK_TOP_UNIVPLL_D26 45
+#define CLK_TOP_APLL 46
+#define CLK_TOP_APLL_D4 47
+#define CLK_TOP_APLL_D8 48
+#define CLK_TOP_APLL_D16 49
+#define CLK_TOP_APLL_D24 50
+#define CLK_TOP_LVDSPLL_D2 51
+#define CLK_TOP_LVDSPLL_D4 52
+#define CLK_TOP_LVDSPLL_D8 53
+#define CLK_TOP_LVDSTX_CLKDIG_CT 54
+#define CLK_TOP_VPLL_DPIX 55
+#define CLK_TOP_TVHDMI_H 56
+#define CLK_TOP_HDMITX_CLKDIG_D2 57
+#define CLK_TOP_HDMITX_CLKDIG_D3 58
+#define CLK_TOP_TVHDMI_D2 59
+#define CLK_TOP_TVHDMI_D4 60
+#define CLK_TOP_MEMPLL_MCK_D4 61
+#define CLK_TOP_AXI_SEL 62
+#define CLK_TOP_SMI_SEL 63
+#define CLK_TOP_MFG_SEL 64
+#define CLK_TOP_IRDA_SEL 65
+#define CLK_TOP_CAM_SEL 66
+#define CLK_TOP_AUD_INTBUS_SEL 67
+#define CLK_TOP_JPG_SEL 68
+#define CLK_TOP_DISP_SEL 69
+#define CLK_TOP_MSDC30_1_SEL 70
+#define CLK_TOP_MSDC30_2_SEL 71
+#define CLK_TOP_MSDC30_3_SEL 72
+#define CLK_TOP_MSDC30_4_SEL 73
+#define CLK_TOP_USB20_SEL 74
+#define CLK_TOP_VENC_SEL 75
+#define CLK_TOP_SPI_SEL 76
+#define CLK_TOP_UART_SEL 77
+#define CLK_TOP_MEM_SEL 78
+#define CLK_TOP_CAMTG_SEL 79
+#define CLK_TOP_AUDIO_SEL 80
+#define CLK_TOP_FIX_SEL 81
+#define CLK_TOP_VDEC_SEL 82
+#define CLK_TOP_DDRPHYCFG_SEL 83
+#define CLK_TOP_DPILVDS_SEL 84
+#define CLK_TOP_PMICSPI_SEL 85
+#define CLK_TOP_MSDC30_0_SEL 86
+#define CLK_TOP_SMI_MFG_AS_SEL 87
+#define CLK_TOP_GCPU_SEL 88
+#define CLK_TOP_DPI1_SEL 89
+#define CLK_TOP_CCI_SEL 90
+#define CLK_TOP_APLL_SEL 91
+#define CLK_TOP_HDMIPLL_SEL 92
+#define CLK_TOP_NR_CLK 93
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMPLL1 1
+#define CLK_APMIXED_ARMPLL2 2
+#define CLK_APMIXED_MAINPLL 3
+#define CLK_APMIXED_UNIVPLL 4
+#define CLK_APMIXED_MMPLL 5
+#define CLK_APMIXED_MSDCPLL 6
+#define CLK_APMIXED_TVDPLL 7
+#define CLK_APMIXED_LVDSPLL 8
+#define CLK_APMIXED_AUDPLL 9
+#define CLK_APMIXED_VDECPLL 10
+#define CLK_APMIXED_NR_CLK 11
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_PMIC_WRAP 1
+#define CLK_INFRA_PMICSPI 2
+#define CLK_INFRA_CCIF1_AP_CTRL 3
+#define CLK_INFRA_CCIF0_AP_CTRL 4
+#define CLK_INFRA_KP 5
+#define CLK_INFRA_CPUM 6
+#define CLK_INFRA_M4U 7
+#define CLK_INFRA_MFGAXI 8
+#define CLK_INFRA_DEVAPC 9
+#define CLK_INFRA_AUDIO 10
+#define CLK_INFRA_MFG_BUS 11
+#define CLK_INFRA_SMI 12
+#define CLK_INFRA_DBGCLK 13
+#define CLK_INFRA_NR_CLK 14
+
+/* PERI_SYS */
+
+#define CLK_PERI_I2C5 1
+#define CLK_PERI_I2C4 2
+#define CLK_PERI_I2C3 3
+#define CLK_PERI_I2C2 4
+#define CLK_PERI_I2C1 5
+#define CLK_PERI_I2C0 6
+#define CLK_PERI_UART3 7
+#define CLK_PERI_UART2 8
+#define CLK_PERI_UART1 9
+#define CLK_PERI_UART0 10
+#define CLK_PERI_IRDA 11
+#define CLK_PERI_NLI 12
+#define CLK_PERI_MD_HIF 13
+#define CLK_PERI_AP_HIF 14
+#define CLK_PERI_MSDC30_3 15
+#define CLK_PERI_MSDC30_2 16
+#define CLK_PERI_MSDC30_1 17
+#define CLK_PERI_MSDC20_2 18
+#define CLK_PERI_MSDC20_1 19
+#define CLK_PERI_AP_DMA 20
+#define CLK_PERI_USB1 21
+#define CLK_PERI_USB0 22
+#define CLK_PERI_PWM 23
+#define CLK_PERI_PWM7 24
+#define CLK_PERI_PWM6 25
+#define CLK_PERI_PWM5 26
+#define CLK_PERI_PWM4 27
+#define CLK_PERI_PWM3 28
+#define CLK_PERI_PWM2 29
+#define CLK_PERI_PWM1 30
+#define CLK_PERI_THERM 31
+#define CLK_PERI_NFI 32
+#define CLK_PERI_USBSLV 33
+#define CLK_PERI_USB1_MCU 34
+#define CLK_PERI_USB0_MCU 35
+#define CLK_PERI_GCPU 36
+#define CLK_PERI_FHCTL 37
+#define CLK_PERI_SPI1 38
+#define CLK_PERI_AUXADC 39
+#define CLK_PERI_PERI_PWRAP 40
+#define CLK_PERI_I2C6 41
+#define CLK_PERI_UART0_SEL 42
+#define CLK_PERI_UART1_SEL 43
+#define CLK_PERI_UART2_SEL 44
+#define CLK_PERI_UART3_SEL 45
+#define CLK_PERI_NR_CLK 46
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
new file mode 100644
index 000000000000..4ad76ed882ad
--- /dev/null
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * 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.
+ *
+ * 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 _DT_BINDINGS_CLK_MT8173_H
+#define _DT_BINDINGS_CLK_MT8173_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_CLKPH_MCK_O 1
+#define CLK_TOP_DPI 2
+#define CLK_TOP_USB_SYSPLL_125M 3
+#define CLK_TOP_HDMITX_DIG_CTS 4
+#define CLK_TOP_ARMCA7PLL_754M 5
+#define CLK_TOP_ARMCA7PLL_502M 6
+#define CLK_TOP_MAIN_H546M 7
+#define CLK_TOP_MAIN_H364M 8
+#define CLK_TOP_MAIN_H218P4M 9
+#define CLK_TOP_MAIN_H156M 10
+#define CLK_TOP_TVDPLL_445P5M 11
+#define CLK_TOP_TVDPLL_594M 12
+#define CLK_TOP_UNIV_624M 13
+#define CLK_TOP_UNIV_416M 14
+#define CLK_TOP_UNIV_249P6M 15
+#define CLK_TOP_UNIV_178P3M 16
+#define CLK_TOP_UNIV_48M 17
+#define CLK_TOP_CLKRTC_EXT 18
+#define CLK_TOP_CLKRTC_INT 19
+#define CLK_TOP_FPC 20
+#define CLK_TOP_HDMITXPLL_D2 21
+#define CLK_TOP_HDMITXPLL_D3 22
+#define CLK_TOP_ARMCA7PLL_D2 23
+#define CLK_TOP_ARMCA7PLL_D3 24
+#define CLK_TOP_APLL1 25
+#define CLK_TOP_APLL2 26
+#define CLK_TOP_DMPLL 27
+#define CLK_TOP_DMPLL_D2 28
+#define CLK_TOP_DMPLL_D4 29
+#define CLK_TOP_DMPLL_D8 30
+#define CLK_TOP_DMPLL_D16 31
+#define CLK_TOP_LVDSPLL_D2 32
+#define CLK_TOP_LVDSPLL_D4 33
+#define CLK_TOP_LVDSPLL_D8 34
+#define CLK_TOP_MMPLL 35
+#define CLK_TOP_MMPLL_D2 36
+#define CLK_TOP_MSDCPLL 37
+#define CLK_TOP_MSDCPLL_D2 38
+#define CLK_TOP_MSDCPLL_D4 39
+#define CLK_TOP_MSDCPLL2 40
+#define CLK_TOP_MSDCPLL2_D2 41
+#define CLK_TOP_MSDCPLL2_D4 42
+#define CLK_TOP_SYSPLL_D2 43
+#define CLK_TOP_SYSPLL1_D2 44
+#define CLK_TOP_SYSPLL1_D4 45
+#define CLK_TOP_SYSPLL1_D8 46
+#define CLK_TOP_SYSPLL1_D16 47
+#define CLK_TOP_SYSPLL_D3 48
+#define CLK_TOP_SYSPLL2_D2 49
+#define CLK_TOP_SYSPLL2_D4 50
+#define CLK_TOP_SYSPLL_D5 51
+#define CLK_TOP_SYSPLL3_D2 52
+#define CLK_TOP_SYSPLL3_D4 53
+#define CLK_TOP_SYSPLL_D7 54
+#define CLK_TOP_SYSPLL4_D2 55
+#define CLK_TOP_SYSPLL4_D4 56
+#define CLK_TOP_TVDPLL 57
+#define CLK_TOP_TVDPLL_D2 58
+#define CLK_TOP_TVDPLL_D4 59
+#define CLK_TOP_TVDPLL_D8 60
+#define CLK_TOP_TVDPLL_D16 61
+#define CLK_TOP_UNIVPLL_D2 62
+#define CLK_TOP_UNIVPLL1_D2 63
+#define CLK_TOP_UNIVPLL1_D4 64
+#define CLK_TOP_UNIVPLL1_D8 65
+#define CLK_TOP_UNIVPLL_D3 66
+#define CLK_TOP_UNIVPLL2_D2 67
+#define CLK_TOP_UNIVPLL2_D4 68
+#define CLK_TOP_UNIVPLL2_D8 69
+#define CLK_TOP_UNIVPLL_D5 70
+#define CLK_TOP_UNIVPLL3_D2 71
+#define CLK_TOP_UNIVPLL3_D4 72
+#define CLK_TOP_UNIVPLL3_D8 73
+#define CLK_TOP_UNIVPLL_D7 74
+#define CLK_TOP_UNIVPLL_D26 75
+#define CLK_TOP_UNIVPLL_D52 76
+#define CLK_TOP_VCODECPLL 77
+#define CLK_TOP_VCODECPLL_370P5 78
+#define CLK_TOP_VENCPLL 79
+#define CLK_TOP_VENCPLL_D2 80
+#define CLK_TOP_VENCPLL_D4 81
+#define CLK_TOP_AXI_SEL 82
+#define CLK_TOP_MEM_SEL 83
+#define CLK_TOP_DDRPHYCFG_SEL 84
+#define CLK_TOP_MM_SEL 85
+#define CLK_TOP_PWM_SEL 86
+#define CLK_TOP_VDEC_SEL 87
+#define CLK_TOP_VENC_SEL 88
+#define CLK_TOP_MFG_SEL 89
+#define CLK_TOP_CAMTG_SEL 90
+#define CLK_TOP_UART_SEL 91
+#define CLK_TOP_SPI_SEL 92
+#define CLK_TOP_USB20_SEL 93
+#define CLK_TOP_USB30_SEL 94
+#define CLK_TOP_MSDC50_0_H_SEL 95
+#define CLK_TOP_MSDC50_0_SEL 96
+#define CLK_TOP_MSDC30_1_SEL 97
+#define CLK_TOP_MSDC30_2_SEL 98
+#define CLK_TOP_MSDC30_3_SEL 99
+#define CLK_TOP_AUDIO_SEL 100
+#define CLK_TOP_AUD_INTBUS_SEL 101
+#define CLK_TOP_PMICSPI_SEL 102
+#define CLK_TOP_SCP_SEL 103
+#define CLK_TOP_ATB_SEL 104
+#define CLK_TOP_VENC_LT_SEL 105
+#define CLK_TOP_DPI0_SEL 106
+#define CLK_TOP_IRDA_SEL 107
+#define CLK_TOP_CCI400_SEL 108
+#define CLK_TOP_AUD_1_SEL 109
+#define CLK_TOP_AUD_2_SEL 110
+#define CLK_TOP_MEM_MFG_IN_SEL 111
+#define CLK_TOP_AXI_MFG_IN_SEL 112
+#define CLK_TOP_SCAM_SEL 113
+#define CLK_TOP_SPINFI_IFR_SEL 114
+#define CLK_TOP_HDMI_SEL 115
+#define CLK_TOP_DPILVDS_SEL 116
+#define CLK_TOP_MSDC50_2_H_SEL 117
+#define CLK_TOP_HDCP_SEL 118
+#define CLK_TOP_HDCP_24M_SEL 119
+#define CLK_TOP_RTC_SEL 120
+#define CLK_TOP_APLL1_DIV0 121
+#define CLK_TOP_APLL1_DIV1 122
+#define CLK_TOP_APLL1_DIV2 123
+#define CLK_TOP_APLL1_DIV3 124
+#define CLK_TOP_APLL1_DIV4 125
+#define CLK_TOP_APLL1_DIV5 126
+#define CLK_TOP_APLL2_DIV0 127
+#define CLK_TOP_APLL2_DIV1 128
+#define CLK_TOP_APLL2_DIV2 129
+#define CLK_TOP_APLL2_DIV3 130
+#define CLK_TOP_APLL2_DIV4 131
+#define CLK_TOP_APLL2_DIV5 132
+#define CLK_TOP_I2S0_M_SEL 133
+#define CLK_TOP_I2S1_M_SEL 134
+#define CLK_TOP_I2S2_M_SEL 135
+#define CLK_TOP_I2S3_M_SEL 136
+#define CLK_TOP_I2S3_B_SEL 137
+#define CLK_TOP_NR_CLK 138
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMCA15PLL 1
+#define CLK_APMIXED_ARMCA7PLL 2
+#define CLK_APMIXED_MAINPLL 3
+#define CLK_APMIXED_UNIVPLL 4
+#define CLK_APMIXED_MMPLL 5
+#define CLK_APMIXED_MSDCPLL 6
+#define CLK_APMIXED_VENCPLL 7
+#define CLK_APMIXED_TVDPLL 8
+#define CLK_APMIXED_MPLL 9
+#define CLK_APMIXED_VCODECPLL 10
+#define CLK_APMIXED_APLL1 11
+#define CLK_APMIXED_APLL2 12
+#define CLK_APMIXED_LVDSPLL 13
+#define CLK_APMIXED_MSDCPLL2 14
+#define CLK_APMIXED_NR_CLK 15
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_DBGCLK 1
+#define CLK_INFRA_SMI 2
+#define CLK_INFRA_AUDIO 3
+#define CLK_INFRA_GCE 4
+#define CLK_INFRA_L2C_SRAM 5
+#define CLK_INFRA_M4U 6
+#define CLK_INFRA_CPUM 7
+#define CLK_INFRA_KP 8
+#define CLK_INFRA_CEC 9
+#define CLK_INFRA_PMICSPI 10
+#define CLK_INFRA_PMICWRAP 11
+#define CLK_INFRA_NR_CLK 12
+
+/* PERI_SYS */
+
+#define CLK_PERI_NFI 1
+#define CLK_PERI_THERM 2
+#define CLK_PERI_PWM1 3
+#define CLK_PERI_PWM2 4
+#define CLK_PERI_PWM3 5
+#define CLK_PERI_PWM4 6
+#define CLK_PERI_PWM5 7
+#define CLK_PERI_PWM6 8
+#define CLK_PERI_PWM7 9
+#define CLK_PERI_PWM 10
+#define CLK_PERI_USB0 11
+#define CLK_PERI_USB1 12
+#define CLK_PERI_AP_DMA 13
+#define CLK_PERI_MSDC30_0 14
+#define CLK_PERI_MSDC30_1 15
+#define CLK_PERI_MSDC30_2 16
+#define CLK_PERI_MSDC30_3 17
+#define CLK_PERI_NLI_ARB 18
+#define CLK_PERI_IRDA 19
+#define CLK_PERI_UART0 20
+#define CLK_PERI_UART1 21
+#define CLK_PERI_UART2 22
+#define CLK_PERI_UART3 23
+#define CLK_PERI_I2C0 24
+#define CLK_PERI_I2C1 25
+#define CLK_PERI_I2C2 26
+#define CLK_PERI_I2C3 27
+#define CLK_PERI_I2C4 28
+#define CLK_PERI_AUXADC 29
+#define CLK_PERI_SPI0 30
+#define CLK_PERI_I2C5 31
+#define CLK_PERI_NFIECC 32
+#define CLK_PERI_SPI 33
+#define CLK_PERI_IRRX 34
+#define CLK_PERI_I2C6 35
+#define CLK_PERI_UART0_SEL 36
+#define CLK_PERI_UART1_SEL 37
+#define CLK_PERI_UART2_SEL 38
+#define CLK_PERI_UART3_SEL 39
+#define CLK_PERI_NR_CLK 40
+
+#endif /* _DT_BINDINGS_CLK_MT8173_H */
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 000000000000..1fb629508db2
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ *
+ * 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 _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST 0
+#define MT8135_INFRA_DRAMC0_A0_RST 1
+#define MT8135_INFRA_CCIF0_RST 2
+#define MT8135_INFRA_APCIRQ_EINT_RST 3
+#define MT8135_INFRA_APXGPT_RST 4
+#define MT8135_INFRA_SCPSYS_RST 5
+#define MT8135_INFRA_CCIF1_RST 6
+#define MT8135_INFRA_PMIC_WRAP_RST 7
+#define MT8135_INFRA_KP_RST 8
+#define MT8135_INFRA_EMI_RST 32
+#define MT8135_INFRA_DRAMC0_RST 34
+#define MT8135_INFRA_SMI_RST 35
+#define MT8135_INFRA_M4U_RST 36
+
+/* PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST 0
+#define MT8135_PERI_UART1_SW_RST 1
+#define MT8135_PERI_UART2_SW_RST 2
+#define MT8135_PERI_UART3_SW_RST 3
+#define MT8135_PERI_IRDA_SW_RST 4
+#define MT8135_PERI_PTP_SW_RST 5
+#define MT8135_PERI_AP_HIF_SW_RST 6
+#define MT8135_PERI_GPCU_SW_RST 7
+#define MT8135_PERI_MD_HIF_SW_RST 8
+#define MT8135_PERI_NLI_SW_RST 9
+#define MT8135_PERI_AUXADC_SW_RST 10
+#define MT8135_PERI_DMA_SW_RST 11
+#define MT8135_PERI_NFI_SW_RST 14
+#define MT8135_PERI_PWM_SW_RST 15
+#define MT8135_PERI_THERM_SW_RST 16
+#define MT8135_PERI_MSDC0_SW_RST 17
+#define MT8135_PERI_MSDC1_SW_RST 18
+#define MT8135_PERI_MSDC2_SW_RST 19
+#define MT8135_PERI_MSDC3_SW_RST 20
+#define MT8135_PERI_I2C0_SW_RST 22
+#define MT8135_PERI_I2C1_SW_RST 23
+#define MT8135_PERI_I2C2_SW_RST 24
+#define MT8135_PERI_I2C3_SW_RST 25
+#define MT8135_PERI_I2C4_SW_RST 26
+#define MT8135_PERI_I2C5_SW_RST 27
+#define MT8135_PERI_I2C6_SW_RST 28
+#define MT8135_PERI_USB_SW_RST 29
+#define MT8135_PERI_SPI1_SW_RST 33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 000000000000..9464b37cf68c
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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.
+ *
+ * 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 _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST 0
+#define MT8173_INFRA_DRAMC0_A0_RST 1
+#define MT8173_INFRA_APCIRQ_EINT_RST 3
+#define MT8173_INFRA_APXGPT_RST 4
+#define MT8173_INFRA_SCPSYS_RST 5
+#define MT8173_INFRA_KP_RST 6
+#define MT8173_INFRA_PMIC_WRAP_RST 7
+#define MT8173_INFRA_MPIP_RST 8
+#define MT8173_INFRA_CEC_RST 9
+#define MT8173_INFRA_EMI_RST 32
+#define MT8173_INFRA_DRAMC0_RST 34
+#define MT8173_INFRA_APMIXEDSYS_RST 35
+#define MT8173_INFRA_MIPI_DSI_RST 36
+#define MT8173_INFRA_TRNG_RST 37
+#define MT8173_INFRA_SYSIRQ_RST 38
+#define MT8173_INFRA_MIPI_CSI_RST 39
+#define MT8173_INFRA_GCE_FAXI_RST 40
+#define MT8173_INFRA_MMIOMMURST 47
+
+
+/* PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST 0
+#define MT8173_PERI_UART1_SW_RST 1
+#define MT8173_PERI_UART2_SW_RST 2
+#define MT8173_PERI_UART3_SW_RST 3
+#define MT8173_PERI_IRRX_SW_RST 4
+#define MT8173_PERI_PWM_SW_RST 8
+#define MT8173_PERI_AUXADC_SW_RST 10
+#define MT8173_PERI_DMA_SW_RST 11
+#define MT8173_PERI_I2C6_SW_RST 13
+#define MT8173_PERI_NFI_SW_RST 14
+#define MT8173_PERI_THERM_SW_RST 16
+#define MT8173_PERI_MSDC2_SW_RST 17
+#define MT8173_PERI_MSDC3_SW_RST 18
+#define MT8173_PERI_MSDC0_SW_RST 19
+#define MT8173_PERI_MSDC1_SW_RST 20
+#define MT8173_PERI_I2C0_SW_RST 22
+#define MT8173_PERI_I2C1_SW_RST 23
+#define MT8173_PERI_I2C2_SW_RST 24
+#define MT8173_PERI_I2C3_SW_RST 25
+#define MT8173_PERI_I2C4_SW_RST 26
+#define MT8173_PERI_HDMI_SW_RST 29
+#define MT8173_PERI_SPI0_SW_RST 33
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index aff923ae8c4b..d87d8eced064 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -116,7 +116,6 @@ __printf(3, 4)
int bdi_register(struct backing_dev_info *bdi, struct device *parent,
const char *fmt, ...);
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
-void bdi_unregister(struct backing_dev_info *bdi);
int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
enum wb_reason reason);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df695313f975..4a943d13625b 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -209,7 +209,7 @@ struct clk_ops {
struct clk_init_data {
const char *name;
const struct clk_ops *ops;
- const char **parent_names;
+ const char * const *parent_names;
u8 num_parents;
unsigned long flags;
};
@@ -426,12 +426,14 @@ extern const struct clk_ops clk_mux_ops;
extern const struct clk_ops clk_mux_ro_ops;
struct clk *clk_register_mux(struct device *dev, const char *name,
- const char **parent_names, u8 num_parents, unsigned long flags,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock);
struct clk *clk_register_mux_table(struct device *dev, const char *name,
- const char **parent_names, u8 num_parents, unsigned long flags,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
@@ -457,7 +459,7 @@ struct clk_fixed_factor {
unsigned int div;
};
-extern struct clk_ops clk_fixed_factor_ops;
+extern const struct clk_ops clk_fixed_factor_ops;
struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div);
@@ -518,7 +520,7 @@ struct clk_composite {
};
struct clk *clk_register_composite(struct device *dev, const char *name,
- const char **parent_names, int num_parents,
+ const char * const *parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
@@ -624,6 +626,8 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
void *data);
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
int of_clk_get_parent_count(struct device_node *np);
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+ unsigned int size);
const char *of_clk_get_parent_name(struct device_node *np, int index);
void of_clk_init(const struct of_device_id *matches);
diff --git a/include/linux/of.h b/include/linux/of.h
index ddeaae6d2083..b871ff9d81d7 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -121,6 +121,8 @@ extern struct device_node *of_stdout;
extern raw_spinlock_t devtree_lock;
#ifdef CONFIG_OF
+void of_core_init(void);
+
static inline bool is_of_node(struct fwnode_handle *fwnode)
{
return fwnode && fwnode->type == FWNODE_OF;
@@ -376,6 +378,10 @@ bool of_console_check(struct device_node *dn, char *name, int index);
#else /* CONFIG_OF */
+static inline void of_core_init(void)
+{
+}
+
static inline bool is_of_node(struct fwnode_handle *fwnode)
{
return false;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 61992cf2e977..d8a82a89f35a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -92,8 +92,6 @@ struct hw_perf_event_extra {
int idx; /* index in shared_regs->regs[] */
};
-struct event_constraint;
-
/**
* struct hw_perf_event - performance event hardware details:
*/
@@ -112,8 +110,6 @@ struct hw_perf_event {
struct hw_perf_event_extra extra_reg;
struct hw_perf_event_extra branch_reg;
-
- struct event_constraint *constraint;
};
struct { /* software */
struct hrtimer hrtimer;
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 497bc14cdb85..0320bbb7d7b5 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -98,7 +98,8 @@ struct inet_connection_sock {
const struct tcp_congestion_ops *icsk_ca_ops;
const struct inet_connection_sock_af_ops *icsk_af_ops;
unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
- __u8 icsk_ca_state:7,
+ __u8 icsk_ca_state:6,
+ icsk_ca_setsockopt:1,
icsk_ca_dst_locked:1;
__u8 icsk_retransmits;
__u8 icsk_pending;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8e3668b44c29..fc57f6b82fc5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -354,7 +354,7 @@ enum ieee80211_rssi_event_data {
};
/**
- * enum ieee80211_rssi_event - data attached to an %RSSI_EVENT
+ * struct ieee80211_rssi_event - data attached to an %RSSI_EVENT
* @data: See &enum ieee80211_rssi_event_data
*/
struct ieee80211_rssi_event {
@@ -388,7 +388,7 @@ enum ieee80211_mlme_event_status {
};
/**
- * enum ieee80211_mlme_event - data attached to an %MLME_EVENT
+ * struct ieee80211_mlme_event - data attached to an %MLME_EVENT
* @data: See &enum ieee80211_mlme_event_data
* @status: See &enum ieee80211_mlme_event_status
* @reason: the reason code if applicable
@@ -401,9 +401,10 @@ struct ieee80211_mlme_event {
/**
* struct ieee80211_event - event to be sent to the driver
- * @type The event itself. See &enum ieee80211_event_type.
+ * @type: The event itself. See &enum ieee80211_event_type.
* @rssi: relevant if &type is %RSSI_EVENT
* @mlme: relevant if &type is %AUTH_EVENT
+ * @u: union holding the above two fields
*/
struct ieee80211_event {
enum ieee80211_event_type type;
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 880dd7437172..c178d13d6f4c 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -250,7 +250,6 @@ DEFINE_EVENT(writeback_class, name, \
DEFINE_WRITEBACK_EVENT(writeback_nowork);
DEFINE_WRITEBACK_EVENT(writeback_wake_background);
DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
-DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
DECLARE_EVENT_CLASS(wbc_class,
TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi),
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index 984169a819ee..d7f1cbc3766c 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -26,6 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. */
#include <linux/types.h>
+#include <linux/virtio_types.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
diff --git a/kernel/compat.c b/kernel/compat.c
index 24f00610c575..333d364be29d 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -912,7 +912,8 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
* bitmap. We must however ensure the end of the
* kernel bitmap is zeroed.
*/
- if (nr_compat_longs-- > 0) {
+ if (nr_compat_longs) {
+ nr_compat_longs--;
if (__get_user(um, umask))
return -EFAULT;
} else {
@@ -954,7 +955,8 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
* We dont want to write past the end of the userspace
* bitmap.
*/
- if (nr_compat_longs-- > 0) {
+ if (nr_compat_longs) {
+ nr_compat_longs--;
if (__put_user(um, umask))
return -EFAULT;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 1a3bf48743ce..eddf1ed4155e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3442,7 +3442,6 @@ static void free_event_rcu(struct rcu_head *head)
if (event->ns)
put_pid_ns(event->ns);
perf_event_free_filter(event);
- perf_event_free_bpf_prog(event);
kfree(event);
}
@@ -3573,6 +3572,8 @@ static void __free_event(struct perf_event *event)
put_callchain_buffers();
}
+ perf_event_free_bpf_prog(event);
+
if (event->destroy)
event->destroy(event);
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 232f00f273cb..725c416085e3 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -493,6 +493,20 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
rb->aux_pages[rb->aux_nr_pages] = page_address(page++);
}
+ /*
+ * In overwrite mode, PMUs that don't support SG may not handle more
+ * than one contiguous allocation, since they rely on PMI to do double
+ * buffering. In this case, the entire buffer has to be one contiguous
+ * chunk.
+ */
+ if ((event->pmu->capabilities & PERF_PMU_CAP_AUX_NO_SG) &&
+ overwrite) {
+ struct page *page = virt_to_page(rb->aux_pages[0]);
+
+ if (page_private(page) != max_order)
+ goto out;
+ }
+
rb->aux_priv = event->pmu->setup_aux(event->cpu, rb->aux_pages, nr_pages,
overwrite);
if (!rb->aux_priv)
diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c
index a28df5206d95..fe9a32591c24 100644
--- a/lib/strnlen_user.c
+++ b/lib/strnlen_user.c
@@ -57,7 +57,8 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
return res + find_zero(data) + 1 - align;
}
res += sizeof(unsigned long);
- if (unlikely(max < sizeof(unsigned long)))
+ /* We already handled 'unsigned long' bytes. Did we do it all ? */
+ if (unlikely(max <= sizeof(unsigned long)))
break;
max -= sizeof(unsigned long);
if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
@@ -89,8 +90,15 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
* Get the size of a NUL-terminated string in user space.
*
* Returns the size of the string INCLUDING the terminating NUL.
- * If the string is too long, returns 'count+1'.
+ * If the string is too long, returns a number larger than @count. User
+ * has to check the return value against "> count".
* On exception (or invalid count), returns 0.
+ *
+ * NOTE! You should basically never use this function. There is
+ * almost never any valid case for using the length of a user space
+ * string, since the string can be changed at any time by other
+ * threads. Use "strncpy_from_user()" instead to get a stable copy
+ * of the string.
*/
long strnlen_user(const char __user *str, long count)
{
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 4abda074ea45..3c365ab6cf5f 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -537,8 +537,9 @@ EXPORT_SYMBOL_GPL(swiotlb_tbl_map_single);
* Allocates bounce buffer and returns its kernel virtual address.
*/
-phys_addr_t map_single(struct device *hwdev, phys_addr_t phys, size_t size,
- enum dma_data_direction dir)
+static phys_addr_t
+map_single(struct device *hwdev, phys_addr_t phys, size_t size,
+ enum dma_data_direction dir)
{
dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 6dc4580df2af..000e7b3b9896 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -359,23 +359,6 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
flush_delayed_work(&bdi->wb.dwork);
}
-/*
- * Called when the device behind @bdi has been removed or ejected.
- *
- * We can't really do much here except for reducing the dirty ratio at
- * the moment. In the future we should be able to set a flag so that
- * the filesystem can handle errors at mark_inode_dirty time instead
- * of only at writeback time.
- */
-void bdi_unregister(struct backing_dev_info *bdi)
-{
- if (WARN_ON_ONCE(!bdi->dev))
- return;
-
- bdi_set_min_ratio(bdi, 0);
-}
-EXPORT_SYMBOL(bdi_unregister);
-
static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
{
memset(wb, 0, sizeof(*wb));
@@ -443,6 +426,7 @@ void bdi_destroy(struct backing_dev_info *bdi)
int i;
bdi_wb_shutdown(bdi);
+ bdi_set_min_ratio(bdi, 0);
WARN_ON(!list_empty(&bdi->work_list));
WARN_ON(delayed_work_pending(&bdi->wb.dwork));
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index a3abe6ed111e..22fd0419b314 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1822,7 +1822,7 @@ static void br_multicast_query_expired(struct net_bridge *br,
if (query->startup_sent < br->multicast_startup_query_count)
query->startup_sent++;
- RCU_INIT_POINTER(querier, NULL);
+ RCU_INIT_POINTER(querier->port, NULL);
br_multicast_send_query(br, NULL, query);
spin_unlock(&br->multicast_lock);
}
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 24c7c96bf5f8..91180a7fc943 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1117,8 +1117,6 @@ static int do_replace(struct net *net, const void __user *user,
return -ENOMEM;
if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
return -ENOMEM;
- if (tmp.num_counters == 0)
- return -EINVAL;
tmp.name[sizeof(tmp.name) - 1] = 0;
@@ -2161,8 +2159,6 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
return -ENOMEM;
if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
return -ENOMEM;
- if (tmp.num_counters == 0)
- return -EINVAL;
memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 1347e11f5cc9..1d00b8922902 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -359,15 +359,7 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
int err;
struct ethtool_cmd cmd;
- if (!dev->ethtool_ops->get_settings)
- return -EOPNOTSUPP;
-
- if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
- return -EFAULT;
-
- cmd.cmd = ETHTOOL_GSET;
-
- err = dev->ethtool_ops->get_settings(dev, &cmd);
+ err = __ethtool_get_settings(dev, &cmd);
if (err < 0)
return err;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index e6f6cc3a1bcf..392e29a0227d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -359,7 +359,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
*/
ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
if (ds == NULL)
- return NULL;
+ return ERR_PTR(-ENOMEM);
ds->dst = dst;
ds->index = index;
@@ -370,7 +370,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
ret = dsa_switch_setup_one(ds, parent);
if (ret)
- return NULL;
+ return ERR_PTR(ret);
return ds;
}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 421a80b09b62..30b544f025ac 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -256,7 +256,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
aead_givcrypt_set_assoc(req, asg, assoclen);
aead_givcrypt_set_giv(req, esph->enc_data,
- XFRM_SKB_CB(skb)->seq.output.low);
+ XFRM_SKB_CB(skb)->seq.output.low +
+ ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));
ESP_SKB_CB(skb)->tmp = tmp;
err = crypto_aead_givencrypt(req);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 9f7269f3c54a..0c152087ca15 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -65,7 +65,6 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
goto drop;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
- skb->mark = be32_to_cpu(tunnel->parms.i_key);
return xfrm_input(skb, nexthdr, spi, encap_type);
}
@@ -91,6 +90,8 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
struct pcpu_sw_netstats *tstats;
struct xfrm_state *x;
struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
+ u32 orig_mark = skb->mark;
+ int ret;
if (!tunnel)
return 1;
@@ -107,7 +108,11 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
x = xfrm_input_state(skb);
family = x->inner_mode->afinfo->family;
- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ skb->mark = be32_to_cpu(tunnel->parms.i_key);
+ ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
+ skb->mark = orig_mark;
+
+ if (!ret)
return -EPERM;
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
@@ -216,8 +221,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
memset(&fl, 0, sizeof(fl));
- skb->mark = be32_to_cpu(tunnel->parms.o_key);
-
switch (skb->protocol) {
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
@@ -233,6 +236,9 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+ /* override mark with tunnel output key */
+ fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
+
return vti_xmit(skb, dev, &fl);
}
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 7a5ae50c80c8..84be008c945c 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -187,6 +187,7 @@ static void tcp_reinit_congestion_control(struct sock *sk,
tcp_cleanup_congestion_control(sk);
icsk->icsk_ca_ops = ca;
+ icsk->icsk_ca_setsockopt = 1;
if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init)
icsk->icsk_ca_ops->init(sk);
@@ -335,8 +336,10 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
rcu_read_lock();
ca = __tcp_ca_find_autoload(name);
/* No change asking for existing value */
- if (ca == icsk->icsk_ca_ops)
+ if (ca == icsk->icsk_ca_ops) {
+ icsk->icsk_ca_setsockopt = 1;
goto out;
+ }
if (!ca)
err = -ENOENT;
else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b5732a54f2ad..17e7339ee5ca 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -420,7 +420,10 @@ void tcp_ca_openreq_child(struct sock *sk, const struct dst_entry *dst)
rcu_read_unlock();
}
- if (!ca_got_dst && !try_module_get(icsk->icsk_ca_ops->owner))
+ /* If no valid choice made yet, assign current system default ca. */
+ if (!ca_got_dst &&
+ (!icsk->icsk_ca_setsockopt ||
+ !try_module_get(icsk->icsk_ca_ops->owner)))
tcp_assign_congestion_control(sk);
tcp_set_ca_state(sk, TCP_CA_Open);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d10b7e0112eb..1c92ea67baef 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1345,10 +1345,8 @@ csum_copy_err:
}
unlock_sock_fast(sk, slow);
- if (noblock)
- return -EAGAIN;
-
- /* starting over for a new packet */
+ /* starting over for a new packet, but check if we need to yield */
+ cond_resched();
msg->msg_flags &= ~MSG_TRUNC;
goto try_again;
}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 31f1b5d5e2ef..7c07ce36aae2 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -248,7 +248,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
aead_givcrypt_set_assoc(req, asg, assoclen);
aead_givcrypt_set_giv(req, esph->enc_data,
- XFRM_SKB_CB(skb)->seq.output.low);
+ XFRM_SKB_CB(skb)->seq.output.low +
+ ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));
ESP_SKB_CB(skb)->tmp = tmp;
err = crypto_aead_givencrypt(req);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index ed9d681207fa..0224c032dca5 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -322,7 +322,6 @@ static int vti6_rcv(struct sk_buff *skb)
}
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
- skb->mark = be32_to_cpu(t->parms.i_key);
rcu_read_unlock();
@@ -342,6 +341,8 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
struct pcpu_sw_netstats *tstats;
struct xfrm_state *x;
struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
+ u32 orig_mark = skb->mark;
+ int ret;
if (!t)
return 1;
@@ -358,7 +359,11 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
x = xfrm_input_state(skb);
family = x->inner_mode->afinfo->family;
- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ skb->mark = be32_to_cpu(t->parms.i_key);
+ ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
+ skb->mark = orig_mark;
+
+ if (!ret)
return -EPERM;
skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev)));
@@ -430,6 +435,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
struct net_device *tdev;
struct xfrm_state *x;
int err = -1;
+ int mtu;
if (!dst)
goto tx_err_link_failure;
@@ -463,6 +469,19 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
skb_dst_set(skb, dst);
skb->dev = skb_dst(skb)->dev;
+ mtu = dst_mtu(dst);
+ if (!skb->ignore_df && skb->len > mtu) {
+ skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu);
+
+ if (skb->protocol == htons(ETH_P_IPV6))
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ else
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+ htonl(mtu));
+
+ return -EMSGSIZE;
+ }
+
err = dst_output(skb);
if (net_xmit_eval(err) == 0) {
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
@@ -495,7 +514,6 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
int ret;
memset(&fl, 0, sizeof(fl));
- skb->mark = be32_to_cpu(t->parms.o_key);
switch (skb->protocol) {
case htons(ETH_P_IPV6):
@@ -516,6 +534,9 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err;
}
+ /* override mark with tunnel output key */
+ fl.flowi_mark = be32_to_cpu(t->parms.o_key);
+
ret = vti6_xmit(skb, dev, &fl);
if (ret < 0)
goto tx_err;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c2ec41617a35..e51fc3eee6db 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -525,10 +525,8 @@ csum_copy_err:
}
unlock_sock_fast(sk, slow);
- if (noblock)
- return -EAGAIN;
-
- /* starting over for a new packet */
+ /* starting over for a new packet, but check if we need to yield */
+ cond_resched();
msg->msg_flags &= ~MSG_TRUNC;
goto try_again;
}
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 526c4feb3b50..b58286ecd156 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -13,6 +13,8 @@
#include <net/dst.h>
#include <net/ip.h>
#include <net/xfrm.h>
+#include <net/ip_tunnels.h>
+#include <net/ip6_tunnel.h>
static struct kmem_cache *secpath_cachep __read_mostly;
@@ -186,6 +188,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
struct xfrm_state *x = NULL;
xfrm_address_t *daddr;
struct xfrm_mode *inner_mode;
+ u32 mark = skb->mark;
unsigned int family;
int decaps = 0;
int async = 0;
@@ -203,6 +206,18 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
XFRM_SPI_SKB_CB(skb)->daddroff);
family = XFRM_SPI_SKB_CB(skb)->family;
+ /* if tunnel is present override skb->mark value with tunnel i_key */
+ if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4) {
+ switch (family) {
+ case AF_INET:
+ mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4->parms.i_key);
+ break;
+ case AF_INET6:
+ mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6->parms.i_key);
+ break;
+ }
+ }
+
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
@@ -229,7 +244,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop;
}
- x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family);
+ x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family);
if (x == NULL) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
xfrm_audit_state_notfound(skb, family, spi, seq);
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index dab57daae408..4fd725a0c500 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -99,6 +99,7 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
+ XFRM_SKB_CB(skb)->seq.output.hi = 0;
if (unlikely(x->replay.oseq == 0)) {
x->replay.oseq--;
xfrm_audit_state_replay_overflow(x, skb);
@@ -177,6 +178,7 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
+ XFRM_SKB_CB(skb)->seq.output.hi = 0;
if (unlikely(replay_esn->oseq == 0)) {
replay_esn->oseq--;
xfrm_audit_state_replay_overflow(x, skb);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f5e39e35d73a..96688cd0f6f1 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -927,8 +927,8 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
x->id.spi != spi)
continue;
- spin_unlock_bh(&net->xfrm.xfrm_state_lock);
xfrm_state_hold(x);
+ spin_unlock_bh(&net->xfrm.xfrm_state_lock);
return x;
}
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 464168426465..0320cb523d9e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2168,6 +2168,7 @@ static const struct hda_fixup alc882_fixups[] = {
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
@@ -5377,6 +5378,13 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x1d, 0x40700001},
{0x21, 0x02211040}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC255_STANDARD_PINS,
+ {0x12, 0x90a60160},
+ {0x14, 0x90170120},
+ {0x17, 0x40000000},
+ {0x1d, 0x40700001},
+ {0x21, 0x02211030}),
+ SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC256_STANDARD_PINS,
{0x13, 0x40000000}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 31a95cca015d..bab6c04932aa 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -449,6 +449,15 @@ static int via_suspend(struct hda_codec *codec)
return 0;
}
+
+static int via_resume(struct hda_codec *codec)
+{
+ /* some delay here to make jack detection working (bko#98921) */
+ msleep(10);
+ codec->patch_ops.init(codec);
+ regcache_sync(codec->core.regmap);
+ return 0;
+}
#endif
#ifdef CONFIG_PM
@@ -475,6 +484,7 @@ static const struct hda_codec_ops via_patch_ops = {
.stream_pm = snd_hda_gen_stream_pm,
#ifdef CONFIG_PM
.suspend = via_suspend,
+ .resume = via_resume,
.check_power_status = via_check_power_status,
#endif
};
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 3e2ef61c627b..8b7e391dd0b8 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -918,6 +918,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
+ case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
case USB_ID(0x046d, 0x0991):
/* Most audio usb devices lie about volume resolution.
* Most Logitech webcams have res = 384.
@@ -1582,12 +1583,6 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
unitid);
return -EINVAL;
}
- /* no bmControls field (e.g. Maya44) -> ignore */
- if (desc->bLength <= 10 + input_pins) {
- usb_audio_dbg(state->chip, "MU %d has no bmControls field\n",
- unitid);
- return 0;
- }
num_ins = 0;
ich = 0;
@@ -1595,6 +1590,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
err = parse_audio_unit(state, desc->baSourceID[pin]);
if (err < 0)
continue;
+ /* no bmControls field (e.g. Maya44) -> ignore */
+ if (desc->bLength <= 10 + input_pins)
+ continue;
err = check_input_term(state, desc->baSourceID[pin], &iterm);
if (err < 0)
return err;
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index b703cb3cda19..e5000da9e9d7 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -437,6 +437,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
.map = ebox44_map,
},
{
+ /* MAYA44 USB+ */
+ .id = USB_ID(0x2573, 0x0008),
+ .map = maya44_map,
+ },
+ {
/* KEF X300A */
.id = USB_ID(0x27ac, 0x1000),
.map = scms_usb3318_map,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 29175346cc4f..b8c97d092a47 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1120,6 +1120,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
+ case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
return true;
}
return false;
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 5bdb781163d1..9b0d8baf2934 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -5,8 +5,10 @@ include ../lib.mk
.PHONY: all all_32 all_64 warn_32bit_failure clean
TARGETS_C_BOTHBITS := sigreturn single_step_syscall
+TARGETS_C_32BIT_ONLY := entry_from_vm86
-BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32)
+TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
+BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
@@ -32,7 +34,7 @@ all_64: $(BINARIES_64)
clean:
$(RM) $(BINARIES_32) $(BINARIES_64)
-$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c
+$(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c
$(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
new file mode 100644
index 000000000000..5c38a187677b
--- /dev/null
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -0,0 +1,114 @@
+/*
+ * entry_from_vm86.c - tests kernel entries from vm86 mode
+ * Copyright (c) 2014-2015 Andrew Lutomirski
+ *
+ * This exercises a few paths that need to special-case vm86 mode.
+ *
+ * GPL v2.
+ */
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/vm86.h>
+
+static unsigned long load_addr = 0x10000;
+static int nerrs = 0;
+
+asm (
+ ".pushsection .rodata\n\t"
+ ".type vmcode_bound, @object\n\t"
+ "vmcode:\n\t"
+ "vmcode_bound:\n\t"
+ ".code16\n\t"
+ "bound %ax, (2048)\n\t"
+ "int3\n\t"
+ "vmcode_sysenter:\n\t"
+ "sysenter\n\t"
+ ".size vmcode, . - vmcode\n\t"
+ "end_vmcode:\n\t"
+ ".code32\n\t"
+ ".popsection"
+ );
+
+extern unsigned char vmcode[], end_vmcode[];
+extern unsigned char vmcode_bound[], vmcode_sysenter[];
+
+static void do_test(struct vm86plus_struct *v86, unsigned long eip,
+ const char *text)
+{
+ long ret;
+
+ printf("[RUN]\t%s from vm86 mode\n", text);
+ v86->regs.eip = eip;
+ ret = vm86(VM86_ENTER, v86);
+
+ if (ret == -1 && errno == ENOSYS) {
+ printf("[SKIP]\tvm86 not supported\n");
+ return;
+ }
+
+ if (VM86_TYPE(ret) == VM86_INTx) {
+ char trapname[32];
+ int trapno = VM86_ARG(ret);
+ if (trapno == 13)
+ strcpy(trapname, "GP");
+ else if (trapno == 5)
+ strcpy(trapname, "BR");
+ else if (trapno == 14)
+ strcpy(trapname, "PF");
+ else
+ sprintf(trapname, "%d", trapno);
+
+ printf("[OK]\tExited vm86 mode due to #%s\n", trapname);
+ } else if (VM86_TYPE(ret) == VM86_UNKNOWN) {
+ printf("[OK]\tExited vm86 mode due to unhandled GP fault\n");
+ } else {
+ printf("[OK]\tExited vm86 mode due to type %ld, arg %ld\n",
+ VM86_TYPE(ret), VM86_ARG(ret));
+ }
+}
+
+int main(void)
+{
+ struct vm86plus_struct v86;
+ unsigned char *addr = mmap((void *)load_addr, 4096,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1,0);
+ if (addr != (unsigned char *)load_addr)
+ err(1, "mmap");
+
+ memcpy(addr, vmcode, end_vmcode - vmcode);
+ addr[2048] = 2;
+ addr[2050] = 3;
+
+ memset(&v86, 0, sizeof(v86));
+
+ v86.regs.cs = load_addr / 16;
+ v86.regs.ss = load_addr / 16;
+ v86.regs.ds = load_addr / 16;
+ v86.regs.es = load_addr / 16;
+
+ assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
+
+ /* #BR -- should deliver SIG??? */
+ do_test(&v86, vmcode_bound - vmcode, "#BR");
+
+ /* SYSENTER -- should cause #GP or #UD depending on CPU */
+ do_test(&v86, vmcode_sysenter - vmcode, "SYSENTER");
+
+ return (nerrs == 0 ? 0 : 1);
+}