Merge android-msm-wahoo-4.4-qt-qpr3 into android-msm-wahoo-4.4
SBMerger: 284775313
Change-Id: Id15c79bd513a5fcb898d857b32d8782977b3388a
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
diff --git a/Makefile b/Makefile
index 49a773f..e6ba668 100644
--- a/Makefile
+++ b/Makefile
@@ -1082,11 +1082,15 @@
uts_len := 64
define filechk_utsrelease.h
- if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
- echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
- exit 1; \
- fi; \
- (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
+ if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
+ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
+ exit 1; \
+ fi; \
+ if [ -n "$(BUILD_NUMBER)" ]; then \
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)-ab$(BUILD_NUMBER)\";) \
+ else \
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";) \
+ fi
endef
define filechk_version.h
diff --git a/build.config.common b/build.config.common
index 632d09e..f694728 100644
--- a/build.config.common
+++ b/build.config.common
@@ -4,8 +4,8 @@
CROSS_COMPILE_ARM32=arm-linux-androideabi-
DEFCONFIG=wahoo_defconfig
EXTRA_CMDS=''
-CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin/
-LD_LIBRARY_PATH=${ROOT_DIR}/prebuilts-master/clang/host/linux-x86/clang-r353983c/lib64:$LD_LIBRARY_PATH
+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r370808/bin/
+LD_LIBRARY_PATH=${ROOT_DIR}/prebuilts-master/clang/host/linux-x86/clang-r370808/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
LINUX_GCC_CROSS_COMPILE_ARM32_PREBUILTS_BIN=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin
diff --git a/build.config.debug_api b/build.config.debug_api
index 43f6377..d832b95 100644
--- a/build.config.debug_api
+++ b/build.config.debug_api
@@ -1,5 +1,5 @@
KERNEL_DIR=private/msm-google
-. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
+. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
@@ -15,5 +15,5 @@
-e CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE \
-d CONFIG_KERNEL_LZ4
(cd ${OUT_DIR} && \
- make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+ make ${CC_LD_ARG} O=${OUT_DIR} olddefconfig)
}
diff --git a/build.config.debug_hang b/build.config.debug_hang
index 801613a..8585c65 100644
--- a/build.config.debug_hang
+++ b/build.config.debug_hang
@@ -1,5 +1,5 @@
KERNEL_DIR=private/msm-google
-. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
+. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
@@ -17,5 +17,5 @@
-e CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE \
-d CONFIG_KERNEL_LZ4
(cd ${OUT_DIR} && \
- make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+ make ${CC_LD_ARG} O=${OUT_DIR} olddefconfig)
}
diff --git a/build.config.debug_locking b/build.config.debug_locking
index bae928a..e9dccea 100644
--- a/build.config.debug_locking
+++ b/build.config.debug_locking
@@ -1,5 +1,5 @@
KERNEL_DIR=private/msm-google
-. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
+. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
@@ -13,5 +13,5 @@
-e CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE \
-d CONFIG_KERNEL_LZ4
(cd ${OUT_DIR} && \
- make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+ make ${CC_LD_ARG} O=${OUT_DIR} olddefconfig)
}
diff --git a/build.config.debug_memory b/build.config.debug_memory
index 774e79d..49fc594 100644
--- a/build.config.debug_memory
+++ b/build.config.debug_memory
@@ -1,5 +1,5 @@
KERNEL_DIR=private/msm-google
-. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
+. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
@@ -37,5 +37,5 @@
-e CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE \
-d CONFIG_KERNEL_LZ4
(cd ${OUT_DIR} && \
- make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+ make ${CC_LD_ARG} O=${OUT_DIR} olddefconfig)
}
diff --git a/build.config.kasan b/build.config.kasan
index 6505347..df6ead1 100644
--- a/build.config.kasan
+++ b/build.config.kasan
@@ -1,11 +1,11 @@
KERNEL_DIR=private/msm-google
-. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
+. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
POST_DEFCONFIG_CMDS="check_defconfig && update_kasan_config"
function update_kasan_config() {
${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
-e CONFIG_KASAN \
- -e CONFIG_KASAN_INLINE \
+ -e CONFIG_KASAN_OUTLINE \
-e CONFIG_TEST_KASAN \
-e CONFIG_KCOV \
-e CONFIG_SLUB \
@@ -14,7 +14,9 @@
-d CONFIG_SLUB_DEBUG_PANIC_ON \
-d CONFIG_KASAN_OUTLINE \
-d CONFIG_KERNEL_LZ4 \
- -d CONFIG_RANDOMIZE_BASE
+ -d CONFIG_RANDOMIZE_BASE \
+ -d CONFIG_CC_WERROR \
+ --set-val CONFIG_FRAME_WARN 0
(cd ${OUT_DIR} && \
- make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+ make ${CC_LD_ARG} O=${OUT_DIR} olddefconfig)
}
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 2d7bafb..2f68589 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -213,7 +213,10 @@
continue;
found = 1;
- driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+ if (!(driver->data_ready[i] & USER_SPACE_DATA_TYPE)) {
+ driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
+ }
pr_debug("diag: wake up logging process\n");
wake_up_interruptible(&driver->wait_q);
}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index d47b925..65db9f5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -26,6 +26,8 @@
#include <asm/atomic.h>
#include "diagfwd_bridge.h"
+#define THRESHOLD_CLIENT_LIMIT 50
+
/* Size of the USB buffers used for read and write*/
#define USB_MAX_OUT_BUF 4096
#define APPS_BUF_SIZE 4096
@@ -498,6 +500,7 @@
wait_queue_head_t wait_q;
struct diag_client_map *client_map;
int *data_ready;
+ atomic_t data_ready_notif[THRESHOLD_CLIENT_LIMIT];
int num_clients;
int polling_reg_flag;
int use_device_tree;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 512b4f9..8c97324 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -138,7 +138,6 @@
/* This is the max number of user-space clients supported at initialization*/
static unsigned int max_clients = 15;
-static unsigned int threshold_client_limit = 50;
module_param(max_clients, uint, 0);
/* Timer variables */
@@ -345,7 +344,7 @@
if (i < driver->num_clients) {
diag_add_client(i, file);
} else {
- if (i < threshold_client_limit) {
+ if (i < THRESHOLD_CLIENT_LIMIT) {
driver->num_clients++;
temp = krealloc(driver->client_map
, (driver->num_clients) * sizeof(struct
@@ -375,11 +374,17 @@
}
}
driver->data_ready[i] = 0x0;
+ atomic_set(&driver->data_ready_notif[i], 0);
driver->data_ready[i] |= MSG_MASKS_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
driver->data_ready[i] |= EVENT_MASKS_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
driver->data_ready[i] |= LOG_MASKS_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
driver->data_ready[i] |= DCI_LOG_MASKS_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
driver->data_ready[i] |= DCI_EVENT_MASKS_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
if (driver->ref_count == 0)
diag_mempool_init();
@@ -1801,8 +1806,10 @@
mutex_unlock(&driver->diagchar_mutex);
return -EINVAL;
}
-
- driver->data_ready[i] |= DEINIT_TYPE;
+ if (!(driver->data_ready[i] & DEINIT_TYPE)) {
+ driver->data_ready[i] |= DEINIT_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
+ }
mutex_unlock(&driver->diagchar_mutex);
wake_up_interruptible(&driver->wait_q);
@@ -2905,16 +2912,6 @@
return 0;
}
-static int check_data_ready(int index)
-{
- int data_type = 0;
-
- mutex_lock(&driver->diagchar_mutex);
- data_type = driver->data_ready[index];
- mutex_unlock(&driver->diagchar_mutex);
- return data_type;
-}
-
static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
@@ -2943,7 +2940,8 @@
pr_err("diag: bad address from user side\n");
return -EFAULT;
}
- wait_event_interruptible(driver->wait_q, (check_data_ready(index)) > 0);
+ wait_event_interruptible(driver->wait_q,
+ atomic_read(&driver->data_ready_notif[index]) > 0);
mutex_lock(&driver->diagchar_mutex);
@@ -2954,6 +2952,7 @@
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;
driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
/* place holder for number of data field */
ret += sizeof(int);
@@ -2967,11 +2966,13 @@
/* In case, the thread wakes up and the logging mode is
not memory device any more, the condition needs to be cleared */
driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
}
if (driver->data_ready[index] & HDLC_SUPPORT_TYPE) {
data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE;
driver->data_ready[index] ^= HDLC_SUPPORT_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
@@ -2993,6 +2994,7 @@
data_type = driver->data_ready[index] & DEINIT_TYPE;
COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
driver->data_ready[index] ^= DEINIT_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
mutex_unlock(&driver->diagchar_mutex);
diag_remove_client_entry(file);
return ret;
@@ -3014,6 +3016,7 @@
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= MSG_MASKS_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
goto exit;
}
@@ -3047,6 +3050,7 @@
}
mutex_unlock(&driver->md_session_lock);
driver->data_ready[index] ^= EVENT_MASKS_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
goto exit;
}
@@ -3066,6 +3070,7 @@
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= LOG_MASKS_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
goto exit;
}
@@ -3077,6 +3082,7 @@
*(driver->apps_req_buf),
driver->apps_req_buf_len);
driver->data_ready[index] ^= PKT_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
driver->in_busy_pktdata = 0;
goto exit;
}
@@ -3088,6 +3094,7 @@
COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->dci_pkt_buf),
driver->dci_pkt_length);
driver->data_ready[index] ^= DCI_PKT_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
driver->in_busy_dcipktdata = 0;
goto exit;
}
@@ -3100,6 +3107,7 @@
COPY_USER_SPACE_OR_EXIT(buf + 8, (dci_ops_tbl[DCI_LOCAL_PROC].
event_mask_composite), DCI_EVENT_MASK_SIZE);
driver->data_ready[index] ^= DCI_EVENT_MASKS_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
goto exit;
}
@@ -3111,6 +3119,7 @@
COPY_USER_SPACE_OR_EXIT(buf+8, (dci_ops_tbl[DCI_LOCAL_PROC].
log_mask_composite), DCI_LOG_MASK_SIZE);
driver->data_ready[index] ^= DCI_LOG_MASKS_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
goto exit;
}
@@ -3165,6 +3174,7 @@
exit_stat = diag_copy_dci(buf, count, entry, &ret);
mutex_lock(&driver->diagchar_mutex);
driver->data_ready[index] ^= DCI_DATA_TYPE;
+ atomic_dec(&driver->data_ready_notif[index]);
mutex_unlock(&driver->diagchar_mutex);
if (exit_stat == 1) {
put_task_struct(task_s);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c745024..ae450f3 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -225,6 +225,7 @@
* situation.
*/
driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+ atomic_inc(&driver->data_ready_notif[i]);
pr_debug("diag: Force wakeup of logging process\n");
wake_up_interruptible(&driver->wait_q);
break;
@@ -499,8 +500,11 @@
mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < driver->num_clients; i++)
- if (driver->client_map[i].pid != 0)
+ if (driver->client_map[i].pid != 0 &&
+ !(driver->data_ready[i] & type)) {
driver->data_ready[i] |= type;
+ atomic_inc(&driver->data_ready_notif[i]);
+ }
wake_up_interruptible(&driver->wait_q);
mutex_unlock(&driver->diagchar_mutex);
}
@@ -517,7 +521,11 @@
if (driver->client_map[j].pid != 0 &&
driver->client_map[j].pid ==
driver->md_session_map[i]->pid) {
- driver->data_ready[j] |= type;
+ if (!(driver->data_ready[i] & type)) {
+ driver->data_ready[j] |= type;
+ atomic_inc(
+ &driver->data_ready_notif[j]);
+ }
break;
}
}
@@ -533,7 +541,10 @@
mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == process_id) {
- driver->data_ready[i] |= data_type;
+ if (!(driver->data_ready[i] & data_type)) {
+ driver->data_ready[i] |= data_type;
+ atomic_inc(&driver->data_ready_notif[i]);
+ }
break;
}
wake_up_interruptible(&driver->wait_q);
@@ -1727,6 +1738,10 @@
, GFP_KERNEL)) == NULL)
goto err;
kmemleak_not_leak(driver->data_ready);
+
+ for (i = 0; i < THRESHOLD_CLIENT_LIMIT; i++)
+ atomic_set(&driver->data_ready_notif[i], 0);
+
if (driver->apps_req_buf == NULL) {
driver->apps_req_buf = kzalloc(DIAG_MAX_REQ_SIZE, GFP_KERNEL);
if (!driver->apps_req_buf)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index ee3c66c..0e6e8fa 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -303,6 +303,7 @@
#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */
#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
+#define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */
static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
@@ -320,6 +321,9 @@
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
+ USB_DEVICE_ID_ELECOM_BM084),
+ HID_BATTERY_QUIRK_IGNORE },
{}
};
@@ -335,13 +339,45 @@
return quirks;
}
+static int hidinput_scale_battery_capacity(struct hid_device *dev,
+ int value)
+{
+ if (dev->battery_min < dev->battery_max &&
+ value >= dev->battery_min && value <= dev->battery_max)
+ value = ((value - dev->battery_min) * 100) /
+ (dev->battery_max - dev->battery_min);
+
+ return value;
+}
+
+static int hidinput_query_battery_capacity(struct hid_device *dev)
+{
+ u8 *buf;
+ int ret;
+
+ buf = kmalloc(2, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
+ dev->battery_report_type, HID_REQ_GET_REPORT);
+ if (ret != 2) {
+ kfree(buf);
+ return -ENODATA;
+ }
+
+ ret = hidinput_scale_battery_capacity(dev, buf[1]);
+ kfree(buf);
+ return ret;
+}
+
static int hidinput_get_battery_property(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *val)
{
struct hid_device *dev = power_supply_get_drvdata(psy);
+ int value;
int ret = 0;
- __u8 *buf;
switch (prop) {
case POWER_SUPPLY_PROP_PRESENT:
@@ -350,29 +386,15 @@
break;
case POWER_SUPPLY_PROP_CAPACITY:
-
- buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- break;
+ if (dev->battery_report_type == HID_FEATURE_REPORT) {
+ value = hidinput_query_battery_capacity(dev);
+ if (value < 0)
+ return value;
+ } else {
+ value = dev->battery_capacity;
}
- ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
- dev->battery_report_type,
- HID_REQ_GET_REPORT);
- if (ret != 2) {
- ret = -ENODATA;
- kfree(buf);
- break;
- }
- ret = 0;
-
- if (dev->battery_min < dev->battery_max &&
- buf[1] >= dev->battery_min &&
- buf[1] <= dev->battery_max)
- val->intval = (100 * (buf[1] - dev->battery_min)) /
- (dev->battery_max - dev->battery_min);
- kfree(buf);
+ val->intval = value;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
@@ -380,7 +402,22 @@
break;
case POWER_SUPPLY_PROP_STATUS:
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ if (!dev->battery_reported &&
+ dev->battery_report_type == HID_FEATURE_REPORT) {
+ value = hidinput_query_battery_capacity(dev);
+ if (value < 0)
+ return value;
+
+ dev->battery_capacity = value;
+ dev->battery_reported = true;
+ }
+
+ if (!dev->battery_reported)
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ else if (dev->battery_capacity == 100)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case POWER_SUPPLY_PROP_SCOPE:
@@ -395,27 +432,33 @@
return ret;
}
-static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
+static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
{
- struct power_supply_desc *psy_desc = NULL;
+ struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = { .drv_data = dev, };
unsigned quirks;
s32 min, max;
+ int error;
- if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
- return false; /* no match */
+ if (dev->battery)
+ return 0; /* already initialized? */
- if (dev->battery != NULL)
- goto out; /* already initialized? */
+ quirks = find_battery_quirk(dev);
+
+ hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
+ dev->bus, dev->vendor, dev->product, dev->version, quirks);
+
+ if (quirks & HID_BATTERY_QUIRK_IGNORE)
+ return 0;
psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);
- if (psy_desc == NULL)
- goto out;
+ if (!psy_desc)
+ return -ENOMEM;
psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
- if (psy_desc->name == NULL) {
- kfree(psy_desc);
- goto out;
+ if (!psy_desc->name) {
+ error = -ENOMEM;
+ goto err_free_mem;
}
psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
@@ -424,11 +467,6 @@
psy_desc->use_for_apm = 0;
psy_desc->get_property = hidinput_get_battery_property;
- quirks = find_battery_quirk(dev);
-
- hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
- dev->bus, dev->vendor, dev->product, dev->version, quirks);
-
min = field->logical_minimum;
max = field->logical_maximum;
@@ -447,17 +485,20 @@
dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
if (IS_ERR(dev->battery)) {
- hid_warn(dev, "can't register power supply: %ld\n",
- PTR_ERR(dev->battery));
- kfree(psy_desc->name);
- kfree(psy_desc);
- dev->battery = NULL;
- } else {
- power_supply_powers(dev->battery, &dev->dev);
+ error = PTR_ERR(dev->battery);
+ hid_warn(dev, "can't register power supply: %d\n", error);
+ goto err_free_name;
}
-out:
- return true;
+ power_supply_powers(dev->battery, &dev->dev);
+ return 0;
+
+err_free_name:
+ kfree(psy_desc->name);
+err_free_mem:
+ kfree(psy_desc);
+ dev->battery = NULL;
+ return error;
}
static void hidinput_cleanup_battery(struct hid_device *dev)
@@ -473,16 +514,33 @@
kfree(psy_desc);
dev->battery = NULL;
}
-#else /* !CONFIG_HID_BATTERY_STRENGTH */
-static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
- struct hid_field *field)
+
+static void hidinput_update_battery(struct hid_device *dev, int value)
{
- return false;
+ if (!dev->battery)
+ return;
+
+ if (value == 0 || value < dev->battery_min || value > dev->battery_max)
+ return;
+
+ dev->battery_capacity = hidinput_scale_battery_capacity(dev, value);
+ dev->battery_reported = true;
+ power_supply_changed(dev->battery);
+}
+#else /* !CONFIG_HID_BATTERY_STRENGTH */
+static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
+ struct hid_field *field)
+{
+ return 0;
}
static void hidinput_cleanup_battery(struct hid_device *dev)
{
}
+
+static void hidinput_update_battery(struct hid_device *dev, int value)
+{
+}
#endif /* CONFIG_HID_BATTERY_STRENGTH */
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
@@ -684,6 +742,11 @@
}
break;
+ case 0x3b: /* Battery Strength */
+ hidinput_setup_battery(device, HID_INPUT_REPORT, field);
+ usage->type = EV_PWR;
+ goto ignore;
+
case 0x3c: /* Invert */
map_key_clear(BTN_TOOL_RUBBER);
break;
@@ -924,11 +987,13 @@
break;
case HID_UP_GENDEVCTRLS:
- if (hidinput_setup_battery(device, HID_INPUT_REPORT, field))
+ switch (usage->hid) {
+ case HID_DC_BATTERYSTRENGTH:
+ hidinput_setup_battery(device, HID_INPUT_REPORT, field);
+ usage->type = EV_PWR;
goto ignore;
- else
- goto unknown;
- break;
+ }
+ goto unknown;
case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
set_bit(EV_REP, input->evbit);
@@ -1006,7 +1071,6 @@
if (usage->code > max)
goto ignore;
-
if (usage->type == EV_ABS) {
int a = field->logical_minimum;
@@ -1065,14 +1129,19 @@
struct input_dev *input;
unsigned *quirks = &hid->quirks;
+ if (!usage->type)
+ return;
+
+ if (usage->type == EV_PWR) {
+ hidinput_update_battery(hid, value);
+ return;
+ }
+
if (!field->hidinput)
return;
input = field->hidinput->input;
- if (!usage->type)
- return;
-
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
@@ -1349,6 +1418,7 @@
struct hid_driver *drv = hid->driver;
struct hid_report_enum *rep_enum;
struct hid_report *rep;
+ struct hid_usage *usage;
int i, j;
rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
@@ -1359,12 +1429,15 @@
continue;
for (j = 0; j < rep->field[i]->maxusage; j++) {
+ usage = &rep->field[i]->usage[j];
+
/* Verify if Battery Strength feature is available */
- hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
+ if (usage->hid == HID_DC_BATTERYSTRENGTH)
+ hidinput_setup_battery(hid, HID_FEATURE_REPORT,
+ rep->field[i]);
if (drv->feature_mapping)
- drv->feature_mapping(hid, rep->field[i],
- rep->field[i]->usage + j);
+ drv->feature_mapping(hid, rep->field[i], usage);
}
}
}
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index bc6ad5f..fa1f56b 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -576,10 +576,14 @@
static inline void sony_schedule_work(struct sony_sc *sc,
enum sony_worker which)
{
+ unsigned long flags;
+
switch (which) {
case SONY_WORKER_STATE:
- if (!sc->defer_initialization)
+ spin_lock_irqsave(&sc->lock, flags);
+ if (!sc->defer_initialization && sc->state_worker_initialized)
schedule_work(&sc->state_worker);
+ spin_unlock_irqrestore(&sc->lock, flags);
break;
case SONY_WORKER_HOTPLUG:
if (sc->hotplug_worker_initialized)
@@ -2489,13 +2493,18 @@
static inline void sony_cancel_work_sync(struct sony_sc *sc)
{
+ unsigned long flags;
+
if (sc->hotplug_worker_initialized)
cancel_work_sync(&sc->hotplug_worker);
- if (sc->state_worker_initialized)
+ if (sc->state_worker_initialized) {
+ spin_lock_irqsave(&sc->lock, flags);
+ sc->state_worker_initialized = 0;
+ spin_unlock_irqrestore(&sc->lock, flags);
cancel_work_sync(&sc->state_worker);
+ }
}
-
static int sony_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e9ae3d5..3fd2185 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -28,13 +28,6 @@
#include <linux/cdev.h>
#include "input-compat.h"
-enum evdev_clock_type {
- EV_CLK_REAL = 0,
- EV_CLK_MONO,
- EV_CLK_BOOT,
- EV_CLK_MAX
-};
-
struct evdev {
int open;
struct input_handle handle;
@@ -56,7 +49,7 @@
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
- unsigned int clk_type;
+ enum input_clock_type clk_type;
bool revoked;
unsigned long *evmasks[EV_CNT];
unsigned int bufsize;
@@ -155,16 +148,12 @@
static void __evdev_queue_syn_dropped(struct evdev_client *client)
{
+ ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev);
+ struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
struct input_event ev;
- ktime_t time;
- time = client->clk_type == EV_CLK_REAL ?
- ktime_get_real() :
- client->clk_type == EV_CLK_MONO ?
- ktime_get() :
- ktime_get_boottime();
-
- ev.time = ktime_to_timeval(time);
+ ev.time.tv_sec = ts.tv_sec;
+ ev.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
ev.type = EV_SYN;
ev.code = SYN_DROPPED;
ev.value = 0;
@@ -191,18 +180,18 @@
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
{
unsigned long flags;
- unsigned int clk_type;
+ enum input_clock_type clk_type;
switch (clkid) {
case CLOCK_REALTIME:
- clk_type = EV_CLK_REAL;
+ clk_type = INPUT_CLK_REAL;
break;
case CLOCK_MONOTONIC:
- clk_type = EV_CLK_MONO;
+ clk_type = INPUT_CLK_MONO;
break;
case CLOCK_BOOTTIME:
- clk_type = EV_CLK_BOOT;
+ clk_type = INPUT_CLK_BOOT;
break;
default:
return -EINVAL;
@@ -304,12 +293,7 @@
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
- ktime_t ev_time[EV_CLK_MAX];
-
- ev_time[EV_CLK_MONO] = ktime_get();
- ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
- ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
- TK_OFFS_BOOT);
+ ktime_t *ev_time = input_get_timestamp(handle->dev);
rcu_read_lock();
diff --git a/drivers/input/input.c b/drivers/input/input.c
index baaddd1..805a475 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -401,6 +401,13 @@
if (dev->num_vals >= 2)
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
+ /*
+ * Reset the timestamp on flush so we won't end up
+ * with a stale one. Note we only need to reset the
+ * monolithic one as we use its presence when deciding
+ * whether to generate a synthetic timestamp.
+ */
+ dev->timestamp[INPUT_CLK_MONO] = ktime_set(0, 0);
} else if (dev->num_vals >= dev->max_vals - 2) {
dev->vals[dev->num_vals++] = input_value_sync;
input_pass_values(dev, dev->vals, dev->num_vals);
@@ -1904,6 +1911,47 @@
EXPORT_SYMBOL(input_free_device);
/**
+ * input_set_timestamp - set timestamp for input events
+ * @dev: input device to set timestamp for
+ * @timestamp: the time at which the event has occurred
+ * in CLOCK_MONOTONIC
+ *
+ * This function is intended to provide to the input system a more
+ * accurate time of when an event actually occurred. The driver should
+ * call this function as soon as a timestamp is acquired ensuring
+ * clock conversions in input_set_timestamp are done correctly.
+ *
+ * The system entering a suspend between timestamp acquisition and
+ * calling input_set_timestamp can result in inaccurate conversions.
+ *
+ */
+void input_set_timestamp(struct input_dev *dev, ktime_t timestamp)
+{
+ dev->timestamp[INPUT_CLK_MONO] = timestamp;
+ dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp);
+ dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(
+ timestamp, TK_OFFS_BOOT);
+}
+EXPORT_SYMBOL(input_set_timestamp);
+
+/**
+ * input_get_timestamp - get timestamp for input events
+ * @dev: input device to get timestamp from
+ *
+ * A valid timestamp is a timestamp of non-zero value.
+ */
+ktime_t *input_get_timestamp(struct input_dev *dev)
+{
+ const ktime_t invalid_timestamp = ktime_set(0, 0);
+
+ if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp))
+ input_set_timestamp(dev, ktime_get());
+
+ return dev->timestamp;
+}
+EXPORT_SYMBOL(input_get_timestamp);
+
+/**
* input_set_capability - mark device as capable of a certain event
* @dev: device that is capable of emitting or accepting event
* @type: type of the event (EV_KEY, EV_REL, etc...)
diff --git a/drivers/input/touchscreen/stm/ftm4_ts.c b/drivers/input/touchscreen/stm/ftm4_ts.c
index fa2b59a..b2786f6 100644
--- a/drivers/input/touchscreen/stm/ftm4_ts.c
+++ b/drivers/input/touchscreen/stm/ftm4_ts.c
@@ -1314,6 +1314,21 @@
#endif
/**
+ * fts_hard_interrupt_handler()
+ * Called by the kernel when the touch interrupt occurs.
+ * This represents the top half of the interrupt.
+ *
+ * Set the input event timestamp here to ensure that we have an accurate
+ * estimate of when the touch event actually occurred.
+ */
+static irqreturn_t fts_hard_interrupt_handler(int irq, void *handle)
+{
+ struct fts_ts_info *info = handle;
+ input_set_timestamp(info->input_dev, ktime_get());
+ return IRQ_WAKE_THREAD;
+}
+
+/**
* fts_interrupt_handler()
*
* Called by the kernel when an interrupt occurs (when the sensor
@@ -1932,7 +1947,7 @@
goto err_enable_irq;
}
- retval = request_threaded_irq(info->irq, NULL,
+ retval = request_threaded_irq(info->irq, fts_hard_interrupt_handler,
fts_interrupt_handler, info->board->irq_type,
FTS_TS_DRV_NAME, info);
if (retval < 0) {
diff --git a/drivers/input/touchscreen/synaptics_dsx_htc/synaptics_dsx_core_htc.c b/drivers/input/touchscreen/synaptics_dsx_htc/synaptics_dsx_core_htc.c
index c070590..494aa5f 100644
--- a/drivers/input/touchscreen/synaptics_dsx_htc/synaptics_dsx_core_htc.c
+++ b/drivers/input/touchscreen/synaptics_dsx_htc/synaptics_dsx_core_htc.c
@@ -2488,6 +2488,20 @@
return;
}
+/**
+ * Called by the kernel when the touch interrupt occurs.
+ * This represents the top half of the interrupt.
+ *
+ * Set the input event timestamp here to ensure that we have an accurate
+ * estimate of when the touch event actually occurred.
+ */
+static irqreturn_t synaptics_rmi4_hardirq(int irq, void *data)
+{
+ struct synaptics_rmi4_data *rmi4_data = data;
+ input_set_timestamp(rmi4_data->input_dev, ktime_get());
+ return IRQ_WAKE_THREAD;
+}
+
static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
{
struct synaptics_rmi4_data *rmi4_data = data;
@@ -2588,7 +2602,8 @@
#if IS_ENABLED(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_HTC)
enable_irq(rmi4_data->irq);
#else
- retval = request_threaded_irq(rmi4_data->irq, NULL,
+ retval = request_threaded_irq(rmi4_data->irq,
+ synaptics_rmi4_hardirq,
synaptics_rmi4_irq, bdata->irq_flags,
PLATFORM_DRIVER_NAME, rmi4_data);
if (retval < 0) {
@@ -5683,7 +5698,7 @@
"tp_direct_interrupt");
#if IS_ENABLED(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_HTC)
- retval = request_threaded_irq(rmi4_data->irq, NULL,
+ retval = request_threaded_irq(rmi4_data->irq, synaptics_rmi4_hardirq,
synaptics_rmi4_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
PLATFORM_DRIVER_NAME,
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index c620e44..f97e3ed 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -636,6 +636,7 @@
unsigned long opn_idx, idx;
BUG_ON(!pvdev);
+ mutex_lock(&pvdev->video_drvdata_mutex);
rc = camera_v4l2_fh_open(filep);
if (rc < 0) {
pr_err("%s : camera_v4l2_fh_open failed Line %d rc %d\n",
@@ -706,6 +707,7 @@
idx |= (1 << find_first_zero_bit((const unsigned long *)&opn_idx,
MSM_CAMERA_STREAM_CNT_BITS));
atomic_cmpxchg(&pvdev->opened, opn_idx, idx);
+ mutex_unlock(&pvdev->video_drvdata_mutex);
return rc;
@@ -720,6 +722,7 @@
vb2_q_fail:
camera_v4l2_fh_release(filep);
fh_open_fail:
+ mutex_unlock(&pvdev->video_drvdata_mutex);
return rc;
}
@@ -750,6 +753,7 @@
if (WARN_ON(!session))
return -EIO;
+ mutex_lock(&pvdev->video_drvdata_mutex);
mutex_lock(&session->close_lock);
opn_idx = atomic_read(&pvdev->opened);
mask = (1 << sp->stream_id);
@@ -791,6 +795,7 @@
}
camera_v4l2_fh_release(filep);
+ mutex_unlock(&pvdev->video_drvdata_mutex);
return 0;
}
@@ -937,6 +942,7 @@
*session = pvdev->vdev->num;
atomic_set(&pvdev->opened, 0);
+ mutex_init(&pvdev->video_drvdata_mutex);
video_set_drvdata(pvdev->vdev, pvdev);
device_init_wakeup(&pvdev->vdev->dev, 1);
goto init_end;
diff --git a/drivers/media/platform/msm/camera_v2/fd/Makefile b/drivers/media/platform/msm/camera_v2/fd/Makefile
index 8d01d3a..a1d33da 100644
--- a/drivers/media/platform/msm/camera_v2/fd/Makefile
+++ b/drivers/media/platform/msm/camera_v2/fd/Makefile
@@ -1,4 +1,3 @@
-GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
ccflags-y += -Idrivers/media/video/msm
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
ccflags-y += -Idrivers/media/platform/msm/camera_v2
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile b/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile
index 0b8dc1d..72808f9 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/Makefile
@@ -1,5 +1,3 @@
-GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-
ccflags-y += -Idrivers/media/platform/msm/camera_v2/jpeg_10
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/Makefile b/drivers/media/platform/msm/camera_v2/jpeg_dma/Makefile
index 21cbadb..239b664 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/Makefile
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/Makefile
@@ -1,4 +1,3 @@
-GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
ccflags-y += -Idrivers/media/video/msm
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
obj-$(CONFIG_MSM_JPEGDMA) += msm_jpeg_dma_dev.o msm_jpeg_dma_hw.o
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index dce47bc..8bdb14f5 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -46,6 +46,7 @@
struct msm_video_device {
struct video_device *vdev;
atomic_t opened;
+ struct mutex video_drvdata_mutex;
};
struct msm_queue_head {
diff --git a/drivers/misc/mnh/mnh-clk.c b/drivers/misc/mnh/mnh-clk.c
index 4bb51cf..9f82b14 100644
--- a/drivers/misc/mnh/mnh-clk.c
+++ b/drivers/misc/mnh/mnh-clk.c
@@ -1,7 +1,7 @@
/*
*
* MNH Clock Driver
- * Copyright (c) 2016-2017, Intel Corporation.
+ * Copyright (c) 2016-2018, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -24,6 +24,8 @@
#include "mnh-hwio.h"
#include "mnh-hwio-bases.h"
#include "mnh-hwio-scu.h"
+#include "mnh-hwio-cpu.h"
+#include "mnh-hwio-ddr-ctl.h"
#include "mnh-clk.h"
#include "mnh-ddr.h"
@@ -38,6 +40,17 @@
#define SCU_OUTf(...) \
HW_OUTf(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
+#define MNH_CPU_IN(reg) \
+ HW_IN(HWIO_CPU_BASE_ADDR, CPU, reg)
+#define MNH_DDR_CTL_IN(reg) \
+ HW_IN(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg)
+#define MNH_DDR_CTL_INf(reg, fld) \
+ HW_INf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, fld)
+#define MNH_DDR_CTL_OUTf(reg, fld, val) \
+ HW_OUTf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, fld, val)
+#define MNH_DDR_CTL_OUT(reg, val) \
+ HW_OUT(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, val)
+
#define PLL_UNLOCK 0x4CD9
#define LP4_LPC_FREQ_SWITCH 0x8A
#define REF_CLK_KHZ 19200
@@ -531,74 +544,7 @@
*/
int mnh_lpddr_freq_change(int index)
{
- int status = 0;
- int timeout = 0;
- enum mnh_lpddr_freq_type ddr_freq;
-
- if (!mnh_clk)
- return -ENODEV;
-
- dev_dbg(mnh_clk->dev, "%s: %d\n", __func__, index);
-
- if (index < LPDDR_FREQ_MIN || index > LPDDR_FREQ_MAX)
- return -EINVAL;
-
- /* Check the requested FSP is already in use */
- ddr_freq = SCU_INf(LPDDR4_LOW_POWER_STS, LPDDR4_CUR_FSP);
- if (ddr_freq == index) {
- dev_dbg(mnh_clk->dev, "%s: requested fsp%d is in use\n",
- __func__, index);
- return 0;
- }
-
- /* Power up LPDDR PLL if the FSP setting uses it */
- if (!SCU_INxf(LPDDR4_FSP_SETTING, index, FSP_SYS200_MODE))
- mnh_lpddr_sys200_mode(false);
-
- /* Disable LPC SW override */
- SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FSP_SW_OVERRIDE, 0);
-
- /* Configure FSP index */
- SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_FREQ_CHG_COPY_NUM, index);
-
- /* Configure LPC cmd for frequency switch */
- SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_EXT_CMD, LP4_LPC_FREQ_SWITCH);
-
- /* Initiate LPC cmd to LPDDR controller */
- dev_dbg(mnh_clk->dev, "%s: lpddr freq switching from fsp%d to fsp%d\n",
- __func__, ddr_freq, index);
- SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_EXT_CMD_REQ, 1);
-
- /* Wait until LPC cmd process is done */
- do {
- status = SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE);
- } while ((++timeout < PLL_LOCK_TIMEOUT) && (status != 1));
-
- /* Clear LPC cmd status */
- SCU_OUTf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE, 1);
-
- /* Check LPC error status */
- if (SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_RSP) == LPC_CMD_ERR) {
- /* Clear error status */
- SCU_OUTf(LPDDR4_LOW_POWER_STS, LPC_CMD_RSP, 1);
- dev_err(mnh_clk->dev, "Failed to process lpc cmd:0x%x\n",
- LP4_LPC_FREQ_SWITCH);
- return -EIO;
- }
-
- /* Check FSPx switch status */
- if (SCU_INf(LPDDR4_LOW_POWER_STS, LPDDR4_CUR_FSP) != index) {
- dev_err(mnh_clk->dev, "Failed to switch to fsp%d\n", index);
- return -EIO;
- }
-
- /* Power down LPDDR PLL if the FSP setting doesn't use it */
- if (SCU_INxf(LPDDR4_FSP_SETTING, index, FSP_SYS200_MODE))
- mnh_lpddr_sys200_mode(true);
-
- mnh_ddr_clr_int_status(mnh_clk->dev);
-
- return 0;
+ return mnh_ddr_sw_switch(index);
}
EXPORT_SYMBOL_GPL(mnh_lpddr_freq_change);
@@ -881,8 +827,7 @@
struct device_attribute *attr,
char *buf)
{
- uint32_t var = SCU_INf(LPDDR4_LOW_POWER_STS,
- LPDDR4_CUR_FSP);
+ uint32_t var = MNH_DDR_CTL_INf(133, CURRENT_REG_COPY);
dev_dbg(mnh_clk->dev, "%s: %d\n", __func__, var);
return snprintf(buf, PAGE_SIZE, "FSP%d\n", var);
diff --git a/drivers/misc/mnh/mnh-ddr-33-100-400-600.h b/drivers/misc/mnh/mnh-ddr-33-100-400-600.h
index f5b42e9..db3b540 100644
--- a/drivers/misc/mnh/mnh-ddr-33-100-400-600.h
+++ b/drivers/misc/mnh/mnh-ddr-33-100-400-600.h
@@ -79,10 +79,10 @@
0x0c000002 /* ctl 66 */,
0x00030103 /* ctl 67 */,
0x01031100 /* ctl 68 */,
- 0x000a0003 /* ctl 69 */,
- 0x001c0003 /* ctl 70 */,
- 0x006e0006 /* ctl 71 */,
- 0x00a6000a /* ctl 72 */,
+ 0x000a000a /* ctl 69 */,
+ 0x001c001c /* ctl 70 */,
+ 0x006e006e /* ctl 71 */,
+ 0x00a600a6 /* ctl 72 */,
0x03050505 /* ctl 73 */,
0x03010302 /* ctl 74 */,
0x03050505 /* ctl 75 */,
@@ -124,9 +124,9 @@
0x06030303 /* ctl 111 */,
0x00030a03 /* ctl 112 */,
0x02030200 /* ctl 113 */,
- 0x00070703 /* ctl 114 */,
+ 0x00070903 /* ctl 114 */,
0x03020302 /* ctl 115 */,
- 0x02000707 /* ctl 116 */,
+ 0x02000709 /* ctl 116 */,
0x07030203 /* ctl 117 */,
0x03020007 /* ctl 118 */,
0x07070302 /* ctl 119 */,
@@ -174,12 +174,12 @@
0x00313131 /* ctl 161 */,
0x00000000 /* ctl 162 */,
0x4d4d4d4d /* ctl 163 */,
- 0x4d4d4dc0 /* ctl 164 */,
+ 0x4d4d4dd0 /* ctl 164 */,
0x0000004d /* ctl 165 */,
0x00000000 /* ctl 166 */,
0x06060606 /* ctl 167 */,
0x01000000 /* ctl 168 */,
- 0x00000001 /* ctl 169 */,
+ 0x01010001 /* ctl 169 */,
0x00000000 /* ctl 170 */,
0x01000000 /* ctl 171 */,
0x00000001 /* ctl 172 */,
@@ -644,7 +644,7 @@
0x01000000 /* pi 70 */,
0x04040401 /* pi 71 */,
0x0a000004 /* pi 72 */,
- 0x01010128 /* pi 73 */,
+ 0x01000028 /* pi 73 */,
0x00000001 /* pi 74 */,
0x00000000 /* pi 75 */,
0x00030003 /* pi 76 */,
@@ -663,8 +663,8 @@
0x00000000 /* pi 89 */,
0x001e0303 /* pi 90 */,
0x000007d0 /* pi 91 */,
- 0x01010300 /* pi 92 */,
- 0x01010101 /* pi 93 */,
+ 0x00000300 /* pi 92 */,
+ 0x01010000 /* pi 93 */,
0x00000101 /* pi 94 */,
0x00000000 /* pi 95 */,
0x00000000 /* pi 96 */,
@@ -688,7 +688,7 @@
0x00120024 /* pi 114 */,
0x00000000 /* pi 115 */,
0x00000000 /* pi 116 */,
- 0x01010100 /* pi 117 */,
+ 0x01010000 /* pi 117 */,
0x00000001 /* pi 118 */,
0x010a140a /* pi 119 */,
0x00010011 /* pi 120 */,
@@ -719,7 +719,7 @@
0x34000000 /* pi 145 */,
0x00000000 /* pi 146 */,
0x00000000 /* pi 147 */,
- 0x01010000 /* pi 148 */,
+ 0x00000000 /* pi 148 */,
0x00000101 /* pi 149 */,
0x31000600 /* pi 150 */,
0x064d4d00 /* pi 151 */,
@@ -766,7 +766,7 @@
},
{
0x76543210 /* phy 0 */,
- 0x0004f008 /* phy 1 */,
+ 0x00051008 /* phy 1 */,
0x00020133 /* phy 2 */,
0x00000000 /* phy 3 */,
0x00000000 /* phy 4 */,
@@ -779,7 +779,7 @@
0x00000000 /* phy 11 */,
0x00000000 /* phy 12 */,
0x00000100 /* phy 13 */,
- 0x001700c0 /* phy 14 */,
+ 0x00170080 /* phy 14 */,
0x020100cc /* phy 15 */,
0x00030066 /* phy 16 */,
0x00000000 /* phy 17 */,
@@ -848,7 +848,7 @@
0x00800080 /* phy 80 */,
0x00800080 /* phy 81 */,
0x00800080 /* phy 82 */,
- 0x00010019 /* phy 83 */,
+ 0x00000019 /* phy 83 */,
0x000001d0 /* phy 84 */,
0x00000000 /* phy 85 */,
0x00000200 /* phy 86 */,
@@ -856,7 +856,7 @@
0x51816152 /* phy 88 */,
0xc0c08161 /* phy 89 */,
0x00010000 /* phy 90 */,
- 0x02001000 /* phy 91 */,
+ 0x0200100c /* phy 91 */,
0x0c0432ff /* phy 92 */,
0x000f0c18 /* phy 93 */,
0x01000140 /* phy 94 */,
@@ -894,7 +894,7 @@
0x00000000 /* phy 126 */,
0x00000000 /* phy 127 */,
0x76543210 /* phy 128 */,
- 0x0004f008 /* phy 129 */,
+ 0x00051008 /* phy 129 */,
0x00020133 /* phy 130 */,
0x00000000 /* phy 131 */,
0x00000000 /* phy 132 */,
@@ -907,7 +907,7 @@
0x00000000 /* phy 139 */,
0x00000000 /* phy 140 */,
0x00000100 /* phy 141 */,
- 0x001700c0 /* phy 142 */,
+ 0x00170080 /* phy 142 */,
0x020100cc /* phy 143 */,
0x00030066 /* phy 144 */,
0x00000000 /* phy 145 */,
@@ -976,7 +976,7 @@
0x00800080 /* phy 208 */,
0x00800080 /* phy 209 */,
0x00800080 /* phy 210 */,
- 0x00010019 /* phy 211 */,
+ 0x00000019 /* phy 211 */,
0x000001d0 /* phy 212 */,
0x00000000 /* phy 213 */,
0x00000200 /* phy 214 */,
@@ -984,7 +984,7 @@
0x51816152 /* phy 216 */,
0xc0c08161 /* phy 217 */,
0x00010000 /* phy 218 */,
- 0x02001000 /* phy 219 */,
+ 0x0200100c /* phy 219 */,
0x0c0432ff /* phy 220 */,
0x000f0c18 /* phy 221 */,
0x01000140 /* phy 222 */,
@@ -1022,7 +1022,7 @@
0x00000000 /* phy 254 */,
0x00000000 /* phy 255 */,
0x76543210 /* phy 256 */,
- 0x0004f008 /* phy 257 */,
+ 0x00051008 /* phy 257 */,
0x00020133 /* phy 258 */,
0x00000000 /* phy 259 */,
0x00000000 /* phy 260 */,
@@ -1035,7 +1035,7 @@
0x00000000 /* phy 267 */,
0x00000000 /* phy 268 */,
0x00000100 /* phy 269 */,
- 0x001700c0 /* phy 270 */,
+ 0x00170080 /* phy 270 */,
0x020100cc /* phy 271 */,
0x00030066 /* phy 272 */,
0x00000000 /* phy 273 */,
@@ -1104,7 +1104,7 @@
0x00800080 /* phy 336 */,
0x00800080 /* phy 337 */,
0x00800080 /* phy 338 */,
- 0x00010019 /* phy 339 */,
+ 0x00000019 /* phy 339 */,
0x000001d0 /* phy 340 */,
0x00000000 /* phy 341 */,
0x00000200 /* phy 342 */,
@@ -1112,7 +1112,7 @@
0x51816152 /* phy 344 */,
0xc0c08161 /* phy 345 */,
0x00010000 /* phy 346 */,
- 0x02001000 /* phy 347 */,
+ 0x0200100c /* phy 347 */,
0x0c0432ff /* phy 348 */,
0x000f0c18 /* phy 349 */,
0x01000140 /* phy 350 */,
@@ -1150,7 +1150,7 @@
0x00000000 /* phy 382 */,
0x00000000 /* phy 383 */,
0x76543210 /* phy 384 */,
- 0x0004f008 /* phy 385 */,
+ 0x00051008 /* phy 385 */,
0x00020133 /* phy 386 */,
0x00000000 /* phy 387 */,
0x00000000 /* phy 388 */,
@@ -1163,7 +1163,7 @@
0x00000000 /* phy 395 */,
0x00000000 /* phy 396 */,
0x00000100 /* phy 397 */,
- 0x001700c0 /* phy 398 */,
+ 0x00170080 /* phy 398 */,
0x020100cc /* phy 399 */,
0x00030066 /* phy 400 */,
0x00000000 /* phy 401 */,
@@ -1232,7 +1232,7 @@
0x00800080 /* phy 464 */,
0x00800080 /* phy 465 */,
0x00800080 /* phy 466 */,
- 0x00010019 /* phy 467 */,
+ 0x00000019 /* phy 467 */,
0x000001d0 /* phy 468 */,
0x00000000 /* phy 469 */,
0x00000200 /* phy 470 */,
@@ -1240,7 +1240,7 @@
0x51816152 /* phy 472 */,
0xc0c08161 /* phy 473 */,
0x00010000 /* phy 474 */,
- 0x02001000 /* phy 475 */,
+ 0x0200100c /* phy 475 */,
0x0c0432ff /* phy 476 */,
0x000f0c18 /* phy 477 */,
0x01000140 /* phy 478 */,
@@ -1311,7 +1311,7 @@
0x000300ce /* phy 543 */,
0x03000300 /* phy 544 */,
0x03000300 /* phy 545 */,
- 0x00000300 /* phy 546 */,
+ 0x000c0300 /* phy 546 */,
0xff020010 /* phy 547 */,
0x00000332 /* phy 548 */,
0x00000000 /* phy 549 */,
@@ -1439,7 +1439,7 @@
0x000300ce /* phy 671 */,
0x03000300 /* phy 672 */,
0x03000300 /* phy 673 */,
- 0x00000300 /* phy 674 */,
+ 0x000c0300 /* phy 674 */,
0xff020010 /* phy 675 */,
0x00000332 /* phy 676 */,
0x00000000 /* phy 677 */,
@@ -1567,7 +1567,7 @@
0x000300ce /* phy 799 */,
0x03000300 /* phy 800 */,
0x03000300 /* phy 801 */,
- 0x00000300 /* phy 802 */,
+ 0x000c0300 /* phy 802 */,
0xff020010 /* phy 803 */,
0x00000332 /* phy 804 */,
0x00000000 /* phy 805 */,
@@ -1695,7 +1695,7 @@
0x000300ce /* phy 927 */,
0x03000300 /* phy 928 */,
0x03000300 /* phy 929 */,
- 0x00000300 /* phy 930 */,
+ 0x000c0300 /* phy 930 */,
0xff020010 /* phy 931 */,
0x00000332 /* phy 932 */,
0x00000000 /* phy 933 */,
@@ -1818,12 +1818,12 @@
0x0f1f0f1f /* phy 1050 */,
0x03000003 /* phy 1051 */,
0x00000300 /* phy 1052 */,
- 0x0b221b02 /* phy 1053 */,
- 0x09240b22 /* phy 1054 */,
+ 0x07221702 /* phy 1053 */,
+ 0x07240722 /* phy 1054 */,
0x00000000 /* phy 1055 */,
0x00000000 /* phy 1056 */,
0x05030000 /* phy 1057 */,
- 0x14000001 /* phy 1058 */,
+ 0x14000801 /* phy 1058 */,
0x63c0ce00 /* phy 1059 */,
0x0000000e /* phy 1060 */,
0x001f0fc0 /* phy 1061 */,
@@ -1847,7 +1847,7 @@
0x00000000 /* phy 1079 */,
0x00000000 /* phy 1080 */,
0x00000000 /* phy 1081 */,
- 0x00000078 /* phy 1082 */,
+ 0x0000007a /* phy 1082 */,
0x00000000 /* phy 1083 */,
0x00010108 /* phy 1084 */,
0x00000000 /* phy 1085 */,
@@ -1870,19 +1870,27 @@
{
{ 83, 0x00020119 } /* setA */,
{ 90, 0x01020000 } /* setA */,
+ { 91, 0x02001000 } /* setA */,
{ 92, 0x0c053eff } /* setA */,
{ 211, 0x00020119 } /* setA */,
{ 218, 0x01020000 } /* setA */,
+ { 219, 0x02001000 } /* setA */,
{ 220, 0x0c053eff } /* setA */,
{ 339, 0x00020119 } /* setA */,
{ 346, 0x01020000 } /* setA */,
+ { 347, 0x02001000 } /* setA */,
{ 348, 0x0c053eff } /* setA */,
{ 467, 0x00020119 } /* setA */,
{ 474, 0x01020000 } /* setA */,
+ { 475, 0x02001000 } /* setA */,
{ 476, 0x0c053eff } /* setA */,
+ { 546, 0x00000300 } /* setA */,
{ 548, 0x0000033e } /* setA */,
+ { 674, 0x00000300 } /* setA */,
{ 676, 0x0000033e } /* setA */,
+ { 802, 0x00000300 } /* setA */,
{ 804, 0x0000033e } /* setA */,
+ { 930, 0x00000300 } /* setA */,
{ 932, 0x0000033e } /* setA */,
{ 1045, 0x01221102 } /* setA */,
{ 1046, 0x00000122 } /* setA */,
@@ -1893,22 +1901,30 @@
{ 83, 0x0003011a } /* setB */,
{ 85, 0x01000000 } /* setB */,
{ 90, 0x02030000 } /* setB */,
+ { 91, 0x02001000 } /* setB */,
{ 92, 0x0c073eff } /* setB */,
{ 211, 0x0003011a } /* setB */,
{ 213, 0x01000000 } /* setB */,
{ 218, 0x02030000 } /* setB */,
+ { 219, 0x02001000 } /* setB */,
{ 220, 0x0c073eff } /* setB */,
{ 339, 0x0003011a } /* setB */,
{ 341, 0x01000000 } /* setB */,
{ 346, 0x02030000 } /* setB */,
+ { 347, 0x02001000 } /* setB */,
{ 348, 0x0c073eff } /* setB */,
{ 467, 0x0003011a } /* setB */,
{ 469, 0x01000000 } /* setB */,
{ 474, 0x02030000 } /* setB */,
+ { 475, 0x02001000 } /* setB */,
{ 476, 0x0c073eff } /* setB */,
+ { 546, 0x00000300 } /* setB */,
{ 548, 0x0000033e } /* setB */,
+ { 674, 0x00000300 } /* setB */,
{ 676, 0x0000033e } /* setB */,
+ { 802, 0x00000300 } /* setB */,
{ 804, 0x0000033e } /* setB */,
+ { 930, 0x00000300 } /* setB */,
{ 932, 0x0000033e } /* setB */,
{ 1045, 0x01221102 } /* setB */,
{ 1046, 0x00000122 } /* setB */,
diff --git a/drivers/misc/mnh/mnh-ddr.c b/drivers/misc/mnh/mnh-ddr.c
index 47f04c0..5d9a937 100644
--- a/drivers/misc/mnh/mnh-ddr.c
+++ b/drivers/misc/mnh/mnh-ddr.c
@@ -1,7 +1,7 @@
/*
*
* MNH DDR Driver
-* Copyright (c) 2016-2017, Intel Corporation.
+* Copyright (c) 2016-2018, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -28,48 +28,52 @@
#define MNH_DDR_CTL_IN(reg) \
HW_IN(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg)
-#define MNH_DDR_CTL_INf(...) \
- HW_INf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, __VA_ARGS__)
-#define MNH_DDR_CTL_OUT(...) \
- HW_OUT(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, __VA_ARGS__)
-#define MNH_DDR_CTL_OUTf(...) \
- HW_OUTf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, __VA_ARGS__)
+#define MNH_DDR_CTL_INf(reg, fld) \
+ HW_INf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, fld)
+#define MNH_DDR_CTL_OUT(reg, val) \
+ HW_OUT(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, val)
+#define MNH_DDR_CTL_OUTf(reg, fld, val) \
+ HW_OUTf(HWIO_DDR_CTL_BASE_ADDR, DDR_CTL, reg, fld, val)
-#define MNH_DDR_PI_INf(...) \
- HW_INf(HWIO_DDR_PI_BASE_ADDR, DDR_PI, __VA_ARGS__)
-#define MNH_DDR_PI_OUTf(...) \
- HW_OUTf(HWIO_DDR_PI_BASE_ADDR, DDR_PI, __VA_ARGS__)
-#define MNH_DDR_PI_OUT(...) \
- HW_OUT(HWIO_DDR_PI_BASE_ADDR, DDR_PI, __VA_ARGS__)
+#define MNH_DDR_PI_INf(reg, fld) \
+ HW_INf(HWIO_DDR_PI_BASE_ADDR, DDR_PI, reg, fld)
+#define MNH_DDR_PI_OUTf(reg, fld, val) \
+ HW_OUTf(HWIO_DDR_PI_BASE_ADDR, DDR_PI, reg, fld, val)
+#define MNH_DDR_PI_OUT(reg, val) \
+ HW_OUT(HWIO_DDR_PI_BASE_ADDR, DDR_PI, reg, val)
-#define MNH_DDR_PHY_INf(...) \
- HW_INf(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, __VA_ARGS__)
-#define MNH_DDR_PHY_OUTf(...) \
- HW_OUTf(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, __VA_ARGS__)
-#define MNH_DDR_PHY_OUT(...) \
- HW_OUT(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, __VA_ARGS__)
+#define MNH_DDR_PHY_INf(reg, fld) \
+ HW_INf(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, reg, fld)
+#define MNH_DDR_PHY_IN(reg) \
+ HW_IN(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, reg)
+#define MNH_DDR_PHY_OUTf(reg, fld, val) \
+ HW_OUTf(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, reg, fld, val)
+#define MNH_DDR_PHY_OUT(reg, val) \
+ HW_OUT(HWIO_DDR_PHY_BASE_ADDR, DDR_PHY, reg, val)
#define MNH_SCU_IN(reg) \
HW_IN(HWIO_SCU_BASE_ADDR, SCU, reg)
-#define MNH_SCU_INf(...) \
- HW_INf(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
-#define MNH_SCU_INx(...) \
- HW_INx(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
-#define MNH_SCU_INxf(...) \
- HW_INxf(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
-#define MNH_SCU_OUTf(...) \
- HW_OUTf(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
-#define MNH_SCU_OUT(...) \
- HW_OUT(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
-#define MNH_SCU_OUTx(...) \
- HW_OUTx(HWIO_SCU_BASE_ADDR, SCU, __VA_ARGS__)
+#define MNH_SCU_INf(reg, fld) \
+ HW_INf(HWIO_SCU_BASE_ADDR, SCU, reg, fld)
+#define MNH_SCU_INx(reg, inst) \
+ HW_INx(HWIO_SCU_BASE_ADDR, SCU, reg, inst)
+#define MNH_SCU_INxf(reg, inst, fld) \
+ HW_INxf(HWIO_SCU_BASE_ADDR, SCU, reg, inst, fld)
+#define MNH_SCU_OUTf(reg, fld, val) \
+ HW_OUTf(HWIO_SCU_BASE_ADDR, SCU, reg, fld, val)
+#define MNH_SCU_OUT(reg, val) \
+ HW_OUT(HWIO_SCU_BASE_ADDR, SCU, reg, val)
+#define MNH_SCU_OUTx(reg, inst, val) \
+ HW_OUTx(HWIO_SCU_BASE_ADDR, SCU, reg, inst, val)
+#define MNH_SCU_OUTxf(reg, inst, fld, val) \
+ HW_OUTxf(HWIO_SCU_BASE_ADDR, SCU, reg, inst, fld, val)
#define MNH_RSTC_INf(fld) \
HW_INf(HWIO_SCU_BASE_ADDR, SCU, RSTC, fld)
-#define MNH_RSTC_OUTf(...) \
- HW_OUTf(HWIO_SCU_BASE_ADDR, SCU, RSTC, __VA_ARGS__)
+#define MNH_RSTC_OUTf(fld, val) \
+ HW_OUTf(HWIO_SCU_BASE_ADDR, SCU, RSTC, fld, val)
-#define WRITE_DDR_REG_CONFIG(_state, ddrblock, regindex) \
+#define WRITE_DDR_REG_CONFIG(ddrblock, regindex) \
do { \
if (_state->ddrblock[regindex]) { \
mnh_reg_write(_state->ddrblock##_base + \
@@ -78,7 +82,7 @@
} \
} while (0)
-#define WRITE_DDR_PHY_CONFIG(_state, fsp, regindex) \
+#define WRITE_DDR_PHY_CONFIG(fsp, regindex) \
do { \
if (_state->phy[fsp][regindex]) { \
mnh_reg_write(_state->phy_base + (regindex * sizeof(u32)), \
@@ -86,92 +90,178 @@
} \
} while (0)
-#define WRITE_SET_ELEMENT(_state, regindex, regvalue) \
+#define WRITE_SET_ELEMENT(regindex, regvalue) \
mnh_reg_write(_state->phy_base + (regindex * sizeof(u32)),\
regvalue)
-#define WRITE_SCU_FSP(_state, fsp) \
+#define WRITE_SCU_FSP(fsp) \
do { \
_state->fsps[fsp] &= 0xFFFFFF00;\
_state->fsps[fsp] |= 0x7d;\
MNH_SCU_OUTx(LPDDR4_FSP_SETTING, fsp, _state->fsps[fsp]); \
} while (0)
-#define SAVE_CURRENT_FSP(dev, _state) \
-do { \
- _state->suspend_fsp = \
- MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPDDR4_CUR_FSP); \
- dev_dbg(dev, "%s: saved fsp: %d\n", __func__, _state->suspend_fsp); \
-} while (0)
+#define WRITE_CLK_FROM_FSP(fsp) mnh_ddr_write_clk_from_fsp(fsp, 1)
+#define WRITE_CLK_FROM_FSP_NO_LOCK(fsp) mnh_ddr_write_clk_from_fsp(fsp, 0)
-#define SAVED_FSP(_state) _state->suspend_fsp
-
-#define WRITE_CLK_FROM_FSP(dev, _state, fsp) \
-do { \
- if (fsp < (MNH_DDR_NUM_FSPS)) { \
- MNH_SCU_OUTf(CCU_CLK_DIV, LPDDR4_REFCLK_DIV, \
- MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, \
- FSP_LPDDR4_REFCLK_DIV)); \
- MNH_SCU_OUTf(CCU_CLK_DIV, AXI_FABRIC_CLK_DIV, \
- MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, \
- FSP_AXI_FABRIC_CLK_DIV)); \
- MNH_SCU_OUTf(CCU_CLK_DIV, PCIE_AXI_CLK_DIV, \
- MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, \
- FSP_PCIE_AXI_CLK_DIV)); \
- MNH_SCU_OUTf(CCU_CLK_CTL, LP4_AXI_SYS200_MODE, \
- MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, \
- FSP_SYS200_MODE)); \
- } else \
- dev_err(dev, "%s: invalid fsp 0x%x", __func__, fsp); \
-} while (0)
-
-#define SAVE_DDR_REG_CONFIG(_state, ddrblock, regindex) \
+#define SAVE_DDR_REG_CONFIG(ddrblock, regindex) \
do { \
_state->ddrblock[regindex] = \
mnh_reg_read(_state->ddrblock##_base + \
- (regindex * sizeof(u32))); \
+ ((regindex) * sizeof(u32))); \
} while (0)
-#define SAVE_DDR_PHY_REG_CONFIG(_state, fsp, regindex) \
+#define SAVE_DDR_PHY_REG_CONFIG(fsp, regindex) \
do { \
_state->phy[fsp][regindex] = \
- mnh_reg_read(_state->phy_base + (regindex * sizeof(u32))); \
+ mnh_reg_read(_state->phy_base + ((regindex) * sizeof(u32))); \
} while (0)
-#define CLR_START(_state, ddrblock) (_state->ddrblock[0] &= (0xFFFFFFFE))
+#define CLR_START(ddrblock) (_state->ddrblock[0] &= (0xFFFFFFFE))
/* timeout for training all FSPs */
#define TRAINING_TIMEOUT msecs_to_jiffies(45)
+#define RESUME_TIMEOUT msecs_to_jiffies(7)
+#define MNH_DDR_ASSERT_ISO_N() \
+ do { \
+ gpiod_set_value_cansleep(_state->iso_n, 0); \
+ udelay(20); \
+ } while (0)
+
+#define MNH_DDR_DEASSERT_ISO_N() \
+ do { \
+ gpiod_set_value_cansleep(_state->iso_n, 1); \
+ udelay(20); \
+ } while (0)
+
+#define LP_CMD_FREQ_SWITCH 0x8A
#define LP_CMD_EXIT_LP 0x81
#define LP_CMD_DSRPD 0xFE
+#define LP_CMD_SRPD 0x3A
+#define LP_CMD_EXIT_SRPD 0x01
/* INT status bits */
+#define DFS_COMPLETE_SBIT 31
+#define DFI_STATE_CHANGE_SBIT 28
+#define INHIBIT_DRAM_CMD_SBIT 27
#define MR_WRITE_SBIT 26
#define MR_READ_SBIT 23
+#define DFI_UPDATE_ERROR_SBIT 13
#define BIST_SBIT 6
#define LP_CMD_SBIT 5
#define INIT_DONE_SBIT 4
+/* PI_INT_STATUS bits */
+#define PI_CONTROL_ERROR_BIT 1
+#define PI_INIT_DONE_BIT 0
+
+static struct mnh_ddr_internal_state *_state;
+
+static void mnh_ddr_disable_lp(void);
+static void mnh_ddr_enable_lp(void);
+
+/*
+ * Write the clk dividers from given FSP index.
+ * fsp: the fsp index [0-3]
+ * pll_freeze: define whether the function uses HW PLL freeze funtionality
+ * inside the function to set all the dividers in one operation (with unfreeze)
+ * 0 to set it off
+ * 1 to set it on
+ */
+void mnh_ddr_write_clk_from_fsp(unsigned int fsp, int pll_freeze)
+{
+ if (fsp >= MNH_DDR_NUM_FSPS) {
+ pr_err("%s invalid fsp 0x%x", __func__, fsp);
+ return;
+ }
+
+ if (pll_freeze) {
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTf(LPDDR4_REFCLK_PLL_CTRL, FRZ_PLL_IN, 1);
+ }
+ MNH_SCU_OUTf(CCU_CLK_DIV, LPDDR4_REFCLK_DIV,
+ MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, FSP_LPDDR4_REFCLK_DIV));
+ MNH_SCU_OUTf(CCU_CLK_DIV, AXI_FABRIC_CLK_DIV,
+ MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, FSP_AXI_FABRIC_CLK_DIV));
+ MNH_SCU_OUTf(CCU_CLK_DIV, PCIE_AXI_CLK_DIV,
+ MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, FSP_PCIE_AXI_CLK_DIV));
+ MNH_SCU_OUTf(CCU_CLK_CTL, LP4_AXI_SYS200_MODE,
+ MNH_SCU_INxf(LPDDR4_FSP_SETTING, fsp, FSP_SYS200_MODE));
+ if (pll_freeze) {
+ MNH_SCU_OUTf(LPDDR4_REFCLK_PLL_CTRL, FRZ_PLL_IN, 0);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0);
+ }
+}
+
+static u32 mnh_ddr_sanity_check(void)
+{
+ /* just verify comm is actually up */
+ u32 val = MNH_DDR_CTL_IN(00);
+
+ /*
+ * If above register reads either 0 or all FF, it indicates that
+ * access to DDR CTL registers are not ready.
+ */
+ if ((val == 0) || (val == 0xFFFFFFFF))
+ return 0;
+ else
+ return 1;
+}
+
/* read entire int_status */
-u64 mnh_ddr_int_status(struct device *dev)
+u64 mnh_ddr_int_status(void)
{
u64 int_stat = ((u64)MNH_DDR_CTL_IN(228) << 32) | MNH_DDR_CTL_IN(227);
return int_stat;
}
EXPORT_SYMBOL(mnh_ddr_int_status);
+int mnh_ddr_print_phy_status(void)
+{
+ int ret = 0;
+ /* call from a context where lp has already been disabled
+ * so ctl and phy reg can be accessed. don't do it here
+ */
+ if ((MNH_DDR_PHY_IN(00) != 0x76543210) ||
+ (MNH_DDR_PHY_IN(256) != 0x76543210) ||
+ (MNH_DDR_PHY_IN(384) != 0x76543210)) {
+ pr_err("%s ERROR PHY 00: 0x%08x 256: 0x%08x 384: 0x%08x\n",
+ __func__,
+ MNH_DDR_PHY_IN(00),
+ MNH_DDR_PHY_IN(256),
+ MNH_DDR_PHY_IN(384));
+ ret = -1;
+ }
+
+ if (MNH_DDR_PHY_INf(1099, PHY_AC_INIT_COMPLETE_OBS) != 0x000003f1) {
+ pr_info("%s PHY_AC_INIT_COMPLETE_OBS: 0x%08x\n",
+ __func__, MNH_DDR_PHY_INf(1099,
+ PHY_AC_INIT_COMPLETE_OBS));
+ ret = -1;
+ }
+ if (MNH_DDR_PHY_INf(1100, PHY_DS_INIT_COMPLETE_OBS) != 0x0000000f) {
+ pr_info("%s PHY_DS_INIT_COMPLETE_OBS: 0x%08x\n",
+ __func__, MNH_DDR_PHY_INf(1100,
+ PHY_DS_INIT_COMPLETE_OBS));
+ ret = -1;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(mnh_ddr_print_phy_status);
+
+
/* clear entire int_status */
-int mnh_ddr_clr_int_status(struct device *dev)
+int mnh_ddr_clr_int_status(void)
{
u64 stat = 0;
- MNH_DDR_CTL_OUT(230, 0x0F);
MNH_DDR_CTL_OUT(229, 0xFFFFFFFF);
- stat = mnh_ddr_int_status(dev);
+ MNH_DDR_CTL_OUT(230, 0x0F);
+ stat = mnh_ddr_int_status();
if (stat) {
- dev_err(dev, "%s: int stat not all clear: %llx\n", __func__,
- stat);
+ pr_err("%s: int stat not all clear: %llx\n",
+ __func__, stat);
return -EIO;
}
return 0;
@@ -202,7 +292,7 @@
}
/* clear single bit in int_status */
-static int mnh_ddr_clr_int_status_bit(struct device *dev, u8 sbit)
+static int mnh_ddr_clr_int_status_bit(u8 sbit)
{
const u32 max_int_status_bit = 35;
const u32 first_upper_bit = 32;
@@ -216,17 +306,33 @@
MNH_DDR_CTL_OUT(229, 1 << sbit);
if (mnh_ddr_int_status_bit(sbit)) {
- dev_err(dev, "%s: bit %d is still set.\n", __func__, sbit);
+ pr_err("%s: bit %d is still set.\n", __func__, sbit);
return -EIO;
}
return 0;
}
-static int mnh_ddr_send_lp_cmd(struct device *dev, u8 cmd)
+/* read single bit in PI_INT_STATUS */
+static u32 mnh_ddr_pi_int_status_bit(u8 sbit)
+{
+ u32 status = 0;
+ const u32 max_int_status_bit = 24;
+
+ if (sbit > max_int_status_bit)
+ return -EINVAL;
+
+ status = MNH_DDR_PI_INf(172, PI_INT_STATUS);
+ pr_debug("%s: PI_INT_STATUS = 0x%x.\n", __func__, status);
+
+ status &= (1 << sbit);
+ return status;
+}
+
+static int mnh_ddr_send_lp_cmd(u8 cmd)
{
u32 timeout = 100000;
- dev_dbg(dev, "%s sending cmd: 0x%x\n", __func__, cmd);
+ pr_debug("%s sending cmd: 0x%x\n", __func__, cmd);
MNH_DDR_CTL_OUTf(112, LP_CMD, cmd);
while (!mnh_ddr_int_status_bit(LP_CMD_SBIT) && --timeout)
@@ -235,29 +341,85 @@
if (!mnh_ddr_int_status_bit(LP_CMD_SBIT))
return -ETIMEDOUT;
- return mnh_ddr_clr_int_status_bit(dev, LP_CMD_SBIT);
+ return mnh_ddr_clr_int_status_bit(LP_CMD_SBIT);
+}
+
+/*
+ * Both chip 0 and chip 1 are written.
+ */
+int mnh_ddr_write_mode_reg(u8 modereg, u8 modevalue)
+{
+ const u64 writeable = 0x0000010101D3FE1E;
+ u32 val = 0;
+ unsigned long timeout = 0;
+ int ret = 0;
+
+ if ((modereg >= 64) ||
+ ((writeable & (1ULL << modereg)) == 0)) {
+ pr_err("%s %d is not writeable.\n",
+ __func__, modereg);
+ return -EIO;
+ }
+
+ pr_debug("%s LP_STATE is 0x%x\n",
+ __func__, MNH_DDR_CTL_INf(121, LP_STATE));
+ val = 0xFF & modereg;
+
+ /*
+ * bit 24 indicates all chip selects
+ * bit 23 indicates indicates a single mode reg
+ */
+ val |= (1 << 23) | (1 << 24);
+ MNH_DDR_CTL_OUTf(140, WRITE_MODEREG, val);
+ MNH_DDR_CTL_OUTf(160, MRSINGLE_DATA_0, modevalue);
+ /* trigger write */
+ val |= (1 << 25);
+ MNH_DDR_CTL_OUTf(140, WRITE_MODEREG, val);
+
+ timeout = jiffies + msecs_to_jiffies(500);
+ while (!mnh_ddr_int_status_bit(MR_WRITE_SBIT) &&
+ time_before(jiffies, timeout)) {
+ udelay(100);
+ }
+
+ if (mnh_ddr_int_status_bit(MR_WRITE_SBIT)) {
+ mnh_ddr_clr_int_status_bit(MR_WRITE_SBIT);
+ } else {
+ pr_err("%s timeout on MR write done. %llx.",
+ __func__, mnh_ddr_int_status());
+ ret = -EIO;
+ }
+ val = MNH_DDR_CTL_INf(141, MRW_STATUS);
+ if (val) {
+ pr_err("%s ERROR status: 0x%x", __func__, val);
+ ret = -EIO;
+ }
+
+ return ret;
}
static void mnh_ddr_enable_lp(void)
{
MNH_DDR_CTL_OUTf(124, LP_AUTO_SR_MC_GATE_IDLE, 0xFF);
- MNH_DDR_CTL_OUTf(122, LP_AUTO_MEM_GATE_EN, 0x4);
- MNH_DDR_CTL_OUTf(122, LP_AUTO_ENTRY_EN, 0x4);
- MNH_DDR_CTL_OUTf(122, LP_AUTO_EXIT_EN, 0xF);
+ if (MNH_DDR_CTL_INf(122, LP_AUTO_EXIT_EN) == 0)
+ MNH_DDR_CTL_OUTf(122, LP_AUTO_EXIT_EN, 0xF);
+ if (MNH_DDR_CTL_INf(122, LP_AUTO_MEM_GATE_EN) == 0)
+ MNH_DDR_CTL_OUTf(122, LP_AUTO_MEM_GATE_EN, 0x4);
+ if (MNH_DDR_CTL_INf(122, LP_AUTO_ENTRY_EN) == 0)
+ MNH_DDR_CTL_OUTf(122, LP_AUTO_ENTRY_EN, 0x4);
}
-static void mnh_ddr_disable_lp(struct device *dev)
+static void mnh_ddr_disable_lp(void)
{
- MNH_DDR_CTL_OUTf(124, LP_AUTO_SR_MC_GATE_IDLE, 0x00);
- MNH_DDR_CTL_OUTf(122, LP_AUTO_MEM_GATE_EN, 0x0);
MNH_DDR_CTL_OUTf(122, LP_AUTO_ENTRY_EN, 0x0);
- MNH_DDR_CTL_OUTf(122, LP_AUTO_EXIT_EN, 0x0);
- mnh_ddr_send_lp_cmd(dev, LP_CMD_EXIT_LP);
+ mnh_ddr_send_lp_cmd(LP_CMD_EXIT_LP);
}
static void mnh_ddr_init_internal_state(struct mnh_ddr_internal_state *_state,
- const struct mnh_ddr_reg_config *cfg)
+ const struct mnh_ddr_reg_config *cfg,
+ struct gpio_desc *iso_n)
{
+ _state->iso_n = iso_n;
_state->ctl_base = HWIO_DDR_CTL_BASE_ADDR;
_state->pi_base = HWIO_DDR_PI_BASE_ADDR;
_state->phy_base = HWIO_DDR_PHY_BASE_ADDR;
@@ -278,18 +440,14 @@
&(cfg->pi[0]),
MNH_DDR_NUM_PI_REG * sizeof(u32));
- _state->suspend_fsp = 0;
_state->tref[0] = cfg->ctl[56] & 0xFFFF;
_state->tref[1] = cfg->ctl[57] & 0xFFFF;
_state->tref[2] = cfg->ctl[58] & 0xFFFF;
_state->tref[3] = cfg->ctl[59] & 0xFFFF;
}
-static void mnh_ddr_init_clocks(struct mnh_ddr_data *data)
+static void mnh_ddr_init_clocks(struct device *dev, int fsp)
{
- struct device *dev = &data->pdev->dev;
- struct mnh_ddr_internal_state *_state = &data->_state;
-
int timeout = 0;
/* MNH_PLL_PASSCODE_SET */
@@ -312,44 +470,327 @@
dev_dbg(dev, "%s lpddr4 pll locked after %d iterations",
__func__, timeout);
- WRITE_SCU_FSP(_state, 0);
- WRITE_SCU_FSP(_state, 1);
- WRITE_SCU_FSP(_state, 2);
- WRITE_SCU_FSP(_state, 3);
+ /* WA for old HW bug to keep AXI, PCIE_AXI clk divs as nonzero
+ * during the first FSP switch
+ */
+ MNH_SCU_OUTf(CCU_CLK_DIV, AXI_FABRIC_CLK_DIV, 0x1);
+ MNH_SCU_OUTf(CCU_CLK_DIV, PCIE_AXI_CLK_DIV, 0x3);
- WRITE_CLK_FROM_FSP(dev, _state, SAVED_FSP(_state));
+ WRITE_SCU_FSP(0);
+ WRITE_SCU_FSP(1);
+ WRITE_SCU_FSP(2);
+ WRITE_SCU_FSP(3);
+
+ WRITE_CLK_FROM_FSP(fsp);
dev_dbg(dev, "%s lpddr4 pll locked", __func__);
MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FSP_SW_OVERRIDE, 0);
/* MNH_PLL_PASSCODE_CLR */
MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x0);
}
-static void mnh_ddr_pull_config(struct mnh_ddr_data *data)
+static void mnh_ddr_clear_lpc_status(void)
{
- struct mnh_ddr_internal_state *_state = &data->_state;
-
- int index, fsp;
- for (index = 0; index < MNH_DDR_NUM_CTL_REG; index++)
- SAVE_DDR_REG_CONFIG(_state, ctl, index);
- CLR_START(_state, ctl);
-
- for (index = 0; index < MNH_DDR_NUM_PI_REG; index++)
- SAVE_DDR_REG_CONFIG(_state, pi, index);
- CLR_START(_state, pi);
-
- for (fsp = 0; fsp < MNH_DDR_NUM_FSPS; fsp++) {
- MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, fsp);
- for (index = 0; index < MNH_DDR_NUM_PHY_REG; index++)
- SAVE_DDR_PHY_REG_CONFIG(_state, fsp, index);
+ /* Paranoia */
+ if (MNH_SCU_INf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ)) {
+ pr_info("%s LP4_FREQ_CHG_REQ already set, clearing", __func__);
+ MNH_SCU_OUTf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ, 1);
+ }
+ if (MNH_SCU_INf(SCU_IRQ_STATUS, LP4_LPC_CMD_DONE)) {
+ pr_info("%s LP4_LPC_CMD_DONE already set, clearing", __func__);
+ MNH_SCU_OUTf(SCU_IRQ_STATUS, LP4_LPC_CMD_DONE, 1);
+ }
+ if (MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_RSP)) {
+ pr_info("%s LPC_CMD_RSP already set, clearing", __func__);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_STS, LPC_CMD_RSP, 1);
+ }
+ if (MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE)) {
+ pr_info("%s LPC_CMD_DONE already set, clearing", __func__);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE, 1);
}
}
-int mnh_ddr_suspend(struct mnh_ddr_data *data, struct gpio_desc *iso_n)
-{
- struct device *dev = &data->pdev->dev;
- struct mnh_ddr_internal_state *_state = &data->_state;
+#define MR_TABLE_LEN 5
+const u8 mrw_fsps[MNH_DDR_NUM_FSPS][MR_TABLE_LEN][2] = {
+ {
+ { 1, 0x06 },
+ { 2, 0x00 },
+ { 3, 0x31 },
+ { 11, 0x00 },
+ { 22, 0x00 }
+ },
+ {
+ { 1, 0x06 },
+ { 2, 0x00 },
+ { 3, 0x31 },
+ { 11, 0x00 },
+ { 22, 0x00 },
+ },
+ {
+ { 1, 0x26 },
+ { 2, 0x12 },
+ { 3, 0x31 },
+ { 11, 0x00 },
+ { 22, 0x00 },
+ },
+ {
+ { 1, 0x46 },
+ { 2, 0x24 },
+ { 3, 0x31 },
+ { 11, 0x00 },
+ { 22, 0x00 },
+ }
+};
- mnh_ddr_disable_lp(dev);
+int mnh_ddr_sw_switch(int index)
+{
+ static int iteration;
+ u8 fsop, fswr;
+ u8 mr13val;
+ int old_lpi_wakeup_en, show_log, timeout;
+ int i, ret = -EIO;
+
+ uint16_t upd_high[MNH_DDR_NUM_FSPS];
+ uint16_t upd_norm[MNH_DDR_NUM_FSPS];
+
+ if ((index < 0) || (index >= MNH_DDR_NUM_FSPS)) {
+ pr_err("%s %d is not a valid FSP\n",
+ __func__, index);
+ return -EINVAL;
+ } else if (MNH_DDR_CTL_INf(133, CURRENT_REG_COPY) == index) {
+ pr_info("%s %d is already in use - skipping\n",
+ __func__, index);
+ return 0;
+ }
+ show_log = iteration++ % 1000;
+ if ((show_log == 0) || (show_log == 1)) {
+ pr_info("%s #%d fsp %d -> %d DLL RESET\n",
+ __func__, (iteration - 1),
+ MNH_DDR_CTL_INf(133, CURRENT_REG_COPY), index);
+ }
+
+ if (!MNH_SCU_INxf(LPDDR4_FSP_SETTING, index, FSP_SYS200_MODE))
+ mnh_lpddr_sys200_mode(false);
+
+ old_lpi_wakeup_en = MNH_DDR_CTL_INf(120, LPI_WAKEUP_EN);
+ /* need to make sure to disable lp, so phy regs
+ * and DRAM mode regs can be accessed.
+ */
+ mnh_ddr_disable_lp();
+ mnh_ddr_clr_int_status();
+
+ /* set software control */
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, index, FSP_SW_CTRL, 1);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0);
+
+ mnh_ddr_clear_lpc_status();
+
+ /* step 0 */
+ MNH_DDR_CTL_OUTf(221, INHIBIT_DRAM_CMD, 3);
+ MNH_DDR_CTL_OUTf(120, LPI_WAKEUP_EN, 0);
+ udelay(10);
+ MNH_DDR_CTL_OUTf(54, AREFRESH, 1);
+ /* CDNS added this line */
+ MNH_DDR_PHY_OUTf(1098, PHY_INIT_UPDATE_CONFIG, 0);
+
+ timeout = 1000;
+ udelay(1); /* CDNS addition start */
+ MNH_DDR_CTL_OUTf(112, LP_CMD, 1);
+ while (!mnh_ddr_int_status_bit(LP_CMD_SBIT) &&
+ timeout-- > 0) {
+ udelay(1);
+ }
+ if (mnh_ddr_clr_int_status_bit(LP_CMD_SBIT)) {
+ pr_err("%s %d LP_CMD not clearing\n",
+ __func__, __LINE__);
+ ret = -EIO;
+ goto sw_switch_error_exit;
+ } /* CDNS addition end */
+
+ timeout = 1000;
+ while (!mnh_ddr_int_status_bit(INHIBIT_DRAM_CMD_SBIT) && timeout-- > 0)
+ udelay(1);
+ if (mnh_ddr_clr_int_status_bit(INHIBIT_DRAM_CMD_SBIT)) {
+ pr_err("%s %d INHIBIT not clearing\n",
+ __func__, __LINE__);
+ ret = -EIO;
+ goto sw_switch_error_exit;
+ }
+
+ MNH_DDR_CTL_OUTf(223, CTRLUPD_REQ_PER_AREF_EN, 0);
+ MNH_DDR_CTL_OUTf(525, CTRLUPD_AREF_HP_ENABLE, 0);
+ MNH_DDR_PHY_OUTf(1100, PHY_UPDATE_MASK, 1);
+ /* step 1 */
+ upd_high[0] = MNH_DDR_CTL_INf(88, UPD_CTRLUPD_HIGH_THRESHOLD_F0);
+ upd_norm[0] = MNH_DDR_CTL_INf(88, UPD_CTRLUPD_NORM_THRESHOLD_F0);
+ upd_high[1] = MNH_DDR_CTL_INf(91, UPD_CTRLUPD_HIGH_THRESHOLD_F1);
+ upd_norm[1] = MNH_DDR_CTL_INf(90, UPD_CTRLUPD_NORM_THRESHOLD_F1);
+ upd_high[2] = MNH_DDR_CTL_INf(93, UPD_CTRLUPD_HIGH_THRESHOLD_F2);
+ upd_norm[2] = MNH_DDR_CTL_INf(93, UPD_CTRLUPD_NORM_THRESHOLD_F2);
+ upd_high[3] = MNH_DDR_CTL_INf(96, UPD_CTRLUPD_HIGH_THRESHOLD_F3);
+ upd_norm[3] = MNH_DDR_CTL_INf(95, UPD_CTRLUPD_NORM_THRESHOLD_F3);
+
+ MNH_DDR_CTL_OUTf(88, UPD_CTRLUPD_HIGH_THRESHOLD_F0, 0);
+ MNH_DDR_CTL_OUTf(88, UPD_CTRLUPD_NORM_THRESHOLD_F0, 0);
+ MNH_DDR_CTL_OUTf(91, UPD_CTRLUPD_HIGH_THRESHOLD_F1, 0);
+ MNH_DDR_CTL_OUTf(90, UPD_CTRLUPD_NORM_THRESHOLD_F1, 0);
+ MNH_DDR_CTL_OUTf(93, UPD_CTRLUPD_HIGH_THRESHOLD_F2, 0);
+ MNH_DDR_CTL_OUTf(93, UPD_CTRLUPD_NORM_THRESHOLD_F2, 0);
+ MNH_DDR_CTL_OUTf(96, UPD_CTRLUPD_HIGH_THRESHOLD_F3, 0);
+ MNH_DDR_CTL_OUTf(95, UPD_CTRLUPD_NORM_THRESHOLD_F3, 0);
+
+ fsop = MNH_DDR_CTL_INf(169, FSP_OP_CURRENT);
+ fswr = !MNH_DDR_CTL_INf(169, FSP_WR_CURRENT);
+
+ mr13val = (fsop << 7) | (fswr << 6) | (1 << 4);
+ if (mnh_ddr_write_mode_reg(13, mr13val)) {
+ pr_err("%s %d error writing MR13\n",
+ __func__, __LINE__);
+ ret = -EIO;
+ goto sw_switch_error_exit;
+ }
+
+ /* step 2 */
+ for (i = 0; i < MR_TABLE_LEN; i++) {
+ if (mnh_ddr_write_mode_reg(mrw_fsps[index][i][0],
+ mrw_fsps[index][i][1])) {
+ pr_err("%s %d error (%d %d) writing mr: 0x%02x\n",
+ __func__, __LINE__, index, i,
+ mrw_fsps[index][i][0]);
+ ret = -EIO;
+ goto sw_switch_error_exit;
+ }
+ }
+
+ /* step 3 */
+ fsop = (fsop == 1) ? 0 : 1;
+ mr13val = (fsop << 7) | (fswr << 6) | (1 << 4) | (1 << 3);
+ if (mnh_ddr_write_mode_reg(13, mr13val)) {
+ pr_err("%s %d error writing MR13\n",
+ __func__, __LINE__);
+ ret = -EIO;
+ goto sw_switch_error_exit;
+ }
+ fswr = (fswr == 1) ? 0 : 1;
+
+ /* step 4 */
+ mnh_ddr_send_lp_cmd(LP_CMD_SRPD);
+ /* step 5 */
+ /* removed using iso for switch */
+ /* step 6 moved to step 0 */
+ /* step 7 */
+ MNH_DDR_PHY_OUTf(1099, PHY_DLL_RST_EN, 1);
+
+ /* step 8 */
+ /* Prepare memory controller for switch */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_FREQ_CHG_COPY_NUM, index);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_EXT_CMD, LP_CMD_FREQ_SWITCH);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LPC_EXT_CMD_REQ, 1);
+
+ timeout = 1000;
+ while (!MNH_SCU_INf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ) &&
+ (timeout-- > 0))
+ udelay(1);
+
+ if (!MNH_SCU_INf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ)) {
+ pr_err("%s: Missed SCU_IRQ_STATUS.LP4_FREQ_CHG_REQ!\n",
+ __func__);
+ ret = -ETIME;
+ goto sw_switch_error_exit;
+ }
+
+ /* clear it */
+ MNH_SCU_OUTf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ, 1);
+ /* load clock settings from the fsp of interest */
+ WRITE_CLK_FROM_FSP(index);
+ /* effect the clock change */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FSP_SW_OVERRIDE, 1);
+ udelay(100);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FSP_SW_OVERRIDE, 0);
+
+ /* step 9 */
+ MNH_DDR_PHY_OUTf(1099, PHY_DLL_RST_EN, 2);
+ /* step 10 */
+ /* inform memory controller freq change is done */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FREQ_CHG_ACK, 1);
+ timeout = 1000;
+ while (!MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE) &&
+ (timeout-- > 0))
+ udelay(1);
+
+ if (!MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE)) {
+ pr_err("%s Missed: LPDDR4_LOW_POWER_STS.LPC_CMD_DONE\n",
+ __func__);
+ ret = -ETIME;
+ goto sw_switch_error_exit;
+ }
+
+ /* steps 11 - 13 removed because we're not using iso */
+
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG, LP4_FSP_SW_OVERRIDE, 0);
+ /* clear done */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_STS, LPC_CMD_DONE, 1);
+ /* step 14 */
+ /* undo previous changes. */
+ MNH_DDR_CTL_OUTf(223, CTRLUPD_REQ_PER_AREF_EN, 1);
+ MNH_DDR_CTL_OUTf(525, CTRLUPD_AREF_HP_ENABLE, 1);
+ /* CDNS added this line */
+ MNH_DDR_PHY_OUTf(1098, PHY_INIT_UPDATE_CONFIG, 7);
+ MNH_DDR_PHY_OUTf(1100, PHY_UPDATE_MASK, 0);
+ MNH_DDR_CTL_OUTf(221, INHIBIT_DRAM_CMD, 0);
+ MNH_DDR_CTL_OUTf(88, UPD_CTRLUPD_HIGH_THRESHOLD_F0, upd_high[0]);
+ MNH_DDR_CTL_OUTf(88, UPD_CTRLUPD_NORM_THRESHOLD_F0, upd_norm[0]);
+ MNH_DDR_CTL_OUTf(91, UPD_CTRLUPD_HIGH_THRESHOLD_F1, upd_high[1]);
+ MNH_DDR_CTL_OUTf(90, UPD_CTRLUPD_NORM_THRESHOLD_F1, upd_norm[1]);
+ MNH_DDR_CTL_OUTf(93, UPD_CTRLUPD_HIGH_THRESHOLD_F2, upd_high[2]);
+ MNH_DDR_CTL_OUTf(93, UPD_CTRLUPD_NORM_THRESHOLD_F2, upd_norm[2]);
+ MNH_DDR_CTL_OUTf(96, UPD_CTRLUPD_HIGH_THRESHOLD_F3, upd_high[3]);
+ MNH_DDR_CTL_OUTf(95, UPD_CTRLUPD_NORM_THRESHOLD_F3, upd_norm[3]);
+
+ MNH_DDR_CTL_OUTf(120, LPI_WAKEUP_EN, old_lpi_wakeup_en);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, index, FSP_SW_CTRL, 0);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0);
+
+ mnh_ddr_clr_int_status_bit(DFI_UPDATE_ERROR_SBIT);
+ mnh_ddr_clr_int_status_bit(DFS_COMPLETE_SBIT);
+ mnh_ddr_clr_int_status_bit(DFI_STATE_CHANGE_SBIT);
+ ret = 0;
+
+ if (MNH_SCU_INxf(LPDDR4_FSP_SETTING, index, FSP_SYS200_MODE))
+ mnh_lpddr_sys200_mode(true);
+
+sw_switch_error_exit:
+ if (mnh_ddr_print_phy_status())
+ ret = -EIO;
+
+ return ret;
+}
+
+static void mnh_ddr_pull_config(void)
+{
+ int index, fsp;
+ for (index = 0; index < MNH_DDR_NUM_CTL_REG; index++)
+ SAVE_DDR_REG_CONFIG(ctl, index);
+ CLR_START(ctl);
+
+ for (index = 0; index < MNH_DDR_NUM_PI_REG; index++)
+ SAVE_DDR_REG_CONFIG(pi, index);
+ CLR_START(pi);
+
+ for (fsp = 0; fsp < MNH_DDR_NUM_BANKED_FSPS; fsp++) {
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, fsp);
+ for (index = 0; index < MNH_DDR_NUM_PHY_REG; index++)
+ SAVE_DDR_PHY_REG_CONFIG(fsp, index);
+ }
+}
+
+int mnh_ddr_suspend(struct device *dev)
+{
+ if (WARN_ON(!_state))
+ return -ENOMEM;
+
+ mnh_ddr_disable_lp();
dev_dbg(dev, "%s: tref 0x%04x 0x%04x 0x%04x 0x%04x\n",
__func__, MNH_DDR_CTL_INf(56, TREF_F0),
@@ -368,12 +809,18 @@
MNH_DDR_CTL_OUTf(58, TREF_F2, _state->tref[2]);
MNH_DDR_CTL_OUTf(59, TREF_F3, _state->tref[3]);
- /* resume to fsp3 */
- mnh_lpddr_freq_change(LPDDR_FREQ_FSP3);
- SAVE_CURRENT_FSP(dev, _state);
- mnh_ddr_pull_config(data);
+ if (MNH_DDR_CTL_INf(133, CURRENT_REG_COPY) !=
+ LPDDR_FREQ_FSP3) {
+ /* resume to fsp3 */
+ if (mnh_lpddr_freq_change(LPDDR_FREQ_FSP3)) {
+ dev_err(dev, "%s ERROR suspend clock switch failed.",
+ __func__);
+ return -EIO;
+ }
+ }
+ mnh_ddr_pull_config();
- mnh_ddr_send_lp_cmd(dev, LP_CMD_DSRPD);
+ mnh_ddr_send_lp_cmd(LP_CMD_DSRPD);
dev_dbg(dev, "%s LP_STATE is 0x%x", __func__,
MNH_DDR_CTL_INf(121, LP_STATE));
@@ -384,44 +831,40 @@
MNH_SCU_OUTf(CCU_CLK_CTL, LP4_REFCLKEN, 0);
udelay(1);
- gpiod_set_value_cansleep(iso_n, 0);
- udelay(1);
-
- dev_dbg(dev, "%s done.", __func__);
+ MNH_DDR_ASSERT_ISO_N();
+ dev_dbg(dev, "%s iso is asserted", __func__);
return 0;
}
EXPORT_SYMBOL(mnh_ddr_suspend);
-int mnh_ddr_resume(struct mnh_ddr_data *data, struct gpio_desc *iso_n)
+int mnh_ddr_resume(struct device *dev)
{
- struct device *dev = &data->pdev->dev;
- struct mnh_ddr_internal_state *_state = &data->_state;
-
int index, fsp;
- int timeout = 0;
+ unsigned long timeout = 0;
+ unsigned long start_jiff, end_jiff;
- mnh_ddr_init_clocks(data);
+ if (WARN_ON(!_state))
+ return -ENOMEM;
+
+ mnh_ddr_init_clocks(dev, LPDDR_FREQ_FSP3);
+
+ if (!mnh_ddr_sanity_check())
+ return -EIO;
for (index = 0; index < MNH_DDR_NUM_CTL_REG; index++)
- WRITE_DDR_REG_CONFIG(_state, ctl, index);
-
- MNH_DDR_CTL_OUTf(23, DFIBUS_FREQ_INIT, SAVED_FSP(_state));
- MNH_DDR_CTL_OUTf(23, DFIBUS_BOOT_FREQ, 0);
-
- MNH_DDR_CTL_OUTf(23, PHY_INDEP_TRAIN_MODE, 0);
- MNH_DDR_CTL_OUTf(23, CDNS_INTRL0, 1);
+ WRITE_DDR_REG_CONFIG(ctl, index);
for (index = 0; index < MNH_DDR_NUM_PI_REG; index++)
- WRITE_DDR_REG_CONFIG(_state, pi, index);
+ WRITE_DDR_REG_CONFIG(pi, index);
- for (fsp = 0; fsp < MNH_DDR_NUM_FSPS; fsp++) {
+ for (fsp = 0; fsp < MNH_DDR_NUM_BANKED_FSPS; fsp++) {
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_MULTICAST_EN, 0);
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, fsp);
for (index = 0; index < MNH_DDR_NUM_PHY_REG; index++) {
if (index != 1025)
- WRITE_DDR_PHY_CONFIG(_state, fsp, index);
+ WRITE_DDR_PHY_CONFIG(fsp, index);
}
MNH_DDR_PHY_OUTf(1084, PHY_CAL_CLK_SELECT_0, 0x4);
}
@@ -441,75 +884,68 @@
udelay(1000);
MNH_DDR_PHY_OUTf(1051, PHY_SET_DFI_INPUT_RST_PAD, 1);
- gpiod_set_value_cansleep(iso_n, 1);
+ MNH_DDR_DEASSERT_ISO_N();
udelay(1000);
-
MNH_DDR_CTL_OUTf(00, START, 1);
+ start_jiff = jiffies;
+ timeout = start_jiff + RESUME_TIMEOUT;
- dev_dbg(dev, "%s waiting for init done.", __func__);
+ dev_dbg(dev, "%s waiting for ctl init done.", __func__);
+ while ((!mnh_ddr_int_status_bit(INIT_DONE_SBIT)) &&
+ time_before(jiffies, timeout))
+ udelay(10);
- timeout = 0;
- while ((timeout < 1000) && (!mnh_ddr_int_status_bit(INIT_DONE_SBIT))) {
- udelay(1);
- timeout++;
- }
+ end_jiff = jiffies;
+ dev_dbg(dev, "%s time elapsed is %u ms",
+ __func__, jiffies_to_msecs(end_jiff - start_jiff));
if (!mnh_ddr_int_status_bit(INIT_DONE_SBIT)) {
dev_err(dev, "%s time out on init done %llx.\n",
- __func__, mnh_ddr_int_status(dev));
+ __func__, mnh_ddr_int_status());
return -ETIMEDOUT;
}
/* need to clear PWRUP_SREFRESH_EXIT to clear interrupt status bit 0 */
MNH_DDR_CTL_OUTf(81, PWRUP_SREFRESH_EXIT, 0);
dev_dbg(dev, "%s got init done %llx.\n", __func__,
- mnh_ddr_int_status(dev));
- mnh_ddr_clr_int_status(dev);
- mnh_lpddr_freq_change(SAVED_FSP(_state));
-
- dev_dbg(dev, "%s: tref 0x%04x 0x%04x 0x%04x 0x%04x\n",
- __func__, MNH_DDR_CTL_INf(56, TREF_F0),
- MNH_DDR_CTL_INf(57, TREF_F1), MNH_DDR_CTL_INf(58, TREF_F2),
- MNH_DDR_CTL_INf(59, TREF_F3));
-
+ mnh_ddr_int_status());
+ mnh_ddr_clr_int_status();
mnh_ddr_enable_lp();
return 0;
}
EXPORT_SYMBOL(mnh_ddr_resume);
-int mnh_ddr_po_init(struct mnh_ddr_data *data, struct gpio_desc *iso_n)
+int mnh_ddr_po_init(struct device *dev, struct gpio_desc *iso_n)
{
- struct device *dev = &data->pdev->dev;
- struct mnh_ddr_internal_state *_state = &data->_state;
-
- int index, setindex;
+ int index, setindex, pi_step;
unsigned long timeout;
const struct mnh_ddr_reg_config *cfg = &mnh_ddr_33_100_400_600;
- mnh_ddr_init_internal_state(_state, cfg);
+ if (WARN_ON(!_state))
+ return -ENOMEM;
+ mnh_ddr_init_internal_state(_state, cfg, iso_n);
dev_dbg(dev, "%s start.", __func__);
/* deassert iso_n */
- gpiod_set_value_cansleep(iso_n, 1);
+ MNH_DDR_DEASSERT_ISO_N();
+ mnh_ddr_init_clocks(dev, LPDDR_FREQ_FSP0);
- mnh_ddr_init_clocks(data);
+ if (!mnh_ddr_sanity_check())
+ return -EIO;
for (index = 0; index < MNH_DDR_NUM_CTL_REG; index++)
- WRITE_DDR_REG_CONFIG(_state, ctl, index);
-
- /* Make sure DRAM will request refresh rate adjustments */
- MNH_DDR_CTL_OUTf(164, MR13_DATA_0, 0xD0);
+ WRITE_DDR_REG_CONFIG(ctl, index);
for (index = 0; index < MNH_DDR_NUM_PI_REG; index++)
- WRITE_DDR_REG_CONFIG(_state, pi, index);
+ WRITE_DDR_REG_CONFIG(pi, index);
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_MULTICAST_EN, 1);
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 0);
for (index = 0; index < MNH_DDR_NUM_PHY_REG; index++)
- WRITE_DDR_PHY_CONFIG(_state, 0, index);
+ WRITE_DDR_PHY_CONFIG(0, index);
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_MULTICAST_EN, 0);
MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 1);
@@ -518,9 +954,8 @@
setindex = 0;
while ((setindex < MNH_DDR_PHY_SET_SIZE) &&
(cfg->phy_setA[setindex][0] != 0xFFFFFFFF)) {
- WRITE_SET_ELEMENT(_state,
- cfg->phy_setA[setindex][0],
- cfg->phy_setA[setindex][1]);
+ WRITE_SET_ELEMENT(cfg->phy_setA[setindex][0],
+ cfg->phy_setA[setindex][1]);
setindex++;
}
@@ -530,40 +965,148 @@
setindex = 0;
while ((setindex < MNH_DDR_PHY_SET_SIZE) &&
(cfg->phy_setB[setindex][0] != 0xFFFFFFFF)) {
- WRITE_SET_ELEMENT(_state,
- cfg->phy_setB[setindex][0],
- cfg->phy_setB[setindex][1]);
+ WRITE_SET_ELEMENT(cfg->phy_setB[setindex][0],
+ cfg->phy_setB[setindex][1]);
setindex++;
}
+ /* set the index back to 1 to enable PI WA training */
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 1);
+ /* Add SCU register change to enable SW switching for all 4 FSPs. */
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, 0, FSP_SW_CTRL, 1);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, 1, FSP_SW_CTRL, 1);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, 2, FSP_SW_CTRL, 1);
+ MNH_SCU_OUTxf(LPDDR4_FSP_SETTING, 3, FSP_SW_CTRL, 1);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x0);
+
dev_dbg(dev, "%s begin training,", __func__);
MNH_DDR_PI_OUTf(00, PI_START, 1);
MNH_DDR_CTL_OUTf(00, START, 1);
- timeout = jiffies + TRAINING_TIMEOUT;
- while (time_before(jiffies, timeout) &&
- (!mnh_ddr_int_status_bit(INIT_DONE_SBIT)))
- usleep_range(100, 200);
+ /*
+ * The 11 DFS events during PI training are to be tracked,
+ * and apply WA at correct points.
+ * 1. FSP0 to FSP1
+ * 2. FSP1 to FSP2
+ * 3. FSP2 to FSP1
+ * 4. FSP1 to FSP2
+ * 5. FSP2 to FSP1 - Program POSTDIV of FSP2 to 1 at
+ * pi_freq_change_req event
+ * 6. FSP1 to FSP2 - Program POSTDIV of FSP2 to 0 at
+ * pi_freq_change_req event, provide 400 MHz, set pi_freq_change_ack = 1
+ * 7. FSP2 to FSP3
+ * 8. FSP3 to FSP2
+ * 9. FSP2 to FSP3
+ * 10. FSP3 to FSP2 - Program POSTDIV of FSP2&FSP3 to 1 at
+ * pi_freq_change_req event, Provide 300 MHz clock instead of usual
+ * 400 MHz clock, set pi_freq_change_ack = 1
+ * 11. FSP2 to FSP3 - Program POSTDIV of FSP2&FSP3 to 0 at
+ * pi_freq_change_req event, provide 600 MHz, set pi_freq_change_ack = 1
+ *
+ */
+ dev_info(dev, "%s PI WA training,", __func__);
+ for (pi_step = 1; pi_step <= 11; pi_step++) {
+ timeout = 10000;
+ while (!MNH_SCU_INf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ) &&
+ (timeout-- > 0))
+ udelay(1);
+ if (!MNH_SCU_INf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ)) {
+ dev_err(dev, "%s: Missed SCU_IRQ_STATUS.LP4_FREQ_CHG_REQ! pi_step=%d, LPDDR4_REQ_FSP=0x%x\n",
+ __func__,
+ pi_step,
+ MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPDDR4_REQ_FSP));
+ return -ETIME;
+ }
+ dev_dbg(dev, "%s: pi_step=%d, LPDDR4_REQ_FSP=0x%x, INDEX=%d\n",
+ __func__,
+ pi_step,
+ MNH_SCU_INf(LPDDR4_LOW_POWER_STS, LPDDR4_REQ_FSP),
+ MNH_DDR_PHY_INf(1025, PHY_FREQ_SEL_INDEX));
+ /* clear it */
+ MNH_SCU_OUTf(SCU_IRQ_STATUS, LP4_FREQ_CHG_REQ, 1);
- if (!mnh_ddr_int_status_bit(INIT_DONE_SBIT)) {
- dev_err(dev, "%s timed out on init done.\n", __func__);
+ /* Change PHY PLL POSTDIV at Step 5,6,10,11 */
+ switch (pi_step) {
+ case 5:
+ /* change postdiv of CA PLL */
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x322);
+ break;
+ case 6:
+ /* change postdiv of CA PLL for f2 register set */
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x122);
+ break;
+ case 10:
+ /* change postdiv of CA PLL for f2/f3 register set */
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 1);
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x322);
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 2);
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x322);
+ break;
+ case 11:
+ /* change postdiv of CA PLL for f2 register set */
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 1);
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x122);
+ MNH_DDR_PHY_OUTf(1025, PHY_FREQ_SEL_INDEX, 2);
+ MNH_DDR_PHY_OUTf(1046, PHY_PLL_CTRL_CA, 0x122);
+ break;
+ }
+
+ /* Freeze the divider settings till all registers are updated */
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTf(LPDDR4_REFCLK_PLL_CTRL, FRZ_PLL_IN, 1);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x0);
+ /* load clock settings from the fsp of interest based on PI's
+ * fsp request
+ */
+ WRITE_CLK_FROM_FSP_NO_LOCK((MNH_SCU_INf(LPDDR4_LOW_POWER_STS,
+ LPDDR4_REQ_FSP)));
+ /* Provide 300 MHz clock */
+ if (pi_step == 10)
+ /* 1200 MHz div by 4 */
+ MNH_SCU_OUTf(CCU_CLK_DIV, LPDDR4_REFCLK_DIV, 3);
+ /* UnFreeze the divider settings till all regs are updated */
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x4CD9);
+ MNH_SCU_OUTf(LPDDR4_REFCLK_PLL_CTRL, FRZ_PLL_IN, 0);
+ MNH_SCU_OUTf(PLL_PASSCODE, PASSCODE, 0x0);
+ /* effect the clock change */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG,
+ LP4_FSP_SW_OVERRIDE, 1);
+ /* inform memory controller freq change is done */
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG,
+ LP4_FREQ_CHG_ACK, 1);
+ MNH_SCU_OUTf(LPDDR4_LOW_POWER_CFG,
+ LP4_FSP_SW_OVERRIDE, 0);
+ }
+
+ timeout = jiffies + msecs_to_jiffies(50);
+ while (!(mnh_ddr_int_status_bit(INIT_DONE_SBIT) &&
+ mnh_ddr_pi_int_status_bit(PI_INIT_DONE_BIT)) &&
+ time_before(jiffies, timeout))
+ udelay(100);
+
+ if (!mnh_ddr_int_status_bit(INIT_DONE_SBIT) ||
+ !mnh_ddr_pi_int_status_bit(PI_INIT_DONE_BIT)) {
+ dev_err(dev, "%s timed out on init done. 0x%llx 0x%08x\n",
+ __func__,
+ mnh_ddr_int_status(),
+ MNH_DDR_PI_INf(172, PI_INT_STATUS));
return -ETIMEDOUT;
}
dev_dbg(dev, "%s got init done %llx.\n", __func__,
- mnh_ddr_int_status(dev));
+ mnh_ddr_int_status());
- mnh_ddr_clr_int_status(dev);
+ mnh_ddr_clr_int_status();
MNH_DDR_CTL_OUTf(165, MR_FSP_DATA_VALID_F0_0, 1);
MNH_DDR_CTL_OUTf(165, MR_FSP_DATA_VALID_F1_0, 1);
MNH_DDR_CTL_OUTf(165, MR_FSP_DATA_VALID_F2_0, 1);
MNH_DDR_CTL_OUTf(166, MR_FSP_DATA_VALID_F3_0, 1);
- dev_dbg(dev, "%s: tref 0x%04x 0x%04x 0x%04x 0x%04x\n",
- __func__, MNH_DDR_CTL_INf(56, TREF_F0),
- MNH_DDR_CTL_INf(57, TREF_F1), MNH_DDR_CTL_INf(58, TREF_F2),
- MNH_DDR_CTL_INf(59, TREF_F3));
-
+ dev_dbg(dev, "%s done\n", __func__);
+ /* settings to take effect on resume */
+ MNH_DDR_CTL_OUTf(23, PHY_INDEP_TRAIN_MODE, 0);
+ MNH_DDR_CTL_OUTf(23, CDNS_INTRL0, 1);
mnh_ddr_enable_lp();
/* Enable FSP3 => 2400 */
@@ -573,10 +1116,8 @@
}
EXPORT_SYMBOL(mnh_ddr_po_init);
-u32 mnh_ddr_mbist(struct mnh_ddr_data *data, enum mnh_ddr_bist_type bist_type)
+u32 mnh_ddr_mbist(struct device *dev, enum mnh_ddr_bist_type bist_type)
{
- struct device *dev = &data->pdev->dev;
-
u32 result = 0;
u32 timeout = 1000000;
const u32 pattern[] = {
@@ -595,7 +1136,7 @@
return 0;
}
- mnh_ddr_disable_lp(dev);
+ mnh_ddr_disable_lp();
old_in_order_accept = MNH_DDR_CTL_INf(223, IN_ORDER_ACCEPT);
MNH_DDR_CTL_OUTf(223, IN_ORDER_ACCEPT, 1);
@@ -625,14 +1166,14 @@
if (!mnh_ddr_int_status_bit(BIST_SBIT)) {
dev_err(dev, "%s: BIST timedout: %llx\n",
- __func__, mnh_ddr_int_status(dev));
+ __func__, mnh_ddr_int_status());
} else {
result = MNH_DDR_CTL_INf(171, BIST_RESULT);
dev_info(dev, "%s: result 0x%02x\n", __func__, result);
}
MNH_DDR_CTL_OUTf(171, BIST_GO, 0);
- mnh_ddr_clr_int_status(dev);
+ mnh_ddr_clr_int_status();
MNH_DDR_CTL_OUTf(223, IN_ORDER_ACCEPT,
old_in_order_accept);
@@ -642,10 +1183,15 @@
}
EXPORT_SYMBOL(mnh_ddr_mbist);
-int mnh_ddr_platform_init(struct platform_device *pdev,
- struct mnh_ddr_data *data)
+int mnh_ddr_platform_init(struct device *dev)
{
- data->pdev = pdev;
+ dev_dbg(dev, "%s\n", __func__);
+
+ _state = devm_kzalloc(dev, sizeof(struct mnh_ddr_internal_state),
+ GFP_KERNEL);
+ if (!_state)
+ return -ENOMEM;
+
return 0;
}
EXPORT_SYMBOL_GPL(mnh_ddr_platform_init);
diff --git a/drivers/misc/mnh/mnh-ddr.h b/drivers/misc/mnh/mnh-ddr.h
index 372ca55..c609cc4 100644
--- a/drivers/misc/mnh/mnh-ddr.h
+++ b/drivers/misc/mnh/mnh-ddr.h
@@ -20,13 +20,13 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
-#include <linux/platform_device.h>
#define MNH_DDR_NUM_CTL_REG (558 + 1)
#define MNH_DDR_NUM_PHY_REG (1100 + 1)
#define MNH_DDR_NUM_PI_REG (191 + 1)
#define MNH_DDR_NUM_FSPS (4)
+#define MNH_DDR_NUM_BANKED_FSPS (3)
#define MNH_DDR_NUM_BASES (3)
/* arbitrary but sufficient size for phy deltas */
@@ -48,10 +48,10 @@
u32 pi_base;
u32 pi[MNH_DDR_NUM_PI_REG];
u32 phy_base;
- u32 phy[MNH_DDR_NUM_FSPS][MNH_DDR_NUM_PHY_REG];
+ u32 phy[MNH_DDR_NUM_BANKED_FSPS][MNH_DDR_NUM_PHY_REG];
u32 fsps[MNH_DDR_NUM_FSPS];
- u32 suspend_fsp;
u32 tref[MNH_DDR_NUM_FSPS];
+ struct gpio_desc *iso_n;
};
enum mnh_ddr_bist_type {
@@ -59,18 +59,15 @@
LIMITED_MOVI1_3N,
};
-struct mnh_ddr_data {
- struct platform_device *pdev;
- struct mnh_ddr_internal_state _state;
-};
+/* mnh-ddr driver init called during mnh-sm probe */
+int mnh_ddr_platform_init(struct device *dev);
-int mnh_ddr_platform_init(struct platform_device *pdev,
- struct mnh_ddr_data *data);
-int mnh_ddr_po_init(struct mnh_ddr_data *data, struct gpio_desc *iso_n);
-int mnh_ddr_resume(struct mnh_ddr_data *data, struct gpio_desc *iso_n);
-int mnh_ddr_suspend(struct mnh_ddr_data *data, struct gpio_desc *iso_n);
-int mnh_ddr_clr_int_status(struct device *dev);
-u64 mnh_ddr_int_status(struct device *dev);
-u32 mnh_ddr_mbist(struct mnh_ddr_data *data, enum mnh_ddr_bist_type bist_type);
+int mnh_ddr_po_init(struct device *dev, struct gpio_desc *iso_n);
+int mnh_ddr_resume(struct device *dev);
+int mnh_ddr_suspend(struct device *dev);
+int mnh_ddr_clr_int_status(void);
+u64 mnh_ddr_int_status(void);
+u32 mnh_ddr_mbist(struct device *dev, enum mnh_ddr_bist_type bist_type);
+int mnh_ddr_sw_switch(int index);
#endif /* __MNH_DDR_H__ */
diff --git a/drivers/misc/mnh/mnh-hwio-cpu.h b/drivers/misc/mnh/mnh-hwio-cpu.h
new file mode 100644
index 0000000..3644dea
--- /dev/null
+++ b/drivers/misc/mnh/mnh-hwio-cpu.h
@@ -0,0 +1,136 @@
+/* auto generated: Monday, August 15th, 2016 12:26:47pm */
+/* gucheng: edit 11/07/2018 for checkpatch */
+/*
+ * Copyright (c) 2016, Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Intel nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __MNH_HWIO_CPU_
+#define __MNH_HWIO_CPU_
+
+#define HWIO_CPU_CFG_REGOFF 0x0
+#define HWIO_CPU_CFG_ADDR(bAddr, regX) (bAddr + HWIO_CPU_CFG_REGOFF)
+#define HWIO_CPU_CFG_CLUSTERIDAFF2_FLDMASK (0xff000000)
+#define HWIO_CPU_CFG_CLUSTERIDAFF2_FLDSHFT (24)
+#define HWIO_CPU_CFG_CLUSTERIDAFF1_FLDMASK (0xff0000)
+#define HWIO_CPU_CFG_CLUSTERIDAFF1_FLDSHFT (16)
+#define HWIO_CPU_CFG_RSVD0_FLDMASK (0xfff0)
+#define HWIO_CPU_CFG_RSVD0_FLDSHFT (4)
+#define HWIO_CPU_CFG_VINITHI_FLDMASK (0x8)
+#define HWIO_CPU_CFG_VINITHI_FLDSHFT (3)
+#define HWIO_CPU_CFG_CFGTE_FLDMASK (0x4)
+#define HWIO_CPU_CFG_CFGTE_FLDSHFT (2)
+#define HWIO_CPU_CFG_CFGEND_FLDMASK (0x2)
+#define HWIO_CPU_CFG_CFGEND_FLDSHFT (1)
+#define HWIO_CPU_CFG_AA64nAA32_FLDMASK (0x1)
+#define HWIO_CPU_CFG_AA64nAA32_FLDSHFT (0)
+
+#define HWIO_CPU_RST_CFG_REGOFF 0x4
+#define HWIO_CPU_RST_CFG_ADDR(bAddr, regX) (bAddr + HWIO_CPU_RST_CFG_REGOFF)
+#define HWIO_CPU_RST_CFG_RSVD0_FLDMASK (0xfffffffc)
+#define HWIO_CPU_RST_CFG_RSVD0_FLDSHFT (2)
+#define HWIO_CPU_RST_CFG_DBGL1RSTDISABLE_FLDMASK (0x2)
+#define HWIO_CPU_RST_CFG_DBGL1RSTDISABLE_FLDSHFT (1)
+#define HWIO_CPU_RST_CFG_L2RSTDISABLE_FLDMASK (0x1)
+#define HWIO_CPU_RST_CFG_L2RSTDISABLE_FLDSHFT (0)
+
+#define HWIO_CPU_RST_STS_REGOFF 0x8
+#define HWIO_CPU_RST_STS_ADDR(bAddr, regX) (bAddr + HWIO_CPU_RST_STS_REGOFF)
+#define HWIO_CPU_RST_STS_RSVD0_FLDMASK (0xfffffffc)
+#define HWIO_CPU_RST_STS_RSVD0_FLDSHFT (2)
+#define HWIO_CPU_RST_STS_DBGRSTREQ_FLDMASK (0x2)
+#define HWIO_CPU_RST_STS_DBGRSTREQ_FLDSHFT (1)
+#define HWIO_CPU_RST_STS_WARMRSTREQ_FLDMASK (0x1)
+#define HWIO_CPU_RST_STS_WARMRSTREQ_FLDSHFT (0)
+
+#define HWIO_CPU_PWR_MGMT_CFG_REGOFF 0x0C
+#define HWIO_CPU_PWR_MGMT_CFG_ADDR(bAddr, regX) \
+ (bAddr + HWIO_CPU_PWR_MGMT_CFG_REGOFF)
+#define HWIO_CPU_PWR_MGMT_CFG_RSVD0_FLDMASK (0xfffffffc)
+#define HWIO_CPU_PWR_MGMT_CFG_RSVD0_FLDSHFT (2)
+#define HWIO_CPU_PWR_MGMT_CFG_L2FLUSHREQ_FLDMASK (0x2)
+#define HWIO_CPU_PWR_MGMT_CFG_L2FLUSHREQ_FLDSHFT (1)
+#define HWIO_CPU_PWR_MGMT_CFG_EVENTI_FLDMASK (0x1)
+#define HWIO_CPU_PWR_MGMT_CFG_EVENTI_FLDSHFT (0)
+
+#define HWIO_CPU_PWR_MGMT_STS_REGOFF 0x10
+#define HWIO_CPU_PWR_MGMT_STS_ADDR(bAddr, regX) \
+ (bAddr + HWIO_CPU_PWR_MGMT_STS_REGOFF)
+#define HWIO_CPU_PWR_MGMT_STS_RSVD0_FLDMASK (0xffffff00)
+#define HWIO_CPU_PWR_MGMT_STS_RSVD0_FLDSHFT (8)
+#define HWIO_CPU_PWR_MGMT_STS_CPUQACTIVE_FLDMASK (0x80)
+#define HWIO_CPU_PWR_MGMT_STS_CPUQACTIVE_FLDSHFT (7)
+#define HWIO_CPU_PWR_MGMT_STS_DBGPWRUPREQ_FLDMASK (0x40)
+#define HWIO_CPU_PWR_MGMT_STS_DBGPWRUPREQ_FLDSHFT (6)
+#define HWIO_CPU_PWR_MGMT_STS_DBGNOPWRDWN_FLDMASK (0x20)
+#define HWIO_CPU_PWR_MGMT_STS_DBGNOPWRDWN_FLDSHFT (5)
+#define HWIO_CPU_PWR_MGMT_STS_SMPEN_FLDMASK (0x10)
+#define HWIO_CPU_PWR_MGMT_STS_SMPEN_FLDSHFT (4)
+#define HWIO_CPU_PWR_MGMT_STS_L2FLUSHDONE_FLDMASK (0x8)
+#define HWIO_CPU_PWR_MGMT_STS_L2FLUSHDONE_FLDSHFT (3)
+#define HWIO_CPU_PWR_MGMT_STS_STANDBYWFE_FLDMASK (0x4)
+#define HWIO_CPU_PWR_MGMT_STS_STANDBYWFE_FLDSHFT (2)
+#define HWIO_CPU_PWR_MGMT_STS_STANDBYWFI_FLDMASK (0x2)
+#define HWIO_CPU_PWR_MGMT_STS_STANDBYWFI_FLDSHFT (1)
+#define HWIO_CPU_PWR_MGMT_STS_EVENTO_FLDMASK (0x1)
+#define HWIO_CPU_PWR_MGMT_STS_EVENTO_FLDSHFT (0)
+
+#define HWIO_CPU_DBG_CFG_REGOFF 0x14
+#define HWIO_CPU_DBG_CFG_ADDR(bAddr, regX) (bAddr + HWIO_CPU_DBG_CFG_REGOFF)
+#define HWIO_CPU_DBG_CFG_RSVD0_FLDMASK (0xfffffffc)
+#define HWIO_CPU_DBG_CFG_RSVD0_FLDSHFT (2)
+#define HWIO_CPU_DBG_CFG_NIDEN_FLDMASK (0x2)
+#define HWIO_CPU_DBG_CFG_NIDEN_FLDSHFT (1)
+#define HWIO_CPU_DBG_CFG_DBGEN_FLDMASK (0x1)
+#define HWIO_CPU_DBG_CFG_DBGEN_FLDSHFT (0)
+
+#define HWIO_CPU_STS_REGOFF 0x18
+#define HWIO_CPU_STS_ADDR(bAddr, regX) (bAddr + HWIO_CPU_STS_REGOFF)
+#define HWIO_CPU_STS_STATUS_FLDMASK (0xffffffff)
+#define HWIO_CPU_STS_STATUS_FLDSHFT (0)
+
+#define HWIO_CPU_SECURE_REGOFF 0x1C
+#define HWIO_CPU_SECURE_ADDR(bAddr, regX) (bAddr + HWIO_CPU_SECURE_REGOFF)
+#define HWIO_CPU_SECURE_SECURE_LOCK_FLDMASK (0x80000000)
+#define HWIO_CPU_SECURE_SECURE_LOCK_FLDSHFT (31)
+#define HWIO_CPU_SECURE_RSVD0_FLDMASK (0x7ffffff8)
+#define HWIO_CPU_SECURE_RSVD0_FLDSHFT (3)
+#define HWIO_CPU_SECURE_CP15SDISABLE_FLDMASK (0x4)
+#define HWIO_CPU_SECURE_CP15SDISABLE_FLDSHFT (2)
+#define HWIO_CPU_SECURE_SPNIDEN_FLDMASK (0x2)
+#define HWIO_CPU_SECURE_SPNIDEN_FLDSHFT (1)
+#define HWIO_CPU_SECURE_SPIDEN_FLDMASK (0x1)
+#define HWIO_CPU_SECURE_SPIDEN_FLDSHFT (0)
+
+#define HWIO_CPU_DBG_BUS_REGOFF 0x20
+#define HWIO_CPU_DBG_BUS_ADDR(bAddr, regX) (bAddr + HWIO_CPU_DBG_BUS_REGOFF)
+#define HWIO_CPU_DBG_BUS_RSVD0_FLDMASK (0xfffffffc)
+#define HWIO_CPU_DBG_BUS_RSVD0_FLDSHFT (2)
+#define HWIO_CPU_DBG_BUS_DBG_MUX_SEL_FLDMASK (0x3)
+#define HWIO_CPU_DBG_BUS_DBG_MUX_SEL_FLDSHFT (0)
+
+#endif /* __MNH_HWIO_CPU_ */
diff --git a/drivers/misc/mnh/mnh-hwio-scu.h b/drivers/misc/mnh/mnh-hwio-scu.h
index 965c450..38dff31 100644
--- a/drivers/misc/mnh/mnh-hwio-scu.h
+++ b/drivers/misc/mnh/mnh-hwio-scu.h
@@ -91,6 +91,8 @@
#define HWIO_SCU_GPS_GPS_FLDMASK (0xffffffff)
#define HWIO_SCU_GPS_GPS_FLDSHFT (0)
+#define MNH_BOOT_STAT (HWIO_SCU_GPS_ADDR(HWIO_SCU_BASE_ADDR, 0))
+
/* General Purpose Scratchpad */
/*
* Allocation:
diff --git a/drivers/misc/mnh/mnh-pcie.c b/drivers/misc/mnh/mnh-pcie.c
index d213336..8dc1b31 100644
--- a/drivers/misc/mnh/mnh-pcie.c
+++ b/drivers/misc/mnh/mnh-pcie.c
@@ -2013,10 +2013,14 @@
dev_dbg(&pdev->dev, "MNH PCIe driver is removed\n");
}
-int mnh_pci_suspend(void)
+int mnh_pci_suspend(struct pci_dev *pdev)
{
- struct pci_dev *pdev = mnh_dev->pdev;
- struct device *dev = &mnh_dev->pdev->dev;
+ struct device *dev;
+
+ if (!pdev || !pci_get_drvdata(pdev))
+ return 0;
+
+ dev = &pdev->dev;
dev_dbg(dev, "%s: enter\n", __func__);
@@ -2042,12 +2046,16 @@
}
EXPORT_SYMBOL_GPL(mnh_pci_suspend);
-int mnh_pci_resume(void)
+int mnh_pci_resume(struct pci_dev *pdev)
{
- struct pci_dev *pdev = mnh_dev->pdev;
- struct device *dev = &mnh_dev->pdev->dev;
+ struct device *dev;
int ret = 0;
+ if (!pdev || !pci_get_drvdata(pdev))
+ return -ENODEV;
+
+ dev = &pdev->dev;
+
dev_dbg(dev, "%s: enter\n", __func__);
mnh_dev->powered = true;
diff --git a/drivers/misc/mnh/mnh-pcie.h b/drivers/misc/mnh/mnh-pcie.h
index e361557..c23bbf3 100644
--- a/drivers/misc/mnh/mnh-pcie.h
+++ b/drivers/misc/mnh/mnh-pcie.h
@@ -474,6 +474,6 @@
void mnh_unmap_mem(
dma_addr_t dma_addr, size_t size, enum dma_data_direction direction);
-int mnh_pci_suspend(void);
-int mnh_pci_resume(void);
+int mnh_pci_suspend(struct pci_dev *pdev);
+int mnh_pci_resume(struct pci_dev *pdev);
#endif /* __MNH_PCIE_HOST */
diff --git a/drivers/misc/mnh/mnh-pwr.c b/drivers/misc/mnh/mnh-pwr.c
index cf9b761..4185429 100644
--- a/drivers/misc/mnh/mnh-pwr.c
+++ b/drivers/misc/mnh/mnh-pwr.c
@@ -264,7 +264,7 @@
* Due to pcie failure, suspend the driver state only after
* updating link status.
*/
- ret = mnh_pci_suspend();
+ ret = mnh_pci_suspend(pcidev);
if (ret)
dev_warn(mnh_pwr->dev,
"%s: mnh_pci_suspend failed (%d)\n",
@@ -273,7 +273,7 @@
mnh_pwr->pcie_failure = false;
} else {
/* suspend the driver state */
- ret = mnh_pci_suspend();
+ ret = mnh_pci_suspend(pcidev);
if (ret)
dev_warn(mnh_pwr->dev,
"%s: mnh_pci_suspend failed (%d)\n",
@@ -363,7 +363,7 @@
pci_restore_state(pcidev);
/* resume the driver state */
- ret = mnh_pci_resume();
+ ret = mnh_pci_resume(pcidev);
if (ret) {
dev_err(mnh_pwr->dev, "%s: mnh_pci_resume failed (%d)\n",
__func__, ret);
diff --git a/drivers/misc/mnh/mnh-sm.c b/drivers/misc/mnh/mnh-sm.c
index 962c64f..965d735 100644
--- a/drivers/misc/mnh/mnh-sm.c
+++ b/drivers/misc/mnh/mnh-sm.c
@@ -191,9 +191,6 @@
/* state of the ddr channel */
enum mnh_ddr_status ddr_status;
- /* mnh-ddr data */
- struct mnh_ddr_data mnh_ddr_data;
-
/* pin used for ddr pad isolation */
struct gpio_desc *ddr_pad_iso_n_pin;
@@ -1383,9 +1380,8 @@
return -EINVAL;
mnh_pwr_set_state(MNH_PWR_S0);
- mnh_ddr_po_init(&mnh_sm_dev->mnh_ddr_data,
- mnh_sm_dev->ddr_pad_iso_n_pin);
- mnh_ddr_mbist(&mnh_sm_dev->mnh_ddr_data, val);
+ mnh_ddr_po_init(mnh_sm_dev->dev, mnh_sm_dev->ddr_pad_iso_n_pin);
+ mnh_ddr_mbist(dev, val);
mnh_pwr_set_state(MNH_PWR_S4);
return count;
@@ -1495,8 +1491,7 @@
int ret;
/* Initialize DDR */
- ret = mnh_ddr_po_init(&mnh_sm_dev->mnh_ddr_data,
- mnh_sm_dev->ddr_pad_iso_n_pin);
+ ret = mnh_ddr_po_init(mnh_sm_dev->dev, mnh_sm_dev->ddr_pad_iso_n_pin);
if (ret) {
dev_err(mnh_sm_dev->dev, "%s: ddr training failed (%d)\n",
__func__, ret);
@@ -1509,9 +1504,16 @@
static int mnh_sm_resume_ddr(void)
{
+ int ret;
+
/* deassert pad isolation, take ddr out of self-refresh mode */
- mnh_ddr_resume(&mnh_sm_dev->mnh_ddr_data,
- mnh_sm_dev->ddr_pad_iso_n_pin);
+ ret = mnh_ddr_resume(mnh_sm_dev->dev);
+ if (ret) {
+ dev_err(mnh_sm_dev->dev, "%s: error resuming dram (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
mnh_sm_dev->ddr_status = MNH_DDR_ACTIVE;
return 0;
}
@@ -1519,8 +1521,7 @@
static int mnh_sm_suspend_ddr(void)
{
/* put ddr into self-refresh mode, assert pad isolation */
- mnh_ddr_suspend(&mnh_sm_dev->mnh_ddr_data,
- mnh_sm_dev->ddr_pad_iso_n_pin);
+ mnh_ddr_suspend(mnh_sm_dev->dev);
mnh_sm_dev->ddr_status = MNH_DDR_SELF_REFRESH;
return 0;
}
@@ -1663,16 +1664,23 @@
int err;
uint32_t val;
- err = mnh_config_read(MNH_BOOT_TRACE, sizeof(val), &val);
+ err = mnh_config_read(MNH_BOOT_STAT, sizeof(val), &val);
+ if (err) {
+ dev_err(dev,
+ "%s: failed reading MNH_BOOT_STAT (%d)\n",
+ __func__, err);
+ } else {
+ dev_info(dev, "MNH_BOOT_STAT = 0x%x\n", val);
+ }
+ err = mnh_config_read(MNH_BOOT_TRACE, sizeof(val), &val);
if (err) {
dev_err(dev,
"%s: failed reading MNH_BOOT_TRACE (%d)\n",
__func__, err);
- return;
+ } else {
+ dev_info(dev, "MNH_BOOT_TRACE = 0x%x\n", val);
}
-
- dev_info(dev, "%s: MNH_BOOT_TRACE = 0x%x\n", __func__, val);
}
static void mnh_sm_enable_ready_irq(bool enable)
@@ -2435,7 +2443,7 @@
}
/* initialize mnh-ddr driver */
- error = mnh_ddr_platform_init(pdev, &mnh_sm_dev->mnh_ddr_data);
+ error = mnh_ddr_platform_init(dev);
if (error) {
dev_err(dev, "failed to initialize mnh-ddr (%d)\n", error);
goto fail_probe_2;
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index 1e3e175..125be43 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -802,6 +802,25 @@
}
EXPORT_SYMBOL(ufs_qcom_phy_dump_regs);
+void ufs_qcom_phy_print_phy_state(struct phy *generic_phy)
+{
+ struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+
+ dev_err(ufs_qcom_phy->dev, "phy->is_iface_clk_enabled = %x\n",
+ ufs_qcom_phy->is_iface_clk_enabled);
+ dev_err(ufs_qcom_phy->dev, "phy->is_ref_clk_enabled = %x\n",
+ ufs_qcom_phy->is_ref_clk_enabled);
+ dev_err(ufs_qcom_phy->dev, "phy->is_dev_ref_clk_enabled = %x\n",
+ ufs_qcom_phy->is_dev_ref_clk_enabled);
+ dev_err(ufs_qcom_phy->dev, "phy->is_powered_on = %x\n",
+ ufs_qcom_phy->is_powered_on);
+ dev_err(ufs_qcom_phy->dev, "phy->vdda_pll.enabled = %x\n",
+ ufs_qcom_phy->vdda_pll.enabled);
+ dev_err(ufs_qcom_phy->dev, "phy->vdda_phy.enabled = %x\n",
+ ufs_qcom_phy->vdda_phy.enabled);
+}
+EXPORT_SYMBOL(ufs_qcom_phy_print_phy_state);
+
void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy)
{
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 49c04c4..7729025 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 2019, The Linux Foundation. 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
@@ -330,11 +330,9 @@
static int ipa3_active_clients_panic_notifier(struct notifier_block *this,
unsigned long event, void *ptr)
{
- ipa3_active_clients_lock();
ipa3_active_clients_log_print_table(active_clients_table_buf,
IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE);
IPAERR("%s", active_clients_table_buf);
- ipa3_active_clients_unlock();
return NOTIFY_DONE;
}
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index eaf5e36..850260e 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -4737,6 +4737,7 @@
{
int rc = 0;
u8 stat;
+ bool debounce_done = false;
rc = smblib_set_prop_typec_power_role_locked(
chg, POWER_SUPPLY_TYPEC_PR_SINK);
@@ -4752,9 +4753,16 @@
smblib_err(chg, "Couldn't read Type-C status 4 rc=%d\n", rc);
return rc;
}
+ smblib_err(chg, "Type-C status 4 :%x\n", stat);
+ if ((stat & TYPEC_VBUS_STATUS_BIT) &&
+ !(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT))
+ goto done;
+
+ debounce_done = true;
*attached = stat & CC_ATTACHED_BIT ? true : false;
+done:
rc = smblib_set_prop_typec_power_role_locked(
chg, POWER_SUPPLY_TYPEC_PR_NONE);
if (rc < 0) {
@@ -4762,6 +4770,9 @@
return rc;
}
+ if (!debounce_done)
+ return -EAGAIN;
+
return 0;
}
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 7d54725..8eae291 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2730,6 +2730,14 @@
ufs_qcom_ice_print_regs(host);
}
+void ufs_qcom_print_phy_state(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
+
+ ufs_qcom_phy_print_phy_state(phy);
+}
+
/**
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
*
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 12154b2..7df08db 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -412,4 +412,6 @@
return !!(host->caps & UFS_QCOM_CAP_SVS2);
}
+void ufs_qcom_print_phy_state(struct ufs_hba *hba);
+
#endif /* UFS_QCOM_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 6daa8ec..f88dc56 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -104,6 +104,10 @@
static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
{
+ hba->h8_err = false;
+ if (type == UFS_ERR_HIBERN8_EXIT || type == UFS_ERR_HIBERN8_ENTER)
+ hba->h8_err = true;
+
ufsdbg_set_err_state(hba);
if (type < UFS_ERR_MAX)
hba->ufs_stats.err_stats[type]++;
@@ -273,7 +277,7 @@
UTP_TASK_REQ_COMPL |\
UFSHCD_ERROR_MASK)
/* UIC command timeout, unit: ms */
-#define UIC_CMD_TIMEOUT 500
+#define UIC_CMD_TIMEOUT 1500
/* NOP OUT retries waiting for NOP IN response */
#define NOP_OUT_RETRIES 10
@@ -286,7 +290,7 @@
#define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */
/* Task management command timeout */
-#define TM_CMD_TIMEOUT 100 /* msecs */
+#define TM_CMD_TIMEOUT 1500 /* msecs */
/* maximum number of retries for a general UIC command */
#define UFS_UIC_COMMAND_RETRIES 3
@@ -821,6 +825,14 @@
}
}
+void ufshcd_print_phy_state(struct ufs_hba *hba)
+{
+ if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN))
+ return;
+
+ ufs_qcom_print_phy_state(hba);
+}
+
static void ufshcd_print_uic_err_hist(struct ufs_hba *hba,
struct ufs_uic_err_reg_hist *err_hist, char *err_name)
{
@@ -5511,10 +5523,10 @@
"Reject UPIU not fully implemented\n");
break;
default:
- result = DID_ERROR << 16;
dev_err(hba->dev,
"Unexpected request response code = %x\n",
result);
+ result = DID_ERROR << 16;
break;
}
break;
@@ -6199,6 +6211,18 @@
hba = container_of(work, struct ufs_hba, eh_work);
+ if (hba->h8_err) {
+ dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x",
+ __func__, hba->saved_err, hba->saved_uic_err);
+ ufshcd_print_host_regs(hba);
+ ufshcd_print_cmd_log(hba);
+ ufshcd_print_host_state(hba);
+ ufshcd_print_pwr_info(hba);
+ ufshcd_print_phy_state(hba);
+ hba->h8_err = false;
+ hba->silence_err_logs = true;
+ }
+
spin_lock_irqsave(hba->host->host_lock, flags);
ufsdbg_set_err_state(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index ed9d6a1e..716293c 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -867,6 +867,7 @@
u32 saved_ce_err;
bool silence_err_logs;
bool force_host_reset;
+ bool h8_err;
/* Device management request data */
struct ufs_dev_cmd dev_cmd;
diff --git a/drivers/soc/qcom/glink_spi_xprt.c b/drivers/soc/qcom/glink_spi_xprt.c
index a2673ef..a691c82 100644
--- a/drivers/soc/qcom/glink_spi_xprt.c
+++ b/drivers/soc/qcom/glink_spi_xprt.c
@@ -492,7 +492,7 @@
- read_id;
if ((offset + size_to_read) > size) {
- pr_err("%s:wrong sz split_sz %u bufsz %u offset %u\n",
+ pr_err("%s:split_size %u buf size %u offset %u\n",
__func__, size_to_read, size, offset);
return -EINVAL;
}
@@ -549,7 +549,7 @@
- write_id;
if ((offset + size_to_write) > size) {
- pr_err("%s:wrong sz split_sz %u bufsz %u offset %u\n",
+ pr_err("%s:split_size %u buf size %u offset %u\n",
__func__, size_to_write, size, offset);
return -EINVAL;
}
diff --git a/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c b/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c
index cf44c89..bce02ec 100644
--- a/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c
+++ b/drivers/staging/qcacld-3.0/core/cds/src/cds_api.c
@@ -2712,8 +2712,8 @@
inline void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump,
void *data)
{
- if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) !=
- WLAN_LOG_LEVEL_ACTIVE)
+ if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) <
+ WLAN_LOG_LEVEL_REPRO)
return;
wlan_pkt_stats_to_logger_thread(pl_hdr, pkt_dump, data);
diff --git a/drivers/staging/qcacld-3.0/core/dp/ol/inc/ol_htt_rx_api.h b/drivers/staging/qcacld-3.0/core/dp/ol/inc/ol_htt_rx_api.h
index db84567..f8783fc 100644
--- a/drivers/staging/qcacld-3.0/core/dp/ol/inc/ol_htt_rx_api.h
+++ b/drivers/staging/qcacld-3.0/core/dp/ol/inc/ol_htt_rx_api.h
@@ -815,6 +815,12 @@
* Return: number of buffers actually replenished
*/
int htt_rx_msdu_buff_in_order_replenish(htt_pdev_handle pdev, uint32_t num);
+#else
+static inline
+int htt_rx_msdu_buff_in_order_replenish(htt_pdev_handle pdev, uint32_t num)
+{
+ return 0;
+}
#endif
/**
diff --git a/drivers/staging/qcacld-3.0/core/dp/txrx/ol_rx_defrag.c b/drivers/staging/qcacld-3.0/core/dp/txrx/ol_rx_defrag.c
index 4496b21..60ec626 100644
--- a/drivers/staging/qcacld-3.0/core/dp/txrx/ol_rx_defrag.c
+++ b/drivers/staging/qcacld-3.0/core/dp/txrx/ol_rx_defrag.c
@@ -316,6 +316,26 @@
#endif
+#ifndef CONFIG_HL_SUPPORT
+static int ol_rx_frag_get_inord_msdu_cnt(qdf_nbuf_t rx_ind_msg)
+{
+ uint32_t *msg_word;
+ uint8_t *rx_ind_data;
+ uint32_t msdu_cnt;
+
+ rx_ind_data = qdf_nbuf_data(rx_ind_msg);
+ msg_word = (uint32_t *)rx_ind_data;
+ msdu_cnt = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1));
+
+ return msdu_cnt;
+}
+#else
+static int ol_rx_frag_get_inord_msdu_cnt(qdf_nbuf_t rx_ind_msg)
+{
+ return 0;
+}
+#endif
+
/*
* Process incoming fragments
*/
@@ -353,7 +373,10 @@
* separate from normal frames
*/
ol_rx_reorder_flush_frag(htt_pdev, peer, tid, seq_num_start);
+ } else {
+ msdu_count = ol_rx_frag_get_inord_msdu_cnt(rx_frag_ind_msg);
}
+
pktlog_bit =
(htt_rx_amsdu_rx_in_order_get_pktlog(rx_frag_ind_msg) == 0x01);
ret = htt_rx_frag_pop(htt_pdev, rx_frag_ind_msg, &head_msdu,
@@ -389,7 +412,11 @@
htt_rx_desc_frame_free(htt_pdev, head_msdu);
}
/* request HTT to provide new rx MSDU buffers for the target to fill. */
- htt_rx_msdu_buff_replenish(htt_pdev);
+ if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev) &&
+ !pdev->cfg.is_high_latency)
+ htt_rx_msdu_buff_in_order_replenish(htt_pdev, msdu_count);
+ else
+ htt_rx_msdu_buff_replenish(htt_pdev);
}
/*
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
index fcd15a9..836ebc7 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
@@ -9319,7 +9319,7 @@
start_log.ring_id = RING_ID_PER_PACKET_STATS;
start_log.verbose_level =
- enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
+ enable ? WLAN_LOG_LEVEL_REPRO : WLAN_LOG_LEVEL_OFF;
start_log.ini_triggered = cds_is_packet_log_enabled();
start_log.user_triggered = user_triggered;
start_log.size = size;
diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h
index 34b5f2c..77d4697 100644
--- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h
+++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_inside_api.h
@@ -94,10 +94,11 @@
#define CSR_ACTIVE_SCAN_LIST_CMD_TIMEOUT (1000*30)
/* ***************************************************************************
- * The MAX BSSID Count should be lower than the command timeout value and it
- * can be of a fraction of 1/3 to 1/2 of the total command timeout value.
+ * The MAX BSSID Count should be lower than the command timeout value.
+ * As in some case auth timeout can take upto 5 sec (in case of SAE auth) try
+ * (command timeout/5000 - 1) candidates.
* ***************************************************************************/
-#define CSR_MAX_BSSID_COUNT (SME_ACTIVE_LIST_CMD_TIMEOUT_VALUE/3000) - 2
+#define CSR_MAX_BSSID_COUNT (SME_ACTIVE_LIST_CMD_TIMEOUT_VALUE/5000) - 1
#define CSR_CUSTOM_CONC_GO_BI 100
extern uint8_t csr_wpa_oui[][CSR_WPA_OUI_SIZE];
bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId);
diff --git a/drivers/staging/qcacld-3.0/core/utils/logging/src/wlan_logging_sock_svc.c b/drivers/staging/qcacld-3.0/core/utils/logging/src/wlan_logging_sock_svc.c
index cf366b1a..d4c3274 100644
--- a/drivers/staging/qcacld-3.0/core/utils/logging/src/wlan_logging_sock_svc.c
+++ b/drivers/staging/qcacld-3.0/core/utils/logging/src/wlan_logging_sock_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1161,7 +1161,7 @@
spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
- if (!gwlan_logging.pkt_stats_pcur_node || (NULL == pkt_stats_dump)) {
+ if (!gwlan_logging.pkt_stats_pcur_node) {
spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
return;
}
@@ -1194,7 +1194,7 @@
pktlog_hdr->size),
data, pktlog_hdr->size);
- if (pkt_stats_dump->type == STOP_MONITOR) {
+ if (pkt_stats_dump && pkt_stats_dump->type == STOP_MONITOR) {
wake_up_thread = true;
wlan_get_pkt_stats_free_node();
}
diff --git a/drivers/staging/qcacld-3.0/core/utils/pktlog/pktlog_internal.c b/drivers/staging/qcacld-3.0/core/utils/pktlog/pktlog_internal.c
index 94ef1a0..97d363b 100644
--- a/drivers/staging/qcacld-3.0/core/utils/pktlog/pktlog_internal.c
+++ b/drivers/staging/qcacld-3.0/core/utils/pktlog/pktlog_internal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -927,6 +927,7 @@
qdf_mem_copy(sw_event.sw_event,
((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)),
pl_hdr.size);
+ cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event);
return A_OK;
}
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c
index f60892f..c2437202 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_main.c
@@ -6548,7 +6548,7 @@
return;
}
- if (start_log->verbose_level == WLAN_LOG_LEVEL_ACTIVE) {
+ if (start_log->verbose_level >= WLAN_LOG_LEVEL_REPRO) {
pktlog_enable(scn, log_state, start_log->ini_triggered,
start_log->user_triggered,
start_log->is_iwpriv_command);
diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c
index 33a031d..6ade8b40 100644
--- a/drivers/thermal/msm_lmh_dcvs.c
+++ b/drivers/thermal/msm_lmh_dcvs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. 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
@@ -206,7 +206,7 @@
uint32_t payload_len;
payload_len = ((enable_val1) ? 6 : 5) * sizeof(uint32_t);
- payload = kcalloc((enable_val1) ? 6 : 5, sizeof(uint32_t), GFP_KERNEL);
+ payload = kzalloc(payload_len, GFP_KERNEL);
if (!payload)
return -ENOMEM;
@@ -230,7 +230,6 @@
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_LMH, MSM_LIMITS_DCVSH), &desc_arg);
kfree(payload);
-
return ret;
}
@@ -359,6 +358,7 @@
return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_THERMAL,
MSM_LIMIT_FREQ_CAP, freq,
freq >= hw->max_freq ? 0 : 1, 1);
+
}
static int lmh_get_cur_limit(int cpu, unsigned long *freq)
@@ -442,7 +442,7 @@
/* Enable the thermal algorithm early */
ret = msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_THERMAL,
- MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
+ MSM_LIMITS_ALGO_MODE_ENABLE, 1, 0, 0);
if (ret)
return ret;
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index c27e0f4..075e6eb 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. 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
@@ -1027,7 +1027,7 @@
uint32_t payload_len;
payload_len = ((enable_val1) ? 6 : 5) * sizeof(uint32_t);
- payload = kcalloc((enable_val1) ? 6 : 5, sizeof(uint32_t), GFP_KERNEL);
+ payload = kzalloc(payload_len, GFP_KERNEL);
if (!payload)
return -ENOMEM;
@@ -1051,7 +1051,6 @@
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_LMH, MSM_LIMITS_DCVSH), &desc_arg);
kfree(payload);
-
return ret;
}
@@ -1066,7 +1065,7 @@
* It is better to use max limits of cluster for given
* cpu if cluster mitigation is supported. It ensures that it
* requests aggregated max limits of all cpus in that cluster.
- */
+ * */
if (core_ptr)
max_freq = cpus[cpu].parent_ptr->limited_max_freq;
@@ -1088,8 +1087,9 @@
cpus[cpu].parent_ptr->freq_idx_high].frequency;
ret = msm_lmh_dcvs_write(affinity, MSM_LIMITS_SUB_FN_THERMAL,
- MSM_LIMITS_FREQ_CAP, max_freq,
- max_freq >= hw_max_freq ? 0 : 1, 1);
+ MSM_LIMITS_FREQ_CAP, max_freq,
+ max_freq >= hw_max_freq ? 0 : 1, 1);
+
if (ret)
return ret;
/*
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 62e2550..80eb297 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -573,7 +573,7 @@
}
*dma_addr = dma_map_single(mdss_smmu->base.dev, cpu_addr, size, dir);
- if (IS_ERR_VALUE(*dma_addr)) {
+ if (dma_mapping_error(mdss_smmu->base.dev, *dma_addr)) {
pr_err("dma map single failed\n");
return -ENOMEM;
}
diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index e75255b..f459110 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -24,3 +24,13 @@
*/
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+#undef __no_sanitize_address
+#define __no_sanitize_address __attribute__((no_sanitize("address")))
+
+/* all clang versions usable with the kernel support KASAN ABI version 5 */
+#define KASAN_ABI_VERSION 5
+
+/* emulate gcc's __SANITIZE_ADDRESS__ flag */
+#if __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__
+#endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 5f31318..8571c02 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -521,10 +521,12 @@
* battery is non-NULL.
*/
struct power_supply *battery;
+ __s32 battery_capacity;
__s32 battery_min;
__s32 battery_max;
__s32 battery_report_type;
__s32 battery_report_id;
+ bool battery_reported;
#endif
unsigned int status; /* see STAT flags above */
diff --git a/include/linux/input.h b/include/linux/input.h
index 1e96769..808a097 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -36,6 +36,13 @@
__s32 value;
};
+enum input_clock_type {
+ INPUT_CLK_REAL = 0,
+ INPUT_CLK_MONO,
+ INPUT_CLK_BOOT,
+ INPUT_CLK_MAX
+};
+
/**
* struct input_dev - represents an input device
* @name: name of the device
@@ -117,6 +124,8 @@
* @vals: array of values queued in the current frame
* @devres_managed: indicates that devices is managed with devres framework
* and needs not be explicitly unregistered or freed.
+ * @timestamp: storage for a timestamp set by input_set_timestamp called
+ * by a driver
*/
struct input_dev {
const char *name;
@@ -187,6 +196,8 @@
struct input_value *vals;
bool devres_managed;
+
+ ktime_t timestamp[INPUT_CLK_MAX];
};
#define to_input_dev(d) container_of(d, struct input_dev, dev)
@@ -381,6 +392,9 @@
int input_flush_device(struct input_handle *handle, struct file *file);
+void input_set_timestamp(struct input_dev *dev, ktime_t timestamp);
+ktime_t *input_get_timestamp(struct input_dev *dev);
+
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
diff --git a/include/linux/phy/phy-qcom-ufs.h b/include/linux/phy/phy-qcom-ufs.h
index 25e7a5f..3564b57 100644
--- a/include/linux/phy/phy-qcom-ufs.h
+++ b/include/linux/phy/phy-qcom-ufs.h
@@ -59,5 +59,6 @@
const char *ufs_qcom_phy_name(struct phy *phy);
int ufs_qcom_phy_configure_lpm(struct phy *generic_phy, bool enable);
void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy);
+void ufs_qcom_phy_print_phy_state(struct phy *generic_phy);
#endif /* PHY_QCOM_UFS_H_ */
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 0e70ecc..8fcad61 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -440,6 +440,26 @@
p[1023] = 1;
}
+static noinline void __init kasan_alloca_oob_left(void)
+{
+ volatile int i = 10;
+ char alloca_array[i];
+ char *p = alloca_array - 1;
+
+ pr_info("out-of-bounds to left on alloca\n");
+ *(volatile char *)p;
+}
+
+static noinline void __init kasan_alloca_oob_right(void)
+{
+ volatile int i = 10;
+ char alloca_array[i];
+ char *p = alloca_array + i;
+
+ pr_info("out-of-bounds to right on alloca\n");
+ *(volatile char *)p;
+}
+
static int __init kmalloc_tests_init(void)
{
/*
@@ -469,6 +489,8 @@
kmem_cache_oob();
kasan_stack_oob();
kasan_global_oob();
+ kasan_alloca_oob_left();
+ kasan_alloca_oob_right();
ksize_unpoisons_memory();
copy_user_test();
use_after_scope_test();
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 2bfdb3c..3c57210 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -802,6 +802,55 @@
}
EXPORT_SYMBOL(__asan_unpoison_stack_memory);
+/* Emitted by compiler to poison alloca()ed objects. */
+void __asan_alloca_poison(unsigned long addr, size_t size)
+{
+ size_t rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
+ size_t padding_size = round_up(size, KASAN_ALLOCA_REDZONE_SIZE) -
+ rounded_up_size;
+ size_t rounded_down_size = round_down(size, KASAN_SHADOW_SCALE_SIZE);
+
+ const void *left_redzone = (const void *)(addr -
+ KASAN_ALLOCA_REDZONE_SIZE);
+ const void *right_redzone = (const void *)(addr + rounded_up_size);
+
+ WARN_ON(!IS_ALIGNED(addr, KASAN_ALLOCA_REDZONE_SIZE));
+
+ kasan_unpoison_shadow((const void *)(addr + rounded_down_size),
+ size - rounded_down_size);
+ kasan_poison_shadow(left_redzone, KASAN_ALLOCA_REDZONE_SIZE,
+ KASAN_ALLOCA_LEFT);
+ kasan_poison_shadow(right_redzone,
+ padding_size + KASAN_ALLOCA_REDZONE_SIZE,
+ KASAN_ALLOCA_RIGHT);
+}
+EXPORT_SYMBOL(__asan_alloca_poison);
+
+/* Emitted by compiler to unpoison alloca()ed areas when the stack unwinds. */
+void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom)
+{
+ if (unlikely(!stack_top || stack_top > stack_bottom))
+ return;
+
+ kasan_unpoison_shadow(stack_top, stack_bottom - stack_top);
+}
+EXPORT_SYMBOL(__asan_allocas_unpoison);
+
+/* Emitted by the compiler to [un]poison local variables. */
+#define DEFINE_ASAN_SET_SHADOW(byte) \
+ void __asan_set_shadow_##byte(const void *addr, size_t size) \
+ { \
+ __memset((void *)addr, 0x##byte, size); \
+ } \
+ EXPORT_SYMBOL(__asan_set_shadow_##byte)
+
+DEFINE_ASAN_SET_SHADOW(00);
+DEFINE_ASAN_SET_SHADOW(f1);
+DEFINE_ASAN_SET_SHADOW(f2);
+DEFINE_ASAN_SET_SHADOW(f3);
+DEFINE_ASAN_SET_SHADOW(f5);
+DEFINE_ASAN_SET_SHADOW(f8);
+
#ifdef CONFIG_MEMORY_HOTPLUG
static int kasan_mem_notifier(struct notifier_block *nb,
unsigned long action, void *data)
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 1229298..d9cf9e2 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -23,6 +23,14 @@
#define KASAN_STACK_PARTIAL 0xF4
#define KASAN_USE_AFTER_SCOPE 0xF8
+/*
+ * alloca redzone shadow values
+ */
+#define KASAN_ALLOCA_LEFT 0xCA
+#define KASAN_ALLOCA_RIGHT 0xCB
+
+#define KASAN_ALLOCA_REDZONE_SIZE 32
+
/* Don't break randconfig/all*config builds */
#ifndef KASAN_ABI_VERSION
#define KASAN_ABI_VERSION 1
@@ -112,4 +120,48 @@
static inline void quarantine_remove_cache(struct kmem_cache *cache) { }
#endif
+/*
+ * Exported functions for interfaces called from assembly or from generated
+ * code. Declarations here to avoid warning about missing declarations.
+ */
+asmlinkage void kasan_unpoison_task_stack_below(const void *watermark);
+void __asan_register_globals(struct kasan_global *globals, size_t size);
+void __asan_unregister_globals(struct kasan_global *globals, size_t size);
+void __asan_loadN(unsigned long addr, size_t size);
+void __asan_storeN(unsigned long addr, size_t size);
+void __asan_handle_no_return(void);
+void __asan_poison_stack_memory(const void *addr, size_t size);
+void __asan_unpoison_stack_memory(const void *addr, size_t size);
+void __asan_alloca_poison(unsigned long addr, size_t size);
+void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom);
+
+void __asan_load1(unsigned long addr);
+void __asan_store1(unsigned long addr);
+void __asan_load2(unsigned long addr);
+void __asan_store2(unsigned long addr);
+void __asan_load4(unsigned long addr);
+void __asan_store4(unsigned long addr);
+void __asan_load8(unsigned long addr);
+void __asan_store8(unsigned long addr);
+void __asan_load16(unsigned long addr);
+void __asan_store16(unsigned long addr);
+
+void __asan_load1_noabort(unsigned long addr);
+void __asan_store1_noabort(unsigned long addr);
+void __asan_load2_noabort(unsigned long addr);
+void __asan_store2_noabort(unsigned long addr);
+void __asan_load4_noabort(unsigned long addr);
+void __asan_store4_noabort(unsigned long addr);
+void __asan_load8_noabort(unsigned long addr);
+void __asan_store8_noabort(unsigned long addr);
+void __asan_load16_noabort(unsigned long addr);
+void __asan_store16_noabort(unsigned long addr);
+
+void __asan_set_shadow_00(const void *addr, size_t size);
+void __asan_set_shadow_f1(const void *addr, size_t size);
+void __asan_set_shadow_f2(const void *addr, size_t size);
+void __asan_set_shadow_f3(const void *addr, size_t size);
+void __asan_set_shadow_f5(const void *addr, size_t size);
+void __asan_set_shadow_f8(const void *addr, size_t size);
+
#endif
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 775e214..d51bc21 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -102,6 +102,10 @@
case KASAN_USE_AFTER_SCOPE:
bug_type = "use-after-scope";
break;
+ case KASAN_ALLOCA_LEFT:
+ case KASAN_ALLOCA_RIGHT:
+ bug_type = "alloca-out-of-bounds";
+ break;
}
return bug_type;
@@ -134,7 +138,7 @@
pr_err("BUG: KASAN: %s in %pS\n",
bug_type, (void *)info->ip);
- pr_err("%s of size %zu at addr %p by task %s/%d\n",
+ pr_err("%s of size %zu at addr %px by task %s/%d\n",
info->is_write ? "Write" : "Read", info->access_size,
info->access_addr, current->comm, task_pid_nr(current));
}
@@ -205,7 +209,7 @@
const char *rel_type;
int rel_bytes;
- pr_err("The buggy address belongs to the object at %p\n"
+ pr_err("The buggy address belongs to the object at %px\n"
" which belongs to the cache %s of size %d\n",
object, cache->name, cache->object_size);
@@ -224,7 +228,7 @@
}
pr_err("The buggy address is located %d bytes %s of\n"
- " %d-byte region [%p, %p)\n",
+ " %d-byte region [%px, %px)\n",
rel_bytes, rel_type, cache->object_size, (void *)object_addr,
(void *)(object_addr + cache->object_size));
}
@@ -301,7 +305,7 @@
char shadow_buf[SHADOW_BYTES_PER_ROW];
snprintf(buffer, sizeof(buffer),
- (i == 0) ? ">%p: " : " %p: ", kaddr);
+ (i == 0) ? ">%px: " : " %px: ", kaddr);
/*
* We should not pass a shadow pointer to generic
* function, because generic functions may try to
diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan
index 5d54925..d809e00 100644
--- a/scripts/Makefile.kasan
+++ b/scripts/Makefile.kasan
@@ -9,18 +9,7 @@
CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
-ifeq ($(cc-name),clang)
-CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
- -mllvm \
- -asan-mapping-offset=$(KASAN_SHADOW_OFFSET) \
- -asan-stack=1 -asan-globals=1 \
- -asan-instrumentation-with-call-threshold=$(call_threshold))
-else
-CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \
- -fasan-shadow-offset=$(KASAN_SHADOW_OFFSET) \
- --param asan-stack=1 --param asan-globals=1 \
- --param asan-instrumentation-with-call-threshold=$(call_threshold))
-endif
+cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)
ifneq ($(CONFIG_COMPILE_TEST),y)
@@ -28,13 +17,24 @@
-fsanitize=kernel-address is not supported by compiler)
endif
else
- ifeq ($(CFLAGS_KASAN),)
- ifneq ($(CONFIG_COMPILE_TEST),y)
- $(warning CONFIG_KASAN: compiler does not support all options.\
- Trying minimal configuration)
- endif
- CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
- endif
+ # -fasan-shadow-offset fails without -fsanitize
+ CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
+ -fasan-shadow-offset=$(KASAN_SHADOW_OFFSET), \
+ $(call cc-option, -fsanitize=kernel-address \
+ -mllvm -asan-mapping-offset=$(KASAN_SHADOW_OFFSET)))
+
+ ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
+ CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
+ else
+ # Now add all the compiler specific options that are valid standalone
+ CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
+ $(call cc-param,asan-globals=1) \
+ $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
+ $(call cc-param,asan-stack=1) \
+ $(call cc-param,asan-use-after-scope=1) \
+ $(call cc-param,asan-instrument-allocas=1)
+ endif
+
endif
CFLAGS_KASAN_NOSANITIZE := -fno-builtin
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index b393d29..31dc821 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -100,7 +100,7 @@
{ COMMON_IPC_PERMS, NULL } },
{ "netlink_route_socket",
{ COMMON_SOCK_PERMS,
- "nlmsg_read", "nlmsg_write", NULL } },
+ "nlmsg_read", "nlmsg_write", "nlmsg_readpriv", NULL } },
{ "netlink_tcpdiag_socket",
{ COMMON_SOCK_PERMS,
"nlmsg_read", "nlmsg_write", NULL } },
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 0464cbb..b45a3a7 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -78,6 +78,7 @@
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+extern int selinux_android_netlink_route;
extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;
extern int selinux_policycap_alwaysnetwork;
@@ -263,6 +264,7 @@
extern void selnl_notify_setenforce(int val);
extern void selnl_notify_policyload(u32 seqno);
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern void selinux_nlmsg_init(void);
#endif /* _SELINUX_SECURITY_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 7f947f7..e7b7462 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -191,3 +191,27 @@
return err;
}
+
+static void nlmsg_set_getlink_perm(u32 perm)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(nlmsg_route_perms); i++) {
+ if (nlmsg_route_perms[i].nlmsg_type == RTM_GETLINK) {
+ nlmsg_route_perms[i].perm = perm;
+ break;
+ }
+ }
+}
+
+/**
+ * Use nlmsg_readpriv as the permission for RTM_GETLINK messages if the
+ * netlink_route_getlink policy capability is set. Otherwise use nlmsg_read.
+ */
+void selinux_nlmsg_init(void)
+{
+ if (selinux_android_netlink_route)
+ nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READPRIV);
+ else
+ nlmsg_set_getlink_perm(NETLINK_ROUTE_SOCKET__NLMSG_READ);
+}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 01fbbbf..5ee23e3 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -2329,6 +2329,10 @@
p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
+ if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE)) {
+ p->android_netlink_route = 1;
+ }
+
if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
rc = ebitmap_read(&p->policycaps, fp);
if (rc)
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 725d594..0d511cf 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -227,6 +227,7 @@
/* The policy database */
struct policydb {
int mls_enabled;
+ int android_netlink_route;
/* symbol tables */
struct symtab symtab[SYM_NUM];
@@ -313,6 +314,7 @@
#define PERM_SYMTAB_SIZE 32
#define POLICYDB_CONFIG_MLS 1
+#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31)
/* the config flags related to unknown classes/perms are bits 2 and 3 */
#define REJECT_UNKNOWN 0x00000002
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0a258c0..2b3907e 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -70,6 +70,7 @@
#include "ebitmap.h"
#include "audit.h"
+int selinux_android_netlink_route;
int selinux_policycap_netpeer;
int selinux_policycap_openperm;
int selinux_policycap_alwaysnetwork;
@@ -1997,6 +1998,9 @@
POLICYDB_CAPABILITY_OPENPERM);
selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_ALWAYSNETWORK);
+
+ selinux_android_netlink_route = policydb.android_netlink_route;
+ selinux_nlmsg_init();
}
static int security_preserve_bools(struct policydb *p);