Merge branch 'caf' into android-msm-mako-3.4-wip
* caf: (219 commits)
usb: msm_otg: Fix error handling bug in driver probe
bluetooth: Add support for LE conn param
msm: ocmem: Initialize the ocmem graphics mPU
msm: ocmem: Add support for low power clients
msm-fb: display: Tearing issue during video playback
ASoC: WCD9304: Fix register sequence for analog mic recording
msm: clock-8974: Correct some audio interface clock structures.
ASoC: wcd9310: Clear the status only for active slimbus ports
msm: kgsl: Allow non-default timeout values in adreno_idle
msm: cache_erp: Add device tree support
ASOC: msm: Add device tree specific changes in compressed driver
drivers: leds-pm8xxx: enable low power mode for RGB LED
msm: 8974: Add function to reserve memory from device tree
msm: clock-8974: Add block reset support for the USB cores
msm_fb: display: Brightness change observed when switching HDMI on
msm: mpq8064: Dummy read to prevent false interrupt from triggering
mmc: msm_sdcc: Enable AUTO_PROG_DONE for CMD25
msm: rpm: remove the sanity check in rpm log
msm: camera: Add some minor code fixes.
msm: Always compile acpuclock-krait when CONFIG_ARCH_MSM_KRAIT is set
...
Conflicts:
arch/arm/mach-msm/clock-8960.c
arch/arm/mach-msm/subsystem_restart.c
drivers/media/video/msm/msm_camirq_router.c
drivers/media/video/msm/msm_mctl.c
drivers/usb/gadget/f_mass_storage.c
drivers/video/msm/msm_fb.c
sound/soc/msm/apq8064.c
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fa0934f..6f8d987 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -172,6 +172,7 @@
select HOLES_IN_ZONE if SPARSEMEM
select MSM_RUN_QUEUE_STATS
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_MSM8930
bool "MSM8930"
@@ -203,6 +204,7 @@
select MSM_PM8X60 if PM
select HOLES_IN_ZONE if SPARSEMEM
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_APQ8064
bool "APQ8064"
@@ -229,6 +231,7 @@
select MIGHT_HAVE_PCI
select ARCH_SUPPORTS_MSI
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_MSM8974
bool "MSM8974"
@@ -370,6 +373,9 @@
select MSM_SMP
bool
+config MSM_KRAIT_WFE_FIXUP
+ bool
+
config ARCH_MSM_CORTEX_A5
bool
select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 313c563..39c0a26 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,10 +23,12 @@
endif
obj-y += acpuclock.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o
obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o clock-pll.o
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
ifndef CONFIG_MSM_SMP
@@ -268,6 +270,7 @@
obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o
obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
obj-$(CONFIG_ARCH_APQ8064) += devices-8960.o devices-8064.o
+obj-$(CONFIG_ARCH_APQ8064) += acpuclock-8064.o
board-8960-all-objs += board-8960.o board-8960-camera.o board-8960-display.o board-8960-pmic.o board-8960-storage.o board-8960-gpiomux.o
board-8930-all-objs += board-8930.o board-8930-camera.o board-8930-display.o board-8930-pmic.o board-8930-storage.o board-8930-gpiomux.o devices-8930.o board-8930-gpu.o
board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-gpiomux.o board-8064-camera.o board-8064-display.o board-8064-gpu.o
@@ -290,10 +293,11 @@
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-regulator.o board-8974-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8974) += acpuclock-krait.o acpuclock-8974.o
+obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -337,7 +341,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
endif
obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
-obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o
obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
new file mode 100644
index 0000000..d46d268
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = 0,
+ .vdd[HFPLL_VDD_LOW] = 945000,
+ .vdd[HFPLL_VDD_NOM] = 1050000,
+};
+
+static struct scalable scalable[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903240,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
+ },
+ [CPU2] = {
+ .hfpll_phys_base = 0x00903280,
+ .aux_clk_sel_phys = 0x020A8014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x6501,
+ .vreg[VREG_CORE] = { "krait2", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait2_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait2_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
+ },
+ [CPU3] = {
+ .hfpll_phys_base = 0x009032C0,
+ .aux_clk_sel_phys = 0x020B8014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x7501,
+ .vreg[VREG_CORE] = { "krait3", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait3_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait3_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
+ },
+};
+
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
+ [0] = BW_MBPS(640), /* At least 80 MHz on bus. */
+ [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+ [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+ [5] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclk-8064",
+};
+
+static struct l2_level l2_freq_tbl[] __initdata __initdata = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 5 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 5 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 5 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 5 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
+};
+
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+ /* TODO: update the faster table when data is available */
+ [PVS_FASTER] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8064_probe(struct platform_device *pdev)
+{
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params);
+}
+
+static struct platform_driver acpuclk_8064_driver = {
+ .driver = {
+ .name = "acpuclk-8064",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8064_init(void)
+{
+ return platform_driver_probe(&acpuclk_8064_driver,
+ acpuclk_8064_probe);
+}
+device_initcall(acpuclk_8064_init);
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
new file mode 100644
index 0000000..8060803
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+/* Corner type vreg VDD values */
+#define LVL_NONE RPM_VREG_CORNER_NONE
+#define LVL_LOW RPM_VREG_CORNER_LOW
+#define LVL_NOM RPM_VREG_CORNER_NOMINAL
+#define LVL_HIGH RPM_VREG_CORNER_HIGH
+
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = LVL_NONE,
+ .vdd[HFPLL_VDD_LOW] = LVL_LOW,
+ .vdd[HFPLL_VDD_NOM] = LVL_NOM,
+};
+
+static struct scalable scalable[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
+ },
+};
+
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
+ [0] = BW_MBPS(640), /* At least 80 MHz on bus. */
+ [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+ [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclk-8627",
+};
+
+/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
+static struct l2_level l2_freq_tbl[] __initdata = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 1 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, LVL_NOM, 1050000, 1 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, LVL_NOM, 1050000, 2 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, LVL_NOM, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, LVL_NOM, 1050000, 2 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, LVL_NOM, 1050000, 3 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, LVL_HIGH, 1150000, 3 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, LVL_HIGH, 1150000, 3 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 4 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 4 },
+};
+
+/* TODO: Update core voltages when data is available. */
+static struct acpu_level acpu_freq_tbl[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(5), 925000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(5), 925000 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(5), 937500 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(5), 962500 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(9), 987500 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(9), 1000000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(9), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(9), 1062500 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(12), 1062500 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(12), 1087500 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(12), 1100000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+};
+
+static struct acpuclk_krait_params acpuclk_8627_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8627_probe(struct platform_device *pdev)
+{
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8627_params);
+}
+
+static struct platform_driver acpuclk_8627_driver = {
+ .driver = {
+ .name = "acpuclk-8627",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8627_init(void)
+{
+ return platform_driver_probe(&acpuclk_8627_driver,
+ acpuclk_8627_probe);
+}
+device_initcall(acpuclk_8627_init);
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
new file mode 100644
index 0000000..d04ce03
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+/* Corner type vreg VDD values */
+#define LVL_NONE RPM_VREG_CORNER_NONE
+#define LVL_LOW RPM_VREG_CORNER_LOW
+#define LVL_NOM RPM_VREG_CORNER_NOMINAL
+#define LVL_HIGH RPM_VREG_CORNER_HIGH
+
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = LVL_NONE,
+ .vdd[HFPLL_VDD_LOW] = LVL_LOW,
+ .vdd[HFPLL_VDD_NOM] = LVL_NOM,
+};
+
+static struct scalable scalable[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
+ },
+};
+
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
+ [0] = BW_MBPS(640), /* At least 80 MHz on bus. */
+ [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+ [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+ [5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
+ [6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
+ [7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclk-8930",
+};
+
+/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
+static struct l2_level l2_freq_tbl[] __initdata = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 2 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, LVL_NOM, 1050000, 2 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, LVL_NOM, 1050000, 2 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, LVL_NOM, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, LVL_NOM, 1050000, 4 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, LVL_NOM, 1050000, 4 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, LVL_HIGH, 1150000, 4 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, LVL_HIGH, 1150000, 4 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 7 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 7 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, LVL_HIGH, 1150000, 7 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
+ [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
+};
+
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 975000 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1000000 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1025000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1125000 },
+ { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
+ { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 925000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 925000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 950000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 950000 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 975000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 975000 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1000000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1000000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1050000 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1075000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1075000 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1100000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1100000 },
+ { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1150000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1150000 },
+ { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1175000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 900000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 900000 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 925000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 925000 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 950000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 950000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1000000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1000000 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1050000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1050000 },
+ { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1100000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1100000 },
+ { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1125000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8930_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8930_probe(struct platform_device *pdev)
+{
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8930_params);
+}
+
+static struct platform_driver acpuclk_8930_driver = {
+ .driver = {
+ .name = "acpuclk-8930",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8930_init(void)
+{
+ return platform_driver_probe(&acpuclk_8930_driver,
+ acpuclk_8930_probe);
+}
+device_initcall(acpuclk_8930_init);
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 7f198d2..8623c2b 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,413 +11,66 @@
* GNU General Public License for more details.
*/
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
-
-#include <asm/mach-types.h>
-#include <asm/cpu.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
#include <mach/rpm-regulator.h>
-#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
-#include <mach/socinfo.h>
-#include <mach/msm-krait-l2-accessors.h>
-#include <mach/rpm-regulator.h>
+#include <mach/msm_bus.h>
#include "acpuclock.h"
-#include "pm.h"
+#include "acpuclock-krait.h"
-/*
- * Source IDs.
- * These must be negative to not overlap with the source IDs
- * used by the 8x60 local clock driver.
- */
-#define PLL_8 0
-#define HFPLL -1
-#define QSB -2
-
-/* Mux source selects. */
-#define PRI_SRC_SEL_SEC_SRC 0
-#define PRI_SRC_SEL_HFPLL 1
-#define PRI_SRC_SEL_HFPLL_DIV2 2
-#define SEC_SRC_SEL_QSB 0
-#define SEC_SRC_SEL_AUX 2
-
-/* HFPLL registers offsets. */
-#define HFPLL_MODE 0x00
-#define HFPLL_CONFIG_CTL 0x04
-#define HFPLL_L_VAL 0x08
-#define HFPLL_M_VAL 0x0C
-#define HFPLL_N_VAL 0x10
-#define HFPLL_DROOP_CTL 0x14
-
-/* CP15 L2 indirect addresses. */
-#define L2CPMR_IADDR 0x500
-#define L2CPUCPMR_IADDR 0x501
-
-#define STBY_KHZ 1
-
-#define HFPLL_LOW_VDD_PLL_L_MAX 0x28
-
-#define SECCLKAGD BIT(4)
-
-/* PTE EFUSE register. */
-#define QFPROM_PTE_EFUSE_ADDR (MSM_QFPROM_BASE + 0x00C0)
-
-/* Corner type vreg VDD values */
-#define LVL_NONE RPM_VREG_CORNER_NONE
-#define LVL_LOW RPM_VREG_CORNER_LOW
-#define LVL_NOM RPM_VREG_CORNER_NOMINAL
-#define LVL_HIGH RPM_VREG_CORNER_HIGH
-
-enum scalables {
- CPU0 = 0,
- CPU1,
- CPU2,
- CPU3,
- L2,
- NUM_SCALABLES
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = 0,
+ .vdd[HFPLL_VDD_LOW] = 850000,
+ .vdd[HFPLL_VDD_NOM] = 1050000,
};
-enum vregs {
- VREG_CORE,
- VREG_MEM,
- VREG_DIG,
- VREG_HFPLL_A,
- VREG_HFPLL_B,
- NUM_VREG
-};
-
-enum hfpll_vdd_levels {
- HFPLL_VDD_NONE,
- HFPLL_VDD_LOW,
- HFPLL_VDD_NOM
-};
-
-enum pvs {
- PVS_SLOW,
- PVS_NOM,
- PVS_FAST,
- PVS_FASTER,
- NUM_PVS
-};
-
-struct vreg {
- const char name[15];
- const unsigned int max_vdd;
- const int rpm_vreg_voter;
- const int rpm_vreg_id;
- struct regulator *reg;
- unsigned int cur_vdd;
-};
-
-struct core_speed {
- unsigned int khz;
- int src;
- unsigned int pri_src_sel;
- unsigned int sec_src_sel;
- unsigned int pll_l_val;
-};
-
-struct l2_level {
- struct core_speed speed;
- unsigned int vdd_dig;
- unsigned int vdd_mem;
- unsigned int bw_level;
-};
-
-struct acpu_level {
- unsigned int use_for_scaling;
- struct core_speed speed;
- struct l2_level *l2_level;
- unsigned int vdd_core;
-};
-
-struct scalable {
- void * __iomem const hfpll_base;
- void * __iomem const aux_clk_sel;
- const uint32_t l2cpmr_iaddr;
- struct core_speed *current_speed;
- struct l2_level *l2_vote;
- struct vreg vreg[NUM_VREG];
- unsigned int *hfpll_vdd_tbl;
- bool regulators_initialized;
- bool clocks_initialized;
-};
-
-static unsigned int hfpll_vdd_tbl_8960[] = {
- [HFPLL_VDD_NONE] = 0,
- [HFPLL_VDD_LOW] = 850000,
- [HFPLL_VDD_NOM] = 1050000
-};
-
-static unsigned int hfpll_vdd_tbl_8064[] = {
- [HFPLL_VDD_NONE] = 0,
- [HFPLL_VDD_LOW] = 945000,
- [HFPLL_VDD_NOM] = 1050000
-};
-
-static unsigned int hfpll_vdd_dig_tbl_8930[] = {
- [HFPLL_VDD_NONE] = LVL_NONE,
- [HFPLL_VDD_LOW] = LVL_LOW,
- [HFPLL_VDD_NOM] = LVL_NOM
-};
-
-static struct scalable scalable_8960[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 3200000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait0_l23", 1800000 },
+ },
[CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 3200000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait1_l23", 1800000 },
+ },
[L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x400,
- .hfpll_vdd_tbl = hfpll_vdd_tbl_8960,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "l2_l23", 1800000 },
+ },
};
-static DEFINE_MUTEX(driver_lock);
-static DEFINE_SPINLOCK(l2_lock);
-
-static struct scalable scalable_8064[] = {
- [CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x240,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x280,
- .aux_clk_sel = MSM_ACC2_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait2", 1300000 },
- .vreg[VREG_MEM] = { "krait2_mem", 1150000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait2_dig", 1150000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU3] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x2C0,
- .aux_clk_sel = MSM_ACC3_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait3", 1300000 },
- .vreg[VREG_MEM] = { "krait3_mem", 1150000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait3_dig", 1150000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .hfpll_vdd_tbl = hfpll_vdd_tbl_8064,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_LVS7 },
- },
-};
-
-static struct scalable scalable_8930[] = {
- [CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", LVL_HIGH,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_VDD_DIG_CORNER
- },
- .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_L23 },
- },
- [CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", LVL_HIGH,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_VDD_DIG_CORNER
- },
- .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_L23 },
- },
- [L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x400,
- .hfpll_vdd_tbl = hfpll_vdd_dig_tbl_8930,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8038_L23 },
- },
-};
-
-/*TODO: Update the rpm vreg id when the rpm driver is ready */
-static struct scalable scalable_8627[] = {
- [CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", LVL_HIGH,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_VDD_DIG_CORNER
- },
- .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8038_L23 },
- },
- [CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", LVL_HIGH,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_VDD_DIG_CORNER
- },
- .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8038_L23 },
- },
- [L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x400,
- .hfpll_vdd_tbl = hfpll_vdd_dig_tbl_8930,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8038_L23 },
- },
-};
-
-static struct l2_level *l2_freq_tbl;
-static struct acpu_level *acpu_freq_tbl;
-static int l2_freq_tbl_size;
-static struct scalable *scalable;
-#define SCALABLE_TO_CPU(sc) ((sc) - scalable)
-
-/* Instantaneous bandwidth requests in MB/s. */
-#define BW_MBPS(_bw) \
- { \
- .vectors = (struct msm_bus_vectors[]){ \
- {\
- .src = MSM_BUS_MASTER_AMPSS_M0, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ib = (_bw) * 1000000UL, \
- .ab = (_bw) * 100000UL, \
- }, \
- { \
- .src = MSM_BUS_MASTER_AMPSS_M1, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ib = (_bw) * 1000000UL, \
- .ab = (_bw) * 100000UL, \
- }, \
- }, \
- .num_paths = 2, \
- }
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(640), /* At least 80 MHz on bus. */
[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -424,70 +78,16 @@
[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
- [7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_client_pdata = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
- .name = "acpuclock",
+ .name = "acpuclk-8960",
};
-static uint32_t bus_perf_client;
-
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#define L2(x) (&l2_freq_tbl_8960_kraitv1[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv1[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 2 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_slow[] = {
- { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 937500 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 962500 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 987500 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1000000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_nom_fast[] = {
- { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 862500 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 862500 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 862500 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 887500 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 925000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 937500 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 962500 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
- { 0, { 0 } }
-};
-
-#undef L2
-#define L2(x) (&l2_freq_tbl_8960_kraitv2[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv2[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
[1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
[2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
@@ -510,7 +110,7 @@
[19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 6 },
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
@@ -537,7 +137,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
@@ -564,7 +164,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
@@ -591,1076 +191,26 @@
{ 0, { 0 } }
};
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#undef L2
-#define L2(x) (&l2_freq_tbl_8064[(x)])
-static struct l2_level l2_freq_tbl_8064[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 7 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 7 },
- [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 7 },
- [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 7 },
- [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 7 },
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
};
-/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8064_slow[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_nom[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_fast[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
- { 0, { 0 } }
-};
-
-/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#undef L2
-#define L2(x) (&l2_freq_tbl_8930[(x)])
-static struct l2_level l2_freq_tbl_8930[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 2 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, LVL_NOM, 1050000, 2 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, LVL_NOM, 1050000, 2 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, LVL_NOM, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, LVL_NOM, 1050000, 4 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, LVL_NOM, 1050000, 4 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, LVL_HIGH, 1150000, 4 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, LVL_HIGH, 1150000, 4 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 7 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 7 },
- [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, LVL_HIGH, 1150000, 7 },
- [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 },
- [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 },
- [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
-};
-
-/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8930_slow[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 975000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 1000000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1000000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1025000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1025000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1125000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8930_nom[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 925000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 925000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 950000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 950000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 975000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 975000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1000000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1000000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1050000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1075000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1075000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1100000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1100000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1150000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1150000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1175000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8930_fast[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 900000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 900000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 925000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 925000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 950000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 950000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1000000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1000000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(11), 1050000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(11), 1050000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1100000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1100000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1125000 },
- { 0, { 0 } }
-};
-/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#undef L2
-#define L2(x) (&l2_freq_tbl_8627[(x)])
-static struct l2_level l2_freq_tbl_8627[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 1 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, LVL_NOM, 1050000, 1 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, LVL_NOM, 1050000, 2 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, LVL_NOM, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, LVL_NOM, 1050000, 2 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, LVL_NOM, 1050000, 3 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, LVL_HIGH, 1150000, 3 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, LVL_HIGH, 1150000, 3 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 4 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 4 },
-};
-
-/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8627[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(5), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(5), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(5), 937500 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(5), 962500 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(9), 987500 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(9), 1000000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(9), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(9), 1062500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(12), 1062500 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(12), 1087500 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(12), 1100000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v1[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8960_kraitv1_slow,
- [PVS_NOM] = acpu_freq_tbl_8960_kraitv1_nom_fast,
- [PVS_FAST] = acpu_freq_tbl_8960_kraitv1_nom_fast,
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v2[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8960_kraitv2_slow,
- [PVS_NOM] = acpu_freq_tbl_8960_kraitv2_nom,
- [PVS_FAST] = acpu_freq_tbl_8960_kraitv2_fast,
-};
-
-/* TODO: update the faster table when data is available */
-static struct acpu_level *acpu_freq_tbl_8064[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8064_slow,
- [PVS_NOM] = acpu_freq_tbl_8064_nom,
- [PVS_FAST] = acpu_freq_tbl_8064_fast,
- [PVS_FASTER] = acpu_freq_tbl_8064_fast,
-};
-
-static struct acpu_level *acpu_freq_tbl_8930_pvs[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8930_slow,
- [PVS_NOM] = acpu_freq_tbl_8930_nom,
- [PVS_FAST] = acpu_freq_tbl_8930_fast,
-};
-
-static struct acpu_level *max_acpu_level;
-
-static unsigned long acpuclk_8960_get_rate(int cpu)
-{
- return scalable[cpu].current_speed->khz;
-}
-
-/* Get the selected source on primary MUX. */
-static int get_pri_clk_src(struct scalable *sc)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- return regval & 0x3;
-}
-
-/* Set the selected source on primary MUX. */
-static void set_pri_clk_src(struct scalable *sc, uint32_t pri_src_sel)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval &= ~0x3;
- regval |= (pri_src_sel & 0x3);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
- /* Wait for switch to complete. */
- mb();
- udelay(1);
-}
-
-/* Get the selected source on secondary MUX. */
-static int get_sec_clk_src(struct scalable *sc)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- return (regval >> 2) & 0x3;
-}
-
-/* Set the selected source on secondary MUX. */
-static void set_sec_clk_src(struct scalable *sc, uint32_t sec_src_sel)
-{
- uint32_t regval;
-
- /* Disable secondary source clock gating during switch. */
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval |= SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Program the MUX. */
- regval &= ~(0x3 << 2);
- regval |= ((sec_src_sel & 0x3) << 2);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Wait for switch to complete. */
- mb();
- udelay(1);
-
- /* Re-enable secondary source clock gating. */
- regval &= ~SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-}
-
-/* Enable an already-configured HFPLL. */
-static void hfpll_enable(struct scalable *sc, bool skip_regulators)
-{
- int rc;
-
- if (!skip_regulators) {
- if (cpu_is_msm8960()) {
- rc = rpm_vreg_set_voltage(
- sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
- 2050000,
- sc->vreg[VREG_HFPLL_A].max_vdd, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_A].name, rc);
- }
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
- sc->vreg[VREG_HFPLL_B].max_vdd, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_B].name, rc);
- }
- /* Disable PLL bypass mode. */
- writel_relaxed(0x2, sc->hfpll_base + HFPLL_MODE);
-
- /*
- * H/W requires a 5us delay between disabling the bypass and
- * de-asserting the reset. Delay 10us just to be safe.
- */
- mb();
- udelay(10);
-
- /* De-assert active-low PLL reset. */
- writel_relaxed(0x6, sc->hfpll_base + HFPLL_MODE);
-
- /* Wait for PLL to lock. */
- mb();
- udelay(60);
-
- /* Enable PLL output. */
- writel_relaxed(0x7, sc->hfpll_base + HFPLL_MODE);
-}
-
-/* Disable a HFPLL for power-savings or while its being reprogrammed. */
-static void hfpll_disable(struct scalable *sc, bool skip_regulators)
-{
- int rc;
-
- /*
- * Disable the PLL output, disable test mode, enable
- * the bypass mode, and assert the reset.
- */
- writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
-
- if (!skip_regulators) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 0,
- 0, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_B].name, rc);
-
- if (cpu_is_msm8960()) {
- rc = rpm_vreg_set_voltage(
- sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
- 0, 0, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_A].name, rc);
- }
- }
-}
-
-/* Program the HFPLL rate. Assumes HFPLL is already disabled. */
-static void hfpll_set_rate(struct scalable *sc, struct core_speed *tgt_s)
-{
- writel_relaxed(tgt_s->pll_l_val, sc->hfpll_base + HFPLL_L_VAL);
-}
-
-/* Return the L2 speed that should be applied. */
-static struct l2_level *compute_l2_level(struct scalable *sc,
- struct l2_level *vote_l)
-{
- struct l2_level *new_l;
- int cpu;
-
- /* Bounds check. */
- BUG_ON(vote_l >= (l2_freq_tbl + l2_freq_tbl_size));
-
- /* Find max L2 speed vote. */
- sc->l2_vote = vote_l;
- new_l = l2_freq_tbl;
- for_each_present_cpu(cpu)
- new_l = max(new_l, scalable[cpu].l2_vote);
-
- return new_l;
-}
-
-/* Update the bus bandwidth request. */
-static void set_bus_bw(unsigned int bw)
-{
- int ret;
-
- /* Bounds check. */
- if (bw >= ARRAY_SIZE(bw_level_tbl)) {
- pr_err("invalid bandwidth request (%d)\n", bw);
- return;
- }
-
- /* Update bandwidth if request has changed. This may sleep. */
- ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
- if (ret)
- pr_err("bandwidth request failed (%d)\n", ret);
-}
-
-/* Set the CPU or L2 clock speed. */
-static void set_speed(struct scalable *sc, struct core_speed *tgt_s,
- enum setrate_reason reason)
-{
- struct core_speed *strt_s = sc->current_speed;
-
- if (tgt_s == strt_s)
- return;
-
- if (strt_s->src == HFPLL && tgt_s->src == HFPLL) {
- /*
- * Move to an always-on source running at a frequency that does
- * not require an elevated CPU voltage. PLL8 is used here.
- */
- set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
- set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
-
- /* Program CPU HFPLL. */
- hfpll_disable(sc, 1);
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 1);
-
- /* Move CPU to HFPLL source. */
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- } else if (strt_s->src == HFPLL && tgt_s->src != HFPLL) {
- /*
- * If responding to CPU_DEAD we must be running on another CPU.
- * Therefore, we can't access the downed CPU's clock MUX CP15
- * registers from here and can't change clock sources. If the
- * CPU is collapsed, however, it is still safe to turn off the
- * PLL without switching the MUX away from it.
- */
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- hfpll_disable(sc, 0);
- } else if (reason == SETRATE_HOTPLUG
- && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
- hfpll_disable(sc, 0);
- }
- } else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
- /*
- * If responding to CPU_UP_PREPARE, we can't change CP15
- * registers for the CPU that's coming up since we're not
- * running on that CPU. That's okay though, since the MUX
- * source was not changed on the way down, either.
- */
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- } else if (reason == SETRATE_HOTPLUG
- && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
- /* PLL was disabled during hot-unplug. Re-enable it. */
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
- }
- } else {
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2])
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- }
-
- sc->current_speed = tgt_s;
-}
-
-/* Apply any per-cpu voltage increases. */
-static int increase_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
- unsigned int vdd_dig, enum setrate_reason reason)
-{
- struct scalable *sc = &scalable[cpu];
- int rc = 0;
-
- /*
- * Increase vdd_mem active-set before vdd_dig.
- * vdd_mem should be >= vdd_dig.
- */
- if (vdd_mem > sc->vreg[VREG_MEM].cur_vdd) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_MEM].name, rc);
- return rc;
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
- }
-
- /* Increase vdd_dig active-set vote. */
- if (vdd_dig > sc->vreg[VREG_DIG].cur_vdd) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_DIG].name, rc);
- return rc;
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
- }
-
- /*
- * Update per-CPU core voltage. Don't do this for the hotplug path for
- * which it should already be correct. Attempting to set it is bad
- * because we don't know what CPU we are running on at this point, but
- * the CPU regulator API requires we call it from the affected CPU.
- */
- if (vdd_core > sc->vreg[VREG_CORE].cur_vdd
- && reason != SETRATE_HOTPLUG) {
- rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_CORE].name, rc);
- return rc;
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- }
-
- return rc;
-}
-
-/* Apply any per-cpu voltage decreases. */
-static void decrease_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
- unsigned int vdd_dig, enum setrate_reason reason)
-{
- struct scalable *sc = &scalable[cpu];
- int ret;
-
- /*
- * Update per-CPU core voltage. This must be called on the CPU
- * that's being affected. Don't do this in the hotplug remove path,
- * where the rail is off and we're executing on the other CPU.
- */
- if (vdd_core < sc->vreg[VREG_CORE].cur_vdd
- && reason != SETRATE_HOTPLUG) {
- ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- return;
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- }
-
- /* Decrease vdd_dig active-set vote. */
- if (vdd_dig < sc->vreg[VREG_DIG].cur_vdd) {
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_DIG].name, ret);
- return;
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
- }
-
- /*
- * Decrease vdd_mem active-set after vdd_dig.
- * vdd_mem should be >= vdd_dig.
- */
- if (vdd_mem < sc->vreg[VREG_MEM].cur_vdd) {
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_MEM].name, ret);
- return;
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
- }
-}
-
-static unsigned int calculate_vdd_mem(struct acpu_level *tgt)
-{
- return tgt->l2_level->vdd_mem;
-}
-
-static unsigned int calculate_vdd_dig(struct acpu_level *tgt)
-{
- unsigned int pll_vdd_dig;
-
- if (tgt->l2_level->speed.src != HFPLL)
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NONE];
- else if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NOM];
- else
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_LOW];
-
- return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
-}
-
-static unsigned int calculate_vdd_core(struct acpu_level *tgt)
-{
- return tgt->vdd_core;
-}
-
-/* Set the CPU's clock rate and adjust the L2 rate, if appropriate. */
-static int acpuclk_8960_set_rate(int cpu, unsigned long rate,
- enum setrate_reason reason)
-{
- struct core_speed *strt_acpu_s, *tgt_acpu_s;
- struct l2_level *tgt_l2_l;
- struct acpu_level *tgt;
- unsigned int vdd_mem, vdd_dig, vdd_core;
- unsigned long flags;
- int rc = 0;
-
- if (cpu > num_possible_cpus())
- return -EINVAL;
-
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
- mutex_lock(&driver_lock);
-
- strt_acpu_s = scalable[cpu].current_speed;
-
- /* Return early if rate didn't change. */
- if (rate == strt_acpu_s->khz)
- goto out;
-
- /* Find target frequency. */
- for (tgt = acpu_freq_tbl; tgt->speed.khz != 0; tgt++) {
- if (tgt->speed.khz == rate) {
- tgt_acpu_s = &tgt->speed;
- break;
- }
- }
- if (tgt->speed.khz == 0) {
- rc = -EINVAL;
- goto out;
- }
-
- /* Calculate voltage requirements for the current CPU. */
- vdd_mem = calculate_vdd_mem(tgt);
- vdd_dig = calculate_vdd_dig(tgt);
- vdd_core = calculate_vdd_core(tgt);
-
- /* Increase VDD levels if needed. */
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
- rc = increase_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
- if (rc)
- goto out;
- }
-
- pr_debug("Switching from ACPU%d rate %u KHz -> %u KHz\n",
- cpu, strt_acpu_s->khz, tgt_acpu_s->khz);
-
- /* Set the CPU speed. */
- set_speed(&scalable[cpu], tgt_acpu_s, reason);
-
- /*
- * Update the L2 vote and apply the rate change. A spinlock is
- * necessary to ensure L2 rate is calulated and set atomically,
- * even if acpuclk_8960_set_rate() is called from an atomic context
- * and the driver_lock mutex is not acquired.
- */
- spin_lock_irqsave(&l2_lock, flags);
- tgt_l2_l = compute_l2_level(&scalable[cpu], tgt->l2_level);
- set_speed(&scalable[L2], &tgt_l2_l->speed, reason);
- spin_unlock_irqrestore(&l2_lock, flags);
-
- /* Nothing else to do for power collapse or SWFI. */
- if (reason == SETRATE_PC || reason == SETRATE_SWFI)
- goto out;
-
- /* Update bus bandwith request. */
- set_bus_bw(tgt_l2_l->bw_level);
-
- /* Drop VDD levels if we can. */
- decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
-
- pr_debug("ACPU%d speed change complete\n", cpu);
-
-out:
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
- mutex_unlock(&driver_lock);
- return rc;
-}
-
-/* Initialize a HFPLL at a given rate and enable it. */
-static void __cpuinit hfpll_init(struct scalable *sc, struct core_speed *tgt_s)
-{
- pr_debug("Initializing HFPLL%d\n", sc - scalable);
-
- /* Disable the PLL for re-programming. */
- hfpll_disable(sc, 1);
-
- /* Configure PLL parameters for integer mode. */
- writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
- writel_relaxed(0, sc->hfpll_base + HFPLL_M_VAL);
- writel_relaxed(1, sc->hfpll_base + HFPLL_N_VAL);
-
- /* Program droop controller. */
- writel_relaxed(0x0108C000, sc->hfpll_base + HFPLL_DROOP_CTL);
-
- /* Set an initial rate and enable the PLL. */
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
-}
-
-/* Voltage regulator initialization. */
-static void __cpuinit regulator_init(int cpu, struct acpu_level *lvl)
-{
- int ret;
- struct scalable *sc = &scalable[cpu];
- unsigned int vdd_mem, vdd_dig, vdd_core;
-
- vdd_mem = calculate_vdd_mem(lvl);
- vdd_dig = calculate_vdd_dig(lvl);
-
- /* Set initial vdd_mem vote. */
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_MEM].name, ret);
- BUG();
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
-
- /* Set initial vdd_dig vote. */
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_DIG].name, ret);
- BUG();
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
-
- /* Setup Krait CPU regulators and initial core voltage. */
- sc->vreg[VREG_CORE].reg = regulator_get(NULL,
- sc->vreg[VREG_CORE].name);
- if (IS_ERR(sc->vreg[VREG_CORE].reg)) {
- pr_err("regulator_get(%s) failed (%ld)\n",
- sc->vreg[VREG_CORE].name,
- PTR_ERR(sc->vreg[VREG_CORE].reg));
- BUG();
- }
- vdd_core = calculate_vdd_core(lvl);
- ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- BUG();
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- ret = regulator_enable(sc->vreg[VREG_CORE].reg);
- if (ret) {
- pr_err("regulator_enable(%s) failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- BUG();
- }
- sc->regulators_initialized = true;
-}
-
-/* Set initial rate for a given core. */
-static void __cpuinit init_clock_sources(struct scalable *sc,
- struct core_speed *tgt_s)
-{
- uint32_t regval;
-
- /* Select PLL8 as AUX source input to the secondary MUX. */
- writel_relaxed(0x3, sc->aux_clk_sel);
-
- /* Switch away from the HFPLL while it's re-initialized. */
- set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
- set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
- hfpll_init(sc, tgt_s);
-
- /* Set PRI_SRC_SEL_HFPLL_DIV2 divider to div-2. */
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval &= ~(0x3 << 6);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Switch to the target clock source. */
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- sc->current_speed = tgt_s;
-}
-
-static void __cpuinit per_cpu_init(void *data)
-{
- int cpu = smp_processor_id();
-
- init_clock_sources(&scalable[cpu], &max_acpu_level->speed);
- scalable[cpu].l2_vote = max_acpu_level->l2_level;
- scalable[cpu].clocks_initialized = true;
-}
-
-/* Register with bus driver. */
-static void __init bus_init(unsigned int init_bw)
-{
- int ret;
-
- bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
- if (!bus_perf_client) {
- pr_err("unable to register bus client\n");
- BUG();
- }
-
- ret = msm_bus_scale_client_update_request(bus_perf_client, init_bw);
- if (ret)
- pr_err("initial bandwidth request failed (%d)\n", ret);
-}
-
-#ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[NR_CPUS][30];
-
-static void __init cpufreq_table_init(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- int i, freq_cnt = 0;
- /* Construct the freq_table tables from acpu_freq_tbl. */
- for (i = 0; acpu_freq_tbl[i].speed.khz != 0
- && freq_cnt < ARRAY_SIZE(*freq_table); i++) {
- if (acpu_freq_tbl[i].use_for_scaling) {
- freq_table[cpu][freq_cnt].index = freq_cnt;
- freq_table[cpu][freq_cnt].frequency
- = acpu_freq_tbl[i].speed.khz;
- freq_cnt++;
- }
- }
- /* freq_table not big enough to store all usable freqs. */
- BUG_ON(acpu_freq_tbl[i].speed.khz != 0);
-
- freq_table[cpu][freq_cnt].index = freq_cnt;
- freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
-
- pr_info("CPU%d: %d scaling frequencies supported.\n",
- cpu, freq_cnt);
-
- /* Register table with CPUFreq. */
- cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
- }
-}
-#else
-static void __init cpufreq_table_init(void) {}
-#endif
-
-#define HOT_UNPLUG_KHZ STBY_KHZ
-static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- static int prev_khz[NR_CPUS];
- static int prev_pri_src[NR_CPUS];
- static int prev_sec_src[NR_CPUS];
- int cpu = (int)hcpu;
-
- switch (action) {
- case CPU_DYING:
- case CPU_DYING_FROZEN:
- /*
- * On Krait v1 and 8064v1, the primary and secondary muxes must
- * be set to QSB before L2 power collapse and restored after.
- */
- if (cpu_is_krait_v1() || cpu_is_apq8064()) {
- prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
- prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
- set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
- set_pri_clk_src(&scalable[cpu], PRI_SRC_SEL_SEC_SRC);
- }
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- prev_khz[cpu] = acpuclk_8960_get_rate(cpu);
- /* Fall through. */
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- if (scalable[cpu].clocks_initialized)
- acpuclk_8960_set_rate(cpu, HOT_UNPLUG_KHZ,
- SETRATE_HOTPLUG);
- break;
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- if (scalable[cpu].clocks_initialized)
- acpuclk_8960_set_rate(cpu, prev_khz[cpu],
- SETRATE_HOTPLUG);
- if (!scalable[cpu].regulators_initialized)
- regulator_init(cpu, max_acpu_level);
- break;
- case CPU_STARTING:
- case CPU_STARTING_FROZEN:
- if (!scalable[cpu].clocks_initialized) {
- per_cpu_init(NULL);
- } else if (cpu_is_krait_v1() || cpu_is_apq8064()) {
- set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
- set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
- }
- break;
- default:
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = {
- .notifier_call = acpuclock_cpu_callback,
-};
-
-static const int krait_needs_vmin(void)
-{
- switch (read_cpuid_id()) {
- case 0x511F04D0:
- case 0x511F04D1:
- case 0x510F06F0:
- return 1;
- default:
- return 0;
- };
-}
-
-static void kraitv2_apply_vmin(struct acpu_level *tbl)
-{
- for (; tbl->speed.khz != 0; tbl++)
- if (tbl->vdd_core < 1150000)
- tbl->vdd_core = 1150000;
-}
-
-static enum pvs __init get_pvs(void)
-{
- uint32_t pte_efuse, pvs;
-
- pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
- pvs = (pte_efuse >> 10) & 0x7;
- if (pvs == 0x7)
- pvs = (pte_efuse >> 13) & 0x7;
-
- switch (pvs) {
- case 0x0:
- case 0x7:
- pr_info("ACPU PVS: Slow\n");
- return PVS_SLOW;
- case 0x1:
- pr_info("ACPU PVS: Nominal\n");
- return PVS_NOM;
- case 0x3:
- pr_info("ACPU PVS: Fast\n");
- return PVS_FAST;
- case 0x4:
- if (cpu_is_apq8064()) {
- pr_info("ACPU PVS: Faster\n");
- return PVS_FASTER;
- }
- default:
- pr_warn("ACPU PVS: Unknown. Defaulting to slow\n");
- return PVS_SLOW;
- }
-}
-
-static void __init select_freq_plan(void)
-{
- struct acpu_level *l;
-
- /* Select frequency tables. */
- if (cpu_is_msm8960()) {
- enum pvs pvs_id = get_pvs();
-
- scalable = scalable_8960;
- if (cpu_is_krait_v1()) {
- acpu_freq_tbl = acpu_freq_tbl_8960_v1[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
- } else {
- acpu_freq_tbl = acpu_freq_tbl_8960_v2[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
- }
- } else if (cpu_is_apq8064()) {
- enum pvs pvs_id = get_pvs();
-
- scalable = scalable_8064;
- acpu_freq_tbl = acpu_freq_tbl_8064[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8064;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
- } else if (cpu_is_msm8627()) {
- scalable = scalable_8627;
- acpu_freq_tbl = acpu_freq_tbl_8627;
- l2_freq_tbl = l2_freq_tbl_8627;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8627);
- } else if (cpu_is_msm8930() || cpu_is_msm8930aa()) {
- enum pvs pvs_id = get_pvs();
-
- scalable = scalable_8930;
- acpu_freq_tbl = acpu_freq_tbl_8930_pvs[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8930;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8930);
- } else {
- BUG();
- }
- BUG_ON(!acpu_freq_tbl);
- if (krait_needs_vmin())
- kraitv2_apply_vmin(acpu_freq_tbl);
-
- /* Find the max supported scaling frequency. */
- for (l = acpu_freq_tbl; l->speed.khz != 0; l++)
- if (l->use_for_scaling)
- max_acpu_level = l;
- BUG_ON(!max_acpu_level);
- pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz);
-}
-
-static struct acpuclk_data acpuclk_8960_data = {
- .set_rate = acpuclk_8960_set_rate,
- .get_rate = acpuclk_8960_get_rate,
- .power_collapse_khz = STBY_KHZ,
- .wait_for_irq_khz = STBY_KHZ,
+static struct acpuclk_krait_params acpuclk_8960_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
};
static int __init acpuclk_8960_probe(struct platform_device *pdev)
{
- int cpu;
-
- select_freq_plan();
-
- for_each_online_cpu(cpu)
- regulator_init(cpu, max_acpu_level);
- bus_init(max_acpu_level->l2_level->bw_level);
-
- init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
- on_each_cpu(per_cpu_init, NULL, true);
-
- cpufreq_table_init();
-
- acpuclk_register(&acpuclk_8960_data);
- register_hotcpu_notifier(&acpuclock_cpu_notifier);
-
- return 0;
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8960_params);
}
static struct platform_driver acpuclk_8960_driver = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c67109e..9ed038b 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -28,21 +28,7 @@
#define LVL_NOM RPM_REGULATOR_CORNER_NORMAL
#define LVL_HIGH RPM_REGULATOR_CORNER_SUPER_TURBO
-static struct hfpll_data hfpll_data_cpu = {
- .mode_offset = 0x00,
- .l_offset = 0x04,
- .m_offset = 0x08,
- .n_offset = 0x0C,
- .config_offset = 0x14,
- /* TODO: Verify magic number for 8974 when available. */
- .config_val = 0x7845C665,
- .low_vdd_l_max = 52,
- .vdd[HFPLL_VDD_NONE] = 0,
- .vdd[HFPLL_VDD_LOW] = 810000,
- .vdd[HFPLL_VDD_NOM] = 900000,
-};
-
-static struct hfpll_data hfpll_data_l2 = {
+static struct hfpll_data hfpll_data __initdata = {
.mode_offset = 0x00,
.l_offset = 0x04,
.m_offset = 0x08,
@@ -56,10 +42,9 @@
.vdd[HFPLL_VDD_NOM] = LVL_NOM,
};
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
.hfpll_phys_base = 0xF908A000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x4501,
.vreg[VREG_CORE] = { "krait0", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait0_mem", 1050000 },
@@ -69,7 +54,6 @@
},
[CPU1] = {
.hfpll_phys_base = 0xF909A000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x5501,
.vreg[VREG_CORE] = { "krait1", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait1_mem", 1050000 },
@@ -79,7 +63,6 @@
},
[CPU2] = {
.hfpll_phys_base = 0xF90AA000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x6501,
.vreg[VREG_CORE] = { "krait2", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait2_mem", 1050000 },
@@ -89,7 +72,6 @@
},
[CPU3] = {
.hfpll_phys_base = 0xF90BA000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x7501,
.vreg[VREG_CORE] = { "krait3", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait3_mem", 1050000 },
@@ -99,14 +81,13 @@
},
[L2] = {
.hfpll_phys_base = 0xF9016000,
- .hfpll_data = &hfpll_data_l2,
.l2cpmr_iaddr = 0x0500,
.vreg[VREG_HFPLL_A] = { "l2_hfpll_a", 2150000 },
.vreg[VREG_HFPLL_B] = { "l2_hfpll_b", 1800000 },
},
};
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(400), /* At least 50 MHz on bus. */
[1] = BW_MBPS(800), /* At least 100 MHz on bus. */
[2] = BW_MBPS(1334), /* At least 167 MHz on bus. */
@@ -114,17 +95,16 @@
[4] = BW_MBPS(3200), /* At least 333 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
.name = "acpuclk-8974",
};
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0 }, LVL_NOM, 1050000, 0 },
- [1] = { { 300000, PLL_0, 0, 2, 0 }, LVL_NOM, 1050000, 2 },
+static struct l2_level l2_freq_tbl[] __initdata = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0 }, LVL_LOW, 1050000, 0 },
+ [1] = { { 300000, PLL_0, 0, 2, 0 }, LVL_LOW, 1050000, 2 },
[2] = { { 384000, HFPLL, 2, 0, 40 }, LVL_NOM, 1050000, 2 },
[3] = { { 460800, HFPLL, 2, 0, 48 }, LVL_NOM, 1050000, 2 },
[4] = { { 537600, HFPLL, 1, 0, 28 }, LVL_NOM, 1050000, 2 },
@@ -137,7 +117,7 @@
[11] = { { 1036800, HFPLL, 1, 0, 54 }, LVL_NOM, 1050000, 4 },
};
-static struct acpu_level acpu_freq_tbl[] = {
+static struct acpu_level acpu_freq_tbl[] __initdata = {
{ 0, {STBY_KHZ, QSB, 0, 0, 0 }, L2(0), 1050000 },
{ 1, { 300000, PLL_0, 0, 2, 0 }, L2(1), 1050000 },
{ 1, { 384000, HFPLL, 2, 0, 40 }, L2(2), 1050000 },
@@ -153,14 +133,20 @@
{ 0, { 0 } }
};
-static struct acpuclk_krait_params acpuclk_8974_params = {
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+};
+
+static struct acpuclk_krait_params acpuclk_8974_params __initdata = {
.scalable = scalable,
- .pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
.l2_freq_tbl = l2_freq_tbl,
- .l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
- .bus_scale_data = &bus_scale_data,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
.qfprom_phys_base = 0xFC4A8000,
};
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 8bd54e3..fd43f57 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -57,7 +57,9 @@
const struct acpu_level *max_acpu_lvl;
const struct l2_level *l2_freq_tbl;
struct scalable *scalable;
+ struct hfpll_data *hfpll_data;
u32 bus_perf_client;
+ struct msm_bus_scale_pdata *bus_scale;
struct device *dev;
} drv;
@@ -130,7 +132,7 @@
}
/* Disable PLL bypass mode. */
- writel_relaxed(0x2, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x2, sc->hfpll_base + drv.hfpll_data->mode_offset);
/*
* H/W requires a 5us delay between disabling the bypass and
@@ -140,14 +142,14 @@
udelay(10);
/* De-assert active-low PLL reset. */
- writel_relaxed(0x6, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x6, sc->hfpll_base + drv.hfpll_data->mode_offset);
/* Wait for PLL to lock. */
mb();
udelay(60);
/* Enable PLL output. */
- writel_relaxed(0x7, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x7, sc->hfpll_base + drv.hfpll_data->mode_offset);
}
/* Disable a HFPLL for power-savings or while it's being reprogrammed. */
@@ -157,7 +159,7 @@
* Disable the PLL output, disable test mode, enable the bypass mode,
* and assert the reset.
*/
- writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->mode_offset);
if (!skip_regulators) {
/* Remove voltage votes required by the HFPLL. */
@@ -170,19 +172,17 @@
static void hfpll_set_rate(struct scalable *sc, const struct core_speed *tgt_s)
{
writel_relaxed(tgt_s->pll_l_val,
- sc->hfpll_base + sc->hfpll_data->l_offset);
+ sc->hfpll_base + drv.hfpll_data->l_offset);
}
/* Return the L2 speed that should be applied. */
-static const struct l2_level *compute_l2_level(struct scalable *sc,
- const struct l2_level *vote_l)
+static unsigned int compute_l2_level(struct scalable *sc, unsigned int vote_l)
{
- const struct l2_level *new_l;
+ unsigned int new_l = 0;
int cpu;
/* Find max L2 speed vote. */
sc->l2_vote = vote_l;
- new_l = drv.l2_freq_tbl;
for_each_present_cpu(cpu)
new_l = max(new_l, drv.scalable[cpu].l2_vote);
@@ -350,23 +350,23 @@
static int calculate_vdd_mem(const struct acpu_level *tgt)
{
- return tgt->l2_level->vdd_mem;
+ return drv.l2_freq_tbl[tgt->l2_level].vdd_mem;
}
static int calculate_vdd_dig(const struct acpu_level *tgt)
{
int pll_vdd_dig;
- const int *hfpll_vdd = drv.scalable[L2].hfpll_data->vdd;
- const u32 low_vdd_l_max = drv.scalable[L2].hfpll_data->low_vdd_l_max;
+ const int *hfpll_vdd = drv.hfpll_data->vdd;
+ const u32 low_vdd_l_max = drv.hfpll_data->low_vdd_l_max;
- if (tgt->l2_level->speed.src != HFPLL)
+ if (drv.l2_freq_tbl[tgt->l2_level].speed.src != HFPLL)
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NONE];
- else if (tgt->l2_level->speed.pll_l_val > low_vdd_l_max)
+ else if (drv.l2_freq_tbl[tgt->l2_level].speed.pll_l_val > low_vdd_l_max)
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NOM];
else
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_LOW];
- return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
+ return max(drv.l2_freq_tbl[tgt->l2_level].vdd_dig, pll_vdd_dig);
}
static int calculate_vdd_core(const struct acpu_level *tgt)
@@ -379,8 +379,8 @@
enum setrate_reason reason)
{
const struct core_speed *strt_acpu_s, *tgt_acpu_s;
- const struct l2_level *tgt_l2_l;
const struct acpu_level *tgt;
+ int tgt_l2_l;
int vdd_mem, vdd_dig, vdd_core;
unsigned long flags;
int rc = 0;
@@ -436,7 +436,7 @@
*/
spin_lock_irqsave(&l2_lock, flags);
tgt_l2_l = compute_l2_level(&drv.scalable[cpu], tgt->l2_level);
- set_speed(&drv.scalable[L2], &tgt_l2_l->speed);
+ set_speed(&drv.scalable[L2], &drv.l2_freq_tbl[tgt_l2_l].speed);
spin_unlock_irqrestore(&l2_lock, flags);
/* Nothing else to do for power collapse or SWFI. */
@@ -444,7 +444,7 @@
goto out;
/* Update bus bandwith request. */
- set_bus_bw(tgt_l2_l->bw_level);
+ set_bus_bw(drv.l2_freq_tbl[tgt_l2_l].bw_level);
/* Drop VDD levels if we can. */
decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
@@ -467,15 +467,15 @@
hfpll_disable(sc, true);
/* Configure PLL parameters for integer mode. */
- writel_relaxed(sc->hfpll_data->config_val,
- sc->hfpll_base + sc->hfpll_data->config_offset);
- writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->m_offset);
- writel_relaxed(1, sc->hfpll_base + sc->hfpll_data->n_offset);
+ writel_relaxed(drv.hfpll_data->config_val,
+ sc->hfpll_base + drv.hfpll_data->config_offset);
+ writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->m_offset);
+ writel_relaxed(1, sc->hfpll_base + drv.hfpll_data->n_offset);
/* Program droop controller, if supported */
- if (sc->hfpll_data->has_droop_ctl)
- writel_relaxed(sc->hfpll_data->droop_val,
- sc->hfpll_base + sc->hfpll_data->droop_offset);
+ if (drv.hfpll_data->has_droop_ctl)
+ writel_relaxed(drv.hfpll_data->droop_val,
+ sc->hfpll_base + drv.hfpll_data->droop_offset);
/* Set an initial rate and enable the PLL. */
hfpll_set_rate(sc, tgt_s);
@@ -679,18 +679,18 @@
}
/* Register with bus driver. */
-static void __init bus_init(struct msm_bus_scale_pdata *bus_scale_data)
+static void __init bus_init(void)
{
int ret;
- drv.bus_perf_client = msm_bus_scale_register_client(bus_scale_data);
+ drv.bus_perf_client = msm_bus_scale_register_client(drv.bus_scale);
if (!drv.bus_perf_client) {
dev_err(drv.dev, "unable to register bus client\n");
BUG();
}
ret = msm_bus_scale_client_update_request(drv.bus_perf_client,
- drv.max_acpu_lvl->l2_level->bw_level);
+ drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].bw_level);
if (ret)
dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret);
}
@@ -792,13 +792,11 @@
tbl->vdd_core = 1150000;
}
-static void __init select_freq_plan(struct acpu_level *const *pvs_tbl,
- u32 qfprom_phys)
+static int __init select_freq_plan(u32 qfprom_phys)
{
- const struct acpu_level *l;
void __iomem *qfprom_base;
u32 pte_efuse, pvs, tbl_idx;
- char *pvs_names[] = { "Slow", "Nominal", "Fast", "Unknown" };
+ char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
qfprom_base = ioremap(qfprom_phys, SZ_256);
/* Select frequency tables. */
@@ -820,6 +818,9 @@
case 0x3:
tbl_idx = PVS_FAST;
break;
+ case 0x4:
+ tbl_idx = PVS_FASTER;
+ break;
default:
tbl_idx = PVS_UNKNOWN;
break;
@@ -828,24 +829,29 @@
tbl_idx = PVS_UNKNOWN;
dev_err(drv.dev, "Unable to map QFPROM base\n");
}
- dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
if (tbl_idx == PVS_UNKNOWN) {
tbl_idx = PVS_SLOW;
dev_warn(drv.dev, "ACPU PVS: Defaulting to %s\n",
pvs_names[tbl_idx]);
+ } else {
+ dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
}
- drv.acpu_freq_tbl = pvs_tbl[tbl_idx];
- if (krait_needs_vmin())
- krait_apply_vmin(drv.acpu_freq_tbl);
+ return tbl_idx;
+}
- /* Find the max supported scaling frequency. */
- for (l = drv.acpu_freq_tbl; l->speed.khz != 0; l++)
+static const struct acpu_level __init *find_max_acpu_lvl(struct acpu_level *tbl)
+{
+ struct acpu_level *l, *max_lvl = NULL;
+
+ for (l = tbl; l->speed.khz != 0; l++)
if (l->use_for_scaling)
- drv.max_acpu_lvl = l;
- BUG_ON(!drv.max_acpu_lvl);
- dev_info(drv.dev, "Max ACPU freq: %lu KHz\n",
- drv.max_acpu_lvl->speed.khz);
+ max_lvl = l;
+
+ BUG_ON(!max_lvl);
+ dev_info(drv.dev, "Max CPU freq: %lu KHz\n", max_lvl->speed.khz);
+
+ return max_lvl;
}
static struct acpuclk_data acpuclk_krait_data = {
@@ -855,20 +861,51 @@
.wait_for_irq_khz = STBY_KHZ,
};
-int __init acpuclk_krait_init(struct device *dev,
- const struct acpuclk_krait_params *params)
+static void __init drv_data_init(struct device *dev,
+ const struct acpuclk_krait_params *params)
{
- struct scalable *l2;
+ int tbl_idx;
+
+ drv.dev = dev;
+ drv.scalable = kmemdup(params->scalable, params->scalable_size,
+ GFP_KERNEL);
+ BUG_ON(!drv.scalable);
+
+ drv.hfpll_data = kmemdup(params->hfpll_data, sizeof(*drv.hfpll_data),
+ GFP_KERNEL);
+ BUG_ON(!drv.hfpll_data);
+
+ drv.l2_freq_tbl = kmemdup(params->l2_freq_tbl, params->l2_freq_tbl_size,
+ GFP_KERNEL);
+ BUG_ON(!drv.l2_freq_tbl);
+
+ drv.bus_scale = kmemdup(params->bus_scale, sizeof(*drv.bus_scale),
+ GFP_KERNEL);
+ BUG_ON(!drv.bus_scale);
+ drv.bus_scale->usecase = kmemdup(drv.bus_scale->usecase,
+ drv.bus_scale->num_usecases * sizeof(*drv.bus_scale->usecase),
+ GFP_KERNEL);
+ BUG_ON(!drv.bus_scale->usecase);
+
+ tbl_idx = select_freq_plan(params->qfprom_phys_base);
+ drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
+ params->pvs_tables[tbl_idx].size,
+ GFP_KERNEL);
+ BUG_ON(!drv.acpu_freq_tbl);
+
+ drv.max_acpu_lvl = find_max_acpu_lvl(drv.acpu_freq_tbl);
+}
+
+static void __init hw_init(void)
+{
+ struct scalable *l2 = &drv.scalable[L2];
int cpu, rc;
- drv.scalable = params->scalable;
- drv.l2_freq_tbl = params->l2_freq_tbl;
- drv.dev = dev;
+ if (krait_needs_vmin())
+ krait_apply_vmin(drv.acpu_freq_tbl);
- select_freq_plan(params->pvs_acpu_freq_tbl, params->qfprom_phys_base);
- bus_init(params->bus_scale_data);
+ bus_init();
- l2 = &drv.scalable[L2];
l2->hfpll_base = ioremap(l2->hfpll_phys_base, SZ_32);
BUG_ON(!l2->hfpll_base);
@@ -878,17 +915,23 @@
rc = rpm_regulator_init(l2, VREG_HFPLL_B,
l2->vreg[VREG_HFPLL_B].max_vdd, false);
BUG_ON(rc);
-
- rc = init_clock_sources(l2, &drv.max_acpu_lvl->l2_level->speed);
+ rc = init_clock_sources(l2,
+ &drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].speed);
BUG_ON(rc);
for_each_online_cpu(cpu) {
rc = per_cpu_init(cpu);
BUG_ON(rc);
}
+}
+
+int __init acpuclk_krait_init(struct device *dev,
+ const struct acpuclk_krait_params *params)
+{
+ drv_data_init(dev, params);
+ hw_init();
cpufreq_table_init();
-
acpuclk_register(&acpuclk_krait_data);
register_hotcpu_notifier(&acpuclk_cpu_notifier);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index f121548..f92aaf3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -15,7 +15,7 @@
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_KRAIT_H
#define STBY_KHZ 1
-
+#define L2(x) (x)
#define BW_MBPS(_bw) \
{ \
.vectors = (struct msm_bus_vectors[]){ \
@@ -50,6 +50,7 @@
PVS_SLOW = 0,
PVS_NOMINAL,
PVS_FAST,
+ PVS_FASTER,
PVS_UNKNOWN,
NUM_PVS
};
@@ -146,7 +147,7 @@
struct acpu_level {
const int use_for_scaling;
const struct core_speed speed;
- const struct l2_level *l2_level;
+ const unsigned int l2_level;
int vdd_core;
};
@@ -162,7 +163,7 @@
* @droop_offset: Droop controller register offset from base address.
* @droop_val: Value to initialize the @config_offset register to.
* @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW.
- * @vdd: voltage requirements for each VDD level.
+ * @vdd: voltage requirements for each VDD level for the L2 PLL.
*/
struct hfpll_data {
const u32 mode_offset;
@@ -185,7 +186,6 @@
* @aux_clk_sel_phys: Physical address of auxiliary MUX.
* @aux_clk_sel: Auxiliary mux input to select at boot.
* @l2cpmr_iaddr: Indirect address of the CPMR MUX/divider CP15 register.
- * @hfpll_data: Descriptive data of HFPLL hardware.
* @cur_speed: Pointer to currently-set speed.
* @l2_vote: L2 performance level vote associate with the current CPU speed.
* @vreg: Array of voltage regulators needed by the scalable.
@@ -197,29 +197,42 @@
const phys_addr_t aux_clk_sel_phys;
const u32 aux_clk_sel;
const u32 l2cpmr_iaddr;
- const struct hfpll_data *hfpll_data;
const struct core_speed *cur_speed;
- const struct l2_level *l2_vote;
+ unsigned int l2_vote;
struct vreg vreg[NUM_VREG];
bool initialized;
};
/**
+ * struct pvs_table - CPU performance level table and size.
+ * @table: CPU performance level table
+ * @size: sizeof(@table)
+ */
+struct pvs_table {
+ struct acpu_level *table;
+ size_t size;
+};
+
+/**
* struct acpuclk_krait_params - SoC specific driver parameters.
* @scalable: Array of scalables.
- * @pvs_acpu_freq_tbl: Array of CPU frequency tables.
+ * @scalable_size: Size of @scalable.
+ * @hfpll_data: HFPLL configuration data.
+ * @pvs_tables: CPU frequency tables.
* @l2_freq_tbl: L2 frequency table.
- * @l2_freq_tbl_size: Number of rows in @l2_freq_tbl.
+ * @l2_freq_tbl_size: Size of @l2_freq_tbl.
* @qfprom_phys_base: Physical base address of QFPROM.
- * @bus_scale_data: MSM bus driver parameters.
+ * @bus_scale: MSM bus driver parameters.
*/
struct acpuclk_krait_params {
struct scalable *scalable;
- struct acpu_level *pvs_acpu_freq_tbl[NUM_PVS];
- const struct l2_level *l2_freq_tbl;
- const size_t l2_freq_tbl_size;
- const phys_addr_t qfprom_phys_base;
- struct msm_bus_scale_pdata *bus_scale_data;
+ size_t scalable_size;
+ struct hfpll_data *hfpll_data;
+ struct pvs_table *pvs_tables;
+ struct l2_level *l2_freq_tbl;
+ size_t l2_freq_tbl_size;
+ phys_addr_t qfprom_phys_base;
+ struct msm_bus_scale_pdata *bus_scale;
};
/**
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index a44ba7a..5aea0ed 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -434,30 +434,26 @@
mutex_lock(&bam_rx_pool_mutexlock);
list_add_tail(&info->list_node, &bam_rx_pool);
rx_len_cached = ++bam_rx_pool_len;
- mutex_unlock(&bam_rx_pool_mutexlock);
-
ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
BUFFER_SIZE, info,
SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
-
if (ret) {
+ list_del(&info->list_node);
+ rx_len_cached = --bam_rx_pool_len;
+ mutex_unlock(&bam_rx_pool_mutexlock);
DMUX_LOG_KERR("%s: sps_transfer_one failed %d\n",
__func__, ret);
- goto fail_transfer;
+
+ dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
+ DMA_FROM_DEVICE);
+
+ goto fail_skb;
}
+ mutex_unlock(&bam_rx_pool_mutexlock);
+
}
return;
-fail_transfer:
- mutex_lock(&bam_rx_pool_mutexlock);
- list_del(&info->list_node);
- --bam_rx_pool_len;
- rx_len_cached = bam_rx_pool_len;
- mutex_unlock(&bam_rx_pool_mutexlock);
-
- dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
- DMA_FROM_DEVICE);
-
fail_skb:
dev_kfree_skb_any(info->skb);
@@ -1078,18 +1074,29 @@
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
+ DMUX_LOG_KERR("%s: have iovec %p but rx pool empty\n",
+ __func__, (void *)iov.addr);
mutex_unlock(&bam_rx_pool_mutexlock);
continue;
}
info = list_first_entry(&bam_rx_pool, struct rx_pkt_info,
list_node);
+ if (info->dma_address != iov.addr) {
+ DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
+ __func__,
+ (void *)iov.addr,
+ (void *)info->dma_address);
+ list_for_each_entry(info, &bam_rx_pool, list_node) {
+ DMUX_LOG_KERR("%s: dma %p\n", __func__,
+ (void *)info->dma_address);
+ if (iov.addr == info->dma_address)
+ break;
+ }
+ }
+ BUG_ON(info->dma_address != iov.addr);
list_del(&info->list_node);
--bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
- if (info->dma_address != iov.addr)
- DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
- __func__,
- (void *)info->dma_address, (void *)iov.addr);
handle_bam_mux_cmd(&info->work);
}
return;
@@ -1123,13 +1130,30 @@
inactive_cycles = 0;
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
+ DMUX_LOG_KERR(
+ "%s: have iovec %p but rx pool empty\n",
+ __func__, (void *)iov.addr);
mutex_unlock(&bam_rx_pool_mutexlock);
continue;
}
info = list_first_entry(&bam_rx_pool,
struct rx_pkt_info, list_node);
- --bam_rx_pool_len;
+ if (info->dma_address != iov.addr) {
+ DMUX_LOG_KERR("%s: iovec %p != dma %p\n",
+ __func__,
+ (void *)iov.addr,
+ (void *)info->dma_address);
+ list_for_each_entry(info, &bam_rx_pool,
+ list_node) {
+ DMUX_LOG_KERR("%s: dma %p\n", __func__,
+ (void *)info->dma_address);
+ if (iov.addr == info->dma_address)
+ break;
+ }
+ }
+ BUG_ON(info->dma_address != iov.addr);
list_del(&info->list_node);
+ --bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
handle_bam_mux_cmd(&info->work);
}
@@ -1888,7 +1912,7 @@
ul_powerdown_finish();
a2_pc_disabled = 0;
a2_pc_disabled_wakelock_skipped = 0;
- disconnect_ack = 0;
+ disconnect_ack = 1;
/* Cleanup Channel States */
mutex_lock(&bam_pdev_mutexlock);
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index c37491d..40995bb 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -243,7 +243,7 @@
{
.src = MSM_BUS_MASTER_VFE,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 140451840,
+ .ab = 274406400,
.ib = 561807360,
},
{
@@ -302,6 +302,27 @@
},
};
+static struct msm_bus_vectors cam_video_ls_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 348192000,
+ .ib = 617103360,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
ARRAY_SIZE(cam_init_vectors),
@@ -323,6 +344,10 @@
ARRAY_SIZE(cam_zsl_vectors),
cam_zsl_vectors,
},
+ {
+ ARRAY_SIZE(cam_video_ls_vectors),
+ cam_video_ls_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 177e1fd..330d7a8 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -1045,7 +1045,8 @@
}
}
-void __init apq8064_set_display_params(char *prim_panel, char *ext_panel)
+void __init apq8064_set_display_params(char *prim_panel, char *ext_panel,
+ unsigned char resolution)
{
/*
* For certain MPQ boards, HDMI should be set as primary display
@@ -1080,4 +1081,6 @@
pr_debug("msm_fb_pdata.ext_panel_name %s\n",
msm_fb_pdata.ext_panel_name);
}
+
+ msm_fb_pdata.ext_resolution = resolution;
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0f9c939..eb36a81e 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -13,10 +13,11 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/msm_dcvs.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8064.h"
@@ -247,5 +248,13 @@
void __init apq8064_init_gpu(void)
{
+ unsigned int version = socinfo_get_version();
+
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 1))
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
+ else
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+
platform_device_register(&device_kgsl_3d0);
}
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index f727852..a84cb39 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -179,11 +179,11 @@
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
- REGULATOR_SUPPLY("krait0", NULL),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8064"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8921_s6", NULL),
- REGULATOR_SUPPLY("krait1", NULL),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8064"),
};
VREG_CONSUMERS(S7) = {
REGULATOR_SUPPLY("8921_s7", NULL),
@@ -221,7 +221,6 @@
REGULATOR_SUPPLY("8921_lvs7", NULL),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("lvds_vdda", "lvds.0"),
- REGULATOR_SUPPLY("hdmi_pll_fs", "mdp.0"),
REGULATOR_SUPPLY("dsi1_vddio", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_vdda", "hdmi_msm.0"),
};
@@ -238,11 +237,11 @@
};
VREG_CONSUMERS(8821_S0) = {
REGULATOR_SUPPLY("8821_s0", NULL),
- REGULATOR_SUPPLY("krait2", NULL),
+ REGULATOR_SUPPLY("krait2", "acpuclk-8064"),
};
VREG_CONSUMERS(8821_S1) = {
REGULATOR_SUPPLY("8821_s1", NULL),
- REGULATOR_SUPPLY("krait3", NULL),
+ REGULATOR_SUPPLY("krait3", "acpuclk-8064"),
};
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
@@ -607,10 +606,37 @@
int msm8064_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+ { \
+ .vreg_id = RPM_VREG_ID_PM8921_##_id, \
+ .sleep_also = _sleep_also, \
+ .voter = _voter, \
+ .supply = _supply, \
+ .dev_name = _dev_name, \
+ }
+static struct rpm_regulator_consumer_mapping
+ msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+ RPM_REG_MAP(LVS7, 0, 1, "krait0_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 2, "krait1_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 4, "krait2_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 5, "krait3_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 6, "l2_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 4, "krait2_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 5, "krait3_mem", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 1, "krait0_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 2, "krait1_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 4, "krait2_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 5, "krait3_dig", "acpuclk-8064"),
+};
+
struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
.init_data = apq8064_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(apq8064_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8960,
.vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
.vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+ .consumer_map = msm_rpm_regulator_consumer_mapping,
+ .consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index bf71b6f..39b58cf 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -657,6 +657,9 @@
static char prim_panel_name[PANEL_NAME_MAX_LEN];
static char ext_panel_name[PANEL_NAME_MAX_LEN];
+
+static int ext_resolution;
+
static int __init prim_display_setup(char *param)
{
if (strnlen(param, PANEL_NAME_MAX_LEN))
@@ -673,9 +676,18 @@
}
early_param("ext_display", ext_display_setup);
+static int __init hdmi_resulution_setup(char *param)
+{
+ int ret;
+ ret = kstrtoint(param, 10, &ext_resolution);
+ return ret;
+}
+early_param("ext_resolution", hdmi_resulution_setup);
+
static void __init apq8064_reserve(void)
{
- apq8064_set_display_params(prim_panel_name, ext_panel_name);
+ apq8064_set_display_params(prim_panel_name, ext_panel_name,
+ ext_resolution);
msm_reserve();
if (apq8064_fmem_pdata.size) {
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
@@ -2037,12 +2049,6 @@
},
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
static void __init apq8064_init_buses(void)
{
msm_bus_rpm_set_mt_mask();
@@ -2148,7 +2154,7 @@
};
static struct platform_device *common_devices[] __initdata = {
- &msm8960_device_acpuclk,
+ &apq8064_device_acpuclk,
&apq8064_device_dmov,
&apq8064_device_qup_spi_gsbi5,
&apq8064_device_ext_5v_vreg,
@@ -2952,7 +2958,6 @@
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
msm_spm_l2_init(msm_spm_l2_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
apq8064_epm_adc_init();
}
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index a241ab3..2258b8d 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -87,7 +87,8 @@
void apq8064_init_fb(void);
void apq8064_allocate_fb_region(void);
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
-void __init apq8064_set_display_params(char *prim_panel, char *ext_panel);
+void __init apq8064_set_display_params(char *prim_panel, char *ext_panel,
+ unsigned char resolution);
void apq8064_init_gpu(void);
void apq8064_pm8xxx_gpio_mpp_init(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 6ee315c..d3e37cd 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -251,7 +251,7 @@
{
.src = MSM_BUS_MASTER_VFE,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 140451840,
+ .ab = 274406400,
.ib = 561807360,
},
{
@@ -310,6 +310,27 @@
},
};
+static struct msm_bus_vectors cam_video_ls_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 348192000,
+ .ib = 617103360,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
ARRAY_SIZE(cam_init_vectors),
@@ -331,6 +352,10 @@
ARRAY_SIZE(cam_zsl_vectors),
cam_zsl_vectors,
},
+ {
+ ARRAY_SIZE(cam_video_ls_vectors),
+ cam_video_ls_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 739dc85..292c031 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -131,6 +131,7 @@
* appropriate function.
*/
#define DISP_RST_GPIO 58
+#define DISP_3D_2D_MODE 1
static int mipi_dsi_cdp_panel_power(int on)
{
static struct regulator *reg_l8, *reg_l23, *reg_l2;
@@ -183,6 +184,19 @@
gpio_free(DISP_RST_GPIO);
return -ENODEV;
}
+ rc = gpio_request(DISP_3D_2D_MODE, "disp_3d_2d");
+ if (rc) {
+ pr_err("request gpio DISP_3D_2D_MODE failed, rc=%d\n",
+ rc);
+ gpio_free(DISP_3D_2D_MODE);
+ return -ENODEV;
+ }
+ rc = gpio_direction_output(DISP_3D_2D_MODE, 0);
+ if (rc) {
+ pr_err("gpio_direction_output failed for %d gpio rc=%d\n",
+ DISP_3D_2D_MODE, rc);
+ return -ENODEV;
+ }
dsi_power_on = true;
}
if (on) {
@@ -222,6 +236,8 @@
gpio_set_value(DISP_RST_GPIO, 0);
usleep(20);
gpio_set_value(DISP_RST_GPIO, 1);
+ gpio_set_value(DISP_3D_2D_MODE, 1);
+ usleep(20);
} else {
gpio_set_value(DISP_RST_GPIO, 0);
@@ -256,6 +272,8 @@
pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
return -EINVAL;
}
+ gpio_set_value(DISP_3D_2D_MODE, 0);
+ usleep(20);
}
return 0;
}
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 066c134..bd343c1 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/socinfo.h>
@@ -160,8 +160,16 @@
void __init msm8930_init_gpu(void)
{
- if (cpu_is_msm8627())
- kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 400000000;
+ unsigned int version = socinfo_get_version();
+
+ if (cpu_is_msm8930aa())
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 450000000;
+
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 2))
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 0, 5, 2);
+ else
+ kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 0, 5, 0);
platform_device_register(&device_kgsl_3d0);
}
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index f06a1b7..af91089 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -172,11 +172,13 @@
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8038_s5", NULL),
- REGULATOR_SUPPLY("krait0", NULL),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8627"),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8930"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8038_s6", NULL),
- REGULATOR_SUPPLY("krait1", NULL),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8627"),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8930"),
};
VREG_CONSUMERS(LVS1) = {
REGULATOR_SUPPLY("8038_lvs1", NULL),
@@ -511,10 +513,39 @@
int msm8930_pm8038_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8930_pm8038_regulator_pdata);
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+ { \
+ .vreg_id = RPM_VREG_ID_PM8038_##_id, \
+ .sleep_also = _sleep_also, \
+ .voter = _voter, \
+ .supply = _supply, \
+ .dev_name = _dev_name, \
+ }
+static struct rpm_regulator_consumer_mapping
+ msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+ RPM_REG_MAP(L23, 0, 1, "krait0_hfpll", "acpuclk-8930"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_hfpll", "acpuclk-8930"),
+ RPM_REG_MAP(L23, 0, 6, "l2_hfpll", "acpuclk-8930"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8930"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8930"),
+ RPM_REG_MAP(VDD_DIG_CORNER, 0, 1, "krait0_dig", "acpuclk-8930"),
+ RPM_REG_MAP(VDD_DIG_CORNER, 0, 2, "krait1_dig", "acpuclk-8930"),
+
+ RPM_REG_MAP(L23, 0, 1, "krait0_hfpll", "acpuclk-8627"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_hfpll", "acpuclk-8627"),
+ RPM_REG_MAP(L23, 0, 6, "l2_hfpll", "acpuclk-8627"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8627"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8627"),
+ RPM_REG_MAP(VDD_DIG_CORNER, 0, 1, "krait0_dig", "acpuclk-8627"),
+ RPM_REG_MAP(VDD_DIG_CORNER, 0, 2, "krait1_dig", "acpuclk-8627"),
+};
+
struct rpm_regulator_platform_data msm8930_rpm_regulator_pdata __devinitdata = {
.init_data = msm8930_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(msm8930_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8930,
.vreg_id_vdd_mem = RPM_VREG_ID_PM8038_L24,
.vreg_id_vdd_dig = RPM_VREG_ID_PM8038_VDD_DIG_CORNER,
+ .consumer_map = msm_rpm_regulator_consumer_mapping,
+ .consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index e695241..d7a077c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -26,7 +26,6 @@
#include <linux/spi/spi.h>
#include <linux/slimbus/slimbus.h>
#include <linux/bootmem.h>
-#include <linux/msm_kgsl.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
@@ -80,6 +79,7 @@
#include <linux/fmem.h>
#include <mach/msm_cache_dump.h>
+#include <mach/kgsl.h>
#ifdef CONFIG_INPUT_MPU3050
#include <linux/input/mpu3050.h>
#endif
@@ -1460,6 +1460,9 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &usb_bus_scale_pdata,
#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+ .mhl_dev_name = "sii8334",
+#endif
};
#endif
@@ -2159,7 +2162,6 @@
};
static struct platform_device *common_devices[] __initdata = {
- &msm8960_device_acpuclk,
&msm8960_device_dmov,
&msm_device_smd,
&msm8960_device_uart_gsbi5,
@@ -2399,12 +2401,6 @@
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
#ifdef CONFIG_I2C
#define I2C_SURF 1
#define I2C_FFA (1 << 1)
@@ -2573,6 +2569,10 @@
msm_spm_l2_init(msm_spm_l2_data);
msm8930_init_buses();
platform_add_devices(msm8930_footswitch, msm8930_num_footswitch);
+ if (cpu_is_msm8627())
+ platform_device_register(&msm8627_device_acpuclk);
+ else if (cpu_is_msm8930() || cpu_is_msm8930aa())
+ platform_device_register(&msm8930_device_acpuclk);
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8930_add_vidc_device();
/*
@@ -2597,7 +2597,6 @@
ARRAY_SIZE(msm_slim_devices));
change_memory_power = &msm8930_change_memory_power;
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
if (PLATFORM_IS_CHARM25())
platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 8acee09..0bb0b8f 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -274,7 +274,7 @@
{
.src = MSM_BUS_MASTER_VFE,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 154275840,
+ .ab = 274406400,
.ib = 617103360,
},
{
@@ -369,6 +369,40 @@
},
};
+static struct msm_bus_vectors cam_video_ls_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 348192000,
+ .ib = 617103360,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+
static struct msm_bus_paths cam_bus_client_config[] = {
{
ARRAY_SIZE(cam_init_vectors),
@@ -390,6 +424,10 @@
ARRAY_SIZE(cam_zsl_vectors),
cam_zsl_vectors,
},
+ {
+ ARRAY_SIZE(cam_video_ls_vectors),
+ cam_video_ls_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index fd326f1..5851990 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -76,6 +76,18 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting gsbi8_uartdm_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi8_uartdm_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting gsbi9_active_cfg = {
.func = GPIOMUX_FUNC_2,
.drv = GPIOMUX_DRV_8MA,
@@ -240,6 +252,12 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting usbsw_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting mdp_vsync_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -304,6 +322,37 @@
},
};
#endif
+/* GSBI8 UART GPIOs for Atheros Bluetooth */
+static struct msm_gpiomux_config msm8960_gsbi8_uartdm_configs[] = {
+ {
+ .gpio = 34,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 35,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 36,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 37,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+};
static struct msm_gpiomux_config msm8960_fusion_gsbi_configs[] = {
{
@@ -760,6 +809,13 @@
[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
}
},
+ /* USB_SW */
+ {
+ .gpio = 25,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &usbsw_cfg,
+ }
+ }
};
static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = {
@@ -975,6 +1031,10 @@
msm_gpiomux_install(msm8960_mdp_vsync_configs,
ARRAY_SIZE(msm8960_mdp_vsync_configs));
+ if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE)
+ msm_gpiomux_install(msm8960_gsbi8_uartdm_configs,
+ ARRAY_SIZE(msm8960_gsbi8_uartdm_configs));
+
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
msm_gpiomux_install(msm8960_gsbi8_uart_configs,
ARRAY_SIZE(msm8960_gsbi8_uart_configs));
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 2664d6b..6ad44d8 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -116,7 +116,6 @@
REGULATOR_SUPPLY("8921_l23", NULL),
REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
- REGULATOR_SUPPLY("hdmi_pll_fs", "mdp.0"),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
@@ -182,11 +181,11 @@
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
- REGULATOR_SUPPLY("krait0", NULL),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8960"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8921_s6", NULL),
- REGULATOR_SUPPLY("krait1", NULL),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8960"),
};
VREG_CONSUMERS(S7) = {
REGULATOR_SUPPLY("8921_s7", NULL),
@@ -562,10 +561,34 @@
int msm_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm_pm8921_regulator_pdata);
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+ { \
+ .vreg_id = RPM_VREG_ID_PM8921_##_id, \
+ .sleep_also = _sleep_also, \
+ .voter = _voter, \
+ .supply = _supply, \
+ .dev_name = _dev_name, \
+ }
+static struct rpm_regulator_consumer_mapping
+ msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+ RPM_REG_MAP(L23, 0, 1, "krait0_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L23, 0, 6, "l2_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8960"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8960"),
+ RPM_REG_MAP(S3, 0, 1, "krait0_dig", "acpuclk-8960"),
+ RPM_REG_MAP(S3, 0, 2, "krait1_dig", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 1, "krait0_s8", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 2, "krait1_s8", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 6, "l2_s8", "acpuclk-8960"),
+};
+
struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata = {
.init_data = msm_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(msm_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8960,
.vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
.vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+ .consumer_map = msm_rpm_regulator_consumer_mapping,
+ .consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a4e45c9..d56bdbd 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -26,7 +26,6 @@
#include <linux/spi/spi.h>
#include <linux/slimbus/slimbus.h>
#include <linux/bootmem.h>
-#include <linux/msm_kgsl.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
@@ -87,6 +86,7 @@
#include <mach/scm.h>
#include <mach/iommu_domains.h>
+#include <mach/kgsl.h>
#include <linux/fmem.h>
#include "timer.h"
@@ -1293,6 +1293,7 @@
.peripheral_platform_device = NULL,
.ramdump_timeout_ms = 600000,
.no_powerdown_after_ramdumps = 1,
+ .image_upgrade_supported = 1,
};
#define MSM_TSIF0_PHYS (0x18200000)
@@ -1488,6 +1489,9 @@
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &usb_bus_scale_pdata,
#endif
+#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
+ .mhl_dev_name = "sii8334",
+#endif
};
#endif
@@ -1911,18 +1915,9 @@
.gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
CY_GEST_GRP3 | CY_GEST_GRP4 |
CY_ACT_DIST,
- /* change act_intrvl to customize the Active power state
- * scanning/processing refresh interval for Operating mode
- */
- .act_intrvl = CY_ACT_INTRVL_DFLT,
- /* change tch_tmout to customize the touch timeout for the
- * Active power state for Operating mode
- */
- .tch_tmout = CY_TCH_TMOUT_DFLT,
- /* change lp_intrvl to customize the Low Power power state
- * scanning/processing refresh interval for Operating mode
- */
- .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .act_intrvl = 10,
+ .tch_tmout = 200,
+ .lp_intrvl = 30,
.sleep_gpio = CYTTSP_TS_SLEEP_GPIO,
.resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
.irq_gpio = CYTTSP_TS_GPIO_IRQ,
@@ -2326,12 +2321,6 @@
.src_clk_rate = 24000000,
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
static struct ks8851_pdata spi_eth_pdata = {
.irq_gpio = KS8851_IRQ_GPIO,
.rst_gpio = KS8851_RST_GPIO,
@@ -2467,7 +2456,36 @@
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
.gpio_config = configure_uart_gpios,
};
+
+static int configure_gsbi8_uart_gpios(int on)
+{
+ int ret = 0, i;
+ int uart_gpios[] = {34, 35, 36, 37};
+
+ for (i = 0; i < ARRAY_SIZE(uart_gpios); i++) {
+ if (on) {
+ ret = gpio_request(uart_gpios[i], NULL);
+ if (ret) {
+ pr_err("%s: unable to request uart gpio[%d]\n",
+ __func__, uart_gpios[i]);
+ break;
+ }
+ } else {
+ gpio_free(uart_gpios[i]);
+ }
+ }
+
+ if (ret && on && i)
+ for (; i >= 0; i--)
+ gpio_free(uart_gpios[i]);
+ return ret;
+}
+
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata = {
+ .gpio_config = configure_gsbi8_uart_gpios,
+};
#else
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata;
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
#endif
@@ -2476,7 +2494,6 @@
&msm8960_device_dmov,
&msm_device_smd,
&msm_device_uart_dm6,
- &msm_device_uart_dm9,
&msm_device_saw_core0,
&msm_device_saw_core1,
&msm8960_device_ext_5v_vreg,
@@ -2696,13 +2713,26 @@
static void __init msm8960_gfx_init(void)
{
+ struct kgsl_device_platform_data *kgsl_3d0_pdata =
+ msm_kgsl_3d0.dev.platform_data;
uint32_t soc_platform_version = socinfo_get_version();
+
if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- struct kgsl_device_platform_data *kgsl_3d0_pdata =
- msm_kgsl_3d0.dev.platform_data;
kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
}
+ if (cpu_is_msm8960ab()) {
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
+ } else {
+
+ /* 8960v3 GPU registers returns 5 for patch release
+ * but it should be 6, so dummy up the chipid here
+ * based the platform type
+ */
+
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3)
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ }
}
static struct msm_rpmrs_level msm_rpmrs_levels[] = {
@@ -3040,7 +3070,6 @@
slim_register_board_info(msm_slim_devices,
ARRAY_SIZE(msm_slim_devices));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
}
static void __init msm8960_rumi3_init(void)
@@ -3070,7 +3099,6 @@
slim_register_board_info(msm_slim_devices,
ARRAY_SIZE(msm_slim_devices));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
}
static void __init msm8960_cdp_init(void)
@@ -3133,8 +3161,14 @@
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
msm_uart_dm9_pdata.wakeup_irq = gpio_to_irq(94); /* GSBI9(2) */
msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+ platform_device_register(&msm_device_uart_dm9);
}
+ /* For 8960 Standalone External Bluetooth Interface */
+ if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE) {
+ msm_device_uart_dm8.dev.platform_data = &msm_uart_dm8_pdata;
+ platform_device_register(&msm_device_uart_dm8);
+ }
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
@@ -3153,7 +3187,6 @@
msm8960_init_dsps();
change_memory_power = &msm8960_change_memory_power;
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
mdm_sglte_device.dev.platform_data = &sglte_platform_data;
platform_device_register(&mdm_sglte_device);
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 557331a..6b46a2f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -208,12 +208,12 @@
static struct resource smd_resource[] = {
{
.name = "modem_smd_in",
- .start = 32 + 17, /* mss_sw_to_kpss_ipc_irq0 */
+ .start = 32 + 25, /* mss_sw_to_kpss_ipc_irq0 */
.flags = IORESOURCE_IRQ,
},
{
.name = "modem_smsm_in",
- .start = 32 + 18, /* mss_sw_to_kpss_ipc_irq1 */
+ .start = 32 + 26, /* mss_sw_to_kpss_ipc_irq1 */
.flags = IORESOURCE_IRQ,
},
{
@@ -383,6 +383,7 @@
static void __init msm_8974_early_memory(void)
{
reserve_info = &msm_8974_reserve_info;
+ of_scan_flat_dt(dt_scan_for_memory_reserve, msm_8974_reserve_table);
}
void __init msm_8974_reserve(void)
@@ -640,6 +641,8 @@
OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
"qseecom", NULL),
OF_DEV_AUXDATA("qcom,mdss_mdp", 0xFD900000, "mdp.0", NULL),
+ OF_DEV_AUXDATA("qcom,msm-tsens", 0xFC4A8000, \
+ "msm-tsens", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 9259161..3726941 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -1188,9 +1188,9 @@
}
/*Toggle Backlight GPIO*/
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
- udelay(190);
+ udelay(100);
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
- udelay(286);
+ udelay(430);
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
/* 1 wire mode starts from this low to high transition */
udelay(50);
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 22095cd..47e8381 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/atmel_maxtouch.h>
#include <linux/input/ft5x06_ts.h>
+#include <linux/leds-msm-tricolor.h>
#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <mach/rpc_server_handset.h>
@@ -162,32 +163,6 @@
};
#define LED_GPIO_PDM 96
-#define LED_RED_GPIO_8625 49
-#define LED_GREEN_GPIO_8625 34
-
-static struct gpio_led gpio_leds_config_8625[] = {
- {
- .name = "green",
- .gpio = LED_GREEN_GPIO_8625,
- },
- {
- .name = "red",
- .gpio = LED_RED_GPIO_8625,
- },
-};
-
-static struct gpio_led_platform_data gpio_leds_pdata_8625 = {
- .num_leds = ARRAY_SIZE(gpio_leds_config_8625),
- .leds = gpio_leds_config_8625,
-};
-
-static struct platform_device gpio_leds_8625 = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &gpio_leds_pdata_8625,
- },
-};
#define MXT_TS_IRQ_GPIO 48
#define MXT_TS_RESET_GPIO 26
@@ -772,6 +747,30 @@
},
};
+static struct led_info tricolor_led_info[] = {
+ [0] = {
+ .name = "red",
+ .flags = LED_COLOR_RED,
+ },
+ [1] = {
+ .name = "green",
+ .flags = LED_COLOR_GREEN,
+ },
+};
+
+static struct led_platform_data tricolor_led_pdata = {
+ .leds = tricolor_led_info,
+ .num_leds = ARRAY_SIZE(tricolor_led_info),
+};
+
+static struct platform_device tricolor_leds_pdev = {
+ .name = "msm-tricolor-leds",
+ .id = -1,
+ .dev = {
+ .platform_data = &tricolor_led_pdata,
+ },
+};
+
void __init msm7627a_add_io_devices(void)
{
/* touchscreen */
@@ -868,24 +867,9 @@
platform_device_register(&kp_pdev_sku3);
/* leds */
- if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
- rc = gpio_tlmm_config(GPIO_CFG(LED_RED_GPIO_8625, 0,
- GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
- GPIO_CFG_16MA), GPIO_CFG_ENABLE);
- if (rc) {
- pr_err("%s: gpio_tlmm_config for %d failed\n",
- __func__, LED_RED_GPIO_8625);
- }
-
- rc = gpio_tlmm_config(GPIO_CFG(LED_GREEN_GPIO_8625, 0,
- GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
- GPIO_CFG_16MA), GPIO_CFG_ENABLE);
- if (rc) {
- pr_err("%s: gpio_tlmm_config for %d failed\n",
- __func__, LED_GREEN_GPIO_8625);
- }
-
- platform_device_register(&gpio_leds_8625);
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
+ machine_is_msm8625_evt()) {
platform_device_register(&pmic_mpp_leds_pdev);
+ platform_device_register(&tricolor_leds_pdev);
}
}
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 7db4bda..ba4e098 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,7 +48,6 @@
#include <mach/msm_battery.h>
#include <linux/smsc911x.h>
#include <linux/atmel_maxtouch.h>
-#include <linux/fmem.h>
#include <linux/msm_adc.h>
#include <linux/ion.h>
#include "devices.h"
@@ -448,9 +447,6 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
- .request_region = request_fmem_c_region,
- .release_region = release_fmem_c_region,
- .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -778,14 +774,6 @@
static void msm7x27a_cfg_uart2dm_serial(void) { }
#endif
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
- .name = "fmem",
- .id = 1,
- .dev = { .platform_data = &fmem_pdata },
-};
-
static struct platform_device *rumi_sim_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
@@ -823,7 +811,6 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_audio_device,
- &fmem_device,
&msm_device_nand,
&msm_device_snd,
&msm_device_adspdec,
@@ -966,32 +953,10 @@
{
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- unsigned int i;
- unsigned int reusable_count = 0;
-
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
- fmem_pdata.size = 0;
- fmem_pdata.align = PAGE_SIZE;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
#endif
#endif
}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 5b9ea36..a694557 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -31,7 +31,6 @@
#include <linux/memblock.h>
#include <linux/input/ft5x06_ts.h>
#include <linux/msm_adc.h>
-#include <linux/fmem.h>
#include <linux/regulator/msm-gpio-regulator.h>
#include <linux/ion.h>
#include <asm/mach/mmc.h>
@@ -144,6 +143,7 @@
static struct android_usb_platform_data android_usb_pdata = {
.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
+ .cdrom = 1,
};
static struct platform_device android_usb_device = {
@@ -393,9 +393,6 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
- .request_region = request_fmem_c_region,
- .release_region = release_fmem_c_region,
- .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -592,9 +589,9 @@
static u32 msm_calculate_batt_capacity(u32 current_voltage);
static struct msm_psy_batt_pdata msm_psy_batt_data = {
- .voltage_min_design = 3200,
+ .voltage_min_design = 3500,
.voltage_max_design = 4200,
- .voltage_fail_safe = 3340,
+ .voltage_fail_safe = 3598,
.avail_chg_sources = AC_CHG | USB_CHG ,
.batt_technology = POWER_SUPPLY_TECHNOLOGY_LION,
.calculate_capacity = &msm_calculate_batt_capacity,
@@ -638,14 +635,6 @@
},
};
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
- .name = "fmem",
- .id = 1,
- .dev = { .platform_data = &fmem_pdata },
-};
-
#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
[GPIO_VREG_ID_##_id] = { \
.init_data = { \
@@ -716,7 +705,6 @@
&asoc_msm_dai0,
&asoc_msm_dai1,
&msm_adc_device,
- &fmem_device,
#ifdef CONFIG_ION_MSM
&ion_dev,
#endif
@@ -857,32 +845,9 @@
{
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- unsigned int i;
- unsigned int reusable_count = 0;
-
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
-
- fmem_pdata.size = 0;
- fmem_pdata.align = PAGE_SIZE;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
#endif
#endif
}
diff --git a/arch/arm/mach-msm/board-swordfish.c b/arch/arm/mach-msm/board-swordfish.c
index 45d5bb0..7262277 100644
--- a/arch/arm/mach-msm/board-swordfish.c
+++ b/arch/arm/mach-msm/board-swordfish.c
@@ -21,7 +21,7 @@
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/android_pmem.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index c3302ec..8a73c84 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -253,22 +253,11 @@
int print_regs = cesr & CESR_PRINT_MASK;
int log_event = cesr & CESR_LOG_EVENT_MASK;
- void *const saw_bases[] = {
- MSM_SAW0_BASE,
- MSM_SAW1_BASE,
- MSM_SAW2_BASE,
- MSM_SAW3_BASE,
- };
-
if (print_regs) {
pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
pr_alert("\tCESR = 0x%08x\n", cesr);
pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
pr_alert("\tMIDR = 0x%08x\n", read_cpuid_id());
- pr_alert("\tPTE fuses = 0x%08x\n",
- readl_relaxed(MSM_QFPROM_BASE + 0xC0));
- pr_alert("\tPMIC_VREG = 0x%08x\n",
- readl_relaxed(saw_bases[cpu] + 0x14));
}
if (cesr & CESR_DCTPE) {
@@ -550,12 +539,18 @@
return 0;
}
+static struct of_device_id cache_erp_match_table[] = {
+ { .compatible = "qcom,cache_erp", },
+ {}
+};
+
static struct platform_driver msm_cache_erp_driver = {
.probe = msm_cache_erp_probe,
.remove = msm_cache_erp_remove,
.driver = {
.name = MODULE_NAME,
.owner = THIS_MODULE,
+ .of_match_table = cache_erp_match_table,
},
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 678c01f..8b57394 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -194,6 +194,7 @@
#define DSI2_ESC_CC_REG REG_MM(0x013C)
#define DSI_PIXEL_CC_REG REG_MM(0x0130)
#define DSI2_PIXEL_CC_REG REG_MM(0x0094)
+#define DSI2_PIXEL_CC2_REG REG_MM(0x0264)
#define DBG_BUS_VEC_A_REG REG_MM(0x01C8)
#define DBG_BUS_VEC_B_REG REG_MM(0x01CC)
#define DBG_BUS_VEC_C_REG REG_MM(0x01D0)
@@ -419,16 +420,16 @@
.fmax[VDD_DIG_##l2] = (f2), \
.fmax[VDD_DIG_##l3] = (f3)
-enum vdd_sr2_pll_levels {
- VDD_SR2_PLL_OFF,
- VDD_SR2_PLL_ON
+enum vdd_sr2_hdmi_pll_levels {
+ VDD_SR2_HDMI_PLL_OFF,
+ VDD_SR2_HDMI_PLL_ON
};
-static int set_vdd_sr2_pll_8960(struct clk_vdd_class *vdd_class, int level)
+static int set_vdd_sr2_hdmi_pll_8960(struct clk_vdd_class *vdd_class, int level)
{
int rc = 0;
- if (level == VDD_SR2_PLL_OFF) {
+ if (level == VDD_SR2_HDMI_PLL_OFF) {
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
RPM_VREG_VOTER3, 0, 0, 1);
if (rc)
@@ -453,20 +454,20 @@
return rc;
}
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll_8960);
+static DEFINE_VDD_CLASS(vdd_sr2_hdmi_pll, set_vdd_sr2_hdmi_pll_8960);
static int sr2_lreg_uv[] = {
- [VDD_SR2_PLL_OFF] = 0,
- [VDD_SR2_PLL_ON] = 1800000,
+ [VDD_SR2_HDMI_PLL_OFF] = 0,
+ [VDD_SR2_HDMI_PLL_ON] = 1800000,
};
-static int set_vdd_sr2_pll_8064(struct clk_vdd_class *vdd_class, int level)
+static int set_vdd_sr2_hdmi_pll_8064(struct clk_vdd_class *vdd_class, int level)
{
return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_LVS7, RPM_VREG_VOTER3,
sr2_lreg_uv[level], sr2_lreg_uv[level], 1);
}
-static int set_vdd_sr2_pll_8930(struct clk_vdd_class *vdd_class, int level)
+static int set_vdd_sr2_hdmi_pll_8930(struct clk_vdd_class *vdd_class, int level)
{
return rpm_vreg_set_voltage(RPM_VREG_ID_PM8038_L23, RPM_VREG_VOTER3,
sr2_lreg_uv[level], sr2_lreg_uv[level], 1);
@@ -498,8 +499,8 @@
.dbg_name = "pll3_clk",
.rate = 1200000000,
.ops = &clk_ops_local_pll,
- .vdd_class = &vdd_sr2_pll,
- .fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
+ .vdd_class = &vdd_sr2_hdmi_pll,
+ .fmax[VDD_SR2_HDMI_PLL_ON] = ULONG_MAX,
CLK_INIT(pll3_clk.c),
.warned = true,
},
@@ -785,7 +786,7 @@
};
/* gfx3d_axi_clk is set as a dependency of gmem_axi_clk at runtime */
-static struct branch_clk gfx3d_axi_clk_8064 = {
+static struct branch_clk gfx3d_axi_clk = {
.b = {
.ctl_reg = MAXI_EN5_REG,
.en_mask = BIT(25),
@@ -799,7 +800,7 @@
.c = {
.dbg_name = "gfx3d_axi_clk",
.ops = &clk_ops_branch,
- CLK_INIT(gfx3d_axi_clk_8064.c),
+ CLK_INIT(gfx3d_axi_clk.c),
},
};
@@ -2688,6 +2689,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi0_src_clk.c),
+ .warned = true,
},
};
@@ -2705,6 +2707,7 @@
.dbg_name = "csi0_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi0_clk.c),
+ .warned = true,
},
};
@@ -2744,6 +2747,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi1_src_clk.c),
+ .warned = true,
},
};
@@ -2761,6 +2765,7 @@
.dbg_name = "csi1_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi1_clk.c),
+ .warned = true,
},
};
@@ -2800,6 +2805,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi2_src_clk.c),
+ .warned = true,
},
};
@@ -2817,6 +2823,7 @@
.dbg_name = "csi2_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi2_clk.c),
+ .warned = true,
},
};
@@ -3406,6 +3413,27 @@
.ctl_val = CC_BANKED(9, 6, n), \
}
+static struct clk_freq_tbl clk_tbl_gfx3d_8960ab[] = {
+ F_GFX3D( 0, gnd, 0, 0),
+ F_GFX3D( 27000000, pxo, 0, 0),
+ F_GFX3D( 48000000, pll8, 1, 8),
+ F_GFX3D( 54857000, pll8, 1, 7),
+ F_GFX3D( 64000000, pll8, 1, 6),
+ F_GFX3D( 76800000, pll8, 1, 5),
+ F_GFX3D( 96000000, pll8, 1, 4),
+ F_GFX3D(128000000, pll8, 1, 3),
+ F_GFX3D(145455000, pll2, 2, 11),
+ F_GFX3D(160000000, pll2, 1, 5),
+ F_GFX3D(177778000, pll2, 2, 9),
+ F_GFX3D(200000000, pll2, 1, 4),
+ F_GFX3D(228571000, pll2, 2, 7),
+ F_GFX3D(266667000, pll2, 1, 3),
+ F_GFX3D(320000000, pll2, 2, 5),
+ F_GFX3D(325000000, pll3, 1, 2),
+ F_GFX3D(400000000, pll2, 1, 2),
+ F_END
+};
+
static struct clk_freq_tbl clk_tbl_gfx3d_8960[] = {
F_GFX3D( 0, gnd, 0, 0),
F_GFX3D( 27000000, pxo, 0, 0),
@@ -3713,6 +3741,27 @@
.ns_val = NS_MND_BANKED8(22, 14, n, m, 3, 0, s##_to_mm_mux), \
.ctl_val = CC_BANKED(9, 6, n), \
}
+static struct clk_freq_tbl clk_tbl_mdp_8960ab[] = {
+ F_MDP( 0, gnd, 0, 0),
+ F_MDP( 9600000, pll8, 1, 40),
+ F_MDP( 13710000, pll8, 1, 28),
+ F_MDP( 27000000, pxo, 0, 0),
+ F_MDP( 29540000, pll8, 1, 13),
+ F_MDP( 34910000, pll8, 1, 11),
+ F_MDP( 38400000, pll8, 1, 10),
+ F_MDP( 59080000, pll8, 2, 13),
+ F_MDP( 76800000, pll8, 1, 5),
+ F_MDP( 85330000, pll8, 2, 9),
+ F_MDP( 96000000, pll8, 1, 4),
+ F_MDP(128000000, pll8, 1, 3),
+ F_MDP(160000000, pll2, 1, 5),
+ F_MDP(177780000, pll2, 2, 9),
+ F_MDP(200000000, pll2, 1, 4),
+ F_MDP(228571000, pll2, 2, 7),
+ F_MDP(266667000, pll2, 1, 3),
+ F_END
+};
+
static struct clk_freq_tbl clk_tbl_mdp[] = {
F_MDP( 0, gnd, 0, 0),
F_MDP( 9600000, pll8, 1, 40),
@@ -3913,11 +3962,6 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned long hdmi_pll_clk_get_rate(struct clk *c)
-{
- return hdmi_pll_get_rate();
-}
-
static struct clk *hdmi_pll_clk_get_parent(struct clk *c)
{
return &pxo_clk.c;
@@ -3926,13 +3970,14 @@
static struct clk_ops clk_ops_hdmi_pll = {
.enable = hdmi_pll_clk_enable,
.disable = hdmi_pll_clk_disable,
- .get_rate = hdmi_pll_clk_get_rate,
.get_parent = hdmi_pll_clk_get_parent,
};
static struct clk hdmi_pll_clk = {
.dbg_name = "hdmi_pll_clk",
.ops = &clk_ops_hdmi_pll,
+ .vdd_class = &vdd_sr2_hdmi_pll,
+ .fmax[VDD_SR2_HDMI_PLL_ON] = ULONG_MAX,
CLK_INIT(hdmi_pll_clk),
};
@@ -3981,8 +4026,9 @@
{
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
unsigned long pll_rate = (unsigned long)nf->extra_freq_data;
- if (pll_rate)
- hdmi_pll_set_rate(pll_rate);
+ if (pll_rate) {
+ hdmi_pll_clk.rate = pll_rate;
+ }
#endif
set_rate_mnd(rcg, nf);
}
@@ -4345,7 +4391,23 @@
.md_val = MD8(8, m, 0, n), \
.ns_val = NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
}
-static struct clk_freq_tbl clk_tbl_aif_osr[] = {
+static struct clk_freq_tbl clk_tbl_aif_osr_492[] = {
+ F_AIF_OSR( 0, gnd, 1, 0, 0),
+ F_AIF_OSR( 512000, pll4, 4, 1, 240),
+ F_AIF_OSR( 768000, pll4, 4, 1, 160),
+ F_AIF_OSR( 1024000, pll4, 4, 1, 120),
+ F_AIF_OSR( 1536000, pll4, 4, 1, 80),
+ F_AIF_OSR( 2048000, pll4, 4, 1, 60),
+ F_AIF_OSR( 3072000, pll4, 4, 1, 40),
+ F_AIF_OSR( 4096000, pll4, 4, 1, 30),
+ F_AIF_OSR( 6144000, pll4, 4, 1, 20),
+ F_AIF_OSR( 8192000, pll4, 4, 1, 15),
+ F_AIF_OSR(12288000, pll4, 4, 1, 10),
+ F_AIF_OSR(24576000, pll4, 4, 1, 5),
+ F_END
+};
+
+static struct clk_freq_tbl clk_tbl_aif_osr_393[] = {
F_AIF_OSR( 0, gnd, 1, 0, 0),
F_AIF_OSR( 512000, pll4, 4, 1, 192),
F_AIF_OSR( 768000, pll4, 4, 1, 128),
@@ -4378,7 +4440,7 @@
.ns_mask = (BM(31, 24) | BM(6, 0)), \
.mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
- .freq_tbl = clk_tbl_aif_osr, \
+ .freq_tbl = clk_tbl_aif_osr_393, \
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
@@ -4404,7 +4466,7 @@
.ns_mask = (BM(31, 24) | BM(6, 0)), \
.mnd_en_mask = BIT(8), \
.set_rate = set_rate_mnd, \
- .freq_tbl = clk_tbl_aif_osr, \
+ .freq_tbl = clk_tbl_aif_osr_393, \
.current_freq = &rcg_dummy_freq, \
.c = { \
.dbg_name = #i "_clk", \
@@ -4485,7 +4547,23 @@
.md_val = MD16(m, n), \
.ns_val = NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_lpa_mux), \
}
-static struct clk_freq_tbl clk_tbl_pcm[] = {
+static struct clk_freq_tbl clk_tbl_pcm_492[] = {
+ { .ns_val = BIT(10) /* external input */ },
+ F_PCM( 512000, pll4, 4, 1, 240),
+ F_PCM( 768000, pll4, 4, 1, 160),
+ F_PCM( 1024000, pll4, 4, 1, 120),
+ F_PCM( 1536000, pll4, 4, 1, 80),
+ F_PCM( 2048000, pll4, 4, 1, 60),
+ F_PCM( 3072000, pll4, 4, 1, 40),
+ F_PCM( 4096000, pll4, 4, 1, 30),
+ F_PCM( 6144000, pll4, 4, 1, 20),
+ F_PCM( 8192000, pll4, 4, 1, 15),
+ F_PCM(12288000, pll4, 4, 1, 10),
+ F_PCM(24576000, pll4, 4, 1, 5),
+ F_END
+};
+
+static struct clk_freq_tbl clk_tbl_pcm_393[] = {
{ .ns_val = BIT(10) /* external input */ },
F_PCM( 512000, pll4, 4, 1, 192),
F_PCM( 768000, pll4, 4, 1, 128),
@@ -4517,7 +4595,7 @@
.ns_mask = BM(31, 16) | BIT(10) | BM(6, 0),
.mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
- .freq_tbl = clk_tbl_pcm,
+ .freq_tbl = clk_tbl_pcm_393,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "pcm_clk",
@@ -4544,7 +4622,7 @@
.ns_mask = (BM(31, 24) | BM(6, 0)),
.mnd_en_mask = BIT(8),
.set_rate = set_rate_mnd,
- .freq_tbl = clk_tbl_aif_osr,
+ .freq_tbl = clk_tbl_aif_osr_393,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "audio_slimbus_clk",
@@ -4830,7 +4908,7 @@
{ TEST_MM_HS(0x35), &vcap_axi_clk.c },
{ TEST_MM_HS(0x36), &rgb_tv_clk.c },
{ TEST_MM_HS(0x37), &npl_tv_clk.c },
- { TEST_MM_HS(0x38), &gfx3d_axi_clk_8064.c },
+ { TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
{ TEST_LPA(0x10), &codec_i2s_mic_bit_clk.c },
@@ -5128,7 +5206,10 @@
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("core_clk", sdc3_clk.c, "msm_sdcc.3"),
CLK_LOOKUP("core_clk", sdc4_clk.c, "msm_sdcc.4"),
- CLK_LOOKUP("ref_clk", tsif_ref_clk.c, ""),
+ CLK_LOOKUP("ref_clk", tsif_ref_clk.c, "msm_tsif.0"),
+ CLK_LOOKUP("iface_clk", tsif_p_clk.c, "msm_tsif.0"),
+ CLK_LOOKUP("ref_clk", tsif_ref_clk.c, "msm_tsif.1"),
+ CLK_LOOKUP("iface_clk", tsif_p_clk.c, "msm_tsif.1"),
CLK_LOOKUP("core_clk", tssc_clk.c, ""),
CLK_LOOKUP("alt_core_clk", usb_hs1_xcvr_clk.c, "msm_otg"),
CLK_LOOKUP("alt_core_clk", usb_hs3_xcvr_clk.c, "msm_ehci_host.0"),
@@ -5235,7 +5316,7 @@
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk",
- gfx3d_axi_clk_8064.c, "footswitch-8x60.2"),
+ gfx3d_axi_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, ""),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, "msm_vcap.0"),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, "footswitch-8x60.10"),
@@ -5341,7 +5422,7 @@
CLK_LOOKUP("core_clk", vfe_axi_clk.c, ""),
CLK_LOOKUP("core_clk", vcodec_axi_a_clk.c, ""),
CLK_LOOKUP("core_clk", vcodec_axi_b_clk.c, ""),
- CLK_LOOKUP("core_clk", gfx3d_axi_clk_8064.c, ""),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, ""),
CLK_LOOKUP("dfab_dsps_clk", dfab_dsps_clk.c, NULL),
CLK_LOOKUP("core_clk", dfab_usb_hs_clk.c, "msm_otg"),
@@ -5371,8 +5452,9 @@
CLK_LOOKUP("core_clk", vfe_axi_clk.c, "msm_iommu.6"),
CLK_LOOKUP("core_clk", vcodec_axi_a_clk.c, "msm_iommu.7"),
CLK_LOOKUP("core_clk", vcodec_axi_b_clk.c, "msm_iommu.8"),
- CLK_LOOKUP("core_clk", gfx3d_axi_clk_8064.c, "msm_iommu.9"),
- CLK_LOOKUP("core_clk", gfx3d_axi_clk_8064.c, "msm_iommu.10"),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.9"),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.10"),
+
CLK_LOOKUP("core_clk", vcap_axi_clk.c, "msm_iommu.11"),
CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c, "msm_vidc.0"),
@@ -5394,7 +5476,7 @@
CLK_LOOKUP("krait3_mclk", krait3_m_clk, ""),
};
-static struct clk_lookup msm_clocks_8960[] = {
+static struct clk_lookup msm_clocks_8960_common[] __initdata = {
CLK_LOOKUP("xo", cxo_a_clk.c, ""),
CLK_LOOKUP("xo", pxo_a_clk.c, ""),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
@@ -5462,7 +5544,10 @@
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, ""),
+ /* used on 8960 SGLTE for console */
CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hsl.1"),
+ /* used on 8960 standalone with Atheros Bluetooth */
+ CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hs.2"),
CLK_LOOKUP("core_clk", gsbi9_uart_clk.c, "msm_serial_hs.1"),
CLK_LOOKUP("core_clk", gsbi10_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi11_uart_clk.c, ""),
@@ -5514,7 +5599,10 @@
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
+ /* used on 8960 SGLTE for serial console */
CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hsl.1"),
+ /* used on 8960 standalone with Atheros Bluetooth */
+ CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hs.2"),
CLK_LOOKUP("iface_clk", gsbi9_p_clk.c, "msm_serial_hs.1"),
CLK_LOOKUP("iface_clk", gsbi10_p_clk.c, "qup_i2c.10"),
CLK_LOOKUP("iface_clk", gsbi11_p_clk.c, ""),
@@ -5573,10 +5661,6 @@
CLK_LOOKUP("byte_clk", dsi2_byte_clk.c, "mipi_dsi.2"),
CLK_LOOKUP("esc_clk", dsi1_esc_clk.c, "mipi_dsi.1"),
CLK_LOOKUP("esc_clk", dsi2_esc_clk.c, "mipi_dsi.2"),
- CLK_LOOKUP("core_clk", gfx2d0_clk.c, "kgsl-2d0.0"),
- CLK_LOOKUP("core_clk", gfx2d0_clk.c, "footswitch-8x60.0"),
- CLK_LOOKUP("core_clk", gfx2d1_clk.c, "kgsl-2d1.1"),
- CLK_LOOKUP("core_clk", gfx2d1_clk.c, "footswitch-8x60.1"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
@@ -5596,8 +5680,6 @@
CLK_LOOKUP("src_clk", tv_src_clk.c, "dtv.0"),
CLK_LOOKUP("src_clk", tv_src_clk.c, "tvenc.0"),
CLK_LOOKUP("tv_src_clk", tv_src_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("enc_clk", tv_enc_clk.c, "tvenc.0"),
- CLK_LOOKUP("dac_clk", tv_dac_clk.c, "tvenc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("mdp_clk", mdp_tv_clk.c, "dtv.0"),
@@ -5626,10 +5708,6 @@
CLK_LOOKUP("slave_iface_clk", dsi1_s_p_clk.c, "mipi_dsi.1"),
CLK_LOOKUP("master_iface_clk", dsi2_m_p_clk.c, "mipi_dsi.2"),
CLK_LOOKUP("slave_iface_clk", dsi2_s_p_clk.c, "mipi_dsi.2"),
- CLK_LOOKUP("iface_clk", gfx2d0_p_clk.c, "kgsl-2d0.0"),
- CLK_LOOKUP("iface_clk", gfx2d0_p_clk.c, "footswitch-8x60.0"),
- CLK_LOOKUP("iface_clk", gfx2d1_p_clk.c, "kgsl-2d1.1"),
- CLK_LOOKUP("iface_clk", gfx2d1_p_clk.c, "footswitch-8x60.1"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
@@ -5643,7 +5721,6 @@
CLK_LOOKUP("iface_clk", smmu_p_clk.c, "msm_iommu"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "msm_rotator.0"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "footswitch-8x60.6"),
- CLK_LOOKUP("iface_clk", tv_enc_p_clk.c, "tvenc.0"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "msm_vidc.0"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, "msm_vfe.0"),
@@ -5684,8 +5761,6 @@
CLK_LOOKUP("core_clk", vcodec_axi_a_clk.c, "msm_iommu.7"),
CLK_LOOKUP("core_clk", vcodec_axi_b_clk.c, "msm_iommu.8"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "msm_iommu.9"),
- CLK_LOOKUP("core_clk", gfx2d0_clk.c, "msm_iommu.10"),
- CLK_LOOKUP("core_clk", gfx2d1_clk.c, "msm_iommu.11"),
CLK_LOOKUP("mdp_iommu_clk", mdp_axi_clk.c, "msm_vidc.0"),
CLK_LOOKUP("rot_iommu_clk", rot_axi_clk.c, "msm_vidc.0"),
@@ -5719,6 +5794,32 @@
CLK_LOOKUP("q6_func_clk", q6_func_clk, ""),
};
+static struct clk_lookup msm_clocks_8960_only[] __initdata = {
+ CLK_LOOKUP("enc_clk", tv_enc_clk.c, "tvenc.0"),
+ CLK_LOOKUP("dac_clk", tv_dac_clk.c, "tvenc.0"),
+ CLK_LOOKUP("iface_clk", tv_enc_p_clk.c, "tvenc.0"),
+
+ CLK_LOOKUP("core_clk", gfx2d0_clk.c, "kgsl-2d0.0"),
+ CLK_LOOKUP("core_clk", gfx2d0_clk.c, "footswitch-8x60.0"),
+ CLK_LOOKUP("core_clk", gfx2d1_clk.c, "kgsl-2d1.1"),
+ CLK_LOOKUP("core_clk", gfx2d1_clk.c, "footswitch-8x60.1"),
+ CLK_LOOKUP("iface_clk", gfx2d0_p_clk.c, "kgsl-2d0.0"),
+ CLK_LOOKUP("iface_clk", gfx2d0_p_clk.c, "footswitch-8x60.0"),
+ CLK_LOOKUP("iface_clk", gfx2d1_p_clk.c, "kgsl-2d1.1"),
+ CLK_LOOKUP("iface_clk", gfx2d1_p_clk.c, "footswitch-8x60.1"),
+ CLK_LOOKUP("core_clk", gfx2d0_clk.c, "msm_iommu.10"),
+ CLK_LOOKUP("core_clk", gfx2d1_clk.c, "msm_iommu.11"),
+};
+
+static struct clk_lookup msm_clocks_8960ab_only[] __initdata = {
+ CLK_LOOKUP("bus_clk", gfx3d_axi_clk.c, "footswitch-8x60.2"),
+ CLK_LOOKUP("div_clk", tv_src_div_clk.c, ""),
+};
+
+static struct clk_lookup msm_clocks_8960[ARRAY_SIZE(msm_clocks_8960_common)
+ + ARRAY_SIZE(msm_clocks_8960_only)
+ + ARRAY_SIZE(msm_clocks_8960ab_only)];
+
static struct clk_lookup msm_clocks_8930[] = {
CLK_LOOKUP("xo", cxo_clk.c, "msm_xo"),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
@@ -6038,7 +6139,7 @@
.mode_reg = LCC_PLL0_MODE_REG,
};
-static struct pll_config pll4_config __initdata = {
+static struct pll_config pll4_config_393 __initdata = {
.l = 0xE,
.m = 0x27A,
.n = 0x465,
@@ -6116,12 +6217,12 @@
*/
/*
* Initialize MM AHB registers: Enable the FPB clock and disable HW
- * gating on 8627 for all clocks. Also set VFE_AHB's
+ * gating on 8627 and 8960 for all clocks. Also set VFE_AHB's
* FORCE_CORE_ON bit to prevent its memory from being collapsed when
* the clock is halted. The sleep and wake-up delays are set to safe
* values.
*/
- if (cpu_is_msm8627()) {
+ if (cpu_is_msm8627() || cpu_is_msm8960ab()) {
rmwreg(0x00000003, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x000007F9, AHB_EN2_REG);
} else {
@@ -6139,7 +6240,7 @@
/* Initialize MM AXI registers: Enable HW gating for all clocks that
* support it. Also set FORCE_CORE_ON bits, and any sleep and wake-up
* delays to safe values. */
- if ((cpu_is_msm8960() &&
+ if (cpu_is_msm8960ab() || (cpu_is_msm8960() &&
SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 3) ||
cpu_is_msm8627()) {
rmwreg(0x000007F9, MAXI_EN_REG, 0x0803FFFF);
@@ -6156,8 +6257,13 @@
rmwreg(0x019FECFF, MAXI_EN5_REG, 0x01FFEFFF);
if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627())
rmwreg(0x000004FF, MAXI_EN5_REG, 0x00000FFF);
+ if (cpu_is_msm8960ab())
+ rmwreg(0x009FE000, MAXI_EN5_REG, 0x01FFE000);
+
if (cpu_is_msm8627())
rmwreg(0x000003C7, SAXI_EN_REG, 0x00003FFF);
+ else if (cpu_is_msm8960ab())
+ rmwreg(0x000001C6, SAXI_EN_REG, 0x00001DF6);
else
rmwreg(0x00003C38, SAXI_EN_REG, 0x00003FFF);
@@ -6185,14 +6291,19 @@
rmwreg(0x80FF0000, VFE_CC_REG, 0xE0FF4010);
rmwreg(0x800000FF, VFE_CC2_REG, 0xE00000FF);
rmwreg(0x80FF0000, VPE_CC_REG, 0xE0FF0010);
- if (cpu_is_msm8960() || cpu_is_apq8064()) {
+ if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()) {
rmwreg(0x80FF0000, DSI2_BYTE_CC_REG, 0xE0FF0010);
rmwreg(0x80FF0000, DSI2_PIXEL_CC_REG, 0xE0FF0010);
rmwreg(0x80FF0000, JPEGD_CC_REG, 0xE0FF0010);
}
+ if (cpu_is_msm8960ab())
+ rmwreg(0x00000001, DSI2_PIXEL_CC2_REG, 0x00000001);
+
if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
cpu_is_msm8627())
- rmwreg(0x80FF0000, TV_CC_REG, 0xE1FFC010);
+ rmwreg(0x80FF0000, TV_CC_REG, 0xE1FFC010);
+ if (cpu_is_msm8960ab())
+ rmwreg(0x00000000, TV_CC_REG, 0x00004010);
if (cpu_is_msm8960()) {
rmwreg(0x80FF0000, GFX2D0_CC_REG, 0xE0FF0010);
@@ -6226,12 +6337,12 @@
writel_relaxed(BIT(15), PDM_CLK_NS_REG);
/* Source SLIMBus xo src from slimbus reference clock */
- if (cpu_is_msm8960())
+ if (cpu_is_msm8960ab() || cpu_is_msm8960())
writel_relaxed(0x3, SLIMBUS_XO_SRC_CLK_CTL_REG);
/* Source the dsi_byte_clks from the DSI PHY PLLs */
rmwreg(0x1, DSI1_BYTE_NS_REG, 0x7);
- if (cpu_is_msm8960() || cpu_is_apq8064())
+ if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064())
rmwreg(0x2, DSI2_BYTE_NS_REG, 0x7);
/* Source the dsi1_esc_clk from the DSI1 PHY PLLs */
@@ -6269,7 +6380,7 @@
is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
if (!is_pll_enabled)
/* Ref clk = 27MHz and program pll4 to 393.2160MHz */
- configure_pll(&pll4_config, &pll4_regs, 1);
+ configure_pll(&pll4_config_393, &pll4_regs, 1);
/* Enable PLL4 source on the LPASS Primary PLL Mux */
writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
@@ -6293,15 +6404,54 @@
}
}
+struct clock_init_data msm8960_clock_init_data __initdata;
static void __init msm8960_clock_pre_init(void)
{
+ /* Initialize clock registers. */
+ reg_init();
+
if (cpu_is_apq8064()) {
- vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8064;
+ vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8064;
} else if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()) {
vdd_dig.set_vdd = set_vdd_dig_8930;
- vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8930;
+ vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8930;
}
+ /* Detect PLL4 programmed for alternate 491.52MHz clock plan. */
+ if (readl_relaxed(LCC_PLL0_L_VAL_REG) == 0x12) {
+ pll4_clk.c.rate = 491520000;
+ audio_slimbus_clk.freq_tbl = clk_tbl_aif_osr_492;
+ mi2s_osr_clk.freq_tbl = clk_tbl_aif_osr_492;
+ codec_i2s_mic_osr_clk.freq_tbl = clk_tbl_aif_osr_492;
+ spare_i2s_mic_osr_clk.freq_tbl = clk_tbl_aif_osr_492;
+ codec_i2s_spkr_osr_clk.freq_tbl = clk_tbl_aif_osr_492;
+ spare_i2s_spkr_osr_clk.freq_tbl = clk_tbl_aif_osr_492;
+ pcm_clk.freq_tbl = clk_tbl_pcm_492;
+ }
+
+ if (cpu_is_msm8960() || cpu_is_msm8960ab())
+ memcpy(msm_clocks_8960, msm_clocks_8960_common,
+ sizeof(msm_clocks_8960_common));
+ if (cpu_is_msm8960ab()) {
+ pll3_clk.c.rate = 650000000;
+ gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960ab;
+ gfx3d_clk.c.fmax[VDD_DIG_LOW] = 192000000;
+ gfx3d_clk.c.fmax[VDD_DIG_NOMINAL] = 325000000;
+ gfx3d_clk.c.fmax[VDD_DIG_HIGH] = 400000000;
+ mdp_clk.freq_tbl = clk_tbl_mdp_8960ab;
+ mdp_clk.c.fmax[VDD_DIG_LOW] = 128000000;
+ mdp_clk.c.fmax[VDD_DIG_NOMINAL] = 266667000;
+
+ memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
+ msm_clocks_8960ab_only, sizeof(msm_clocks_8960ab_only));
+ msm8960_clock_init_data.size -=
+ ARRAY_SIZE(msm_clocks_8960_only);
+ } else if (cpu_is_msm8960()) {
+ memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
+ msm_clocks_8960_only, sizeof(msm_clocks_8960_only));
+ msm8960_clock_init_data.size -=
+ ARRAY_SIZE(msm_clocks_8960ab_only);
+ }
/*
* Change the freq tables for and voltage requirements for
* clocks which differ between 8960 and 8064.
@@ -6320,7 +6470,7 @@
memcpy(vfe_clk.c.fmax, fmax_vfe_8064,
sizeof(vfe_clk.c.fmax));
- gmem_axi_clk.c.depends = &gfx3d_axi_clk_8064.c;
+ gmem_axi_clk.c.depends = &gfx3d_axi_clk.c;
}
/*
@@ -6342,9 +6492,6 @@
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
clk_ops_local_pll.enable = sr_pll_clk_enable;
-
- /* Initialize clock registers. */
- reg_init();
}
static void __init msm8960_clock_post_init(void)
@@ -6372,8 +6519,8 @@
clk_set_rate(&usb_hs4_xcvr_clk.c, 60000000);
}
clk_set_rate(&usb_fs1_src_clk.c, 60000000);
- if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
- cpu_is_msm8627())
+ if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_msm8930() ||
+ cpu_is_msm8930aa() || cpu_is_msm8627())
clk_set_rate(&usb_fs2_src_clk.c, 60000000);
clk_set_rate(&usb_hsic_xcvr_fs_clk.c, 60000000);
clk_set_rate(&usb_hsic_hsic_src_clk.c, 480000000);
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 6c9a566..6b58257 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -593,10 +593,12 @@
#define RPM_MEM_CLK_TYPE 0x326b6c63
#define CXO_ID 0x0
+#define QDSS_ID 0x1
#define PNOC_ID 0x0
#define SNOC_ID 0x1
#define CNOC_ID 0x2
+#define MMSSNOC_AHB_ID 0x4
#define BIMC_ID 0x0
#define OCMEM_ID 0x1
@@ -604,6 +606,8 @@
DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, RPM_BUS_CLK_TYPE,
+ MMSSNOC_AHB_ID, NULL);
DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
@@ -611,10 +615,10 @@
DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
static struct pll_vote_clk gpll0_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
- .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.parent = &cxo_clk_src.c,
@@ -2111,6 +2115,7 @@
static struct branch_clk gcc_usb30_master_clk = {
.cbcr_reg = USB30_MASTER_CBCR,
+ .bcr_reg = USB_30_BCR,
.parent = &usb30_master_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[GCC_BASE],
@@ -2145,6 +2150,7 @@
static struct branch_clk gcc_usb_hs_system_clk = {
.cbcr_reg = USB_HS_SYSTEM_CBCR,
+ .bcr_reg = USB_HS_BCR,
.parent = &usb_hs_system_clk_src.c,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -2167,6 +2173,7 @@
static struct branch_clk gcc_usb_hsic_clk = {
.cbcr_reg = USB_HSIC_CBCR,
+ .bcr_reg = USB_HS_HSIC_BCR,
.parent = &usb_hsic_clk_src.c,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -3963,15 +3970,29 @@
},
};
+struct rcg_clk audio_core_lpaif_pcmoe_clk_src = {
+ .cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clock,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_pcmoe_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP1(LOW, 12290000),
+ CLK_INIT(audio_core_lpaif_pcmoe_clk_src.c),
+ },
+};
+
static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
.cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
.parent = &audio_core_lpaif_codec_spkr_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
},
};
@@ -3980,9 +4001,9 @@
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
},
};
@@ -3993,9 +4014,9 @@
.max_div = 15,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
},
};
@@ -4190,6 +4211,17 @@
},
};
+struct branch_clk audio_core_lpaif_pcmoe_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
+ .parent = &audio_core_lpaif_pcmoe_clk_src.c,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_pcmoe_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcmoe_clk.c),
+ },
+};
+
static struct branch_clk q6ss_ahb_lfabif_clk = {
.cbcr_reg = LPASS_Q6SS_AHB_LFABIF_CBCR,
.has_sibling = 1,
@@ -4386,6 +4418,7 @@
{&audio_core_lpaif_quad_clk_src.c, LPASS_BASE, 0x0014},
{&audio_core_lpaif_pcm0_clk_src.c, LPASS_BASE, 0x0013},
{&audio_core_lpaif_pcm1_clk_src.c, LPASS_BASE, 0x0012},
+ {&audio_core_lpaif_pcmoe_clk_src.c, LPASS_BASE, 0x000f},
{&audio_core_slimbus_core_clk.c, LPASS_BASE, 0x003d},
{&audio_core_slimbus_lfabif_clk.c, LPASS_BASE, 0x003e},
{&q6ss_xo_clk.c, LPASS_BASE, 0x002b},
@@ -4789,6 +4822,8 @@
CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk_src", audio_core_lpaif_pcmoe_clk_src.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcmoe_clk.c, ""),
CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
@@ -4830,6 +4865,36 @@
CLK_LOOKUP("bus_a_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
CLK_LOOKUP("bus_a_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
+
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
};
static struct pll_config_regs gpll0_regs __initdata = {
@@ -4986,7 +5051,7 @@
.main_output_mask = BIT(0),
};
-#define PLL_AUX_OUTPUT BIT(1)
+#define PLL_AUX_OUTPUT_BIT 1
static void __init reg_init(void)
{
@@ -5007,7 +5072,7 @@
/* Active GPLL0's aux output. This is needed by acpuclock. */
regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
- regval |= BIT(PLL_AUX_OUTPUT);
+ regval |= BIT(PLL_AUX_OUTPUT_BIT);
writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
/* Vote for GPLL0 to turn on. Needed by acpuclock. */
@@ -5028,6 +5093,13 @@
clk_set_rate(&ocmemnoc_clk_src.c, 333330000);
/*
+ * Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
+ * source. Sleep set vote is 0.
+ */
+ clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
+ clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
+
+ /*
* Hold an active set vote for CXO; this is because CXO is expected
* to remain on whenever CPUs aren't power collapsed.
*/
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 4493ddc..1769f07 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3522,6 +3522,7 @@
CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("smi_clk", smi_clk.c, "msm_bus"),
CLK_LOOKUP("smi_a_clk", smi_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8x60"),
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
@@ -3873,7 +3874,7 @@
int rc;
/* Vote for MMFPB to be at least 64MHz when an Apps CPU is active. */
- struct clk *mmfpb_a_clk = clk_get(NULL, "mmfpb_a_clk");
+ struct clk *mmfpb_a_clk = clk_get_sys("clock-8x60", "mmfpb_a_clk");
if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
PTR_ERR(mmfpb_a_clk)))
return PTR_ERR(mmfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index c04ea05..03fed69 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -90,7 +90,6 @@
#define PLL_PWRDN_B BIT(3)
#define PD_PLL BIT(1)
-static unsigned current_rate;
static unsigned hdmi_pll_on;
int hdmi_pll_enable(void)
@@ -220,11 +219,6 @@
hdmi_pll_on = 0;
}
-unsigned hdmi_pll_get_rate(void)
-{
- return current_rate;
-}
-
int hdmi_pll_set_rate(unsigned rate)
{
unsigned int set_power_dwn = 0;
@@ -379,7 +373,6 @@
if (set_power_dwn)
hdmi_pll_enable();
- current_rate = rate;
if (!ahb_enabled)
writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG);
diff --git a/arch/arm/mach-msm/clock-dss-8960.h b/arch/arm/mach-msm/clock-dss-8960.h
index 4734cde..72e70fc 100644
--- a/arch/arm/mach-msm/clock-dss-8960.h
+++ b/arch/arm/mach-msm/clock-dss-8960.h
@@ -15,7 +15,6 @@
int hdmi_pll_enable(void);
void hdmi_pll_disable(void);
-unsigned hdmi_pll_get_rate(void);
int hdmi_pll_set_rate(unsigned rate);
#endif
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 8096c10..207dbef 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -54,15 +54,11 @@
return (rc < 0) ? rc : iv.value * r->factor;
}
-#define RPM_SMD_KEY_RATE 0x007A484B
-#define RPM_SMD_KEY_ENABLE 0x62616E45
-
static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
uint32_t context, int noirq)
{
- u32 rpm_key = r->branch ? RPM_SMD_KEY_ENABLE : RPM_SMD_KEY_RATE;
struct msm_rpm_kvp kvp = {
- .key = rpm_key,
+ .key = r->rpm_key,
.data = (void *)&value,
.length = sizeof(value),
};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index ce878ce..22691c5 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -17,6 +17,10 @@
#include <mach/rpm.h>
#include <mach/rpm-smd.h>
+#define RPM_SMD_KEY_RATE 0x007A484B
+#define RPM_SMD_KEY_ENABLE 0x62616E45
+#define RPM_SMD_KEY_STATE 0x54415453
+
struct clk_ops;
struct clk_rpmrs_data;
extern struct clk_ops clk_ops_rpm;
@@ -24,6 +28,7 @@
struct rpm_clk {
const int rpm_res_type;
+ const int rpm_key;
const int rpm_clk_id;
const int rpm_status_id;
const bool active_only;
@@ -47,12 +52,14 @@
extern struct clk_rpmrs_data clk_rpmrs_data;
extern struct clk_rpmrs_data clk_rpmrs_data_smd;
-#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, rpmrsdata) \
+#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, key, \
+ rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.factor = 1000, \
.rpmrs_data = (rpmrsdata),\
@@ -67,6 +74,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.active_only = true, \
.factor = 1000, \
@@ -80,12 +88,13 @@
};
#define __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, stat_id, r, \
- rpmrsdata) \
+ key, rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.last_set_khz = ((r) / 1000), \
.last_set_sleep_khz = ((r) / 1000), \
@@ -104,6 +113,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.last_set_khz = ((r) / 1000), \
.active_only = true, \
@@ -119,12 +129,14 @@
}, \
};
-#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, rpmrsdata) \
+#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, \
+ key, rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &active, \
.factor = 1, \
.rpmrs_data = (rpmrsdata),\
@@ -139,6 +151,7 @@
.rpm_res_type = (type), \
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
+ .rpm_key = (key), \
.peer = &name, \
.active_only = true, \
.factor = 1, \
@@ -153,21 +166,26 @@
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
- MSM_RPM_STATUS_ID_##r_id##_CLK, dep, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_##r_id##_CLK, dep, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_QDSS(name, active) \
__DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
- MSM_RPM_STATUS_ID_QDSS_CLK, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_QDSS_CLK, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
- MSM_RPM_STATUS_ID_##r_id##_CLK, r, &clk_rpmrs_data)
+ MSM_RPM_STATUS_ID_##r_id##_CLK, r, 0, &clk_rpmrs_data)
#define DEFINE_CLK_RPM_SMD(name, active, type, r_id, dep) \
- __DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, &clk_rpmrs_data_smd)
+ __DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, \
+ RPM_SMD_KEY_RATE, &clk_rpmrs_data_smd)
-#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, dep) \
- __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, dep, \
- &clk_rpmrs_data_smd)
+#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, r) \
+ __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, r, \
+ RPM_SMD_KEY_ENABLE, &clk_rpmrs_data_smd)
+
+#define DEFINE_CLK_RPM_SMD_QDSS(name, active, type, r_id) \
+ __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, \
+ 0, RPM_SMD_KEY_STATE, &clk_rpmrs_data_smd)
#endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 56d3c6f..df2aa4e 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -181,7 +181,7 @@
int clock_debug_add(struct clk *clock);
void clock_debug_print_enabled(void);
#else
-static inline int clock_debug_init(struct clk_init_data *data) { return 0; }
+static inline int clock_debug_init(struct clock_init_data *data) { return 0; }
static inline int clock_debug_add(struct clk *clock) { return 0; }
static inline void clock_debug_print_enabled(void) { return; }
#endif
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index a523f7e..98f3b0f 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -878,6 +878,11 @@
},
};
+struct platform_device apq8064_device_acpuclk = {
+ .name = "acpuclk-8064",
+ .id = -1,
+};
+
#define SHARED_IMEM_TZ_BASE 0x2a03f720
static struct resource tzlog_resources[] = {
{
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index a36e7d7..1f954c8 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -355,6 +355,16 @@
.id = MSM_BUS_FAB_CPSS_FPB,
};
+struct platform_device msm8627_device_acpuclk = {
+ .name = "acpuclk-8627",
+ .id = -1,
+};
+
+struct platform_device msm8930_device_acpuclk = {
+ .name = "acpuclk-8930",
+ .id = -1,
+};
+
static struct fs_driver_data gfx3d_fs_data = {
.clks = (struct fs_clk_data[]){
{ .name = "core_clk", .reset_rate = 27000000 },
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 7d93fe7..9a0c2d7 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -19,7 +19,7 @@
#include <linux/gpio.h>
#include <linux/coresight.h>
#include <asm/clkdev.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/android_pmem.h>
#include <mach/irqs-8960.h>
#include <mach/dma.h>
@@ -292,6 +292,52 @@
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
+
+/* GSBI 8 used into UARTDM Mode */
+static struct resource msm_uart_dm8_resources[] = {
+ {
+ .start = MSM_UART8DM_PHYS,
+ .end = MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GSBI8_UARTDM_IRQ,
+ .end = GSBI8_UARTDM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_GSBI8_PHYS,
+ .end = MSM_GSBI8_PHYS + 4 - 1,
+ .name = "gsbi_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMOV_HSUART_GSBI8_TX_CHAN,
+ .end = DMOV_HSUART_GSBI8_RX_CHAN,
+ .name = "uartdm_channels",
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = DMOV_HSUART_GSBI8_TX_CRCI,
+ .end = DMOV_HSUART_GSBI8_RX_CRCI,
+ .name = "uartdm_crci",
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static u64 msm_uart_dm8_dma_mask = DMA_BIT_MASK(32);
+struct platform_device msm_device_uart_dm8 = {
+ .name = "msm_serial_hs",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(msm_uart_dm8_resources),
+ .resource = msm_uart_dm8_resources,
+ .dev = {
+ .dma_mask = &msm_uart_dm8_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
/*
* GSBI 9 used into UARTDM Mode
* For 8960 Fusion 2.2 Primary IPC
@@ -3812,6 +3858,7 @@
#define AP2MDM_PMIC_PWR_EN 22
#define AP2MDM_KPDPWR_N 79
#define AP2MDM_SOFT_RESET 78
+#define USB_SW 25
static struct resource sglte_resources[] = {
{
@@ -3856,6 +3903,12 @@
.name = "AP2MDM_SOFT_RESET",
.flags = IORESOURCE_IO,
},
+ {
+ .start = USB_SW,
+ .end = USB_SW,
+ .name = "USB_SW",
+ .flags = IORESOURCE_IO,
+ },
};
struct platform_device mdm_sglte_device = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 4619cca..69d7430 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/regulator/machine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index c159926..8912e96 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/regulator/machine.h>
#include <linux/init.h>
#include <linux/irq.h>
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 4b02f7a..f04ef9d 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -17,7 +17,7 @@
#include <linux/platform_device.h>
#include <linux/msm_rotator.h>
#include <linux/dma-mapping.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/android_pmem.h>
#include <linux/regulator/machine.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 2ced412..3920abe 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -20,7 +20,7 @@
#include <mach/dma.h>
#include <asm/mach/mmc.h>
#include <asm/clkdev.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/msm_rotator.h>
#include <mach/msm_hsusb.h>
#include "footswitch.h"
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 2ecc852..ec4a14f 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/msm_kgsl.h>
+#include <mach/kgsl.h>
#include <linux/dma-mapping.h>
#include <asm/clkdev.h>
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index a300a47..2391eda 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -53,6 +53,7 @@
extern struct platform_device msm_device_uart_dm12;
extern struct platform_device *msm_device_uart_gsbi9;
extern struct platform_device msm_device_uart_dm6;
+extern struct platform_device msm_device_uart_dm8;
extern struct platform_device msm_device_uart_dm9;
extern struct platform_device msm8960_device_uart_gsbi2;
@@ -419,8 +420,11 @@
extern struct platform_device msm7x27a_device_acpuclk;
extern struct platform_device msm7x27aa_device_acpuclk;
extern struct platform_device msm7x30_device_acpuclk;
+extern struct platform_device apq8064_device_acpuclk;
extern struct platform_device msm8625_device_acpuclk;
+extern struct platform_device msm8627_device_acpuclk;
extern struct platform_device msm8x50_device_acpuclk;
extern struct platform_device msm8x60_device_acpuclk;
+extern struct platform_device msm8930_device_acpuclk;
extern struct platform_device msm8960_device_acpuclk;
extern struct platform_device msm9615_device_acpuclk;
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index e5dca00..12f5aa9 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -356,7 +356,7 @@
}
if (!dmov_conf[adm].channel_active) {
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10));
}
spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
error:
@@ -573,7 +573,7 @@
if (!dmov_conf[adm].channel_active && valid) {
disable_irq_nosync(dmov_conf[adm].irq);
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10));
}
mutex_unlock(&dmov_conf[adm].lock);
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
index b9b877a..e528650 100644
--- a/arch/arm/mach-msm/gss-8064.c
+++ b/arch/arm/mach-msm/gss-8064.c
@@ -43,6 +43,8 @@
static int crash_shutdown;
+static struct subsys_device *gss_8064_dev;
+
#define MAX_SSR_REASON_LEN 81U
static void log_gss_sfr(void)
@@ -72,7 +74,7 @@
static void restart_gss(void)
{
log_gss_sfr();
- subsystem_restart("gss");
+ subsystem_restart_dev(gss_8064_dev);
}
static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
@@ -91,7 +93,7 @@
#define Q6_FW_WDOG_ENABLE 0x08882024
#define Q6_SW_WDOG_ENABLE 0x08982024
-static int gss_shutdown(const struct subsys_data *subsys)
+static int gss_shutdown(const struct subsys_desc *desc)
{
pil_force_shutdown("gss");
disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
@@ -99,14 +101,14 @@
return 0;
}
-static int gss_powerup(const struct subsys_data *subsys)
+static int gss_powerup(const struct subsys_desc *desc)
{
pil_force_boot("gss");
enable_irq(GSS_A5_WDOG_EXPIRED);
return 0;
}
-void gss_crash_shutdown(const struct subsys_data *subsys)
+void gss_crash_shutdown(const struct subsys_desc *desc)
{
crash_shutdown = 1;
smsm_reset_modem(SMSM_RESET);
@@ -122,7 +124,7 @@
};
static int gss_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
int ret = 0;
@@ -157,7 +159,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data gss_8064 = {
+static struct subsys_desc gss_8064 = {
.name = "gss",
.shutdown = gss_shutdown,
.powerup = gss_powerup,
@@ -167,7 +169,10 @@
static int gss_subsystem_restart_init(void)
{
- return ssr_register_subsystem(&gss_8064);
+ gss_8064_dev = subsys_register(&gss_8064);
+ if (IS_ERR(gss_8064_dev))
+ return PTR_ERR(gss_8064_dev);
+ return 0;
}
static int gss_open(struct inode *inode, struct file *filep)
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 73ede10..76aa627 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -201,8 +201,8 @@
};
struct msm_camera_csi_lane_params {
- uint8_t csi_lane_assign;
- uint8_t csi_lane_mask;
+ uint16_t csi_lane_assign;
+ uint16_t csi_lane_mask;
};
struct msm_camera_gpio_conf {
@@ -487,6 +487,7 @@
struct msm_fb_platform_data {
int (*detect_client)(const char *name);
int mddi_prescan;
+ unsigned char ext_resolution;
int (*allow_set_offset)(void);
char prim_panel_name[PANEL_NAME_MAX_LEN];
char ext_panel_name[PANEL_NAME_MAX_LEN];
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 2b27750..2cb565f 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -134,14 +134,16 @@
struct msm_camera_csid_params {
uint8_t lane_cnt;
- uint8_t lane_assign;
+ uint16_t lane_assign;
+ uint8_t phy_sel;
struct msm_camera_csid_lut_params lut_params;
};
struct msm_camera_csiphy_params {
uint8_t lane_cnt;
uint8_t settle_cnt;
- uint8_t lane_mask;
+ uint16_t lane_mask;
+ uint8_t combo_mode;
};
struct msm_camera_csi2_params {
@@ -564,6 +566,7 @@
S_STEREO_VIDEO,
S_STEREO_CAPTURE,
S_DEFAULT,
+ S_LIVESHOT,
S_EXIT
};
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index ba621e6..6a389de 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -188,6 +188,12 @@
#define DMOV_HSUART_GSBI6_RX_CHAN 8
#define DMOV_HSUART_GSBI6_RX_CRCI 11
+#define DMOV_HSUART_GSBI8_TX_CHAN 7
+#define DMOV_HSUART_GSBI8_TX_CRCI 10
+
+#define DMOV_HSUART_GSBI8_RX_CHAN 8
+#define DMOV_HSUART_GSBI8_RX_CRCI 9
+
#define DMOV_HSUART_GSBI9_TX_CHAN 4
#define DMOV_HSUART_GSBI9_TX_CRCI 13
@@ -263,6 +269,9 @@
#define DMOV8064_CE_OUT_CHAN 1
#define DMOV8064_CE_OUT_CRCI 15
+#define DMOV8064_TSIF_CHAN 2
+#define DMOV8064_TSIF_CRCI 1
+
/* no client rate control ifc (eg, ram) */
#define DMOV_NONE_CRCI 0
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 4bfbe61..28c53db 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -35,6 +35,9 @@
*/
#define MAX_NUM_MIDS 32
+/* Maximum number of SMT entries allowed by the system */
+#define MAX_NUM_SMR 128
+
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
@@ -69,6 +72,9 @@
* @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance
* @pclk: The clock for the IOMMU bus interconnect
+ * @name: Human-readable name of this IOMMU device
+ * @gdsc: Regulator needed to power this HW block (v2 only)
+ * @nsmr: Size of the SMT on this HW block (v2 only)
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -81,6 +87,7 @@
struct clk *pclk;
const char *name;
struct regulator *gdsc;
+ unsigned int nsmr;
};
/**
@@ -89,6 +96,10 @@
* @pdev: Platform device associated wit this HW instance
* @attached_elm: List element for domains to track which devices are
* attached to them
+ * @attached_domain Domain currently attached to this context (if any)
+ * @name Human-readable name of this context device
+ * @sids List of Stream IDs mapped to this context (v2 only)
+ * @nsid Number of Stream IDs mapped to this context (v2 only)
*
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank
* within each IOMMU hardware instance
@@ -99,6 +110,8 @@
struct list_head attached_elm;
struct iommu_domain *attached_domain;
const char *name;
+ u32 sids[MAX_NUM_SMR];
+ unsigned int nsid;
};
/*
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
index fac13b3..b01dbd8 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
@@ -16,8 +16,6 @@
#define CTX_SHIFT 12
#define CTX_OFFSET 0x8000
-#define MAX_NUM_SMR 128
-
#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
(readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
diff --git a/arch/arm/mach-msm/include/mach/kgsl.h b/arch/arm/mach-msm/include/mach/kgsl.h
new file mode 100644
index 0000000..a51cc46
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/kgsl.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 _ARCH_ARM_MACH_KGSL_H
+#define _ARCH_ARM_MACH_KGSL_H
+
+/* Clock flags to show which clocks should be controled by a given platform */
+#define KGSL_CLK_SRC 0x00000001
+#define KGSL_CLK_CORE 0x00000002
+#define KGSL_CLK_IFACE 0x00000004
+#define KGSL_CLK_MEM 0x00000008
+#define KGSL_CLK_MEM_IFACE 0x00000010
+#define KGSL_CLK_AXI 0x00000020
+
+#define KGSL_MAX_PWRLEVELS 5
+
+#define KGSL_CONVERT_TO_MBPS(val) \
+ (val*1000*1000U)
+
+#define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory"
+#define KGSL_3D0_IRQ "kgsl_3d0_irq"
+#define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory"
+#define KGSL_2D0_IRQ "kgsl_2d0_irq"
+#define KGSL_2D1_REG_MEMORY "kgsl_2d1_reg_memory"
+#define KGSL_2D1_IRQ "kgsl_2d1_irq"
+
+#define ADRENO_CHIPID(_co, _ma, _mi, _pa) \
+ ((((_co) & 0xFF) << 24) | \
+ (((_ma) & 0xFF) << 16) | \
+ (((_mi) & 0xFF) << 8) | \
+ ((_pa) & 0xFF))
+
+enum kgsl_iommu_context_id {
+ KGSL_IOMMU_CONTEXT_USER = 0,
+ KGSL_IOMMU_CONTEXT_PRIV = 1,
+};
+
+struct kgsl_iommu_ctx {
+ const char *iommu_ctx_name;
+ enum kgsl_iommu_context_id ctx_id;
+};
+
+struct kgsl_device_iommu_data {
+ const struct kgsl_iommu_ctx *iommu_ctxs;
+ int iommu_ctx_count;
+ unsigned int physstart;
+ unsigned int physend;
+};
+
+struct kgsl_pwrlevel {
+ unsigned int gpu_freq;
+ unsigned int bus_freq;
+ unsigned int io_fraction;
+};
+
+struct kgsl_device_platform_data {
+ struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
+ int init_level;
+ int num_levels;
+ int (*set_grp_async)(void);
+ unsigned int idle_timeout;
+ bool strtstp_sleepwake;
+ unsigned int nap_allowed;
+ unsigned int clk_map;
+ unsigned int idle_needed;
+ struct msm_bus_scale_pdata *bus_scale_table;
+ struct kgsl_device_iommu_data *iommu_data;
+ int iommu_count;
+ struct msm_dcvs_core_info *core_info;
+ unsigned int chipid;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
index 637a3cc..c4877cc 100644
--- a/arch/arm/mach-msm/include/mach/mdm2.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -31,6 +31,7 @@
struct mdm_vddmin_resource *vddmin_resource;
struct platform_device *peripheral_platform_device;
const unsigned int ramdump_timeout_ms;
+ int image_upgrade_supported;
};
#endif
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index c0e6791..4f8e0c1 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -122,6 +122,23 @@
(virt) - MEMBANK0_PAGE_OFFSET + MEMBANK0_PHYS_OFFSET)
#endif
+/*
+ * Need a temporary unique variable that no one will ever see to
+ * hold the compat string. Line number gives this easily.
+ * Need another layer of indirection to get __LINE__ to expand
+ * properly as opposed to appending and ending up with
+ * __compat___LINE__
+ */
+#define __CONCAT(a, b) ___CONCAT(a, b)
+#define ___CONCAT(a, b) a ## b
+
+#define EXPORT_COMPAT(com) \
+static char *__CONCAT(__compat_, __LINE__) __used \
+ __attribute((__section__(".exportcompat.init"))) = com
+
+extern char *__compat_exports_start[];
+extern char *__compat_exports_end[];
+
#endif
#if defined CONFIG_ARCH_MSM_SCORPION || defined CONFIG_ARCH_MSM_KRAIT
@@ -139,4 +156,5 @@
#ifndef CONFIG_ARCH_MSM7X27
#define CONSISTENT_DMA_SIZE (SZ_1M * 14)
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
new file mode 100644
index 0000000..3b8c9fd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 __MSM_MEMORY_DUMP_H
+#define __MSM_MEMORY_DUMP_H
+
+#include <linux/types.h>
+
+enum dump_client_type {
+ MSM_CPU_CTXT = 0,
+ MSM_CACHE,
+ MSM_OCMEM,
+ MSM_ETB,
+ MSM_ETM,
+ MSM_TMC,
+ MAX_NUM_CLIENTS,
+};
+
+struct msm_client_dump {
+ enum dump_client_type id;
+ unsigned long start_addr;
+ unsigned long end_addr;
+};
+
+struct msm_dump_table {
+ u32 version;
+ u32 num_entries;
+ struct msm_client_dump client_entries[MAX_NUM_CLIENTS];
+};
+
+struct msm_memory_dump {
+ unsigned long dump_table_phys;
+ struct msm_dump_table *dump_table_ptr;
+};
+
+#define TABLE_MAJOR(val) (val >> 20)
+#define TABLE_MINOR(val) (val & 0xFFFFF)
+#define MK_TABLE(ma, mi) ((ma << 20) | mi)
+
+#ifndef CONFIG_MSM_MEMORY_DUMP
+static inline int msm_dump_table_register(struct msm_client_dump *entry)
+{
+ return -EIO;
+}
+#else
+int msm_dump_table_register(struct msm_client_dump *client_entry);
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 7afb38d..5ca5861 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -66,5 +66,8 @@
extern struct reserve_info *reserve_info;
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data);
+
unsigned long __init reserve_memory_for_fmem(unsigned long, unsigned long);
#endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index b0475ed..415f8ed 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -22,7 +22,9 @@
/* Maximum number of slots in DM */
#define OCMEM_MAX_CHUNKS 32
-#define MIN_CHUNK_SIZE (SZ_1K/8)
+#define MIN_CHUNK_SIZE 128
+
+struct ocmem_notifier;
struct ocmem_buf {
unsigned long addr;
@@ -59,7 +61,7 @@
/* IMEM Clients */
OCMEM_LP_AUDIO,
OCMEM_SENSORS,
- OCMEM_BLAST,
+ OCMEM_OTHER_OS,
OCMEM_CLIENT_MAX,
};
@@ -80,9 +82,11 @@
/* APIS */
/* Notification APIs */
-void *ocmem_notifier_register(int client_id, struct notifier_block *nb);
+struct ocmem_notifier *ocmem_notifier_register(int client_id,
+ struct notifier_block *nb);
-int ocmem_notifier_unregister(void *notif_hndl, struct notifier_block *nb);
+int ocmem_notifier_unregister(struct ocmem_notifier *notif_hndl,
+ struct notifier_block *nb);
/* Obtain the maximum quota for the client */
unsigned long get_max_quota(int client_id);
@@ -104,8 +108,13 @@
int ocmem_shrink(int client_id, struct ocmem_buf *buf,
unsigned long new_size);
-int ocmem_expand(int client_id, struct ocmem_buf *buf,
- unsigned long new_size);
+/* Transfer APIs */
+int ocmem_map(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list);
+
+
+int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list);
/* Priority Enforcement APIs */
int ocmem_evict(int client_id);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index dd976ea..70b5a45 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -20,12 +20,13 @@
#include "ocmem.h"
#include <mach/msm_iomap.h>
#include <asm/io.h>
+#include <linux/platform_device.h>
#define OCMEM_PHYS_BASE 0xFEC00000
#define OCMEM_PHYS_SIZE 0x180000
-#define TO_OCMEM 0x1
-#define TO_DDR 0x2
+#define TO_OCMEM 0x0
+#define TO_DDR 0x1
struct ocmem_zone;
@@ -38,7 +39,7 @@
int owner;
int active_regions;
int max_regions;
- struct list_head region_list;
+ struct list_head req_list;
unsigned long z_start;
unsigned long z_end;
unsigned long z_head;
@@ -61,12 +62,41 @@
SCHED_DUMP,
};
+struct ocmem_plat_data {
+ void __iomem *vbase;
+ unsigned long size;
+ unsigned long base;
+ struct ocmem_partition *parts;
+ int nr_parts;
+ void __iomem *reg_base;
+ void __iomem *br_base;
+ void __iomem *dm_base;
+ unsigned nr_regions;
+ unsigned nr_macros;
+ unsigned nr_ports;
+ int ocmem_irq;
+ int dm_irq;
+ bool interleaved;
+};
+
+struct ocmem_eviction_data {
+ struct completion completion;
+ struct list_head victim_list;
+ struct list_head req_list;
+ struct work_struct work;
+ int prio;
+ int pending;
+ bool passive;
+};
+
struct ocmem_req {
struct rw_semaphore rw_sem;
/* Chain in sched queue */
struct list_head sched_list;
/* Chain in zone list */
struct list_head zone_list;
+ /* Chain in eviction list */
+ struct list_head eviction_list;
int owner;
int prio;
uint32_t req_id;
@@ -83,6 +113,7 @@
unsigned long req_start;
unsigned long req_end;
unsigned long req_sz;
+ struct ocmem_eviction_data *edata;
};
struct ocmem_handle {
@@ -133,13 +164,20 @@
int ocmem_notifier_init(void);
int check_notifier(int);
+const char *get_name(int);
+int check_id(int);
int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
int ocmem_sched_init(void);
+int ocmem_rdm_init(struct platform_device *);
int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
unsigned long, bool, bool);
int process_free(int, struct ocmem_handle *);
-int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *,
- int direction);
+int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *, int);
+int process_evict(int);
+int process_restore(int);
+int process_shrink(int, struct ocmem_handle *, unsigned long);
+int ocmem_rdm_transfer(int, struct ocmem_map_list *,
+ unsigned long, int);
unsigned long process_quota(int);
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
index 319c2d8..a32e168 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
@@ -29,7 +29,8 @@
* in this enum correspond to MSM8974 for PMIC PM8841 SMPS 2 (VDD_Dig).
*/
enum rpm_regulator_voltage_corner {
- RPM_REGULATOR_CORNER_RETENTION = 1,
+ RPM_REGULATOR_CORNER_NONE = 1,
+ RPM_REGULATOR_CORNER_RETENTION,
RPM_REGULATOR_CORNER_SVS_KRAIT,
RPM_REGULATOR_CORNER_SVS_SOC,
RPM_REGULATOR_CORNER_NORMAL,
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 9110632..2c3d395 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -94,7 +94,9 @@
int __init socinfo_init(void) __must_check;
const int read_msm_cpu_type(void);
const int get_core_count(void);
+const int cpu_is_krait(void);
const int cpu_is_krait_v1(void);
+const int cpu_is_krait_v2(void);
static inline int cpu_is_msm7x01(void)
{
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 51ace96..6d15f47 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,8 @@
#define SUBSYS_NAME_MAX_LENGTH 40
+struct subsys_device;
+
enum {
RESET_SOC = 1,
RESET_SUBSYS_COUPLED,
@@ -25,29 +27,23 @@
RESET_LEVEL_MAX
};
-struct subsys_data {
+struct subsys_desc {
const char *name;
- int (*shutdown) (const struct subsys_data *);
- int (*powerup) (const struct subsys_data *);
- void (*crash_shutdown) (const struct subsys_data *);
- int (*ramdump) (int, const struct subsys_data *);
- /* Internal use only */
- struct list_head list;
- void *notif_handle;
-
- struct mutex shutdown_lock;
- struct mutex powerup_lock;
-
- void *restart_order;
- struct subsys_data *single_restart_list[1];
+ int (*shutdown)(const struct subsys_desc *desc);
+ int (*powerup)(const struct subsys_desc *desc);
+ void (*crash_shutdown)(const struct subsys_desc *desc);
+ int (*ramdump)(int, const struct subsys_desc *desc);
};
#if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
-int get_restart_level(void);
-int subsystem_restart(const char *subsys_name);
-int ssr_register_subsystem(struct subsys_data *subsys);
+extern int get_restart_level(void);
+extern int subsystem_restart_dev(struct subsys_device *dev);
+extern int subsystem_restart(const char *name);
+
+extern struct subsys_device *subsys_register(struct subsys_desc *desc);
+extern void subsys_unregister(struct subsys_device *dev);
#else
@@ -56,16 +52,24 @@
return 0;
}
-static inline int subsystem_restart(const char *subsystem_name)
+static inline int subsystem_restart_dev(struct subsys_device *dev)
{
return 0;
}
-static inline int ssr_register_subsystem(struct subsys_data *subsys)
+static inline int subsystem_restart(const char *name)
{
return 0;
}
+static inline
+struct subsys_device *subsys_register(struct subsys_desc *desc)
+{
+ return NULL;
+}
+
+static inline void subsys_unregister(struct subsys_device *dev) { }
+
#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
#endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index f443e59..4153bd4 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -39,6 +39,11 @@
DEFINE_MUTEX(domain_mutex);
static atomic_t domain_nums = ATOMIC_INIT(-1);
+int msm_use_iommu()
+{
+ return iommu_present(&platform_bus_type);
+}
+
int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
unsigned long size,
@@ -163,6 +168,11 @@
if (size & (align - 1))
return -EINVAL;
+ if (!msm_use_iommu()) {
+ *iova_val = phys;
+ return 0;
+ }
+
ret = msm_allocate_iova_address(domain_no, partition_no, size, align,
&iova);
@@ -185,6 +195,9 @@
unsigned int partition_no,
unsigned long size)
{
+ if (!msm_use_iommu())
+ return;
+
iommu_unmap_range(msm_get_iommu_domain(domain_no), iova, size);
msm_free_iova_address(iova, domain_no, partition_no, size);
}
@@ -388,11 +401,6 @@
return -EINVAL;
}
-int msm_use_iommu()
-{
- return iommu_present(&platform_bus_type);
-}
-
static int __init iommu_domain_probe(struct platform_device *pdev)
{
struct iommu_domains_pdata *p = pdev->dev.platform_data;
diff --git a/arch/arm/mach-msm/krait-scm.c b/arch/arm/mach-msm/krait-scm.c
new file mode 100644
index 0000000..eb48d35
--- /dev/null
+++ b/arch/arm/mach-msm/krait-scm.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/sysfs.h>
+#include <linux/sysdev.h>
+
+#include <mach/scm.h>
+
+#define CPU_CONFIG_CMD 5
+#define CPU_CONFIG_QUERY_CMD 6
+
+static int query_cpu_config(void)
+{
+ struct cpu_config_query_req_resp {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+ struct cpu_config_query_resp {
+ u32 ret0;
+ u32 ret1;
+ u32 ret2;
+ u32 ret3;
+ } response = {0};
+ int ret;
+
+ request.id = 1;
+ ret = scm_call(SCM_SVC_BOOT, CPU_CONFIG_QUERY_CMD, &request,
+ sizeof(request), &response, sizeof(response));
+ return ret ? : response.ret0;
+}
+
+static void set_cpu_config(int enable)
+{
+ struct cpu_config_req {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+
+ request.id = 1;
+ request.arg0 = enable;
+ scm_call(SCM_SVC_BOOT, CPU_CONFIG_CMD, &request, sizeof(request),
+ NULL, 0);
+}
+
+void enable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(1);
+}
+
+void disable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(0);
+}
+
+int cpu_config_on_each_cpu(bool enable)
+{
+ work_func_t func = enable ? enable_cpu_config : disable_cpu_config;
+ return schedule_on_each_cpu(func);
+}
+
+static ssize_t show_cpuctl(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", query_cpu_config());
+}
+
+static ssize_t store_cpuctl(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned val;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+ ret = cpu_config_on_each_cpu(val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static SYSDEV_CLASS_ATTR(cpuctl, 0600, show_cpuctl, store_cpuctl);
+
+static int __init init_scm_cpu(void)
+{
+ return sysfs_create_file(&cpu_subsys.dev_root->kobj,
+ &attr_cpuctl.attr);
+}
+module_init(init_scm_cpu);
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
index 1018360..be18b68 100644
--- a/arch/arm/mach-msm/lpass-8660.c
+++ b/arch/arm/mach-msm/lpass-8660.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
@@ -35,6 +36,8 @@
#define MODULE_NAME "lpass_8x60"
#define SCM_Q6_NMI_CMD 0x1
+static struct subsys_device *subsys_8x60_q6_dev;
+
/* Subsystem restart: QDSP6 data, functions */
static void *q6_ramdump_dev;
static void q6_fatal_fn(struct work_struct *);
@@ -44,7 +47,7 @@
static void q6_fatal_fn(struct work_struct *work)
{
pr_err("%s: Watchdog bite received from Q6!\n", MODULE_NAME);
- subsystem_restart("lpass");
+ subsystem_restart_dev(subsys_8x60_q6_dev);
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
}
@@ -65,7 +68,7 @@
pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
}
-int subsys_q6_shutdown(const struct subsys_data *crashed_subsys)
+int subsys_q6_shutdown(const struct subsys_desc *crashed_subsys)
{
void __iomem *q6_wdog_addr =
ioremap_nocache(Q6SS_WDOG_ENABLE, 8);
@@ -82,7 +85,7 @@
return 0;
}
-int subsys_q6_powerup(const struct subsys_data *crashed_subsys)
+int subsys_q6_powerup(const struct subsys_desc *crashed_subsys)
{
int ret = pil_force_boot("q6");
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
@@ -93,7 +96,7 @@
static struct ramdump_segment q6_segments[] = { {0x46700000, 0x47F00000 -
0x46700000}, {0x28400000, 0x12800} };
static int subsys_q6_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
if (enable)
return do_ramdump(q6_ramdump_dev, q6_segments,
@@ -102,7 +105,7 @@
return 0;
}
-void subsys_q6_crash_shutdown(const struct subsys_data *crashed_subsys)
+void subsys_q6_crash_shutdown(const struct subsys_desc *crashed_subsys)
{
send_q6_nmi();
}
@@ -117,7 +120,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data subsys_8x60_q6 = {
+static struct subsys_desc subsys_8x60_q6 = {
.name = "lpass",
.shutdown = subsys_q6_shutdown,
.powerup = subsys_q6_powerup,
@@ -127,6 +130,7 @@
static void __exit lpass_fatal_exit(void)
{
+ subsys_unregister(subsys_8x60_q6_dev);
iounmap(q6_wakeup_intr);
free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
}
@@ -156,7 +160,9 @@
if (!q6_wakeup_intr)
pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
- ret = ssr_register_subsystem(&subsys_8x60_q6);
+ subsys_8x60_q6_dev = subsys_register(&subsys_8x60_q6);
+ if (IS_ERR(subsys_8x60_q6_dev))
+ ret = PTR_ERR(subsys_8x60_q6_dev);
out:
return ret;
}
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index a546ff3..794eb52 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -165,7 +165,7 @@
pr_debug("%s: Q6 NMI was sent.\n", __func__);
}
-static int lpass_shutdown(const struct subsys_data *subsys)
+static int lpass_shutdown(const struct subsys_desc *subsys)
{
send_q6_nmi();
pil_force_shutdown("q6");
@@ -174,7 +174,7 @@
return 0;
}
-static int lpass_powerup(const struct subsys_data *subsys)
+static int lpass_powerup(const struct subsys_desc *subsys)
{
int ret = pil_force_boot("q6");
enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
@@ -183,7 +183,7 @@
/* RAM segments - address and size for 8960 */
static struct ramdump_segment q6_segments[] = { {0x8da00000, 0x8f200000 -
0x8da00000}, {0x28400000, 0x20000} };
-static int lpass_ramdump(int enable, const struct subsys_data *subsys)
+static int lpass_ramdump(int enable, const struct subsys_desc *subsys)
{
pr_debug("%s: enable[%d]\n", __func__, enable);
if (enable)
@@ -194,7 +194,7 @@
return 0;
}
-static void lpass_crash_shutdown(const struct subsys_data *subsys)
+static void lpass_crash_shutdown(const struct subsys_desc *subsys)
{
q6_crash_shutdown = 1;
send_q6_nmi();
@@ -211,7 +211,9 @@
return IRQ_HANDLED;
}
-static struct subsys_data lpass_8960 = {
+static struct subsys_device *lpass_8960_dev;
+
+static struct subsys_desc lpass_8960 = {
.name = "lpass",
.shutdown = lpass_shutdown,
.powerup = lpass_powerup,
@@ -221,7 +223,10 @@
static int __init lpass_restart_init(void)
{
- return ssr_register_subsystem(&lpass_8960);
+ lpass_8960_dev = subsys_register(&lpass_8960);
+ if (IS_ERR(lpass_8960_dev))
+ return PTR_ERR(lpass_8960_dev);
+ return 0;
}
static int __init lpass_fatal_init(void)
@@ -288,6 +293,7 @@
{
subsys_notif_unregister_notifier(ssr_notif_hdle, &rnb);
subsys_notif_unregister_notifier(ssr_modem_notif_hdle, &mnb);
+ subsys_unregister(lpass_8960_dev);
free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
}
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index e65f71c..ea368ae 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -49,8 +49,8 @@
static void msm_lpm_exit_sleep(void *limits, bool from_idle,
bool notify_rpm, bool collapsed)
{
- /* TODO */
- return;
+ msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
+ from_idle, notify_rpm, collapsed);
}
void msm_lpm_show_resources(void)
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index f57f974..e5be352 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -18,14 +18,14 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/cpu.h>
-#include <mach/mpm.h>
#include <linux/notifier.h>
#include <linux/hrtimer.h>
#include <linux/tick.h>
+#include <mach/mpm.h>
+#include <mach/rpm-smd.h>
#include "spm.h"
#include "lpm_resources.h"
#include "rpm-notifier.h"
-#include <mach/rpm-smd.h>
#include "idle.h"
/*Debug Definitions*/
@@ -243,6 +243,7 @@
uint32_t key, uint8_t *value)
{
int ret = 0;
+ int msg_id;
if (!handle)
return ret;
@@ -255,10 +256,18 @@
return ret;
}
- ret = msm_rpm_send_request_noirq(handle);
- if (ret < 0) {
+ msg_id = msm_rpm_send_request_noirq(handle);
+ if (!msg_id) {
pr_err("%s: Error sending RPM request key %u, handle 0x%x\n",
__func__, key, (unsigned int)handle);
+ ret = -EIO;
+ return ret;
+ }
+
+ ret = msm_rpm_wait_for_ack(msg_id);
+ if (ret < 0) {
+ pr_err("%s: Couldn't get ACK from RPM for Msg %d Error %d",
+ __func__, msg_id, ret);
return ret;
}
if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
@@ -666,12 +675,14 @@
return ret;
}
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm)
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
{
/* MPM exit sleep
if (msm_lpm_use_mpm(limits))
msm_mpm_exit_sleep(from_idle);*/
+
+ msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
}
static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 9973fbf..bc06d7b 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -83,14 +83,14 @@
/**
* msm_lpmrs_exit_sleep() - Exit sleep, reset the MPM and L2 mode.
- * @ sclk_count - Sleep Clock count.
* @ limits: pointer to resource limits of the most recent low power mode.
* @from_idle: bool to determine if this call being made as a part of
* idle power collapse.
* @notify_rpm: bool that informs if this is an RPM notified power collapse.
+ * @collapsed: bool that informs if the Krait was power collapsed.
*/
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm);
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed);
/**
* msm_lpmrs_module_init() - Init function that parses the device tree to
* get the low power resource attributes and registers with RPM driver for
@@ -112,9 +112,8 @@
return 0;
}
-static inline void msm_lpmrs_exit_sleep(uint32_t sclk_count,
- struct msm_rpmrs_limits *limits, bool from_idle,
- bool notify_rpm)
+static inline void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
{
return;
}
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index cbdc92a..4280fb4 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -73,14 +73,14 @@
}
-static int charm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+static int charm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
{
charm_ready = 0;
power_down_charm();
return 0;
}
-static int charm_subsys_powerup(const struct subsys_data *crashed_subsys)
+static int charm_subsys_powerup(const struct subsys_desc *crashed_subsys)
{
power_on_charm();
boot_type = CHARM_NORMAL_BOOT;
@@ -92,7 +92,7 @@
}
static int charm_subsys_ramdumps(int want_dumps,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
charm_ram_dump_status = 0;
if (want_dumps) {
@@ -105,7 +105,9 @@
return charm_ram_dump_status;
}
-static struct subsys_data charm_subsystem = {
+static struct subsys_device *charm_subsys;
+
+static struct subsys_desc charm_subsystem = {
.shutdown = charm_subsys_shutdown,
.ramdump = charm_subsys_ramdumps,
.powerup = charm_subsys_powerup,
@@ -229,7 +231,7 @@
static void charm_status_fn(struct work_struct *work)
{
pr_info("Reseting the charm because status changed\n");
- subsystem_restart("external_modem");
+ subsystem_restart_dev(charm_subsys);
}
static DECLARE_WORK(charm_status_work, charm_status_fn);
@@ -239,7 +241,7 @@
pr_info("Reseting the charm due to an errfatal\n");
if (get_restart_level() == RESET_SOC)
pm8xxx_stay_on();
- subsystem_restart("external_modem");
+ subsystem_restart_dev(charm_subsys);
}
static DECLARE_WORK(charm_fatal_work, charm_fatal_fn);
@@ -349,7 +351,11 @@
atomic_notifier_chain_register(&panic_notifier_list, &charm_panic_blk);
charm_debugfs_init();
- ssr_register_subsystem(&charm_subsystem);
+ charm_subsys = subsys_register(&charm_subsystem);
+ if (IS_ERR(charm_subsys)) {
+ ret = PTR_ERR(charm_subsys);
+ goto fatal_err;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 6e7086e..e74af2e 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -249,6 +249,33 @@
}
}
+static void mdm_image_upgrade(struct mdm_modem_drv *mdm_drv, int type)
+{
+ switch (type) {
+ case APQ_CONTROLLED_UPGRADE:
+ pr_debug("%s APQ controlled modem image upgrade\n", __func__);
+ mdm_drv->mdm_ready = 0;
+ mdm_toggle_soft_reset(mdm_drv);
+ break;
+ case MDM_CONTROLLED_UPGRADE:
+ pr_debug("%s MDM controlled modem image upgrade\n", __func__);
+ mdm_drv->mdm_ready = 0;
+ /*
+ * If we have no image currently present on the modem, then we
+ * would be in PBL, in which case the status gpio would not go
+ * high.
+ */
+ mdm_drv->disable_status_check = 1;
+ if (mdm_drv->usb_switch_gpio > 0) {
+ pr_info("%s Switching usb control to MDM\n", __func__);
+ gpio_direction_output(mdm_drv->usb_switch_gpio, 1);
+ } else
+ pr_err("%s usb switch gpio unavailable\n", __func__);
+ break;
+ default:
+ pr_err("%s invalid upgrade type\n", __func__);
+ }
+}
static struct mdm_ops mdm_cb = {
.power_on_mdm_cb = mdm_power_on_common,
.reset_mdm_cb = mdm_power_on_common,
@@ -256,6 +283,7 @@
.power_down_mdm_cb = mdm_power_down_common,
.debug_state_changed_cb = debug_state_changed,
.status_cb = mdm_status_changed,
+ .image_upgrade_cb = mdm_image_upgrade,
};
static int __init mdm_modem_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 1f54abd..c853b0b 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -56,6 +56,7 @@
#define EXTERNAL_MODEM "external_modem"
static struct mdm_modem_drv *mdm_drv;
+static struct subsys_device *mdm_subsys_dev;
DECLARE_COMPLETION(mdm_needs_reload);
DECLARE_COMPLETION(mdm_boot);
@@ -150,11 +151,13 @@
* If the mdm modem did not pull the MDM2AP_STATUS gpio
* high then call subsystem_restart.
*/
- if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) {
- pr_err("%s: MDM2AP_STATUS gpio did not go high\n",
- __func__);
- mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ if (!mdm_drv->disable_status_check) {
+ if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) {
+ pr_err("%s: MDM2AP_STATUS gpio did not go high\n",
+ __func__);
+ mdm_drv->mdm_ready = 0;
+ subsystem_restart_dev(mdm_subsys_dev);
+ }
}
}
@@ -238,6 +241,15 @@
else
put_user(0, (unsigned long __user *) arg);
break;
+ case IMAGE_UPGRADE:
+ pr_debug("%s Image upgrade ioctl recieved\n", __func__);
+ if (mdm_drv->pdata->image_upgrade_supported &&
+ mdm_drv->ops->image_upgrade_cb) {
+ get_user(status, (unsigned long __user *) arg);
+ mdm_drv->ops->image_upgrade_cb(mdm_drv, status);
+ } else
+ pr_debug("%s Image upgrade not supported\n", __func__);
+ break;
default:
pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
ret = -EINVAL;
@@ -271,7 +283,7 @@
(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
pr_info("%s: Reseting the mdm due to an errfatal\n", __func__);
mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ subsystem_restart_dev(mdm_subsys_dev);
}
return IRQ_HANDLED;
}
@@ -332,7 +344,7 @@
pr_info("%s: unexpected reset external modem\n", __func__);
mdm_drv->mdm_unexpected_reset_occurred = 1;
mdm_drv->mdm_ready = 0;
- subsystem_restart(EXTERNAL_MODEM);
+ subsystem_restart_dev(mdm_subsys_dev);
} else if (value == 1) {
cancel_delayed_work(&mdm2ap_status_check_work);
pr_info("%s: status = 1: mdm is now ready\n", __func__);
@@ -349,7 +361,7 @@
return IRQ_HANDLED;
}
-static int mdm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
{
mdm_drv->mdm_ready = 0;
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
@@ -363,11 +375,10 @@
mdm_drv->ops->reset_mdm_cb(mdm_drv);
else
mdm_drv->mdm_unexpected_reset_occurred = 0;
-
return 0;
}
-static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
+static int mdm_subsys_powerup(const struct subsys_desc *crashed_subsys)
{
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
@@ -390,7 +401,7 @@
}
static int mdm_subsys_ramdumps(int want_dumps,
- const struct subsys_data *crashed_subsys)
+ const struct subsys_desc *crashed_subsys)
{
mdm_drv->mdm_ram_dump_status = 0;
if (want_dumps) {
@@ -411,7 +422,7 @@
return mdm_drv->mdm_ram_dump_status;
}
-static struct subsys_data mdm_subsystem = {
+static struct subsys_desc mdm_subsystem = {
.shutdown = mdm_subsys_shutdown,
.ramdump = mdm_subsys_ramdumps,
.powerup = mdm_subsys_powerup,
@@ -514,6 +525,12 @@
if (pres)
mdm_drv->mdm2ap_pblrdy = pres->start;
+ /*USB_SW*/
+ pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "USB_SW");
+ if (pres)
+ mdm_drv->usb_switch_gpio = pres->start;
+
mdm_drv->boot_type = CHARM_NORMAL_BOOT;
mdm_drv->ops = mdm_ops;
@@ -556,6 +573,13 @@
if (mdm_drv->ap2mdm_wakeup_gpio > 0)
gpio_request(mdm_drv->ap2mdm_wakeup_gpio, "AP2MDM_WAKEUP");
+ if (mdm_drv->usb_switch_gpio > 0) {
+ if (gpio_request(mdm_drv->usb_switch_gpio, "USB_SW")) {
+ pr_err("%s Failed to get usb switch gpio\n", __func__);
+ mdm_drv->usb_switch_gpio = -1;
+ }
+ }
+
gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
@@ -588,7 +612,11 @@
mdm_debugfs_init();
/* Register subsystem handlers */
- ssr_register_subsystem(&mdm_subsystem);
+ mdm_subsys_dev = subsys_register(&mdm_subsystem);
+ if (IS_ERR(mdm_subsys_dev)) {
+ ret = PTR_ERR(mdm_subsys_dev);
+ goto fatal_err;
+ }
/* ERR_FATAL irq. */
irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index 7ac3727..7aba83d 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -23,6 +23,7 @@
void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
void (*debug_state_changed_cb)(int value);
void (*status_cb)(struct mdm_modem_drv *mdm_drv, int value);
+ void (*image_upgrade_cb)(struct mdm_modem_drv *mdm_drv, int type);
};
/* Private mdm2 data structure */
@@ -37,6 +38,7 @@
unsigned ap2mdm_soft_reset_gpio;
unsigned ap2mdm_pmic_pwr_en_gpio;
unsigned mdm2ap_pblrdy;
+ unsigned usb_switch_gpio;
int mdm_errfatal_irq;
int mdm_status_irq;
@@ -46,6 +48,7 @@
enum charm_boot_type boot_type;
int mdm_debug_on;
int mdm_unexpected_reset_occurred;
+ int disable_status_check;
struct mdm_ops *ops;
struct mdm_platform_data *pdata;
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index a1b21c5..63c2d3a 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -37,6 +37,7 @@
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <linux/sched.h>
+#include <linux/of_fdt.h>
/* fixme */
#include <asm/tlbflush.h>
@@ -381,3 +382,117 @@
{
return fmem_set_state(FMEM_T_STATE);
}
+
+static char * const memtype_names[] = {
+ [MEMTYPE_SMI_KERNEL] = "SMI_KERNEL",
+ [MEMTYPE_SMI] = "SMI",
+ [MEMTYPE_EBI0] = "EBI0",
+ [MEMTYPE_EBI1] = "EBI1",
+};
+
+static int reserve_memory_type(char *mem_name,
+ struct memtype_reserve *reserve_table,
+ int size)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(memtype_names); i++) {
+ if (memtype_names[i] && strcmp(mem_name,
+ memtype_names[i]) == 0) {
+ reserve_table[i].size += size;
+ return 0;
+ }
+ }
+
+ pr_err("Could not find memory type %s\n", mem_name);
+ return -EINVAL;
+}
+
+static int check_for_compat(unsigned long node)
+{
+ char **start = __compat_exports_start;
+
+ for ( ; start < __compat_exports_end; start++)
+ if (of_flat_dt_is_compatible(node, *start))
+ return 1;
+
+ return 0;
+}
+
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ char *memory_name_prop;
+ unsigned int *memory_remove_prop;
+ unsigned long memory_name_prop_length;
+ unsigned long memory_remove_prop_length;
+ unsigned long memory_size_prop_length;
+ unsigned int *memory_size_prop;
+ unsigned int memory_size;
+ unsigned int memory_start;
+ int ret;
+
+ memory_name_prop = of_get_flat_dt_prop(node,
+ "qcom,memory-reservation-type",
+ &memory_name_prop_length);
+ memory_remove_prop = of_get_flat_dt_prop(node,
+ "qcom,memblock-remove",
+ &memory_remove_prop_length);
+
+ if (memory_name_prop || memory_remove_prop) {
+ if (!check_for_compat(node))
+ goto out;
+ } else {
+ goto out;
+ }
+
+ if (memory_name_prop) {
+ if (strnlen(memory_name_prop, memory_name_prop_length) == 0) {
+ WARN(1, "Memory name was malformed\n");
+ goto mem_remove;
+ }
+
+ memory_size_prop = of_get_flat_dt_prop(node,
+ "qcom,memory-reservation-size",
+ &memory_size_prop_length);
+
+ if (memory_size_prop &&
+ (memory_size_prop_length == sizeof(unsigned int))) {
+ memory_size = be32_to_cpu(*memory_size_prop);
+
+ if (reserve_memory_type(memory_name_prop,
+ data, memory_size) == 0)
+ pr_info("%s reserved %s size %x\n",
+ uname, memory_name_prop, memory_size);
+ else
+ WARN(1, "Node %s reserve failed\n",
+ uname);
+ } else {
+ WARN(1, "Node %s specified bad/nonexistent size\n",
+ uname);
+ }
+ }
+
+mem_remove:
+
+ if (memory_remove_prop) {
+ if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+ WARN(1, "Memory remove malformed\n");
+ goto out;
+ }
+
+ memory_start = be32_to_cpu(memory_remove_prop[0]);
+ memory_size = be32_to_cpu(memory_remove_prop[1]);
+
+ ret = memblock_remove(memory_start, memory_size);
+ if (ret)
+ WARN(1, "Failed to remove memory %x-%x\n",
+ memory_start, memory_start+memory_size);
+ else
+ pr_info("Node %s removed memory %x-%x\n", uname,
+ memory_start, memory_start+memory_size);
+ }
+
+out:
+ return 0;
+}
diff --git a/arch/arm/mach-msm/modem-8660.c b/arch/arm/mach-msm/modem-8660.c
index 9c558e4..096ed9c 100644
--- a/arch/arm/mach-msm/modem-8660.c
+++ b/arch/arm/mach-msm/modem-8660.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
@@ -48,6 +49,8 @@
module_param(reset_modem, int, 0644);
#endif
+static struct subsys_device *modem_8660_dev;
+
/* Subsystem restart: Modem data, functions */
static void *modem_ramdump_dev;
static void modem_fatal_fn(struct work_struct *);
@@ -75,7 +78,7 @@
mb();
iounmap(hwio_modem_reset_addr);
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
enable_irq(MARM_WDOG_EXPIRED);
}
@@ -93,7 +96,7 @@
if (modem_state == 0 || modem_state & panic_smsm_states) {
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
enable_irq(MARM_WDOG_EXPIRED);
} else if (modem_state & reset_smsm_states) {
@@ -135,13 +138,13 @@
goto out;
}
pr_err("%s: Modem error fatal'ed.", MODULE_NAME);
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8660_dev);
}
out:
return NOTIFY_DONE;
}
-static int modem_shutdown(const struct subsys_data *crashed_subsys)
+static int modem_shutdown(const struct subsys_desc *crashed_subsys)
{
void __iomem *modem_wdog_addr;
@@ -178,7 +181,7 @@
return 0;
}
-static int modem_powerup(const struct subsys_data *crashed_subsys)
+static int modem_powerup(const struct subsys_desc *crashed_subsys)
{
int ret;
@@ -192,8 +195,7 @@
static struct ramdump_segment modem_segments[] = {
{0x42F00000, 0x46000000 - 0x42F00000} };
-static int modem_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
{
if (enable)
return do_ramdump(modem_ramdump_dev, modem_segments,
@@ -202,8 +204,7 @@
return 0;
}
-static void modem_crash_shutdown(
- const struct subsys_data *crashed_subsys)
+static void modem_crash_shutdown(const struct subsys_desc *crashed_subsys)
{
/* If modem hasn't already crashed, send SMSM_RESET. */
if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
@@ -225,7 +226,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data subsys_8660_modem = {
+static struct subsys_desc subsys_8660_modem = {
.name = "modem",
.shutdown = modem_shutdown,
.powerup = modem_powerup,
@@ -260,13 +261,16 @@
goto out;
}
- ret = ssr_register_subsystem(&subsys_8660_modem);
+ modem_8660_dev = subsys_register(&subsys_8660_modem);
+ if (IS_ERR(modem_8660_dev))
+ ret = PTR_ERR(modem_8660_dev);
out:
return ret;
}
static void __exit modem_8660_exit(void)
{
+ subsys_unregister(modem_8660_dev);
free_irq(MARM_WDOG_EXPIRED, NULL);
}
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index fd7b7b5..73b9b1f 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -35,6 +35,8 @@
static int crash_shutdown;
+static struct subsys_device *modem_8960_dev;
+
#define MAX_SSR_REASON_LEN 81U
#define Q6_FW_WDOG_ENABLE 0x08882024
#define Q6_SW_WDOG_ENABLE 0x08982024
@@ -66,7 +68,7 @@
static void restart_modem(void)
{
log_modem_sfr();
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8960_dev);
}
static void modem_wdog_check(struct work_struct *work)
@@ -101,7 +103,7 @@
}
}
-static int modem_shutdown(const struct subsys_data *subsys)
+static int modem_shutdown(const struct subsys_desc *subsys)
{
void __iomem *q6_fw_wdog_addr;
void __iomem *q6_sw_wdog_addr;
@@ -142,7 +144,7 @@
#define MODEM_WDOG_CHECK_TIMEOUT_MS 10000
-static int modem_powerup(const struct subsys_data *subsys)
+static int modem_powerup(const struct subsys_desc *subsys)
{
pil_force_boot("modem_fw");
pil_force_boot("modem");
@@ -153,7 +155,7 @@
return 0;
}
-void modem_crash_shutdown(const struct subsys_data *subsys)
+void modem_crash_shutdown(const struct subsys_desc *subsys)
{
crash_shutdown = 1;
smsm_reset_modem(SMSM_RESET);
@@ -176,8 +178,7 @@
static void *modemsw_ramdump_dev;
static void *smem_ramdump_dev;
-static int modem_ramdump(int enable,
- const struct subsys_data *crashed_subsys)
+static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
{
int ret = 0;
@@ -234,7 +235,7 @@
return IRQ_HANDLED;
}
-static struct subsys_data modem_8960 = {
+static struct subsys_desc modem_8960 = {
.name = "modem",
.shutdown = modem_shutdown,
.powerup = modem_powerup,
@@ -244,13 +245,16 @@
static int modem_subsystem_restart_init(void)
{
- return ssr_register_subsystem(&modem_8960);
+ modem_8960_dev = subsys_register(&modem_8960);
+ if (IS_ERR(modem_8960_dev))
+ return PTR_ERR(modem_8960_dev);
+ return 0;
}
static int modem_debug_set(void *data, u64 val)
{
if (val == 1)
- subsystem_restart("modem");
+ subsystem_restart_dev(modem_8960_dev);
return 0;
}
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 954e5cc..3c219be 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -221,7 +221,7 @@
/* save the contents of GIC CPU interface and Distributor
* Disable all the Interrupts, if we enter from idle pc
*/
- msm_gic_save(modem_wake, from_idle);
+ msm_gic_save();
irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
enable_irq(MSM8625_INT_A9_M2A_6);
pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/msm-krait-l2-accessors.c b/arch/arm/mach-msm/msm-krait-l2-accessors.c
index 3d341e3..41a2490 100644
--- a/arch/arm/mach-msm/msm-krait-l2-accessors.c
+++ b/arch/arm/mach-msm/msm-krait-l2-accessors.c
@@ -14,19 +14,83 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <asm/mach-types.h>
+#include <asm/cputype.h>
DEFINE_RAW_SPINLOCK(l2_access_lock);
+#define L2CPMR 0x500
+#define L2CPUCPMR 0x501
+#define L2CPUVRF8 0x708
+#define CPUNDX_MASK (0x7 << 12)
+
+/*
+ * For Krait versions found in APQ8064v1.x, save L2CPUVRF8 before
+ * L2CPMR or L2CPUCPMR writes and restore it after to work around an
+ * issue where L2CPUVRF8 becomes corrupt.
+ */
+static bool l2cpuvrf8_needs_fix(u32 reg_addr)
+{
+ switch (read_cpuid_id()) {
+ case 0x510F06F0: /* KR28M4A10 */
+ case 0x510F06F1: /* KR28M4A10B */
+ case 0x510F06F2: /* KR28M4A11 */
+ break;
+ default:
+ return false;
+ };
+
+ switch (reg_addr & ~CPUNDX_MASK) {
+ case L2CPMR:
+ case L2CPUCPMR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static u32 l2cpuvrf8_fix_save(u32 reg_addr, u32 *l2cpuvrf8_val)
+{
+ u32 l2cpuvrf8_addr = L2CPUVRF8 | (reg_addr & CPUNDX_MASK);
+
+ mb();
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mrc p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ : [l2cpdr]"=r" (*l2cpuvrf8_val)
+ : [l2cpselr]"r" (l2cpuvrf8_addr)
+ );
+
+ return l2cpuvrf8_addr;
+}
+
+static void l2cpuvrf8_fix_restore(u32 l2cpuvrf8_addr, u32 l2cpuvrf8_val)
+{
+ mb();
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mcr p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ "isb\n\t"
+ :
+ : [l2cpselr]"r" (l2cpuvrf8_addr),
+ [l2cpdr]"r" (l2cpuvrf8_val)
+ );
+}
+
u32 set_get_l2_indirect_reg(u32 reg_addr, u32 val)
{
unsigned long flags;
+ u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
u32 ret_val;
+
/* CP15 registers are not emulated on RUMI3. */
if (machine_is_msm8960_rumi3())
return 0;
raw_spin_lock_irqsave(&l2_access_lock, flags);
+ if (l2cpuvrf8_needs_fix(reg_addr))
+ l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
mb();
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
@@ -36,6 +100,10 @@
: [l2cpdr_read]"=r" (ret_val)
: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
);
+
+ if (l2cpuvrf8_addr)
+ l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
return ret_val;
@@ -45,11 +113,17 @@
void set_l2_indirect_reg(u32 reg_addr, u32 val)
{
unsigned long flags;
+ u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
+
/* CP15 registers are not emulated on RUMI3. */
if (machine_is_msm8960_rumi3())
return;
raw_spin_lock_irqsave(&l2_access_lock, flags);
+
+ if (l2cpuvrf8_needs_fix(reg_addr))
+ l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
mb();
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
@@ -58,6 +132,10 @@
:
: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
);
+
+ if (l2cpuvrf8_addr)
+ l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
}
EXPORT_SYMBOL(set_l2_indirect_reg);
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index ab62c20..924577f 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -2,7 +2,9 @@
# Makefile for msm-bus driver specific files
#
obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o
-obj-y += msm_bus_rpm.o msm_bus_bimc.o msm_bus_noc.o
+obj-y += msm_bus_bimc.o msm_bus_noc.o
+obj-$(CONFIG_MSM_RPM) += msm_bus_rpm.o
+obj-$(CONFIG_MSM_RPM_SMD) += msm_bus_rpm_smd.o
obj-$(CONFIG_ARCH_MSM8X60) += msm_bus_board_8660.o
obj-$(CONFIG_ARCH_MSM8960) += msm_bus_board_8960.o
obj-$(CONFIG_ARCH_MSM9615) += msm_bus_board_9615.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index 823f14d..2072cb1 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -1817,44 +1817,45 @@
info->node_info->id, info->node_info->priv_id, add_bw);
binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data;
- if (!info->node_info->qport) {
- MSM_BUS_DBG("No qos ports to update!\n");
- return;
- }
if (info->node_info->num_mports == 0) {
MSM_BUS_DBG("BIMC: Skip Master BW\n");
goto skip_mas_bw;
}
+ ports = info->node_info->num_mports;
bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
- ports = INTERLEAVED_VAL(fab_pdata, ports);
for (i = 0; i < ports; i++) {
- MSM_BUS_DBG("qport: %d\n", info->node_info->qport[i]);
sel_cd->mas[info->node_info->masterp[i]].bw += bw;
sel_cd->mas[info->node_info->masterp[i]].hw_id =
info->node_info->mas_hw_id;
- qbw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
- qbw.ws = info->node_info->ws;
- /* Threshold low = 90% of bw */
- qbw.thl = (90 * bw) / 100;
- /* Threshold medium = bw */
- qbw.thm = bw;
- /* Threshold high = 10% more than bw */
- qbw.thh = (110 * bw) / 100;
- /* Check if info is a shared master.
- * If it is, mark it dirty
- * If it isn't, then set QOS Bandwidth
- **/
- MSM_BUS_DBG("BIMC: Update mas_bw for ID: %d -> %ld\n",
+ MSM_BUS_DBG("BIMC: Update mas_bw for ID: %d -> %llu\n",
info->node_info->priv_id,
sel_cd->mas[info->node_info->masterp[i]].bw);
if (info->node_info->hw_sel == MSM_BUS_RPM)
sel_cd->mas[info->node_info->masterp[i]].dirty = 1;
- else
+ else {
+ if (!info->node_info->qport) {
+ MSM_BUS_DBG("No qos ports to update!\n");
+ break;
+ }
+ MSM_BUS_DBG("qport: %d\n", info->node_info->qport[i]);
+ qbw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
+ qbw.ws = info->node_info->ws;
+ /* Threshold low = 90% of bw */
+ qbw.thl = (90 * bw) / 100;
+ /* Threshold medium = bw */
+ qbw.thm = bw;
+ /* Threshold high = 10% more than bw */
+ qbw.thh = (110 * bw) / 100;
+ /* Check if info is a shared master.
+ * If it is, mark it dirty
+ * If it isn't, then set QOS Bandwidth
+ **/
msm_bus_bimc_set_qos_bw(binfo,
info->node_info->qport[i], &qbw);
+ }
}
skip_mas_bw:
@@ -1870,7 +1871,7 @@
sel_cd->slv[hop->node_info->slavep[i]].bw += bw;
sel_cd->slv[hop->node_info->slavep[i]].hw_id =
hop->node_info->slv_hw_id;
- MSM_BUS_DBG("BIMC: Update slave_bw: ID: %d -> %ld\n",
+ MSM_BUS_DBG("BIMC: Update slave_bw: ID: %d -> %llu\n",
hop->node_info->priv_id,
sel_cd->slv[hop->node_info->slavep[i]].bw);
MSM_BUS_DBG("BIMC: Update slave_bw: index: %d\n",
@@ -1893,6 +1894,7 @@
*fab_pdata, void *hw_data, void **cdata)
{
MSM_BUS_DBG("\nReached BIMC Commit\n");
+ msm_bus_remote_hw_commit(fab_pdata, hw_data, cdata);
return 0;
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 264afbd..333fe4b 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -123,7 +123,7 @@
struct msm_bus_node_hw_info {
bool dirty;
unsigned int hw_id;
- unsigned long bw;
+ uint64_t bw;
};
struct msm_bus_hw_algorithm {
@@ -202,6 +202,8 @@
int curr;
};
+int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
+ *fab_pdata, void *hw_data, void **cdata);
int msm_bus_fabric_device_register(struct msm_bus_fabric_device *fabric);
void msm_bus_fabric_device_unregister(struct msm_bus_fabric_device *fabric);
struct msm_bus_fabric_device *msm_bus_get_fabric_device(int fabid);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
index 5179d2a..2597e27 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -518,14 +518,12 @@
return;
}
- if (!info->node_info->qport) {
- MSM_BUS_DBG("NOC: No QoS Ports to update bw\n");
- return;
+ if (info->node_info->num_mports == 0) {
+ MSM_BUS_DBG("NOC: Skip Master BW\n");
+ goto skip_mas_bw;
}
ports = info->node_info->num_mports;
- qos_bw.ws = info->node_info->ws;
-
bw = INTERLEAVED_BW(fab_pdata, add_bw, ports);
MSM_BUS_DBG("NOC: Update bw for: %d: %ld\n",
@@ -534,26 +532,36 @@
sel_cd->mas[info->node_info->masterp[i]].bw += bw;
sel_cd->mas[info->node_info->masterp[i]].hw_id =
info->node_info->mas_hw_id;
- qos_bw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
- MSM_BUS_DBG("NOC: Update mas_bw for ID: %d, BW: %ld, QoS: %u\n",
+ MSM_BUS_DBG("NOC: Update mas_bw: ID: %d, BW: %llu ports:%d\n",
info->node_info->priv_id,
sel_cd->mas[info->node_info->masterp[i]].bw,
- qos_bw.ws);
+ ports);
/* Check if info is a shared master.
* If it is, mark it dirty
* If it isn't, then set QOS Bandwidth
**/
if (info->node_info->hw_sel == MSM_BUS_RPM)
sel_cd->mas[info->node_info->masterp[i]].dirty = 1;
- else
+ else {
+ if (!info->node_info->qport) {
+ MSM_BUS_DBG("No qos ports to update!\n");
+ break;
+ }
+ qos_bw.bw = sel_cd->mas[info->node_info->masterp[i]].
+ bw;
+ qos_bw.ws = info->node_info->ws;
msm_bus_noc_set_qos_bw(ninfo,
info->node_info->qport[i],
info->node_info->perm_mode, &qos_bw);
+ MSM_BUS_DBG("NOC: QoS: Update mas_bw: ws: %u\n",
+ qos_bw.ws);
+ }
}
+skip_mas_bw:
ports = hop->node_info->num_sports;
if (ports == 0) {
- MSM_BUS_ERR("\nDIVIDE BY 0, hop: %d\n",
+ MSM_BUS_DBG("\nDIVIDE BY 0, hop: %d\n",
hop->node_info->priv_id);
return;
}
@@ -562,7 +570,7 @@
sel_cd->slv[hop->node_info->slavep[i]].bw += bw;
sel_cd->slv[hop->node_info->slavep[i]].hw_id =
hop->node_info->slv_hw_id;
- MSM_BUS_DBG("NOC: Update slave_bw for ID: %d -> %ld\n",
+ MSM_BUS_DBG("NOC: Update slave_bw for ID: %d -> %llu\n",
hop->node_info->priv_id,
sel_cd->slv[hop->node_info->slavep[i]].bw);
MSM_BUS_DBG("NOC: Update slave_bw for hw_id: %d, index: %d\n",
@@ -581,6 +589,7 @@
*fab_pdata, void *hw_data, void **cdata)
{
MSM_BUS_DBG("\nReached NOC Commit\n");
+ msm_bus_remote_hw_commit(fab_pdata, hw_data, cdata);
return 0;
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
index 4653431..2213132 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
@@ -946,6 +946,12 @@
return status;
}
+int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
+ *fab_pdata, void *hw_data, void **cdata)
+{
+ return 0;
+}
+
int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo)
{
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_rpm_smd.c b/arch/arm/mach-msm/msm_bus/msm_bus_rpm_smd.c
new file mode 100644
index 0000000..88fab96
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_rpm_smd.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
+#include "msm_bus_core.h"
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/rpm-smd.h>
+
+/* Stubs for backward compatibility */
+void msm_bus_rpm_set_mt_mask()
+{
+}
+
+bool msm_bus_rpm_is_mem_interleaved(void)
+{
+ return true;
+}
+
+struct commit_data {
+ struct msm_bus_node_hw_info *mas_arb;
+ struct msm_bus_node_hw_info *slv_arb;
+};
+
+#ifdef CONFIG_DEBUG_FS
+void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, const int max_size,
+ void *cdata, int nmasters, int nslaves, int ntslaves)
+{
+ int c;
+ struct commit_data *cd = (struct commit_data *)cdata;
+
+ *curr += scnprintf(buf + *curr, max_size - *curr, "\nMas BW:\n");
+ for (c = 0; c < nmasters; c++)
+ *curr += scnprintf(buf + *curr, max_size - *curr,
+ "%d: %llu\t", cd->mas_arb[c].hw_id,
+ cd->mas_arb[c].bw);
+ *curr += scnprintf(buf + *curr, max_size - *curr, "\nSlave BW:\n");
+ for (c = 0; c < nslaves; c++) {
+ *curr += scnprintf(buf + *curr, max_size - *curr,
+ "%d: %llu\t", cd->slv_arb[c].hw_id,
+ cd->slv_arb[c].bw);
+ }
+}
+#endif
+
+static int msm_bus_rpm_compare_cdata(
+ struct msm_bus_fabric_registration *fab_pdata,
+ struct commit_data *cd1, struct commit_data *cd2)
+{
+ size_t n;
+ int ret;
+
+ n = sizeof(struct msm_bus_node_hw_info) * fab_pdata->nmasters * 2;
+ ret = memcmp(cd1->mas_arb, cd2->mas_arb, n);
+ if (ret) {
+ MSM_BUS_DBG("Master Arb Data not equal\n");
+ return ret;
+ }
+
+ n = sizeof(struct msm_bus_node_hw_info) * fab_pdata->nslaves * 2;
+ ret = memcmp(cd1->slv_arb, cd2->slv_arb, n);
+ if (ret) {
+ MSM_BUS_DBG("Master Arb Data not equal\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int msm_bus_rpm_req(int ctx, uint32_t rsc_type, uint32_t key,
+ struct msm_bus_node_hw_info *hw_info, bool valid)
+{
+ struct msm_rpm_request *rpm_req;
+ int ret = 0, msg_id;
+
+ if (ctx == ACTIVE_CTX)
+ ctx = MSM_RPM_CTX_ACTIVE_SET;
+ else if (ctx == DUAL_CTX)
+ ctx = MSM_RPM_CTX_SLEEP_SET;
+
+ rpm_req = msm_rpm_create_request(ctx, rsc_type, hw_info->hw_id, 1);
+ if (rpm_req == NULL) {
+ MSM_BUS_WARN("RPM: Couldn't create RPM Request\n");
+ return -ENXIO;
+ }
+
+ if (valid) {
+ ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)
+ &hw_info->bw, (int)(sizeof(uint64_t)));
+ if (ret) {
+ MSM_BUS_WARN("RPM: Add KVP failed for RPM Req:%u\n",
+ rsc_type);
+ return ret;
+ }
+
+ MSM_BUS_DBG("Added Key: %d, Val: %llu, size: %d\n", key,
+ hw_info->bw, sizeof(uint64_t));
+ } else {
+ /* Invalidate RPM requests */
+ ret = msm_rpm_add_kvp_data(rpm_req, 0, NULL, 0);
+ if (ret) {
+ MSM_BUS_WARN("RPM: Add KVP failed for RPM Req:%u\n",
+ rsc_type);
+ return ret;
+ }
+ }
+
+ msg_id = msm_rpm_send_request(rpm_req);
+ if (!msg_id) {
+ MSM_BUS_WARN("RPM: No message ID for req\n");
+ return -ENXIO;
+ }
+
+ ret = msm_rpm_wait_for_ack(msg_id);
+ if (ret) {
+ MSM_BUS_WARN("RPM: Ack failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int msm_bus_rpm_commit_arb(struct msm_bus_fabric_registration
+ *fab_pdata, int ctx, void *rpm_data,
+ struct commit_data *cd, bool valid)
+{
+ int i, status = 0, rsc_type, key;
+
+ MSM_BUS_DBG("Context: %d\n", ctx);
+ rsc_type = RPM_BUS_MASTER_REQ;
+ key = RPM_MASTER_FIELD_BW;
+ for (i = 0; i < fab_pdata->nmasters; i++) {
+ if (cd->mas_arb[i].dirty) {
+ MSM_BUS_DBG("MAS HWID: %d, BW: %llu DIRTY: %d\n",
+ cd->mas_arb[i].hw_id,
+ cd->mas_arb[i].bw,
+ cd->mas_arb[i].dirty);
+ status = msm_bus_rpm_req(ctx, rsc_type, key,
+ &cd->mas_arb[i], valid);
+ if (status) {
+ MSM_BUS_ERR("RPM: Req fail: mas:%d, bw:%llu\n",
+ cd->mas_arb[i].hw_id,
+ cd->mas_arb[i].bw);
+ break;
+ } else {
+ cd->mas_arb[i].dirty = false;
+ }
+ }
+ }
+
+ rsc_type = RPM_BUS_SLAVE_REQ;
+ key = RPM_SLAVE_FIELD_BW;
+ for (i = 0; i < fab_pdata->nslaves; i++) {
+ if (cd->slv_arb[i].dirty) {
+ MSM_BUS_DBG("SLV HWID: %d, BW: %llu DIRTY: %d\n",
+ cd->slv_arb[i].hw_id,
+ cd->slv_arb[i].bw,
+ cd->slv_arb[i].dirty);
+ status = msm_bus_rpm_req(ctx, rsc_type, key,
+ &cd->slv_arb[i], valid);
+ if (status) {
+ MSM_BUS_ERR("RPM: Req fail: slv:%d, bw:%llu\n",
+ cd->slv_arb[i].hw_id,
+ cd->slv_arb[i].bw);
+ break;
+ } else {
+ cd->slv_arb[i].dirty = false;
+ }
+ }
+ }
+
+ return status;
+}
+
+/**
+* msm_bus_remote_hw_commit() - Commit the arbitration data to RPM
+* @fabric: Fabric for which the data should be committed
+**/
+int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
+ *fab_pdata, void *hw_data, void **cdata)
+{
+
+ int ret;
+ bool valid;
+ struct commit_data *dual_cd, *act_cd;
+ void *rpm_data = hw_data;
+
+ MSM_BUS_DBG("\nReached RPM Commit\n");
+ dual_cd = (struct commit_data *)cdata[DUAL_CTX];
+ act_cd = (struct commit_data *)cdata[ACTIVE_CTX];
+
+ /*
+ * If the arb data for active set and sleep set is
+ * different, commit both sets.
+ * If the arb data for active set and sleep set is
+ * the same, invalidate the sleep set.
+ */
+ ret = msm_bus_rpm_compare_cdata(fab_pdata, act_cd, dual_cd);
+ if (!ret)
+ /* Invalidate sleep set.*/
+ valid = false;
+ else
+ valid = true;
+
+ ret = msm_bus_rpm_commit_arb(fab_pdata, DUAL_CTX, rpm_data,
+ dual_cd, valid);
+ if (ret)
+ MSM_BUS_ERR("Error comiting fabric:%d in %d ctx\n",
+ fab_pdata->id, DUAL_CTX);
+
+ valid = true;
+ ret = msm_bus_rpm_commit_arb(fab_pdata, ACTIVE_CTX, rpm_data, act_cd,
+ valid);
+ if (ret)
+ MSM_BUS_ERR("Error comiting fabric:%d in %d ctx\n",
+ fab_pdata->id, ACTIVE_CTX);
+
+ return ret;
+}
+
+int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
+ struct msm_bus_hw_algorithm *hw_algo)
+{
+ if (!pdata->ahb)
+ pdata->rpm_enabled = 1;
+ return 0;
+}
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index 200d717..6dde576 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -722,6 +722,8 @@
.unlocked_ioctl = dsps_ioctl,
};
+static struct subsys_device *dsps_dev;
+
/**
* Fatal error handler
* Resets DSPS.
@@ -735,7 +737,7 @@
pr_err("%s: DSPS already resetting. Count %d\n", __func__,
atomic_read(&drv->crash_in_progress));
} else {
- subsystem_restart("dsps");
+ subsystem_restart_dev(dsps_dev);
}
}
@@ -765,7 +767,7 @@
* called by the restart notifier
*
*/
-static int dsps_shutdown(const struct subsys_data *subsys)
+static int dsps_shutdown(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
disable_irq_nosync(drv->wdog_irq);
@@ -779,7 +781,7 @@
* called by the restart notifier
*
*/
-static int dsps_powerup(const struct subsys_data *subsys)
+static int dsps_powerup(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
dsps_power_on_handler();
@@ -794,7 +796,7 @@
* called by the restart notifier
*
*/
-static void dsps_crash_shutdown(const struct subsys_data *subsys)
+static void dsps_crash_shutdown(const struct subsys_desc *subsys)
{
pr_debug("%s\n", __func__);
dsps_crash_shutdown_g = 1;
@@ -806,7 +808,7 @@
* called by the restart notifier
*
*/
-static int dsps_ramdump(int enable, const struct subsys_data *subsys)
+static int dsps_ramdump(int enable, const struct subsys_desc *subsys)
{
int ret = 0;
pr_debug("%s\n", __func__);
@@ -838,7 +840,7 @@
return ret;
}
-static struct subsys_data dsps_ssrops = {
+static struct subsys_desc dsps_ssrops = {
.name = "dsps",
.shutdown = dsps_shutdown,
.powerup = dsps_powerup,
@@ -919,9 +921,10 @@
goto smsm_register_err;
}
- ret = ssr_register_subsystem(&dsps_ssrops);
- if (ret) {
- pr_err("%s: ssr_register_subsystem fail %d\n", __func__,
+ dsps_dev = subsys_register(&dsps_ssrops);
+ if (IS_ERR(dsps_dev)) {
+ ret = PTR_ERR(dsps_dev);
+ pr_err("%s: subsys_register fail %d\n", __func__,
ret);
goto ssr_register_err;
}
@@ -953,6 +956,7 @@
{
pr_debug("%s.\n", __func__);
+ subsys_unregister(dsps_dev);
dsps_power_off_handler();
dsps_free_resources();
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
new file mode 100644
index 0000000..4f48a0d
--- /dev/null
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/export.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memory_dump.h>
+
+
+/*TODO: Needs to be set to correct value */
+#define DUMP_TABLE_OFFSET 0x20
+#define MSM_DUMP_TABLE_VERSION MK_TABLE(1, 0)
+
+static struct msm_memory_dump mem_dump_data;
+
+static int msm_memory_dump_panic(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ writel_relaxed(0, MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
+ return 0;
+}
+
+static struct notifier_block msm_memory_dump_blk = {
+ .notifier_call = msm_memory_dump_panic,
+};
+
+int msm_dump_table_register(struct msm_client_dump *client_entry)
+{
+ struct msm_client_dump *entry;
+ struct msm_dump_table *table = mem_dump_data.dump_table_ptr;
+
+ if (!table || table->num_entries >= MAX_NUM_CLIENTS)
+ return -EINVAL;
+ entry = &table->client_entries[table->num_entries];
+ entry->id = client_entry->id;
+ entry->start_addr = client_entry->start_addr;
+ entry->end_addr = client_entry->end_addr;
+ table->num_entries++;
+ /* flush cache */
+ dmac_flush_range(table, table + sizeof(struct msm_dump_table));
+ return 0;
+}
+EXPORT_SYMBOL(msm_dump_table_register);
+
+static int __init init_memory_dump(void)
+{
+ struct msm_dump_table *table;
+
+ mem_dump_data.dump_table_ptr = kzalloc(sizeof(struct msm_dump_table),
+ GFP_KERNEL);
+ if (!mem_dump_data.dump_table_ptr) {
+ printk(KERN_ERR "unable to allocate memory for dump table\n");
+ return -ENOMEM;
+ }
+ table = mem_dump_data.dump_table_ptr;
+ table->version = MSM_DUMP_TABLE_VERSION;
+ mem_dump_data.dump_table_phys = virt_to_phys(table);
+ /* TODO: Need to write physical address of table to IMEM */
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_memory_dump_blk);
+ printk(KERN_INFO "MSM Memory Dump table set up\n");
+ return 0;
+}
+
+early_initcall(init_memory_dump);
+
diff --git a/arch/arm/mach-msm/msm_smem_iface.c b/arch/arm/mach-msm/msm_smem_iface.c
new file mode 100644
index 0000000..b09fda5
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 "msm_smem_iface.h"
+
+/**
+ * mem_get_cpr_info() - Copy Core Power Reduction (CPR) driver specific
+ * data from Shared memory (SMEM).
+ * @cpr_info - Pointer to CPR data. Memory to be allocated and freed by
+ * calling function.
+ *
+ * Copy CPR specific data from SMEM to cpr_info.
+ */
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info)
+{
+ struct boot_info_for_apps *boot_info;
+ struct cpr_info_type *temp_cpr_info;
+ uint32_t smem_boot_info_size;
+
+ boot_info = smem_get_entry(SMEM_BOOT_INFO_FOR_APPS,
+ &smem_boot_info_size);
+ BUG_ON(!boot_info);
+ if (smem_boot_info_size < sizeof(struct boot_info_for_apps)) {
+ pr_err("%s: Shared boot info data structure too small!\n",
+ __func__);
+ BUG();
+ } else {
+ pr_debug("%s: Shared boot info available.\n", __func__);
+ }
+ temp_cpr_info = (struct cpr_info_type *) &(boot_info->cpr_info);
+ cpr_info->ring_osc = temp_cpr_info->ring_osc;
+ cpr_info->turbo_quot = temp_cpr_info->turbo_quot;
+ cpr_info->pvs_fuse = temp_cpr_info->pvs_fuse;
+}
diff --git a/arch/arm/mach-msm/msm_smem_iface.h b/arch/arm/mach-msm/msm_smem_iface.h
new file mode 100644
index 0000000..2da0232
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+#define __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+
+#include <mach/msm_smsm.h>
+#include "smd_private.h"
+
+#define MAX_KEY_EVENTS 10
+#define MAX_SEC_KEY_PAYLOAD 32
+
+struct boot_shared_ssd_status_info {
+ uint32_t update_status; /* To check if process is successful or not */
+ uint32_t bl_error_code; /* To indicate error code in bootloader */
+};
+
+struct boot_symmetric_key_info {
+ uint32_t key_len; /* Encrypted Symmetric Key Length */
+ uint32_t iv_len; /* Initialization Vector Length */
+ uint8_t key[MAX_SEC_KEY_PAYLOAD]; /* Encrypted Symmetric Key */
+ uint8_t iv[MAX_SEC_KEY_PAYLOAD]; /* Initialization Vector */
+};
+
+struct cpr_info_type {
+ uint8_t ring_osc; /* CPR FUSE [0]: TURBO RO SEL BIT */
+ uint8_t turbo_quot; /* CPRFUSE[1:7] : TURBO QUOT*/
+ uint8_t pvs_fuse; /* TURBO PVS FUSE */
+};
+
+struct boot_info_for_apps {
+ uint32_t apps_image_start_addr; /* apps image start address */
+ uint32_t boot_flags; /* bit mask of upto 32 flags */
+ struct boot_shared_ssd_status_info ssd_status_info; /* SSD status */
+ struct boot_symmetric_key_info key_info;
+ uint16_t boot_keys_pressed[MAX_KEY_EVENTS]; /* Log of key presses */
+ uint32_t timetick; /* Modem tick timer value before apps out of reset */
+ struct cpr_info_type cpr_info;
+ uint8_t PAD[25];
+};
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info);
+
+#endif /* __ARCH_ARM_MACH_MSM_SMEM_IFACE_H */
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 43c7fc8..753f6fb 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -10,7 +10,6 @@
* GNU General Public License for more details.
*/
-#include <mach/ocmem_priv.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -18,10 +17,12 @@
#include <linux/rbtree.h>
#include <linux/genalloc.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <mach/ocmem_priv.h>
/* This code is to temporarily work around the default state of OCMEM
regions in Virtio. These registers will be read from DT in a subsequent
@@ -29,8 +30,9 @@
*/
#define OCMEM_REGION_CTL_BASE 0xFDD0003C
-#define OCMEM_REGION_CTL_SIZE 0xC
+#define OCMEM_REGION_CTL_SIZE 0xFD0
#define REGION_ENABLE 0x00003333
+#define GRAPHICS_REGION_CTL (0x17F000)
struct ocmem_partition {
const char *name;
@@ -41,14 +43,6 @@
unsigned int p_tail;
};
-struct ocmem_plat_data {
- void __iomem *vbase;
- unsigned long size;
- unsigned long base;
- struct ocmem_partition *parts;
- unsigned nr_parts;
-};
-
struct ocmem_zone zones[OCMEM_CLIENT_MAX];
struct ocmem_zone *get_zone(unsigned id)
@@ -62,6 +56,7 @@
static struct ocmem_plat_data *ocmem_pdata;
#define CLIENT_NAME_MAX 10
+
/* Must be in sync with enum ocmem_client */
static const char *client_names[OCMEM_CLIENT_MAX] = {
"graphics",
@@ -71,7 +66,7 @@
"voice",
"lp_audio",
"sensors",
- "blast",
+ "other_os",
};
struct ocmem_quota_table {
@@ -92,7 +87,7 @@
{ "voice", OCMEM_VOICE, 0x0, 0x0, 0x0, 0 },
{ "hp_audio", OCMEM_HP_AUDIO, 0x0, 0x0, 0x0, 0},
{ "lp_audio", OCMEM_LP_AUDIO, 0x80000, 0xA0000, 0xA0000, 0},
- { "blast", OCMEM_BLAST, 0x120000, 0x20000, 0x20000, 0},
+ { "other_os", OCMEM_OTHER_OS, 0x120000, 0x20000, 0x20000, 0},
{ "sensors", OCMEM_SENSORS, 0x140000, 0x40000, 0x40000, 0},
};
@@ -106,6 +101,18 @@
return -EINVAL;
}
+int check_id(int id)
+{
+ return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+const char *get_name(int id)
+{
+ if (!check_id(id))
+ return NULL;
+ return client_names[id];
+}
+
inline unsigned long phys_to_offset(unsigned long addr)
{
if (!ocmem_pdata)
@@ -183,8 +190,216 @@
return pdata;
}
+int __devinit of_ocmem_parse_regions(struct device *dev,
+ struct ocmem_partition **part)
+{
+ const char *name;
+ struct device_node *child = NULL;
+ int nr_parts = 0;
+ int i = 0;
+ int rc = 0;
+ int id = -1;
+
+ /*Compute total partitions */
+ for_each_child_of_node(dev->of_node, child)
+ nr_parts++;
+
+ if (nr_parts == 0)
+ return 0;
+
+ *part = devm_kzalloc(dev, nr_parts * sizeof(**part),
+ GFP_KERNEL);
+
+ if (!*part)
+ return -ENOMEM;
+
+ for_each_child_of_node(dev->of_node, child)
+ {
+ const u32 *addr;
+ u32 min;
+ u64 size;
+ u64 p_start;
+
+ addr = of_get_address(child, 0, &size, NULL);
+
+ if (!addr) {
+ dev_err(dev, "Invalid addr for partition %d, ignored\n",
+ i);
+ continue;
+ }
+
+ rc = of_property_read_u32(child, "qcom,ocmem-part-min", &min);
+
+ if (rc) {
+ dev_err(dev, "No min for partition %d, ignored\n", i);
+ continue;
+ }
+
+ rc = of_property_read_string(child, "qcom,ocmem-part-name",
+ &name);
+
+ if (rc) {
+ dev_err(dev, "No name for partition %d, ignored\n", i);
+ continue;
+ }
+
+ id = get_id(name);
+
+ if (id < 0) {
+ dev_err(dev, "Ignoring invalid partition %s\n", name);
+ continue;
+ }
+
+ p_start = of_translate_address(child, addr);
+
+ if (p_start == OF_BAD_ADDR) {
+ dev_err(dev, "Invalid offset for partition %d\n", i);
+ continue;
+ }
+
+ (*part)[i].p_start = p_start;
+ (*part)[i].p_size = size;
+ (*part)[i].id = id;
+ (*part)[i].name = name;
+ (*part)[i].p_min = min;
+ (*part)[i].p_tail = of_property_read_bool(child, "tail");
+ i++;
+ }
+
+ return i;
+}
+
static struct ocmem_plat_data *parse_dt_config(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+ struct ocmem_plat_data *pdata = NULL;
+ struct ocmem_partition *parts = NULL;
+ struct resource *ocmem_irq;
+ struct resource *dm_irq;
+ struct resource *ocmem_mem;
+ struct resource *reg_base;
+ struct resource *br_base;
+ struct resource *dm_base;
+ struct resource *ocmem_mem_io;
+ unsigned nr_parts = 0;
+ unsigned nr_regions = 0;
+
+ pdata = devm_kzalloc(dev, sizeof(struct ocmem_plat_data),
+ GFP_KERNEL);
+
+ if (!pdata) {
+ dev_err(dev, "Unable to allocate memory for platform data\n");
+ return NULL;
+ }
+
+ ocmem_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "ocmem_physical");
+ if (!ocmem_mem) {
+ dev_err(dev, "No OCMEM memory resource\n");
+ return NULL;
+ }
+
+ ocmem_mem_io = request_mem_region(ocmem_mem->start,
+ resource_size(ocmem_mem), pdev->name);
+
+ if (!ocmem_mem_io) {
+ dev_err(dev, "Could not claim OCMEM memory\n");
+ return NULL;
+ }
+
+ pdata->base = ocmem_mem->start;
+ pdata->size = resource_size(ocmem_mem);
+ pdata->vbase = devm_ioremap_nocache(dev, ocmem_mem->start,
+ resource_size(ocmem_mem));
+ if (!pdata->vbase) {
+ dev_err(dev, "Could not ioremap ocmem memory\n");
+ return NULL;
+ }
+
+ reg_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "ocmem_ctrl_physical");
+ if (!reg_base) {
+ dev_err(dev, "No OCMEM register resource\n");
+ return NULL;
+ }
+
+ pdata->reg_base = devm_ioremap_nocache(dev, reg_base->start,
+ resource_size(reg_base));
+ if (!pdata->reg_base) {
+ dev_err(dev, "Could not ioremap register map\n");
+ return NULL;
+ }
+
+ br_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "br_ctrl_physical");
+ if (!br_base) {
+ dev_err(dev, "No OCMEM BR resource\n");
+ return NULL;
+ }
+
+ pdata->br_base = devm_ioremap_nocache(dev, br_base->start,
+ resource_size(br_base));
+ if (!pdata->br_base) {
+ dev_err(dev, "Could not ioremap BR resource\n");
+ return NULL;
+ }
+
+ dm_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dm_ctrl_physical");
+ if (!dm_base) {
+ dev_err(dev, "No OCMEM DM resource\n");
+ return NULL;
+ }
+
+ pdata->dm_base = devm_ioremap_nocache(dev, dm_base->start,
+ resource_size(dm_base));
+ if (!pdata->dm_base) {
+ dev_err(dev, "Could not ioremap DM resource\n");
+ return NULL;
+ }
+
+ ocmem_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "ocmem_irq");
+
+ if (!ocmem_irq) {
+ dev_err(dev, "No OCMEM IRQ resource\n");
+ return NULL;
+ }
+
+ dm_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "dm_irq");
+
+ if (!dm_irq) {
+ dev_err(dev, "No DM IRQ resource\n");
+ return NULL;
+ }
+
+ if (of_property_read_u32(node, "qcom,ocmem-num-regions",
+ &nr_regions)) {
+ dev_err(dev, "No OCMEM memory regions specified\n");
+ }
+
+ if (nr_regions == 0) {
+ dev_err(dev, "No hardware memory regions found\n");
+ return NULL;
+ }
+
+ /* Figure out the number of partititons */
+ nr_parts = of_ocmem_parse_regions(dev, &parts);
+ if (nr_parts <= 0) {
+ dev_err(dev, "No valid OCMEM partitions found\n");
+ goto pdata_error;
+ } else
+ dev_dbg(dev, "Found %d ocmem partitions\n", nr_parts);
+
+ pdata->nr_parts = nr_parts;
+ pdata->parts = parts;
+ pdata->nr_regions = nr_regions;
+ pdata->ocmem_irq = ocmem_irq->start;
+ pdata->dm_irq = dm_irq->start;
+ return pdata;
+pdata_error:
return NULL;
}
@@ -225,7 +440,7 @@
return -EBUSY;
}
- start = pdata->base + part->p_start;
+ start = part->p_start;
ret = gen_pool_add(zone->z_pool, start,
part->p_size, -1);
@@ -254,7 +469,7 @@
zone->owner = part->id;
zone->active_regions = 0;
zone->max_regions = 0;
- INIT_LIST_HEAD(&zone->region_list);
+ INIT_LIST_HEAD(&zone->req_list);
zone->z_ops = z_ops;
if (part->p_tail) {
z_ops->allocate = allocate_tail;
@@ -273,7 +488,7 @@
zone->z_end, part->p_size/SZ_1K);
}
- dev_info(dev, "Total active zones = %d\n", active_zones);
+ dev_dbg(dev, "Total active zones = %d\n", active_zones);
return 0;
}
@@ -282,7 +497,7 @@
struct device *dev = &pdev->dev;
void *ocmem_region_vbase = NULL;
- if (!pdev->dev.of_node->child) {
+ if (!pdev->dev.of_node) {
dev_info(dev, "Missing Configuration in Device Tree\n");
ocmem_pdata = parse_static_config(pdev);
} else {
@@ -297,6 +512,8 @@
BUG_ON(!IS_ALIGNED(ocmem_pdata->size, PAGE_SIZE));
BUG_ON(!IS_ALIGNED(ocmem_pdata->base, PAGE_SIZE));
+ dev_info(dev, "OCMEM Virtual addr %p\n", ocmem_pdata->vbase);
+
platform_set_drvdata(pdev, ocmem_pdata);
if (ocmem_zone_init(pdev))
@@ -316,7 +533,14 @@
writel_relaxed(REGION_ENABLE, ocmem_region_vbase);
writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 4);
writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 8);
- dev_info(dev, "initialized successfully\n");
+ /* Enable the ocmem graphics mpU as a workaround in Virtio */
+ /* This will be programmed by TZ after TZ support is integrated */
+ writel_relaxed(GRAPHICS_REGION_CTL, ocmem_region_vbase + 0xFCC);
+
+ if (ocmem_rdm_init(pdev))
+ return -EBUSY;
+
+ dev_dbg(dev, "initialized successfully\n");
return 0;
}
@@ -326,7 +550,7 @@
}
static struct of_device_id msm_ocmem_dt_match[] = {
- { .compatible = "qcom,msm_ocmem",
+ { .compatible = "qcom,msm-ocmem",
},
{}
};
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index bed13de..bb32fca 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -13,10 +13,8 @@
#include <linux/slab.h>
#include <mach/ocmem_priv.h>
-static inline int check_id(int id)
-{
- return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
+static DEFINE_MUTEX(ocmem_eviction_lock);
+static DECLARE_BITMAP(evicted, OCMEM_CLIENT_MAX);
static struct ocmem_handle *generate_handle(void)
{
@@ -61,6 +59,24 @@
return 0;
}
+static int __ocmem_shrink(int id, struct ocmem_buf *buf, unsigned long len)
+{
+ int ret = 0;
+ struct ocmem_handle *handle = buffer_to_handle(buf);
+
+ if (!handle)
+ return -EINVAL;
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_shrink(id, handle, len);
+ mutex_unlock(&handle->handle_mutex);
+
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+}
+
static struct ocmem_buf *__ocmem_allocate_range(int id, unsigned long min,
unsigned long max, unsigned long step, bool block, bool wait)
{
@@ -218,6 +234,15 @@
return __ocmem_free(client_id, buffer);
}
+int ocmem_shrink(int client_id, struct ocmem_buf *buffer, unsigned long len)
+{
+ if (!buffer)
+ return -EINVAL;
+ if (len >= buffer->len)
+ return -EINVAL;
+ return __ocmem_shrink(client_id, buffer, len);
+}
+
int pre_validate_chunk_list(struct ocmem_map_list *list)
{
int i = 0;
@@ -236,8 +261,12 @@
for (i = 0; i < list->num_chunks; i++) {
if (!chunks[i].ddr_paddr ||
- chunks[i].size < MIN_CHUNK_SIZE)
+ chunks[i].size < MIN_CHUNK_SIZE ||
+ !IS_ALIGNED(chunks[i].size, MIN_CHUNK_SIZE)) {
+ pr_err("Invalid ocmem chunk at index %d (p: %lx, size %lx)\n",
+ i, chunks[i].ddr_paddr, chunks[i].size);
return -EINVAL;
+ }
}
return 0;
}
@@ -265,7 +294,7 @@
return -EINVAL;
}
- if (!pre_validate_chunk_list(list))
+ if (pre_validate_chunk_list(list) != 0)
return -EINVAL;
handle = buffer_to_handle(buffer);
@@ -303,14 +332,10 @@
return -EINVAL;
}
- if (!pre_validate_chunk_list(list))
+ if (pre_validate_chunk_list(list) != 0)
return -EINVAL;
handle = buffer_to_handle(buffer);
-
- if (!handle)
- return -EINVAL;
-
mutex_lock(&handle->handle_mutex);
ret = process_xfer(client_id, handle, list, TO_DDR);
mutex_unlock(&handle->handle_mutex);
@@ -325,3 +350,52 @@
}
return process_quota(client_id);
}
+
+/* Synchronous eviction/restore calls */
+/* Only a single eviction or restoration is allowed */
+/* Evictions/Restorations cannot be concurrent with other maps */
+int ocmem_evict(int client_id)
+{
+ int ret = 0;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ocmem_eviction_lock);
+ if (test_bit(client_id, evicted)) {
+ pr_err("ocmem: Previous eviction was not restored by %d\n",
+ client_id);
+ mutex_unlock(&ocmem_eviction_lock);
+ return -EINVAL;
+ }
+
+ ret = process_evict(client_id);
+ if (ret == 0)
+ set_bit(client_id, evicted);
+
+ mutex_unlock(&ocmem_eviction_lock);
+ return ret;
+}
+
+int ocmem_restore(int client_id)
+{
+ int ret = 0;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ocmem_eviction_lock);
+ if (!test_bit(client_id, evicted)) {
+ pr_err("ocmem: No previous eviction by %d\n", client_id);
+ mutex_unlock(&ocmem_eviction_lock);
+ return -EINVAL;
+ }
+ ret = process_restore(client_id);
+ clear_bit(client_id, evicted);
+ mutex_unlock(&ocmem_eviction_lock);
+ return ret;
+}
diff --git a/arch/arm/mach-msm/ocmem_notifier.c b/arch/arm/mach-msm/ocmem_notifier.c
index 58ad3d9..9fbcd73 100644
--- a/arch/arm/mach-msm/ocmem_notifier.c
+++ b/arch/arm/mach-msm/ocmem_notifier.c
@@ -24,11 +24,6 @@
unsigned listeners;
} notifiers[OCMEM_CLIENT_MAX];
-static int check_id(int id)
-{
- return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
-
int check_notifier(int id)
{
int ret = 0;
@@ -75,7 +70,8 @@
return ret;
}
-void *ocmem_notifier_register(int client_id, struct notifier_block *nb)
+struct ocmem_notifier *ocmem_notifier_register(int client_id,
+ struct notifier_block *nb)
{
int ret = 0;
@@ -115,13 +111,12 @@
}
EXPORT_SYMBOL(ocmem_notifier_register);
-int ocmem_notifier_unregister(void *hndl, struct notifier_block *nb)
+int ocmem_notifier_unregister(struct ocmem_notifier *nc_hndl,
+ struct notifier_block *nb)
{
int ret = 0;
- struct ocmem_notifier *nc_hndl = (struct ocmem_notifier *) hndl;
-
if (!nc_hndl) {
pr_err("ocmem: Invalid notification handle\n");
return -EINVAL;
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
new file mode 100644
index 0000000..6b93d04
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <mach/ocmem_priv.h>
+
+#define RDM_MAX_ENTRIES 32
+#define RDM_MAX_CLIENTS 2
+
+/* Data Mover Parameters */
+#define DM_BLOCK_128 0x0
+#define DM_BLOCK_256 0x1
+#define DM_BR_ID_LPASS 0x0
+#define DM_BR_ID_GPS 0x1
+
+#define DM_INTR_CLR (0x8)
+#define DM_INTR_MASK (0xC)
+#define DM_GEN_STATUS (0x10)
+#define DM_STATUS (0x14)
+#define DM_CTRL (0x1000)
+#define DM_TBL_BASE (0x1010)
+#define DM_TBL_IDX(x) ((x) * 0x18)
+#define DM_TBL_n(x) (DM_TBL_BASE + (DM_TBL_IDX(x)))
+#define DM_TBL_n_offset(x) DM_TBL_n(x)
+#define DM_TBL_n_size(x) (DM_TBL_n(x)+0x4)
+#define DM_TBL_n_paddr(x) (DM_TBL_n(x)+0x8)
+#define DM_TBL_n_ctrl(x) (DM_TBL_n(x)+0x10)
+
+#define BR_CTRL (0x0)
+#define BR_CLIENT_BASE (0x4)
+#define BR_CLIENT_n_IDX(x) ((x) * 0x4)
+#define BR_CLIENT_n_ctrl(x) (BR_CLIENT_BASE + (BR_CLIENT_n_IDX(x)))
+#define BR_STATUS (0x14)
+/* 16 entries per client are supported */
+/* Use entries 0 - 15 for client0 */
+#define BR_CLIENT0_MASK (0x1000)
+/* Use entries 16- 31 for client1 */
+#define BR_CLIENT1_MASK (0x2010)
+
+#define BR_TBL_BASE (0x40)
+#define BR_TBL_IDX(x) ((x) * 0x18)
+#define BR_TBL_n(x) (BR_TBL_BASE + (BR_TBL_IDX(x)))
+#define BR_TBL_n_offset(x) BR_TBL_n(x)
+#define BR_TBL_n_size(x) (BR_TBL_n(x)+0x4)
+#define BR_TBL_n_paddr(x) (BR_TBL_n(x)+0x8)
+#define BR_TBL_n_ctrl(x) (BR_TBL_n(x)+0x10)
+
+/* Constants and Shifts */
+#define BR_TBL_ENTRY_ENABLE 0x1
+#define BR_TBL_START 0x0
+#define BR_TBL_END 0x8
+#define BR_RW_SHIFT 0x2
+
+#define DM_TBL_START 0x10
+#define DM_TBL_END 0x18
+#define DM_CLIENT_SHIFT 0x8
+#define DM_BR_ID_SHIFT 0x4
+#define DM_BR_BLK_SHIFT 0x1
+#define DM_DIR_SHIFT 0x0
+
+#define DM_DONE 0x1
+#define DM_INTR_ENABLE 0x0
+#define DM_INTR_DISABLE 0x1
+
+static void *br_base;
+static void *dm_base;
+
+static atomic_t dm_pending;
+static wait_queue_head_t dm_wq;
+/* Shadow tables for debug purposes */
+struct ocmem_br_table {
+ unsigned int offset;
+ unsigned int size;
+ unsigned int ddr_low;
+ unsigned int ddr_high;
+ unsigned int ctrl;
+} br_table[RDM_MAX_ENTRIES];
+
+/* DM Table replicates an entire BR table */
+/* Note: There are more than 1 BRs in the system */
+struct ocmem_dm_table {
+ unsigned int offset;
+ unsigned int size;
+ unsigned int ddr_low;
+ unsigned int ddr_high;
+ unsigned int ctrl;
+} dm_table[RDM_MAX_ENTRIES];
+
+/* Wrapper that will shadow these values later */
+static int ocmem_read(void *at)
+{
+ return readl_relaxed(at);
+}
+
+/* Wrapper that will shadow these values later */
+static int ocmem_write(unsigned long val, void *at)
+{
+ writel_relaxed(val, at);
+ return 0;
+}
+
+static inline int client_ctrl_id(int id)
+{
+ return (id == OCMEM_SENSORS) ? 1 : 0;
+}
+
+static inline int client_slot_start(int id)
+{
+
+ return client_ctrl_id(id) * 16;
+}
+
+static irqreturn_t ocmem_dm_irq_handler(int irq, void *dev_id)
+{
+ atomic_set(&dm_pending, 0);
+ ocmem_write(DM_INTR_DISABLE, dm_base + DM_INTR_CLR);
+ wake_up_interruptible(&dm_wq);
+ return IRQ_HANDLED;
+}
+
+/* Lock during transfers */
+int ocmem_rdm_transfer(int id, struct ocmem_map_list *clist,
+ unsigned long start, int direction)
+{
+ int num_chunks = clist->num_chunks;
+ int slot = client_slot_start(id);
+ int table_start = 0;
+ int table_end = 0;
+ int br_ctrl = 0;
+ int br_id = 0;
+ int dm_ctrl = 0;
+ int i = 0;
+ int j = 0;
+ int status = 0;
+
+ for (i = 0, j = slot; i < num_chunks; i++, j++) {
+
+ struct ocmem_chunk *chunk = &clist->chunks[i];
+ int sz = chunk->size;
+ int paddr = chunk->ddr_paddr;
+ int tbl_n_ctrl = 0;
+
+ tbl_n_ctrl |= BR_TBL_ENTRY_ENABLE;
+ if (chunk->ro)
+ tbl_n_ctrl |= (1 << BR_RW_SHIFT);
+
+ /* Table Entry n of BR and DM */
+ ocmem_write(start, br_base + BR_TBL_n_offset(j));
+ ocmem_write(sz, br_base + BR_TBL_n_size(j));
+ ocmem_write(paddr, br_base + BR_TBL_n_paddr(j));
+ ocmem_write(tbl_n_ctrl, br_base + BR_TBL_n_ctrl(j));
+
+ ocmem_write(start, dm_base + DM_TBL_n_offset(j));
+ ocmem_write(sz, dm_base + DM_TBL_n_size(j));
+ ocmem_write(paddr, dm_base + DM_TBL_n_paddr(j));
+ ocmem_write(tbl_n_ctrl, dm_base + DM_TBL_n_ctrl(j));
+
+ start += sz;
+ }
+
+ br_id = client_ctrl_id(id);
+ table_start = slot;
+ table_end = slot + num_chunks - 1;
+ br_ctrl |= (table_start << BR_TBL_START);
+ br_ctrl |= (table_end << BR_TBL_END);
+
+ ocmem_write(br_ctrl, (br_base + BR_CLIENT_n_ctrl(br_id)));
+ /* Enable BR */
+ ocmem_write(0x1, br_base + BR_CTRL);
+
+ /* Compute DM Control Value */
+ dm_ctrl |= (table_start << DM_TBL_START);
+ dm_ctrl |= (table_end << DM_TBL_END);
+
+ dm_ctrl |= (DM_BR_ID_LPASS << DM_BR_ID_SHIFT);
+ dm_ctrl |= (DM_BLOCK_256 << DM_BR_BLK_SHIFT);
+ dm_ctrl |= (direction << DM_DIR_SHIFT);
+
+ status = ocmem_read(dm_base + DM_STATUS);
+ pr_debug("Transfer status before %x\n", status);
+ atomic_set(&dm_pending, 1);
+ /* Trigger DM */
+ ocmem_write(dm_ctrl, dm_base + DM_CTRL);
+ pr_debug("ocmem: rdm: dm_ctrl %x br_ctrl %x\n", dm_ctrl, br_ctrl);
+
+ wait_event_interruptible(dm_wq,
+ atomic_read(&dm_pending) == 0);
+
+ return 0;
+}
+
+int ocmem_rdm_init(struct platform_device *pdev)
+{
+
+ struct ocmem_plat_data *pdata = NULL;
+ int rc = 0;
+
+ pdata = platform_get_drvdata(pdev);
+
+ br_base = pdata->br_base;
+ dm_base = pdata->dm_base;
+
+ rc = devm_request_irq(&pdev->dev, pdata->dm_irq, ocmem_dm_irq_handler,
+ IRQF_TRIGGER_RISING, "ocmem_dm_irq", pdata);
+
+ if (rc) {
+ dev_err(&pdev->dev, "Failed to request dm irq");
+ return -EINVAL;
+ }
+
+ init_waitqueue_head(&dm_wq);
+ /* enable dm interrupts */
+ ocmem_write(DM_INTR_ENABLE, dm_base + DM_INTR_MASK);
+ return 0;
+}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 10a267c..f6d066d 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -54,7 +54,7 @@
MIN_PRIO = 0x0,
NO_PRIO = MIN_PRIO,
PRIO_SENSORS = 0x1,
- PRIO_BLAST = 0x1,
+ PRIO_OTHER_OS = 0x1,
PRIO_LP_AUDIO = 0x1,
PRIO_HP_AUDIO = 0x2,
PRIO_VOICE = 0x3,
@@ -75,6 +75,21 @@
*/
#define SCHED_DELAY 10
+static struct list_head rdm_queue;
+static struct mutex rdm_mutex;
+static struct workqueue_struct *ocmem_rdm_wq;
+static struct workqueue_struct *ocmem_eviction_wq;
+
+static struct ocmem_eviction_data *evictions[OCMEM_CLIENT_MAX];
+
+struct ocmem_rdm_work {
+ int id;
+ struct ocmem_map_list *list;
+ struct ocmem_handle *handle;
+ int direction;
+ struct work_struct work;
+};
+
/* OCMEM Operational modes */
enum ocmem_client_modes {
OCMEM_PERFORMANCE = 1,
@@ -107,7 +122,7 @@
{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
{OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
{OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
- {OCMEM_BLAST, PRIO_BLAST, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+ {OCMEM_OTHER_OS, PRIO_OTHER_OS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
};
static struct rb_root sched_tree;
@@ -119,6 +134,8 @@
struct rb_node region_rb;
/* Hash map of requests */
struct idr region_idr;
+ /* Chain in eviction list */
+ struct list_head eviction_list;
unsigned long r_start;
unsigned long r_end;
unsigned long r_sz;
@@ -244,6 +261,7 @@
if (!p)
return NULL;
idr_init(&p->region_idr);
+ INIT_LIST_HEAD(&p->eviction_list);
p->r_start = p->r_end = p->r_sz = 0x0;
p->max_prio = NO_PRIO;
return p;
@@ -461,10 +479,14 @@
{
int rc = 0;
+ down_write(&req->rw_sem);
+
mutex_lock(&sched_mutex);
rc = __sched_map(req);
mutex_unlock(&sched_mutex);
+ up_write(&req->rw_sem);
+
if (rc == OP_FAIL)
return -EINVAL;
@@ -475,10 +497,14 @@
{
int rc = 0;
+ down_write(&req->rw_sem);
+
mutex_lock(&sched_mutex);
rc = __sched_unmap(req);
mutex_unlock(&sched_mutex);
+ up_write(&req->rw_sem);
+
if (rc == OP_FAIL)
return -EINVAL;
@@ -713,6 +739,104 @@
}
/* Must be called with sched_mutex held */
+static int __sched_shrink(struct ocmem_req *req, unsigned long new_sz)
+{
+ int owner = req->owner;
+ int ret = 0;
+
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+ struct ocmem_region *region = NULL;
+ unsigned long alloc_addr = 0x0;
+
+ struct ocmem_zone *zone = get_zone(owner);
+
+ BUG_ON(!zone);
+
+ /* The shrink should not be called for zero size */
+ BUG_ON(new_sz == 0);
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req)
+ goto invalid_op_error;
+ if (matched_req != req)
+ goto invalid_op_error;
+
+
+ ret = zone->z_ops->free(zone,
+ matched_req->req_start, matched_req->req_sz);
+
+ if (ret < 0) {
+ pr_err("Zone Allocation operation failed\n");
+ goto internal_error;
+ }
+
+ alloc_addr = zone->z_ops->allocate(zone, new_sz);
+
+ if (alloc_addr < 0) {
+ pr_err("Zone Allocation operation failed\n");
+ goto internal_error;
+ }
+
+ /* Detach the region from the interval tree */
+ /* This is to guarantee that the change in size
+ * causes the tree to be rebalanced if required */
+
+ detach_req(matched_region, req);
+ if (req_count(matched_region) == 0) {
+ remove_region(matched_region);
+ region = matched_region;
+ } else {
+ region = create_region();
+ if (!region) {
+ pr_err("ocmem: Unable to create region\n");
+ goto internal_error;
+ }
+ }
+ /* update the request */
+ req->req_start = alloc_addr;
+ req->req_sz = new_sz;
+ req->req_end = alloc_addr + req->req_sz;
+
+ if (req_count(region) == 0) {
+ remove_region(matched_region);
+ destroy_region(matched_region);
+ }
+
+ /* update request state */
+ SET_STATE(req, R_MUST_GROW);
+ SET_STATE(req, R_MUST_MAP);
+ req->op = SCHED_MAP;
+
+ /* attach the request to the region */
+ attach_req(region, req);
+ populate_region(region, req);
+ update_region_prio(region);
+
+ /* update the tree with new region */
+ if (insert_region(region)) {
+ pr_err("ocmem: Failed to insert the region\n");
+ zone->z_ops->free(zone, alloc_addr, new_sz);
+ detach_req(region, req);
+ update_region_prio(region);
+ /* req will be destroyed by the caller */
+ goto region_error;
+ }
+ return OP_COMPLETE;
+
+region_error:
+ destroy_region(region);
+internal_error:
+ pr_err("ocmem: shrink: Failed\n");
+ return OP_FAIL;
+invalid_op_error:
+ pr_err("ocmem: shrink: Failed to find matching region\n");
+ return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
static int __sched_allocate(struct ocmem_req *req, bool can_block,
bool can_wait)
{
@@ -906,12 +1030,6 @@
return req;
}
-int process_xfer(int id, struct ocmem_handle *handle,
- struct ocmem_map_list *list, int direction)
-{
-
- return 0;
-}
unsigned long process_quota(int id)
{
@@ -989,6 +1107,35 @@
return 0;
}
+static int do_shrink(struct ocmem_req *req, unsigned long shrink_size)
+{
+
+ int rc = 0;
+ struct ocmem_buf *buffer = NULL;
+
+ down_write(&req->rw_sem);
+ buffer = req->buffer;
+
+ /* Take the scheduler mutex */
+ mutex_lock(&sched_mutex);
+ rc = __sched_shrink(req, shrink_size);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ goto err_op_fail;
+
+ else if (rc == OP_COMPLETE) {
+ buffer->addr = device_address(req->owner, req->req_start);
+ buffer->len = req->req_sz;
+ }
+
+ up_write(&req->rw_sem);
+ return 0;
+err_op_fail:
+ up_write(&req->rw_sem);
+ return -EINVAL;
+}
+
static void ocmem_sched_wk_func(struct work_struct *work);
DECLARE_DELAYED_WORK(ocmem_sched_thread, ocmem_sched_wk_func);
@@ -1076,6 +1223,250 @@
return 0;
}
+static void ocmem_rdm_worker(struct work_struct *work)
+{
+ int offset = 0;
+ int rc = 0;
+ int event;
+ struct ocmem_rdm_work *work_data = container_of(work,
+ struct ocmem_rdm_work, work);
+ int id = work_data->id;
+ struct ocmem_map_list *list = work_data->list;
+ int direction = work_data->direction;
+ struct ocmem_handle *handle = work_data->handle;
+ struct ocmem_req *req = handle_to_req(handle);
+ struct ocmem_buf *buffer = handle_to_buffer(handle);
+
+ down_write(&req->rw_sem);
+ offset = phys_to_offset(req->req_start);
+ rc = ocmem_rdm_transfer(id, list, offset, direction);
+ if (work_data->direction == TO_OCMEM)
+ event = (rc == 0) ? OCMEM_MAP_DONE : OCMEM_MAP_FAIL;
+ else
+ event = (rc == 0) ? OCMEM_UNMAP_DONE : OCMEM_UNMAP_FAIL;
+
+ up_write(&req->rw_sem);
+ kfree(work_data);
+ dispatch_notification(id, event, buffer);
+}
+
+int queue_transfer(struct ocmem_req *req, struct ocmem_handle *handle,
+ struct ocmem_map_list *list, int direction)
+{
+ struct ocmem_rdm_work *work_data = NULL;
+
+ down_write(&req->rw_sem);
+
+ work_data = kzalloc(sizeof(struct ocmem_rdm_work), GFP_ATOMIC);
+ if (!work_data)
+ BUG();
+
+ work_data->handle = handle;
+ work_data->list = list;
+ work_data->id = req->owner;
+ work_data->direction = direction;
+ INIT_WORK(&work_data->work, ocmem_rdm_worker);
+ up_write(&req->rw_sem);
+ queue_work(ocmem_rdm_wq, &work_data->work);
+ return 0;
+}
+
+int process_xfer_out(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list)
+{
+ struct ocmem_req *req = NULL;
+ int rc = 0;
+
+ req = handle_to_req(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (!is_mapped(req)) {
+ pr_err("Buffer is not already mapped\n");
+ goto transfer_out_error;
+ }
+
+ rc = process_unmap(req, req->req_start, req->req_end);
+ if (rc < 0) {
+ pr_err("Unmapping the buffer failed\n");
+ goto transfer_out_error;
+ }
+
+ rc = queue_transfer(req, handle, list, TO_DDR);
+
+ if (rc < 0) {
+ pr_err("Failed to queue rdm transfer to DDR\n");
+ goto transfer_out_error;
+ }
+
+ return 0;
+
+transfer_out_error:
+ return -EINVAL;
+}
+
+int process_xfer_in(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list)
+{
+ struct ocmem_req *req = NULL;
+ int rc = 0;
+
+ req = handle_to_req(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (is_mapped(req)) {
+ pr_err("Buffer is already mapped\n");
+ goto transfer_in_error;
+ }
+
+ rc = process_map(req, req->req_start, req->req_end);
+ if (rc < 0) {
+ pr_err("Mapping the buffer failed\n");
+ goto transfer_in_error;
+ }
+
+ rc = queue_transfer(req, handle, list, TO_OCMEM);
+
+ if (rc < 0) {
+ pr_err("Failed to queue rdm transfer to OCMEM\n");
+ goto transfer_in_error;
+ }
+
+ return 0;
+transfer_in_error:
+ return -EINVAL;
+}
+
+int process_shrink(int id, struct ocmem_handle *handle, unsigned long size)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf *buffer = NULL;
+ struct ocmem_eviction_data *edata = NULL;
+ int rc = 0;
+
+ if (is_blocked(id)) {
+ pr_err("Client %d cannot request free\n", id);
+ return -EINVAL;
+ }
+
+ req = handle_to_req(handle);
+ buffer = handle_to_buffer(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (req->req_start != core_address(id, buffer->addr)) {
+ pr_err("Invalid buffer handle passed for shrink\n");
+ return -EINVAL;
+ }
+
+ edata = req->edata;
+
+ if (is_tcm(req->owner))
+ do_unmap(req);
+
+ if (size == 0) {
+ pr_info("req %p being shrunk to zero\n", req);
+ rc = do_free(req);
+ if (rc < 0)
+ return -EINVAL;
+ } else {
+ rc = do_shrink(req, size);
+ if (rc < 0)
+ return -EINVAL;
+ }
+
+ edata->pending--;
+ if (edata->pending == 0) {
+ pr_debug("All regions evicted");
+ complete(&edata->completion);
+ }
+
+ return 0;
+}
+
+int process_xfer(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list, int direction)
+{
+ int rc = 0;
+
+ if (is_tcm(id)) {
+ WARN(1, "Mapping operation is invalid for client\n");
+ return -EINVAL;
+ }
+
+ if (direction == TO_DDR)
+ rc = process_xfer_out(id, handle, list);
+ else if (direction == TO_OCMEM)
+ rc = process_xfer_in(id, handle, list);
+ return rc;
+}
+
+int ocmem_eviction_thread(struct work_struct *work)
+{
+ return 0;
+}
+
+int process_evict(int id)
+{
+ struct ocmem_eviction_data *edata = NULL;
+ int prio = ocmem_client_table[id].priority;
+ struct rb_node *rb_node = NULL;
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf buffer;
+ int j = 0;
+
+ edata = kzalloc(sizeof(struct ocmem_eviction_data), GFP_ATOMIC);
+
+ INIT_LIST_HEAD(&edata->victim_list);
+ INIT_LIST_HEAD(&edata->req_list);
+ edata->prio = prio;
+ edata->pending = 0;
+ edata->passive = 1;
+ evictions[id] = edata;
+
+ mutex_lock(&sched_mutex);
+
+ for (rb_node = rb_first(&sched_tree); rb_node;
+ rb_node = rb_next(rb_node)) {
+ struct ocmem_region *tmp_region = NULL;
+ tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+ if (tmp_region->max_prio < prio) {
+ for (j = id - 1; j > NO_PRIO; j--) {
+ req = find_req_match(j, tmp_region);
+ if (req) {
+ pr_info("adding %p to eviction list\n",
+ tmp_region);
+ list_add_tail(
+ &tmp_region->eviction_list,
+ &edata->victim_list);
+ list_add_tail(
+ &req->eviction_list,
+ &edata->req_list);
+ edata->pending++;
+ req->edata = edata;
+ buffer.addr = req->req_start;
+ buffer.len = 0x0;
+ dispatch_notification(req->owner,
+ OCMEM_ALLOC_SHRINK, &buffer);
+ }
+ }
+ } else {
+ pr_info("skipping %p from eviction\n", tmp_region);
+ }
+ }
+ mutex_unlock(&sched_mutex);
+ pr_debug("Waiting for all regions to be shrunk\n");
+ if (edata->pending > 0) {
+ init_completion(&edata->completion);
+ wait_for_completion(&edata->completion);
+ }
+ return 0;
+}
+
static int do_allocate(struct ocmem_req *req, bool can_block, bool can_wait)
{
int rc = 0;
@@ -1113,6 +1504,31 @@
return -EINVAL;
}
+int process_restore(int id)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_req *next = NULL;
+ struct ocmem_eviction_data *edata = evictions[id];
+
+ if (!edata)
+ return 0;
+
+ list_for_each_entry_safe(req, next, &edata->req_list, eviction_list)
+ {
+ if (req) {
+ pr_debug("ocmem: Fetched evicted request %p\n",
+ req);
+ list_del(&req->sched_list);
+ req->op = SCHED_ALLOCATE;
+ sched_enqueue(req);
+ }
+ }
+ kfree(edata);
+ evictions[id] = NULL;
+ pr_debug("Restore all evicted regions\n");
+ ocmem_schedule_pending();
+ return 0;
+}
int process_allocate(int id, struct ocmem_handle *handle,
unsigned long min, unsigned long max,
@@ -1185,6 +1601,7 @@
rc = do_allocate(req, true, false);
+
if (rc < 0)
goto do_allocate_error;
@@ -1251,5 +1668,13 @@
for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
INIT_LIST_HEAD(&sched_queue[i]);
+ mutex_init(&rdm_mutex);
+ INIT_LIST_HEAD(&rdm_queue);
+ ocmem_rdm_wq = alloc_workqueue("ocmem_rdm_wq", 0, 0);
+ if (!ocmem_rdm_wq)
+ return -ENOMEM;
+ ocmem_eviction_wq = alloc_workqueue("ocmem_eviction_wq", 0, 0);
+ if (!ocmem_eviction_wq)
+ return -ENOMEM;
return 0;
}
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 3f6eb95..540ffbb 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -565,18 +565,6 @@
static void msm_pil_debugfs_remove(struct pil_device *pil) { }
#endif
-static int __msm_pil_shutdown(struct device *dev, void *data)
-{
- pil_shutdown(to_pil_device(dev));
- return 0;
-}
-
-static int msm_pil_shutdown_at_boot(void)
-{
- return bus_for_each_dev(&pil_bus_type, NULL, NULL, __msm_pil_shutdown);
-}
-late_initcall(msm_pil_shutdown_at_boot);
-
static void pil_device_release(struct device *dev)
{
struct pil_device *pil = to_pil_device(dev);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 6e86baa..e203667 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,7 +24,6 @@
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/tick.h>
-#include <linux/delay.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/system.h>
@@ -591,7 +590,7 @@
static int64_t msm_pm_timer_enter_suspend(int64_t *period)
{
- int time = 0;
+ int64_t time = 0;
if (msm_pm_use_qtimer)
return sched_clock();
@@ -799,28 +798,6 @@
return 0;
}
-static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
-
-static DEFINE_PER_CPU_SHARED_ALIGNED(enum msm_pm_sleep_mode,
- msm_pm_last_slp_mode);
-
-bool msm_pm_verify_cpu_pc(unsigned int cpu)
-{
- enum msm_pm_sleep_mode mode = per_cpu(msm_pm_last_slp_mode, cpu);
-
- if (msm_pm_slp_sts) {
- int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
- + cpu * msm_pm_slp_sts->cpu_offset);
-
- if ((acc_sts & msm_pm_slp_sts->mask) &&
- ((mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) ||
- (mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)))
- return true;
- }
-
- return false;
-}
-
void msm_pm_cpu_enter_lowpower(unsigned int cpu)
{
int i;
@@ -836,54 +813,14 @@
if (MSM_PM_DEBUG_HOTPLUG & msm_pm_debug_mask)
pr_notice("CPU%u: %s: shutting down cpu\n", cpu, __func__);
- if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_POWER_COLLAPSE;
+ if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE])
msm_pm_power_collapse(false);
- } else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
+ else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE])
msm_pm_power_collapse_standalone(false);
- } else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_RETENTION;
+ else if (allow[MSM_PM_SLEEP_MODE_RETENTION])
msm_pm_retention();
- } else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT;
+ else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT])
msm_pm_swfi();
- } else
- per_cpu(msm_pm_last_slp_mode, cpu) = MSM_PM_SLEEP_MODE_NR;
-}
-
-int msm_pm_wait_cpu_shutdown(unsigned int cpu)
-{
-
- int timeout = 10;
-
- if (!msm_pm_slp_sts)
- return 0;
-
- while (timeout--) {
-
- /*
- * Check for the SPM of the core being hotplugged to set
- * its sleep state.The SPM sleep state indicates that the
- * core has been power collapsed.
- */
-
- int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
- + cpu * msm_pm_slp_sts->cpu_offset);
- mb();
-
- if (acc_sts & msm_pm_slp_sts->mask)
- return 0;
-
- usleep(100);
- }
- pr_warn("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
- __func__, cpu);
- return -EBUSY;
}
static int msm_pm_enter(suspend_state_t state)
@@ -980,12 +917,6 @@
/******************************************************************************
* Initialization routine
*****************************************************************************/
-void __init msm_pm_init_sleep_status_data(
- struct msm_pm_sleep_status_data *data)
-{
- msm_pm_slp_sts = data;
-}
-
void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
{
if (ops)
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 70d54da..c722ff6 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -70,12 +70,6 @@
extern struct msm_pm_platform_data msm_pm_sleep_modes[];
-struct msm_pm_sleep_status_data {
- void *base_addr;
- uint32_t cpu_offset;
- uint32_t mask;
-};
-
struct msm_pm_sleep_ops {
void *(*lowest_limits)(bool from_idle,
enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
@@ -93,19 +87,11 @@
int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
void msm_pm_cpu_enter_lowpower(unsigned int cpu);
-void __init msm_pm_init_sleep_status_data(
- struct msm_pm_sleep_status_data *sleep_data);
-
-
#ifdef CONFIG_MSM_PM8X60
void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
-int msm_pm_wait_cpu_shutdown(unsigned int cpu);
-bool msm_pm_verify_cpu_pc(unsigned int cpu);
void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops);
#else
static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
-static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
-static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
static inline void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops) {}
#endif
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index ae7a3cd..7a8e4c3 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1280,7 +1280,7 @@
static int64_t msm_pm_timer_enter_suspend(int64_t *period)
{
- int time = 0;
+ int64_t time = 0;
time = msm_timer_get_sclk_time(period);
if (!time)
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index 03dd295..34e5b81 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -459,7 +459,7 @@
if (datacb_data->pkt.fw_data.fw_ptr_status &&
be32_to_cpu(datacb_data->pkt.fw_data.rec_length) &&
be32_to_cpu(datacb_data->pkt.fw_data.rec_length)
- <= MAX_FRAME_SIZE) {
+ <= MAX_REC_BUF_SIZE) {
MM_DBG("Copy FW link:rec_buf_size \
= 0x%08x, rec_length=0x%08x\n",
@@ -484,7 +484,7 @@
} else if (datacb_data->pkt.rw_data.rw_ptr_status &&
be32_to_cpu(datacb_data->pkt.rw_data.rec_length) &&
be32_to_cpu(datacb_data->pkt.rw_data.rec_length)
- <= MAX_FRAME_SIZE) {
+ <= MAX_REC_BUF_SIZE) {
MM_DBG("Copy RW link:rec_buf_size \
=0x%08x, rec_length=0x%08x\n",
@@ -509,12 +509,12 @@
} else {
MM_ERR("FW: ptr_status %d, rec_length=0x%08x,"
"RW: ptr_status %d, rec_length=0x%08x\n",
- datacb_data->pkt.rw_data.fw_ptr_status, \
+ datacb_data->pkt.fw_data.fw_ptr_status, \
be32_to_cpu( \
datacb_data->pkt.fw_data.rec_length), \
- datacb_data->pkt.rw_data.fw_ptr_status, \
+ datacb_data->pkt.rw_data.rw_ptr_status, \
be32_to_cpu( \
- datacb_data->pkt.fw_data.rec_length));
+ datacb_data->pkt.rw_data.rec_length));
}
if (rec_status != RPC_VOC_REC_STAT_DONE) {
/* Not end of record */
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 2403c02..a0bfb27 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -372,10 +372,14 @@
if (q6.state == APR_Q6_NOIMG) {
q6.pil = pil_get("q6");
if (IS_ERR(q6.pil)) {
- rc = PTR_ERR(q6.pil);
- pr_err("APR: Unable to load q6 image, error:%d\n", rc);
- mutex_unlock(&q6.lock);
- return svc;
+ q6.pil = pil_get("adsp");
+ if (IS_ERR(q6.pil)) {
+ rc = PTR_ERR(q6.pil);
+ pr_err("APR: Unable to load q6 image, error:%d\n",
+ rc);
+ mutex_unlock(&q6.lock);
+ return svc;
+ }
}
q6.state = APR_Q6_LOADED;
}
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 5d7cd76..a7adc47 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -248,6 +248,17 @@
return (void *)rd_dev;
}
+void destroy_ramdump_device(void *dev)
+{
+ struct ramdump_device *rd_dev = dev;
+
+ if (IS_ERR_OR_NULL(rd_dev))
+ return;
+
+ misc_deregister(&rd_dev->device);
+ kfree(rd_dev);
+}
+
int do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments)
{
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/ramdump.h
index 0b60a44..9006010 100644
--- a/arch/arm/mach-msm/ramdump.h
+++ b/arch/arm/mach-msm/ramdump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
};
void *create_ramdump_device(const char *dev_name);
+void destroy_ramdump_device(void *dev);
int do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments);
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index fdff231..a8af9e7 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -68,6 +68,7 @@
RPM_REGULATOR_PARAM_QUIET_MODE,
RPM_REGULATOR_PARAM_FREQ_REASON,
RPM_REGULATOR_PARAM_CORNER,
+ RPM_REGULATOR_PARAM_BYPASS,
RPM_REGULATOR_PARAM_MAX,
};
@@ -111,7 +112,8 @@
PARAM(HEAD_ROOM, 1, 0, 0, 1, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
PARAM(QUIET_MODE, 0, 1, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
PARAM(FREQ_REASON, 0, 1, 0, 1, "resn", 0, 8, "qcom,init-freq-reason"),
- PARAM(CORNER, 0, 1, 0, 0, "corn", 0, 5, "qcom,init-voltage-corner"),
+ PARAM(CORNER, 0, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
+ PARAM(BYPASS, 1, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
};
struct rpm_vreg_request {
@@ -440,6 +442,7 @@
RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
+ RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
}
static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -682,7 +685,7 @@
* regulator_set_voltage function to the actual corner values
* sent to the RPM.
*/
- corner = min_uV - RPM_REGULATOR_CORNER_RETENTION;
+ corner = min_uV - RPM_REGULATOR_CORNER_NONE;
if (corner < params[RPM_REGULATOR_PARAM_CORNER].min
|| corner > params[RPM_REGULATOR_PARAM_CORNER].max) {
@@ -716,7 +719,7 @@
struct rpm_regulator *reg = rdev_get_drvdata(rdev);
return reg->req.param[RPM_REGULATOR_PARAM_CORNER]
- + RPM_REGULATOR_CORNER_RETENTION;
+ + RPM_REGULATOR_CORNER_NONE;
}
static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index b8bb27b..697d504 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -24,6 +24,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/slab.h>
@@ -36,6 +37,19 @@
#include <mach/rpm-smd.h>
#include "rpm-notifier.h"
+/* Debug Definitions */
+
+enum {
+ MSM_RPM_LOG_REQUEST_PRETTY = BIT(0),
+ MSM_RPM_LOG_REQUEST_RAW = BIT(1),
+ MSM_RPM_LOG_REQUEST_SHOW_MSG_ID = BIT(2),
+};
+
+static int msm_rpm_debug_mask;
+module_param_named(
+ debug_mask, msm_rpm_debug_mask, int, S_IRUGO | S_IWUSR
+);
+
struct msm_rpm_driver_data {
const char *ch_name;
uint32_t ch_type;
@@ -492,6 +506,140 @@
}
}
+#define DEBUG_PRINT_BUFFER_SIZE 512
+
+static void msm_rpm_log_request(struct msm_rpm_request *cdata)
+{
+ char buf[DEBUG_PRINT_BUFFER_SIZE];
+ size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
+ char name[5];
+ u32 value;
+ int i, j, prev_valid;
+ int valid_count = 0;
+ int pos = 0;
+
+ name[4] = 0;
+
+ for (i = 0; i < cdata->write_idx; i++)
+ if (cdata->kvp[i].valid)
+ valid_count++;
+
+ pos += scnprintf(buf + pos, buflen - pos, "%sRPM req: ", KERN_INFO);
+ if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_SHOW_MSG_ID)
+ pos += scnprintf(buf + pos, buflen - pos, "msg_id=%u, ",
+ cdata->msg_hdr.msg_id);
+ pos += scnprintf(buf + pos, buflen - pos, "s=%s",
+ (cdata->msg_hdr.set == MSM_RPM_CTX_ACTIVE_SET ? "act" : "slp"));
+
+ if ((msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY)
+ && (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_RAW)) {
+ /* Both pretty and raw formatting */
+ memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", rsc_type=0x%08X (%s), rsc_id=%u; ",
+ cdata->msg_hdr.resource_type, name,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ memcpy(name, &cdata->kvp[i].key, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos,
+ "[key=0x%08X (%s), value=%s",
+ cdata->kvp[i].key, name,
+ (cdata->kvp[i].nbytes ? "0x" : "null"));
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j++)
+ pos += scnprintf(buf + pos, buflen - pos,
+ "%02X ",
+ cdata->kvp[i].value[j]);
+
+ if (cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos, buflen - pos, "(");
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j += 4) {
+ value = 0;
+ memcpy(&value, &cdata->kvp[i].value[j],
+ min(sizeof(uint32_t),
+ cdata->kvp[i].nbytes - j));
+ pos += scnprintf(buf + pos, buflen - pos, "%u",
+ value);
+ if (j + 4 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ if (cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos, buflen - pos, ")");
+ pos += scnprintf(buf + pos, buflen - pos, "]");
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ } else if (msm_rpm_debug_mask & MSM_RPM_LOG_REQUEST_PRETTY) {
+ /* Pretty formatting only */
+ memcpy(name, &cdata->msg_hdr.resource_type, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos, " %s %u; ", name,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ memcpy(name, &cdata->kvp[i].key, sizeof(uint32_t));
+ pos += scnprintf(buf + pos, buflen - pos, "%s=%s",
+ name, (cdata->kvp[i].nbytes ? "" : "null"));
+
+ for (j = 0; j < cdata->kvp[i].nbytes; j += 4) {
+ value = 0;
+ memcpy(&value, &cdata->kvp[i].value[j],
+ min(sizeof(uint32_t),
+ cdata->kvp[i].nbytes - j));
+ pos += scnprintf(buf + pos, buflen - pos, "%u",
+ value);
+
+ if (j + 4 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ } else {
+ /* Raw formatting only */
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", rsc_type=0x%08X, rsc_id=%u; ",
+ cdata->msg_hdr.resource_type,
+ cdata->msg_hdr.resource_id);
+
+ for (i = 0, prev_valid = 0; i < cdata->write_idx; i++) {
+ if (!cdata->kvp[i].valid)
+ continue;
+
+ pos += scnprintf(buf + pos, buflen - pos,
+ "[key=0x%08X, value=%s",
+ cdata->kvp[i].key,
+ (cdata->kvp[i].nbytes ? "0x" : "null"));
+ for (j = 0; j < cdata->kvp[i].nbytes; j++) {
+ pos += scnprintf(buf + pos, buflen - pos,
+ "%02X",
+ cdata->kvp[i].value[j]);
+ if (j + 1 < cdata->kvp[i].nbytes)
+ pos += scnprintf(buf + pos,
+ buflen - pos, " ");
+ }
+ pos += scnprintf(buf + pos, buflen - pos, "]");
+ if (prev_valid + 1 < valid_count)
+ pos += scnprintf(buf + pos, buflen - pos, ", ");
+ prev_valid++;
+ }
+ }
+
+ pos += scnprintf(buf + pos, buflen - pos, "\n");
+ printk(buf);
+}
+
static int msm_rpm_send_data(struct msm_rpm_request *cdata,
int msg_type, bool noirq)
{
@@ -546,6 +694,10 @@
tmpbuff += cdata->kvp[i].nbytes;
}
+ if (msm_rpm_debug_mask
+ & (MSM_RPM_LOG_REQUEST_PRETTY | MSM_RPM_LOG_REQUEST_RAW))
+ msm_rpm_log_request(cdata);
+
if (standalone) {
for (i = 0; (i < cdata->write_idx); i++)
cdata->kvp[i].valid = false;
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index 3ed55da..4835cef 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -115,13 +115,11 @@
continue;
}
/*
- * Ensure that the reported buffer size is within limits of
- * known maximum size and that all indices are 4 byte aligned.
- * These conditions are required to interact with a ULog buffer
+ * Ensure that all indices are 4 byte aligned.
+ * This conditions is required to interact with a ULog buffer
* properly.
*/
- if (tail_idx - head_idx > pdata->log_len ||
- !IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
+ if (!IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
break;
msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 54512ab..948dbbb 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -559,7 +559,11 @@
* on DEM-based targets. Grabbing a wakelock in this case will
* abort the power-down sequencing.
*/
- smsm_cb_snapshot(0);
+ if (smsm_info.intr_mask &&
+ (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS))
+ & notify_mask)) {
+ smsm_cb_snapshot(0);
+ }
}
void smd_diag(void)
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index fdbc387..b9fe341 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -725,6 +725,8 @@
SMD_APPS_MODEM,
};
#endif
+module_param_named(loopback_edge, smd_ch_edge[LOOPBACK_INX],
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
static int smd_pkt_dummy_probe(struct platform_device *pdev)
{
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 281e7b8..817c2dc 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -798,6 +798,11 @@
};
}
+const int cpu_is_krait(void)
+{
+ return ((read_cpuid_id() & 0xFF00FC00) == 0x51000400);
+}
+
const int cpu_is_krait_v1(void)
{
switch (read_cpuid_id()) {
@@ -810,3 +815,22 @@
return 0;
};
}
+
+const int cpu_is_krait_v2(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x511F04D0:
+ case 0x511F04D1:
+ case 0x511F04D2:
+ case 0x511F04D3:
+ case 0x511F04D4:
+
+ case 0x510F06F0:
+ case 0x510F06F1:
+ case 0x510F06F2:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 42c1feb..6d73e1d 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -17,7 +17,6 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/io.h>
@@ -25,11 +24,13 @@
#include <linux/time.h>
#include <linux/wakelock.h>
#include <linux/suspend.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <asm/current.h>
#include <mach/peripheral-loader.h>
-#include <mach/scm.h>
#include <mach/socinfo.h>
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
@@ -46,30 +47,40 @@
struct mutex shutdown_lock;
struct mutex powerup_lock;
- struct subsys_data *subsys_ptrs[];
-};
-
-struct restart_wq_data {
- struct subsys_data *subsys;
- struct wake_lock ssr_wake_lock;
- char wlname[64];
- int use_restart_order;
- struct work_struct work;
+ struct subsys_device *subsys_ptrs[];
};
struct restart_log {
struct timeval time;
- struct subsys_data *subsys;
+ struct subsys_device *dev;
struct list_head list;
};
-static int restart_level;
+struct subsys_device {
+ struct subsys_desc *desc;
+ struct list_head list;
+ struct wake_lock wake_lock;
+ char wlname[64];
+ struct work_struct work;
+ spinlock_t restart_lock;
+ bool restarting;
+
+ void *notify;
+
+ struct mutex shutdown_lock;
+ struct mutex powerup_lock;
+
+ void *restart_order;
+};
+
static int enable_ramdumps = 1;
+module_param(enable_ramdumps, int, S_IRUGO | S_IWUSR);
+
struct workqueue_struct *ssr_wq;
static LIST_HEAD(restart_log_list);
static LIST_HEAD(subsystem_list);
-static DEFINE_SPINLOCK(subsystem_list_lock);
+static DEFINE_MUTEX(subsystem_list_lock);
static DEFINE_MUTEX(soc_order_reg_lock);
static DEFINE_MUTEX(restart_log_mutex);
@@ -126,10 +137,7 @@
static struct subsys_soc_restart_order **restart_orders;
static int n_restart_orders;
-module_param(enable_ramdumps, int, S_IRUGO | S_IWUSR);
-
-static struct subsys_soc_restart_order *_update_restart_order(
- struct subsys_data *subsys);
+static int restart_level = RESET_SUBSYS_INDEPENDENT;
int get_restart_level()
{
@@ -152,18 +160,14 @@
return ret;
switch (restart_level) {
-
case RESET_SOC:
case RESET_SUBSYS_COUPLED:
case RESET_SUBSYS_INDEPENDENT:
pr_info("Phase %d behavior activated.\n", restart_level);
- break;
-
+ break;
default:
restart_level = old_val;
return -EINVAL;
- break;
-
}
return 0;
}
@@ -171,62 +175,29 @@
module_param_call(restart_level, restart_level_set, param_get_int,
&restart_level, 0644);
-static struct subsys_data *_find_subsystem(const char *subsys_name)
-{
- struct subsys_data *subsys;
- unsigned long flags;
-
- spin_lock_irqsave(&subsystem_list_lock, flags);
- list_for_each_entry(subsys, &subsystem_list, list)
- if (!strncmp(subsys->name, subsys_name,
- SUBSYS_NAME_MAX_LENGTH)) {
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
- return subsys;
- }
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
-
- return NULL;
-}
-
-static struct subsys_soc_restart_order *_update_restart_order(
- struct subsys_data *subsys)
+static struct subsys_soc_restart_order *
+update_restart_order(struct subsys_device *dev)
{
int i, j;
-
- if (!subsys)
- return NULL;
-
- if (!subsys->name)
- return NULL;
+ struct subsys_soc_restart_order *order;
+ const char *name = dev->desc->name;
+ int len = SUBSYS_NAME_MAX_LENGTH;
mutex_lock(&soc_order_reg_lock);
for (j = 0; j < n_restart_orders; j++) {
- for (i = 0; i < restart_orders[j]->count; i++)
- if (!strncmp(restart_orders[j]->subsystem_list[i],
- subsys->name, SUBSYS_NAME_MAX_LENGTH)) {
-
- restart_orders[j]->subsys_ptrs[i] =
- subsys;
- mutex_unlock(&soc_order_reg_lock);
- return restart_orders[j];
+ order = restart_orders[j];
+ for (i = 0; i < order->count; i++) {
+ if (!strncmp(order->subsystem_list[i], name, len)) {
+ order->subsys_ptrs[i] = dev;
+ goto found;
}
+ }
}
-
+ order = NULL;
+found:
mutex_unlock(&soc_order_reg_lock);
- return NULL;
-}
-
-static void _send_notification_to_order(struct subsys_data
- **restart_list, int count,
- enum subsys_notif_type notif_type)
-{
- int i;
-
- for (i = 0; i < count; i++)
- if (restart_list[i])
- subsys_notif_queue_notification(
- restart_list[i]->notif_handle, notif_type);
+ return order;
}
static int max_restarts;
@@ -235,7 +206,7 @@
static long max_history_time = 3600;
module_param(max_history_time, long, 0644);
-static void do_epoch_check(struct subsys_data *subsys)
+static void do_epoch_check(struct subsys_device *dev)
{
int n = 0;
struct timeval *time_first = NULL, *curr_time;
@@ -258,7 +229,7 @@
r_log = kmalloc(sizeof(struct restart_log), GFP_KERNEL);
if (!r_log)
goto out;
- r_log->subsys = subsys;
+ r_log->dev = dev;
do_gettimeofday(&r_log->time);
curr_time = &r_log->time;
INIT_LIST_HEAD(&r_log->list);
@@ -300,45 +271,111 @@
mutex_unlock(&restart_log_mutex);
}
-static void subsystem_restart_wq_func(struct work_struct *work)
+static void for_each_subsys_device(struct subsys_device **list, unsigned count,
+ void *data, void (*fn)(struct subsys_device *, void *))
{
- struct restart_wq_data *r_work = container_of(work,
- struct restart_wq_data, work);
- struct subsys_data **restart_list;
- struct subsys_data *subsys = r_work->subsys;
- struct subsys_soc_restart_order *soc_restart_order = NULL;
+ while (count--) {
+ struct subsys_device *dev = *list++;
+ if (!dev)
+ continue;
+ fn(dev, data);
+ }
+}
- struct mutex *powerup_lock;
- struct mutex *shutdown_lock;
+static void __send_notification_to_order(struct subsys_device *dev, void *data)
+{
+ enum subsys_notif_type type = (enum subsys_notif_type)data;
- int i;
- int restart_list_count = 0;
+ subsys_notif_queue_notification(dev->notify, type);
+}
+static void send_notification_to_order(struct subsys_device **l, unsigned n,
+ enum subsys_notif_type t)
+{
+ for_each_subsys_device(l, n, (void *)t, __send_notification_to_order);
+}
+
+static void subsystem_shutdown(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
#if defined(CONFIG_LGE_CRASH_HANDLER)
int ssr_magic_number = get_ssr_magic_number();
#endif
- if (r_work->use_restart_order)
- soc_restart_order = subsys->restart_order;
- /* It's OK to not take the registration lock at this point.
+ pr_info("[%p]: Shutting down %s\n", current, name);
+ if (dev->desc->shutdown(dev->desc) < 0) {
+#if defined(CONFIG_LGE_CRASH_HANDLER)
+ msm_set_restart_mode(ssr_magic_number | SUB_THD_F_SD);
+#endif
+ WARN(1, "subsys-restart: [%p]: Failed to shutdown %s!",
+ current, name);
+ }
+}
+
+static void subsystem_ramdump(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
+
+ if (dev->desc->ramdump)
+ if (dev->desc->ramdump(enable_ramdumps, dev->desc) < 0)
+ pr_warn("%s[%p]: Ramdump failed.\n", name, current);
+}
+
+static void subsystem_powerup(struct subsys_device *dev, void *data)
+{
+ const char *name = dev->desc->name;
+#if defined(CONFIG_LGE_CRASH_HANDLER)
+ int ssr_magic_number = get_ssr_magic_number();
+#endif
+
+ pr_info("[%p]: Powering up %s\n", current, name);
+ if (dev->desc->powerup(dev->desc) < 0) {
+#if defined(CONFIG_LGE_CRASH_HANDLER)
+ msm_set_restart_mode(ssr_magic_number | SUB_THD_F_PWR);
+#endif
+ WARN(1, "[%p]: Failed to powerup %s!", current, name);
+ }
+}
+
+static void subsystem_restart_wq_func(struct work_struct *work)
+{
+ struct subsys_device *dev = container_of(work,
+ struct subsys_device, work);
+ struct subsys_device **list;
+ struct subsys_desc *desc = dev->desc;
+ struct subsys_soc_restart_order *soc_restart_order = NULL;
+ struct mutex *powerup_lock;
+ struct mutex *shutdown_lock;
+ unsigned count;
+ unsigned long flags;
+#if defined(CONFIG_LGE_CRASH_HANDLER)
+ int ssr_magic_number = get_ssr_magic_number();
+#endif
+
+ if (restart_level != RESET_SUBSYS_INDEPENDENT)
+ soc_restart_order = dev->restart_order;
+
+ /*
+ * It's OK to not take the registration lock at this point.
* This is because the subsystem list inside the relevant
* restart order is not being traversed.
*/
if (!soc_restart_order) {
- restart_list = subsys->single_restart_list;
- restart_list_count = 1;
- powerup_lock = &subsys->powerup_lock;
- shutdown_lock = &subsys->shutdown_lock;
+ list = &dev;
+ count = 1;
+ powerup_lock = &dev->powerup_lock;
+ shutdown_lock = &dev->shutdown_lock;
} else {
- restart_list = soc_restart_order->subsys_ptrs;
- restart_list_count = soc_restart_order->count;
+ list = soc_restart_order->subsys_ptrs;
+ count = soc_restart_order->count;
powerup_lock = &soc_restart_order->powerup_lock;
shutdown_lock = &soc_restart_order->shutdown_lock;
}
pr_debug("[%p]: Attempting to get shutdown lock!\n", current);
- /* Try to acquire shutdown_lock. If this fails, these subsystems are
+ /*
+ * Try to acquire shutdown_lock. If this fails, these subsystems are
* already being restarted - return.
*/
if (!mutex_trylock(shutdown_lock))
@@ -346,7 +383,8 @@
pr_debug("[%p]: Attempting to get powerup lock!\n", current);
- /* Now that we've acquired the shutdown lock, either we're the first to
+ /*
+ * Now that we've acquired the shutdown lock, either we're the first to
* restart these subsystems or some other thread is doing the powerup
* sequence for these subsystems. In the latter case, panic and bail
* out, since a subsystem died in its powerup sequence.
@@ -359,42 +397,23 @@
__func__, current);
}
- do_epoch_check(subsys);
+ do_epoch_check(dev);
- /* Now it is necessary to take the registration lock. This is because
- * the subsystem list in the SoC restart order will be traversed
- * and it shouldn't be changed until _this_ restart sequence completes.
+ /*
+ * It's necessary to take the registration lock because the subsystem
+ * list in the SoC restart order will be traversed and it shouldn't be
+ * changed until _this_ restart sequence completes.
*/
mutex_lock(&soc_order_reg_lock);
pr_debug("[%p]: Starting restart sequence for %s\n", current,
- r_work->subsys->name);
+ desc->name);
+ send_notification_to_order(list, count, SUBSYS_BEFORE_SHUTDOWN);
+ for_each_subsys_device(list, count, NULL, subsystem_shutdown);
+ send_notification_to_order(list, count, SUBSYS_AFTER_SHUTDOWN);
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_BEFORE_SHUTDOWN);
-
- for (i = 0; i < restart_list_count; i++) {
-
- if (!restart_list[i])
- continue;
-
- pr_info("[%p]: Shutting down %s\n", current,
- restart_list[i]->name);
-
- if (restart_list[i]->shutdown(subsys) < 0) {
-#if defined(CONFIG_LGE_CRASH_HANDLER)
- msm_set_restart_mode(ssr_magic_number | SUB_THD_F_SD);
-#endif
- WARN(1, "subsys-restart: %s[%p]: Failed to shutdown %s!",
- __func__, current, restart_list[i]->name);
- }
- }
-
- _send_notification_to_order(restart_list, restart_list_count,
- SUBSYS_AFTER_SHUTDOWN);
-
- /* Now that we've finished shutting down these subsystems, release the
+ /*
+ * Now that we've finished shutting down these subsystems, release the
* shutdown lock. If a subsystem restart request comes in for a
* subsystem in _this_ restart order after the unlock below, and
* before the powerup lock is released, panic and bail out.
@@ -402,44 +421,14 @@
mutex_unlock(shutdown_lock);
/* Collect ram dumps for all subsystems in order here */
- for (i = 0; i < restart_list_count; i++) {
- if (!restart_list[i])
- continue;
+ for_each_subsys_device(list, count, NULL, subsystem_ramdump);
- if (restart_list[i]->ramdump)
- if (restart_list[i]->ramdump(enable_ramdumps,
- subsys) < 0)
- pr_warn("%s[%p]: Ramdump failed.\n",
- restart_list[i]->name, current);
- }
-
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_BEFORE_POWERUP);
-
- for (i = restart_list_count - 1; i >= 0; i--) {
-
- if (!restart_list[i])
- continue;
-
- pr_info("[%p]: Powering up %s\n", current,
- restart_list[i]->name);
-
- if (restart_list[i]->powerup(subsys) < 0) {
-#if defined(CONFIG_LGE_CRASH_HANDLER)
- msm_set_restart_mode(ssr_magic_number | SUB_THD_F_PWR);
-#endif
- WARN(1, "%s[%p]: Failed to powerup %s!", __func__,
- current, restart_list[i]->name);
- }
- }
-
- _send_notification_to_order(restart_list,
- restart_list_count,
- SUBSYS_AFTER_POWERUP);
+ send_notification_to_order(list, count, SUBSYS_BEFORE_POWERUP);
+ for_each_subsys_device(list, count, NULL, subsystem_powerup);
+ send_notification_to_order(list, count, SUBSYS_AFTER_POWERUP);
pr_info("[%p]: Restart sequence for %s completed.\n",
- current, r_work->subsys->name);
+ current, desc->name);
mutex_unlock(powerup_lock);
@@ -448,79 +437,41 @@
pr_debug("[%p]: Released powerup lock!\n", current);
out:
- wake_unlock(&r_work->ssr_wake_lock);
- wake_lock_destroy(&r_work->ssr_wake_lock);
- kfree(r_work);
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ wake_unlock(&dev->wake_lock);
+ dev->restarting = false;
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
}
-static void __subsystem_restart(struct subsys_data *subsys)
+static void __subsystem_restart_dev(struct subsys_device *dev)
{
- struct restart_wq_data *data = NULL;
- int rc;
-#if defined(CONFIG_LGE_CRASH_HANDLER)
- int ssr_magic_number = get_ssr_magic_number();
-#endif
+ struct subsys_desc *desc = dev->desc;
+ unsigned long flags;
- pr_debug("Restarting %s [level=%d]!\n", subsys->name,
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ if (!dev->restarting) {
+ pr_debug("Restarting %s [level=%d]!\n", desc->name,
restart_level);
- data = kzalloc(sizeof(struct restart_wq_data), GFP_ATOMIC);
- if (!data) {
-#if defined(CONFIG_LGE_CRASH_HANDLER)
- msm_set_restart_mode(ssr_magic_number | SUB_UNAB_THD);
-#endif
- pr_err("%s: Unable to allocate memory to restart %s.",
- __func__, subsys->name);
- return;
+ dev->restarting = true;
+ wake_lock(&dev->wake_lock);
+ queue_work(ssr_wq, &dev->work);
}
-
- data->subsys = subsys;
-
- if (restart_level != RESET_SUBSYS_INDEPENDENT)
- data->use_restart_order = 1;
-
- snprintf(data->wlname, sizeof(data->wlname), "ssr(%s)", subsys->name);
- wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND, data->wlname);
- wake_lock(&data->ssr_wake_lock);
-
- INIT_WORK(&data->work, subsystem_restart_wq_func);
- rc = queue_work(ssr_wq, &data->work);
- if (rc < 0) {
-#if defined(CONFIG_LGE_CRASH_HANDLER)
- msm_set_restart_mode(ssr_magic_number | SUB_UNAB_THD);
-#endif
- pr_err("%s: Unable to schedule work to restart %s (%d).",
- __func__, subsys->name, rc);
- }
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
}
-int subsystem_restart(const char *subsys_name)
+int subsystem_restart_dev(struct subsys_device *dev)
{
- struct subsys_data *subsys;
+ const char *name = dev->desc->name;
#if defined(CONFIG_LGE_CRASH_HANDLER)
u32 ssr_magic_number;
#endif
- if (!subsys_name) {
- pr_err("Invalid subsystem name.\n");
- return -EINVAL;
- }
-
pr_info("Restart sequence requested for %s, restart_level = %d.\n",
- subsys_name, restart_level);
-
- /* List of subsystems is protected by a lock. New subsystems can
- * still come in.
- */
- subsys = _find_subsystem(subsys_name);
-
- if (!subsys) {
- pr_warn("Unregistered subsystem %s!\n", subsys_name);
- return -EINVAL;
- }
+ name, restart_level);
#if defined(CONFIG_LGE_CRASH_HANDLER)
- set_ssr_magic_number(subsys_name);
+ set_ssr_magic_number(name);
ssr_magic_number = get_ssr_magic_number();
#endif
@@ -528,69 +479,91 @@
case RESET_SUBSYS_COUPLED:
case RESET_SUBSYS_INDEPENDENT:
- __subsystem_restart(subsys);
+ __subsystem_restart_dev(dev);
break;
-
case RESET_SOC:
#if defined(CONFIG_LGE_CRASH_HANDLER)
msm_set_restart_mode(ssr_magic_number | SUB_RESET_SOC);
#endif
- WARN(1, "subsys-restart: Resetting the SoC - %s crashed.",
- subsys->name);
+ WARN(1, "subsys-restart: Resetting the SoC - %s crashed.", name);
break;
-
default:
#if defined(CONFIG_LGE_CRASH_HANDLER)
msm_set_restart_mode(ssr_magic_number | SUB_UNKNOWN);
#endif
pr_err("subsys-restart: Unknown restart level!\n");
- break;
-
+ break;
}
return 0;
}
+EXPORT_SYMBOL(subsystem_restart_dev);
+
+int subsystem_restart(const char *name)
+{
+ struct subsys_device *dev;
+
+ mutex_lock(&subsystem_list_lock);
+ list_for_each_entry(dev, &subsystem_list, list)
+ if (!strncmp(dev->desc->name, name, SUBSYS_NAME_MAX_LENGTH))
+ goto found;
+ dev = NULL;
+found:
+ mutex_unlock(&subsystem_list_lock);
+ if (dev)
+ return subsystem_restart_dev(dev);
+ return -ENODEV;
+}
EXPORT_SYMBOL(subsystem_restart);
-int ssr_register_subsystem(struct subsys_data *subsys)
+struct subsys_device *subsys_register(struct subsys_desc *desc)
{
- unsigned long flags;
+ struct subsys_device *dev;
- if (!subsys)
- goto err;
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
- if (!subsys->name)
- goto err;
+ dev->desc = desc;
+ dev->notify = subsys_notif_add_subsys(desc->name);
+ dev->restart_order = update_restart_order(dev);
- if (!subsys->powerup || !subsys->shutdown)
- goto err;
+ snprintf(dev->wlname, sizeof(dev->wlname), "ssr(%s)", desc->name);
+ wake_lock_init(&dev->wake_lock, WAKE_LOCK_SUSPEND, dev->wlname);
+ INIT_WORK(&dev->work, subsystem_restart_wq_func);
+ spin_lock_init(&dev->restart_lock);
- subsys->notif_handle = subsys_notif_add_subsys(subsys->name);
- subsys->restart_order = _update_restart_order(subsys);
- subsys->single_restart_list[0] = subsys;
+ mutex_init(&dev->shutdown_lock);
+ mutex_init(&dev->powerup_lock);
- mutex_init(&subsys->shutdown_lock);
- mutex_init(&subsys->powerup_lock);
+ mutex_lock(&subsystem_list_lock);
+ list_add(&dev->list, &subsystem_list);
+ mutex_unlock(&subsystem_list_lock);
- spin_lock_irqsave(&subsystem_list_lock, flags);
- list_add(&subsys->list, &subsystem_list);
- spin_unlock_irqrestore(&subsystem_list_lock, flags);
-
- return 0;
-
-err:
- return -EINVAL;
+ return dev;
}
-EXPORT_SYMBOL(ssr_register_subsystem);
+EXPORT_SYMBOL(subsys_register);
+
+void subsys_unregister(struct subsys_device *dev)
+{
+ if (IS_ERR_OR_NULL(dev))
+ return;
+ mutex_lock(&subsystem_list_lock);
+ list_del(&dev->list);
+ mutex_unlock(&subsystem_list_lock);
+ wake_lock_destroy(&dev->wake_lock);
+ kfree(dev);
+}
+EXPORT_SYMBOL(subsys_unregister);
static int ssr_panic_handler(struct notifier_block *this,
unsigned long event, void *ptr)
{
- struct subsys_data *subsys;
+ struct subsys_device *dev;
- list_for_each_entry(subsys, &subsystem_list, list)
- if (subsys->crash_shutdown)
- subsys->crash_shutdown(subsys);
+ list_for_each_entry(dev, &subsystem_list, list)
+ if (dev->desc->crash_shutdown)
+ dev->desc->crash_shutdown(dev->desc);
return NOTIFY_DONE;
}
@@ -647,10 +620,7 @@
static int __init subsys_restart_init(void)
{
- restart_level = RESET_SUBSYS_INDEPENDENT;
-
ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
-
if (!ssr_wq) {
pr_err("%s: out of memory\n", __func__);
return -ENOMEM;
@@ -658,7 +628,6 @@
return ssr_init_soc_restart_orders();
}
-
arch_initcall(subsys_restart_init);
MODULE_DESCRIPTION("Subsystem Restart Driver");
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 6e8d57c..4295d9b 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/wcnss_wlan.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
@@ -37,6 +38,7 @@
static int riva_crash;
static int ss_restart_inprogress;
static int enable_riva_ssr;
+static struct subsys_device *riva_8960_dev;
static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
uint32_t new_state)
@@ -83,7 +85,7 @@
}
ss_restart_inprogress = true;
- subsystem_restart("riva");
+ subsystem_restart_dev(riva_8960_dev);
}
static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
@@ -100,7 +102,7 @@
panic(MODULE_NAME ": Watchdog bite received from Riva");
ss_restart_inprogress = true;
- subsystem_restart("riva");
+ subsystem_restart_dev(riva_8960_dev);
return IRQ_HANDLED;
}
@@ -126,7 +128,7 @@
}
/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_data *subsys)
+static int riva_shutdown(const struct subsys_desc *subsys)
{
pil_force_shutdown("wcnss");
flush_delayed_work(&cancel_vote_work);
@@ -135,7 +137,7 @@
return 0;
}
-static int riva_powerup(const struct subsys_data *subsys)
+static int riva_powerup(const struct subsys_desc *subsys)
{
struct platform_device *pdev = wcnss_get_platform_device();
struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
@@ -162,7 +164,7 @@
static struct ramdump_segment riva_segments[] = {{0x8f200000,
0x8f700000 - 0x8f200000} };
-static int riva_ramdump(int enable, const struct subsys_data *subsys)
+static int riva_ramdump(int enable, const struct subsys_desc *subsys)
{
pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
if (enable)
@@ -174,14 +176,14 @@
}
/* Riva crash handler */
-static void riva_crash_shutdown(const struct subsys_data *subsys)
+static void riva_crash_shutdown(const struct subsys_desc *subsys)
{
pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
if (riva_crash != true)
smsm_riva_reset();
}
-static struct subsys_data riva_8960 = {
+static struct subsys_desc riva_8960 = {
.name = "riva",
.shutdown = riva_shutdown,
.powerup = riva_powerup,
@@ -208,7 +210,10 @@
static int __init riva_restart_init(void)
{
- return ssr_register_subsystem(&riva_8960);
+ riva_8960_dev = subsys_register(&riva_8960);
+ if (IS_ERR(riva_8960_dev))
+ return PTR_ERR(riva_8960_dev);
+ return 0;
}
static int __init riva_ssr_module_init(void)
@@ -253,6 +258,7 @@
static void __exit riva_ssr_module_exit(void)
{
+ subsys_unregister(riva_8960_dev);
free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
}