Victor Fragoso
Published © GPL3+

USB to Ethernet using OpenLinux at NL668-LA

Quickstart tutorial with instructions to use an USB to Ethernet converter on NL668 OpenLinux.

AdvancedProtip1.5 hours903
USB to Ethernet using OpenLinux at NL668-LA

Things used in this project

Hardware components

NL668-LA
Fibocom NL668-LA
×1

Story

Read more

Code

gpio-usbdetect.c

C/C++
fibo_kernel/drivers/platform/msm/gpio-usbdetect.c
/* Copyright (c) 2013-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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/of_platform.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/power_supply.h>
#include <linux/regulator/consumer.h>

// //<!-- add usbdetecten command by caogang@2016-06-08
// int gpio_detect_irq = -1;
// static int usb_detect_val = 0;
// static int enable = 0;
// //end-->
// static struct gpio_usbdetect *global_usb = NULL;//sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.

// //+sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
// #define FEATURE_USB_SLEEP_CTRL
// #ifdef FEATURE_USB_SLEEP_CTRL
// #include <linux/delay.h>
// #endif
// //-sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.

struct gpio_usbdetect {
	struct platform_device	*pdev;
	struct regulator	*vin;
	struct power_supply	*usb_psy;
	int			vbus_det_irq;
	
// #ifdef FEATURE_USB_SLEEP_CTRL
// 	struct delayed_work vbus_det_work;	//sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
// #endif
	struct regulator	*vdd33;
	struct regulator	*vdd12;
	int			gpio_usbdetect;
	bool			notify_host_mode;
	bool			disable_device_mode;
};

static int gpio_enable_ldos(struct gpio_usbdetect *usb, int on)
{
	struct platform_device *pdev = usb->pdev;
	int ret = 0;

	if (!on)
		goto disable_regulator;

	if (of_get_property(pdev->dev.of_node, "vin-supply", NULL)) {
		usb->vin = devm_regulator_get(&pdev->dev, "vin");
		if (IS_ERR(usb->vin)) {
			dev_err(&pdev->dev, "Failed to get VIN regulator: %ld\n",
				PTR_ERR(usb->vin));
			return PTR_ERR(usb->vin);
		}
	}

	if (of_get_property(pdev->dev.of_node, "vdd33-supply", NULL)) {
		usb->vdd33 = devm_regulator_get(&pdev->dev, "vdd33");
		if (IS_ERR(usb->vdd33)) {
			dev_err(&pdev->dev, "Failed to get vdd33 regulator: %ld\n",
				PTR_ERR(usb->vdd33));
			return PTR_ERR(usb->vdd33);
		}
	}

	if (of_get_property(pdev->dev.of_node, "vdd12-supply", NULL)) {
		usb->vdd12 = devm_regulator_get(&pdev->dev, "vdd12");
		if (IS_ERR(usb->vdd12)) {
			dev_err(&pdev->dev, "Failed to get vdd12 regulator: %ld\n",
				PTR_ERR(usb->vdd12));
			return PTR_ERR(usb->vdd12);
		}
	}

	if (usb->vin) {
		ret = regulator_enable(usb->vin);
		if (ret) {
			dev_err(&pdev->dev, "Failed to enable VIN regulator: %d\n",
									ret);
			return ret;
		}
	}

	if (usb->vdd33) {
		ret = regulator_set_optimum_mode(usb->vdd33, 500000);
		if (ret < 0) {
			dev_err(&pdev->dev, "unable to set load for vdd33\n");
			goto disable_vin;
		}

		ret = regulator_set_voltage(usb->vdd33, 3300000, 3300000);
		if (ret) {
			dev_err(&pdev->dev, "unable to set volt for vdd33\n");
			regulator_set_optimum_mode(usb->vdd33, 0);
			goto disable_vin;
		}
		ret = regulator_enable(usb->vdd33);
		if (ret) {
			dev_err(&pdev->dev, "unable to enable vdd33 regulator\n");
			regulator_set_voltage(usb->vdd33, 0, 3300000);
			regulator_set_optimum_mode(usb->vdd33, 0);
			goto disable_vin;
		}
		dev_dbg(&pdev->dev, "vdd33 successful\n");
	}

	if (usb->vdd12) {
		ret = regulator_set_optimum_mode(usb->vdd12, 500000);
		if (ret < 0) {
			dev_err(&pdev->dev, "unable to set load for vdd12\n");
			goto disable_3p3;
		}

		ret = regulator_set_voltage(usb->vdd12, 1220000, 1220000);
		if (ret) {
			dev_err(&pdev->dev, "unable to set volt for vddi12\n");
			regulator_set_optimum_mode(usb->vdd12, 0);
			goto disable_3p3;
		}
		ret = regulator_enable(usb->vdd12);
		if (ret) {
			dev_err(&pdev->dev, "unable to enable vdd12 regulator\n");
			regulator_set_voltage(usb->vdd12, 0, 1225000);
			regulator_set_optimum_mode(usb->vdd12, 0);
			goto disable_3p3;
		}
		dev_dbg(&pdev->dev, "vdd12 successful\n");
	}

	return ret;

disable_regulator:
	if (usb->vdd12) {
		regulator_disable(usb->vdd12);
		regulator_set_voltage(usb->vdd12, 0, 1225000);
		regulator_set_optimum_mode(usb->vdd12, 0);
	}

disable_3p3:
	if (usb->vdd33) {
		regulator_disable(usb->vdd33);
		regulator_set_voltage(usb->vdd33, 0, 3300000);
		regulator_set_optimum_mode(usb->vdd33, 0);
	}

disable_vin:
	if (usb->vin)
		regulator_disable(usb->vin);

	return ret;
}

static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data)
{
	struct gpio_usbdetect *usb = data;
	int vbus;

	if (gpio_is_valid(usb->gpio_usbdetect))
		vbus = gpio_get_value(usb->gpio_usbdetect);
	else
		vbus = !!irq_read_line(irq);

// //<!-- add usbdetecten command by caogang@2016-06-08
// 	usb_detect_val = vbus;
// 	printk(KERN_INFO "%s: vbus=%d enable=%d\n", __func__, vbus, enable);
// 	if (0 == enable)
// 	{
// 		printk(KERN_ERR "%s: gpio_detect irq do nothing\n", __func__);
// 		return IRQ_HANDLED;
// 	}
// //end-->

	if (vbus) {
		if (usb->notify_host_mode)
			power_supply_set_usb_otg(usb->usb_psy, 0);

		if (!usb->disable_device_mode) {
			power_supply_set_supply_type(usb->usb_psy,
						POWER_SUPPLY_TYPE_USB);
			power_supply_set_present(usb->usb_psy, vbus);
		}
	} else {
		/* notify gpio_state = LOW as disconnect */
		power_supply_set_supply_type(usb->usb_psy,
				POWER_SUPPLY_TYPE_UNKNOWN);
		power_supply_set_present(usb->usb_psy, vbus);
//	power_supply_set_online(usb->usb_psy, vbus);//sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.
		/* Cheeck if low gpio_state be treated as HOST mode */
		if (usb->notify_host_mode)
			power_supply_set_usb_otg(usb->usb_psy, 1);
	}
	return IRQ_HANDLED;
}

// /*Begin sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.*/
// static void report_vbus_state(struct gpio_usbdetect *usb)
// {
// 	unsigned long flags;

// 	/* Read and report initial VBUS state */
// 	local_irq_save(flags);
// 	gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb);
// 	local_irq_restore(flags);
// }
// /*End sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.*/

// //+sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
// #ifdef FEATURE_USB_SLEEP_CTRL
// static void vbus_det_work_func_t(struct work_struct *work)
// {
// 	unsigned long flags;
// 	struct gpio_usbdetect *usb = container_of(work,
// 			struct gpio_usbdetect, vbus_det_work.work);

// 	/* Read and report initial VBUS state */
// 	local_irq_save(flags);
// 	gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb);
// 	local_irq_restore(flags);
// }
// #endif
// //-sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.

static int gpio_usbdetect_probe(struct platform_device *pdev)
{
	struct gpio_usbdetect *usb;
	struct power_supply *usb_psy;
	int rc;
	unsigned long flags;

//	printk(KERN_DEBUG "func:%s, line:%d, start\n", __func__, __LINE__);

	usb_psy = power_supply_get_by_name("usb");
	if (!usb_psy) {
		dev_dbg(&pdev->dev, "USB power_supply not found, deferring probe\n");
		return -EPROBE_DEFER;
	}

	usb = devm_kzalloc(&pdev->dev, sizeof(*usb), GFP_KERNEL);
	if (!usb)
		return -ENOMEM;

	usb->pdev = pdev;
	usb->usb_psy = usb_psy;
	usb->notify_host_mode = of_property_read_bool(pdev->dev.of_node,
					"qcom,notify-host-mode");
	usb->disable_device_mode = of_property_read_bool(pdev->dev.of_node,
					"qcom,disable-device-mode");
	rc = gpio_enable_ldos(usb, 1);
	if (rc)
		return rc;

	usb->vbus_det_irq = platform_get_irq_byname(pdev, "vbus_det_irq");
	if (usb->vbus_det_irq < 0) {
		dev_err(&pdev->dev, "vbus_det_irq failed\n");
		rc = usb->vbus_det_irq;
		goto disable_ldo;
	}

	rc = devm_request_irq(&pdev->dev, usb->vbus_det_irq,
			      gpio_usbdetect_vbus_irq,
			      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
			      "vbus_det_irq", usb);
	if (rc) {
		dev_err(&pdev->dev, "request for vbus_det_irq failed: %d\n",
			rc);
		goto disable_ldo;
	}

	usb->gpio_usbdetect = of_get_named_gpio(pdev->dev.of_node,
					"qcom,gpio-mode-sel", 0);

	if (gpio_is_valid(usb->gpio_usbdetect)) {
		rc = devm_gpio_request(&pdev->dev, usb->gpio_usbdetect,
					"GPIO_MODE_SEL");
		if (rc) {
			dev_err(&pdev->dev, "gpio req failed for gpio_%d\n",
						 usb->gpio_usbdetect);
			goto disable_ldo;
		}
		rc = gpio_direction_input(usb->gpio_usbdetect);
		if (rc) {
			dev_err(&pdev->dev, "Invalid input from GPIO_%d\n",
					usb->gpio_usbdetect);
			goto disable_ldo;
		}
	}

	enable_irq_wake(usb->vbus_det_irq);
	dev_set_drvdata(&pdev->dev, usb);

// //+sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
// #ifdef FEATURE_USB_SLEEP_CTRL
// 	INIT_DELAYED_WORK(&usb->vbus_det_work, vbus_det_work_func_t);
// 	schedule_delayed_work(&usb->vbus_det_work, msecs_to_jiffies(200));
// #else
	/* Read and report initial VBUS state */
	local_irq_save(flags);
	gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb);
	local_irq_restore(flags);
// #endif
// //-sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.

// //<!-- add usbdetecten command by caogang@2016-06-08
//     gpio_detect_irq = usb->vbus_det_irq;
// 	global_usb = usb;//sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.
// //end-->

	return 0;

disable_ldo:
	gpio_enable_ldos(usb, 0);

	return rc;
}

static int gpio_usbdetect_remove(struct platform_device *pdev)
{
	struct gpio_usbdetect *usb = dev_get_drvdata(&pdev->dev);

//	printk(KERN_DEBUG "func:%s, line:%d, start", __func__, __LINE__);
	disable_irq_wake(usb->vbus_det_irq);
	disable_irq(usb->vbus_det_irq);

	gpio_enable_ldos(usb, 0);

	return 0;
}

static struct of_device_id of_match_table[] = {
	{ .compatible = "qcom,gpio-usbdetect", },
	{}
};

static struct platform_driver gpio_usbdetect_driver = {
	.driver		= {
		.name	= "qcom,gpio-usbdetect",
		.of_match_table = of_match_table,
	},
	.probe		= gpio_usbdetect_probe,
	.remove		= gpio_usbdetect_remove,
};

module_driver(gpio_usbdetect_driver, platform_driver_register,
		platform_driver_unregister);

// //<!-- add usbdetecten command by caogang@2016-06-08
// static int irq_set_enable(const char *val, struct kernel_param *kp)
// {
// 	if (!val) val = "0";

// 	/* One of =[yYnN01] */
// 	switch (val[0]) {
// 		case 'y': case 'Y': case '1':
// 			*(int *)kp->arg = 1;
// 			printk(KERN_DEBUG "%s: irq:%d 1\n",__func__, gpio_detect_irq);
// 			enable_irq(gpio_detect_irq);
// 			report_vbus_state(global_usb);//sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.
// 			return 0;
// 		case 'n': case 'N': case '0':
// 			*(int *)kp->arg = 0;
// 			printk(KERN_DEBUG "%s: irq:%d 0 \n",__func__, gpio_detect_irq);
// 			disable_irq(gpio_detect_irq);
// 			report_vbus_state(global_usb);//sunxuebin.fb,ADD,20180722,for if exec usbdetecten=1 let the usb connectivity refer to vbus state.
// 			return 0;
// 	}
// 	return -EINVAL;
// }

// static int irq_get_enable(char *buffer, struct kernel_param *kp)
// {
// 	return sprintf(buffer, "%c", (*(int *)kp->arg) ? '1' : '0');
// }

// module_param(usb_detect_val, int, 0444);
// #define module_param_call_custom(name)              \
//     module_param_call(name, irq_set_##name, irq_get_##name, &name, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
// module_param_call_custom(enable);
// MODULE_PARM_DESC(enable, "An visible int under sysfs");
// //end-->

MODULE_DESCRIPTION("GPIO USB VBUS Detection driver");
MODULE_LICENSE("GPL v2");

mdm9607-perf_defconfig

C/C++
fibo_kernel/arch/arm/configs/mdm9607-perf_defconfig
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_IPC_NS is not set
# CONFIG_PID_NS is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
CONFIG_PROFILING=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MDM9607=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
# CONFIG_HW_PERF_EVENTS is not set
CONFIG_CMA=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_DISABLE_NET_SKB_FRAG_CACHE=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V2=y
CONFIG_IPV6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETFILTER=y
CONFIG_NETFILTER_DEBUG=n
CONFIG_BRIDGE_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_SNMP=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NF_CT_NETLINK_TIMEOUT=y
CONFIG_NF_CT_NETLINK_HELPER=y
CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
CONFIG_NETFILTER_XT_TARGET_LOG=n
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=n
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=n
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_IP_SET=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NATTYPE_MODULE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=n
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_IP_NF_TARGET_TTL=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_AH=y
CONFIG_IP6_NF_MATCH_FRAG=y
CONFIG_IP6_NF_MATCH_OPTS=y
CONFIG_IP6_NF_MATCH_HL=y
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
CONFIG_IP6_NF_MATCH_MH=y
CONFIG_IP6_NF_MATCH_RT=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
CONFIG_BRIDGE_EBT_T_FILTER=y
CONFIG_BRIDGE_EBT_T_NAT=y
CONFIG_BRIDGE_EBT_ARP=y
CONFIG_BRIDGE_EBT_IP=y
CONFIG_BRIDGE_EBT_IP6=y
CONFIG_BRIDGE_EBT_ARPREPLY=y
CONFIG_BRIDGE_EBT_DNAT=y
CONFIG_BRIDGE_EBT_SNAT=y
CONFIG_BRIDGE=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_PRIO=y
CONFIG_RMNET_DATA=y
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=n
#start: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_CAN=n
CONFIG_CAN_VCAN=n
CONFIG_BT=n
CONFIG_BT_HCIUART=n
CONFIG_BT_HCIUART_H4=n
CONFIG_BT_HCIUART_IBS=n
CONFIG_MSM_BT_POWER=n
CONFIG_CFG80211=n
CONFIG_CFG80211_DEBUGFS=n
CONFIG_CFG80211_INTERNAL_REGDB=n
CONFIG_CFG80211_WEXT=n
#end: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_RFKILL=y
CONFIG_IPC_ROUTER=y
CONFIG_IPC_ROUTER_SECURITY=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=4
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_MSM_QPIC_NAND=y
CONFIG_MTD_UBI=y
CONFIG_MTD_NAND=y
#start: add winbond spi nand config, frank.zhou 2020.12.04
CONFIG_MTD_SPI_NAND_WINBOND=n
#end: add winbond spi nand config, frank.zhou 2020.12.04
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
#start: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_QSEECOM=n
CONFIG_SCSI=n
CONFIG_BLK_DEV_SD=n
CONFIG_CHR_DEV_SG=n
CONFIG_CHR_DEV_SCH=n
CONFIG_SCSI_CONSTANTS=n
CONFIG_SCSI_LOGGING=n
CONFIG_SCSI_SCAN_ASYNC=n
#end: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_NETDEVICES=y
CONFIG_TUN=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
CONFIG_KS8851=y
# CONFIG_NET_VENDOR_MICROCHIP is not set
CONFIG_MSM_RMNET_BAM=y
# CONFIG_NET_VENDOR_NATSEMI is not set
CONFIG_QCOM_EMAC=m
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_STMICRO is not set
#start: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_AT803X_PHY=n
CONFIG_QCA8337_SWITCH=n
CONFIG_PPP=n
CONFIG_PPP_ASYNC=n
CONFIG_WCNSS_MEM_PRE_ALLOC=n
CONFIG_CNSS_CRYPTO=n
CONFIG_CNSS=n
CONFIG_CNSS_SDIO=n
CONFIG_CLD_HL_SDIO_CORE=n
#end: reduce function for 1+1,frank.zhou 2019.11.05
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
CONFIG_SERIO_LIBPS2=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MSM_HS=y
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_SMD=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
#start open spi function, frank.zhou 2019.10.08
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=y
#end open spi function, frank.zhou 2019.10.08
CONFIG_PPS=y
CONFIG_PINCTRL_MDM9607=y
CONFIG_DEBUG_GPIO=n
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_SUPPLY=y
#start: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_SMB1351_USB_CHARGER=n
CONFIG_SMB358_CHARGER=n
#end: reduce function for 1+1,frank.zhou 2019.11.05
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_MSM=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_THERMAL_MONITOR=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_WCD9306_CODEC=y
CONFIG_WCD9330_CODEC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_STUB=y
CONFIG_REGULATOR_MEM_ACC=y
CONFIG_REGULATOR_SPM=y
CONFIG_REGULATOR_CPR=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_NAU88C22=y
CONFIG_SND_SOC_RT5616=y
CONFIG_SND_SOC_MDM9607=y

CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MSM=y
CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=n
CONFIG_USB_STORAGE=n
CONFIG_USB_STORAGE_DEBUG=n
CONFIG_USB_STORAGE_DATAFAB=n
CONFIG_USB_STORAGE_FREECOM=n
CONFIG_USB_STORAGE_ISD200=n
CONFIG_USB_STORAGE_USBAT=n
CONFIG_USB_STORAGE_SDDR09=n
CONFIG_USB_STORAGE_SDDR55=n
CONFIG_USB_STORAGE_JUMPSHOT=n
CONFIG_USB_STORAGE_ALAUDA=n
CONFIG_USB_STORAGE_ONETOUCH=n
CONFIG_USB_STORAGE_KARMA=n
CONFIG_USB_STORAGE_CYPRESS_ATACB=n
CONFIG_USB_EHSET_TEST_FIXTURE=n

CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=n
CONFIG_USB_GADGET_DEBUG_FS=n
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_CI13XXX_MSM_HSIC=n
CONFIG_USB_G_ANDROID=y
#start: disable emmc driver, fibocom 2021.02.27
CONFIG_MMC=n
CONFIG_MMC_PERF_PROFILING=n
CONFIG_MMC_CLKGATE=n
CONFIG_MMC_PARANOID_SD_INIT=n
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_TEST=n
CONFIG_MMC_SDHCI=n
CONFIG_MMC_SDHCI_PLTFM=n
CONFIG_MMC_SDHCI_MSM=n
#end: disable emmc driver, fibocom 2021.02.27
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_QPNP=y
CONFIG_DMADEVICES=y
CONFIG_QCOM_SPS_DMA=y
CONFIG_UIO=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_BUS_TOPOLOGY_ADHOC=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_REVID=y
CONFIG_SPS=y
CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_GSI=y
CONFIG_MSM_SPMI=y
CONFIG_MSM_SPMI_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
CONFIG_MSM_ADSP_LOADER=y
CONFIG_MSM_MEMORY_DUMP_V2=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_COMMON_LOG=n
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=n
CONFIG_MSM_RPM_LOG=n
CONFIG_MSM_RPM_STATS_LOG=n
CONFIG_MSM_SCM=y
CONFIG_MSM_MPM_OF=y
CONFIG_MSM_SMEM=y
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_DEBUG=n
CONFIG_MSM_SMEM_LOGGING=n
CONFIG_MSM_SMP2P=y
CONFIG_MSM_SMP2P_TEST=y
CONFIG_MSM_SPM=y
CONFIG_MSM_QMI_INTERFACE=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_TRACER_PKT=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_BUFFER_CB=y
CONFIG_SENSORS_BMI160_IIO=n
CONFIG_SENSORS_BMI160_IIO_RING=n
CONFIG_CORESIGHT=n
CONFIG_CORESIGHT_EVENT=n
CONFIG_CORESIGHT_FUSE=n
CONFIG_CORESIGHT_CTI=n
CONFIG_CORESIGHT_CTI_SAVE_DISABLE=n
CONFIG_CORESIGHT_TMC=n
CONFIG_CORESIGHT_TPIU=n
CONFIG_CORESIGHT_FUNNEL=n
CONFIG_CORESIGHT_REPLICATOR=n
CONFIG_CORESIGHT_STM=n
CONFIG_CORESIGHT_HWEVENT=n
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=n
CONFIG_MAGIC_SYSRQ=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_RECURSIVE_FAULT=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_IPC_LOGGING=y
CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_DEV_QCRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_QMI_ENCDEC=y
#start: add usb detect by gpio, fibocom
CONFIG_GPIO_USB_DETECT=y
#end: add usb detect by gpio, fibocom
CONFIG_ZRAM=y
CONFIG_ZRAM_LZ4_COMPRESS=y
CONFIG_ZRAM_DEBUG=n
CONFIG_ZSMALLOC=y
CONFIG_WATCHDOG=y
CONFIG_SOFT_WATCHDOG=y
CONFIG_USB_F_UAC1=y
CONFIG_SND_USB_AUDIO=y

CONFIG_USB_RTL8152=y
CONFIG_NETDEVICES=y
CONFIG_USB_NET_DRIVERS=y
CONFIG_MII=y

mdm9607.dtsi

C/C++
fibo_kernel/arch/arm/boot/dts/fibocom/nl668-cn-12/mdm9607.dtsi
/*
 * Copyright (c) 2015-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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "skeleton.dtsi"
#include <dt-bindings/clock/mdm-clocks-9607.h>
#include <dt-bindings/clock/msm-clocks-a7.h>
#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>

/ {
	model = "Qualcomm Technologies, Inc. MDM 9607";
	compatible = "qcom,mdm9607";
	qcom,msm-id = <290 0x10000>, <296 0x10000>, <297 0x10000>,
		      <298 0x10000>, <299 0x10000>;
	interrupt-parent = <&intc>;

	aliases {
		/* Remove SDC1 by fanhang@2018.7.25 */
		//sdhc1 = &sdhc_1;/* SDC1 for SDIO slot */
		qpic_nand1 = &qnand_1;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		modem_adsp_mem: modem_adsp_region@0 {
			compatible = "removed-dma-pool";
			no-map-fixup;
			reg = <0x82a00000 0x4800000>; //reg = <0x82a00000 0x5000000>;
		};

		cnss_debug_mem: cnss_debug_region@0 {
			compatible = "removed-dma-pool";
			no-map;
			reg = <0x87a00000 0x200000>;
			status = "disabled";
		};

		external_image_mem: external_image_region@0 {
			compatible = "removed-dma-pool";
			no-map;
			reg = <0x87c00000 0x400000>;
		};

		audio_mem: audio_region@0 {
			compatible = "shared-dma-pool";
			reusable;
			alignment = <0x400000>;
			size = <0x400000>;
		};

		qseecom_mem: qseecom_region@0 {
			compatible = "shared-dma-pool";
			reusable;
			alignment = <0x400000>;
			size = <0x0400000>;
			status = "disabled";
		};
	};

	aliases {
		/* smdtty devices */
		smd7 = &smdtty_data1;
		smd8 = &smdtty_data4;
		smd11 = &smdtty_data11;
		smd21 = &smdtty_data21;
		smd36 = &smdtty_loopback;
		/* spi device */
		//spi1  = &spi_1; //del spi1, fibocom
		spi5 = &spi_5;

		/* i2c device */
		i2c2 = &i2c_2;
		i2c4 = &i2c_4;

		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
	};

	cpus {
		#size-cells = <0>;
		#address-cells = <1>;

		CPU0: cpu@0 {
			device_type = "cpu";
			compatible = "arm,cortex-a7";
			reg = <0x0>;
			qcom,limits-info = <&mitigation_profile0>;
		};
	};
	soc: soc { };
};

#include "mdm9607-ion.dtsi"
#include "mdm9607-smp2p.dtsi"
#include "mdm9607-bus.dtsi"
#include "mdm9607-coresight.dtsi"
#include "mdm9607-pm.dtsi"

&soc {
	#address-cells = <1>;
	#size-cells = <1>;
	ranges;

	intc: interrupt-controller@b000000 {
		compatible = "qcom,msm-qgic2";
		interrupt-controller;
		#interrupt-cells = <3>;
		reg = <0x0b000000 0x1000>,
		      <0x0b002000 0x1000>;
	};

	qcom,mpm2-sleep-counter@4a3000 {
		compatible = "qcom,mpm2-sleep-counter";
		reg = <0x4a3000 0x1000>;
		clock-frequency = <32768>;
	};

	timer@b020000 {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;
		compatible = "arm,armv7-timer-mem";
		reg = <0xb020000 0x1000>;
		clock-frequency = <19200000>;

		frame@b021000 {
			frame-number = <0>;
			interrupts = <0 7 0x4>,
				     <0 6 0x4>;
			reg = <0xb021000 0x1000>,
			      <0xb022000 0x1000>;
		};

		frame@b023000 {
			frame-number = <1>;
			interrupts = <0 8 0x4>;
			reg = <0xb023000 0x1000>;
			status = "disabled";
		};

		frame@b024000 {
			frame-number = <2>;
			interrupts = <0 9 0x4>;
			reg = <0xb024000 0x1000>;
			status = "disabled";
		};

		frame@b025000 {
			frame-number = <3>;
			interrupts = <0 10 0x4>;
			reg = <0xb025000 0x1000>;
			status = "disabled";
		};

		frame@b026000 {
			frame-number = <4>;
			interrupts = <0 11 0x4>;
			reg = <0xb026000 0x1000>;
			status = "disabled";
		};

		frame@b027000 {
			frame-number = <5>;
			interrupts = <0 12 0x4>;
			reg = <0xb027000 0x1000>;
			status = "disabled";
		};

		frame@b028000 {
			frame-number = <6>;
			interrupts = <0 13 0x4>;
			reg = <0xb028000 0x1000>;
			status = "disabled";
		};

		frame@b029000 {
			frame-number = <7>;
			interrupts = <0 14 0x4>;
			reg = <0xb029000 0x1000>;
			status = "disabled";
		};
	};

	qcom,wdt@b017000 {
		compatible = "qcom,msm-watchdog";
		reg = <0xb017000 0x1000>;
		reg-names = "wdt-base";
		interrupts = <0 3 0>, <0 4 0>;
		qcom,bark-time = <11000>;
		qcom,pet-time = <10000>;
		qcom,wakeup-enable;
	};

	qcom,msm-rtb {
		compatible = "qcom,msm-rtb";
		qcom,rtb-size = <0x10000>; /* 64K EBI1 buffer */
	};

	qcom,msm-imem@8600000 {
		compatible = "qcom,msm-imem";
		reg = <0x08600000 0x1000>; /* Address and size of IMEM */
		ranges = <0x0 0x08600000 0x1000>;
		#address-cells = <1>;
		#size-cells = <1>;

		mem_dump_table@10 {
			compatible = "qcom,msm-imem-mem_dump_table";
			reg = <0x10 8>;
		};

		restart_reason@65c {
			compatible = "qcom,msm-imem-restart_reason";
			reg = <0x65c 4>;
		};

		boot_stats@6b0 {
			compatible = "qcom,msm-imem-boot_stats";
			reg = <0x6b0 32>;
		};

		pil@94c {
			compatible = "qcom,msm-imem-pil";
			reg = <0x94c 200>;
		};
	};

	restart@4ab000 {
		compatible = "qcom,pshold";
		reg = <0x4ab000 0x4>,
		      <0x193d100 0x4>;
		      reg-names = "pshold-base", "tcsr-boot-misc-detect";
	};

	jtag_fuse: jtagfuse@a601c {
		compatible = "qcom,jtag-fuse-v2";
		reg = <0xa601c 0x8>;
		reg-names = "fuse-base";
		status = "disabled";
	};

	jtag_mm: jtagmm@6042000 {
		compatible = "qcom,jtagv8-mm";
		reg = <0x6042000 0x1000>,
		      <0x6040000 0x1000>;
		reg-names = "etm-base", "debug-base";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		qcom,coresight-jtagmm-cpu = <&CPU0>;
		status = "disabled";
	};

	clock_gcc: qcom,gcc@1800000 {
		compatible = "qcom,gcc-mdm9607";
		reg = <0x1800000 0x80000>,
			<0x0b008000 0x00050>;
		reg-names = "cc_base", "apcs_base";
		vdd_dig-supply = <&mdm9607_s3_level>;
		vdd_stromer_dig-supply = <&mdm9607_s3_level_ao>;
		#clock-cells = <1>;
	};

	clock_debug: qcom,debug@1874000 {
		compatible = "qcom,cc-debug-mdm9607";
		reg = <0x1800000 0x80000>,
			<0xb01101c 0x8>;
		reg-names = "cc_base", "meas";
		#clock-cells = <1>;
	};

	clock_cpu: qcom,clock-a7@0b010008 {
		compatible = "qcom,clock-a7-mdm9607";
		reg = <0x0b010008 0x8>,
				<0x000a412c 0x8>;
		reg-names = "rcg-base", "efuse";
		qcom,safe-freq = < 400000000 >;
		cpu-vdd-supply = <&apc_vreg_corner>;
		clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
					<&clock_gcc clk_a7sspll>;
		clock-names = "clk-1", "clk-5";
		qcom,speed4-bin-v0 =
				<          0 0>,
				<  400000000 1>,
				<  800000000 2>,
				<  998400000 3>,
				< 1094400000 4>,
				< 1190400000 5>,
				< 1248000000 6>,
				< 1305600000 7>;
		qcom,a7ssmux-opp-store-vcorner = <&CPU0>;
		#clock-cells = <1>;
	};

	cpubw: qcom,cpubw {
		compatible = "qcom,devbw";
		governor = "cpufreq";
		qcom,src-dst-ports = <1 512>;
		qcom,active-only;
		qcom,bw-tbl =
			<  366 /*  48   MHz */>,
			<  732 /*  96   MHz */>,
			<  915 /* 120   MHz */>,
			< 1145 /* 150.15 MHz */>,
			< 1831 /* 240   MHz */>,
			< 2291 /* 300.3 MHZ */>;
	};

	devfreq-cpufreq {
		cpubw-cpufreq {
			target-dev = <&cpubw>;
			cpu-to-dev-map =
				 <  400000   732>,
				 <  800000   915>,
				 <  998400  1145>,
				 < 1094400  1831>,
				 < 1305600  2291>;
		};
	};

	qcom,cpu-bwmon {
		compatible = "qcom,bimc-bwmon2";
		reg = <0x408000 0x300>, <0x401000 0x200>;
		reg-names = "base", "global_base";
		interrupts = <0 183 4>;
		qcom,mport = <0>;
		qcom,target-dev = <&cpubw>;
	};

	qcom,msm-cpufreq {
		reg = <0 4>;
		compatible = "qcom,msm-cpufreq";
		clocks = <&clock_cpu  clk_a7ssmux>;
		clock-names = "cpu0_clk";
		qcom,cpufreq-table =
				<  400000 >,
				<  800000 >,
				<  998400 >,
				< 1094400 >,
				< 1190400 >,
				< 1248000 >,
				< 1305600 >;
	};

	qcom,sps {
		compatible = "qcom,msm_sps_4k";
		qcom,pipe-attr-ee;
	};

	blsp1_uart5: serial@78b3000 { /* BLSP1 UART5 */
		compatible = "qcom,msm-lsuart-v14";
		reg = <0x78b3000 0x200>;
		interrupts = <0 121 0>;
		clocks = <&clock_gcc clk_gcc_blsp1_uart5_apps_clk>,
			 <&clock_gcc clk_gcc_blsp1_ahb_clk>;
		clock-names = "core_clk", "iface_clk";
		status = "disabled";
	};

	dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
		#dma-cells = <4>;
		compatible = "qcom,sps-dma";
		reg = <0x7884000 0x2b000>;
		interrupts = <0 238 0>;
		qcom,summing-threshold = <10>;
	};

	i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */
		compatible = "qcom,i2c-msm-v2";
		#address-cells = <1>;
		#size-cells = <0>;
		reg-names = "qup_phys_addr";
		reg = <0x78b6000 0x1000>;
		interrupt-names = "qup_irq";
		interrupts = <0 96 0>;
		qcom,clk-freq-out = <400000>;
		qcom,clk-freq-in  = <19200000>;
		clock-names = "iface_clk", "core_clk";
		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
			<&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>;

		pinctrl-names = "i2c_active", "i2c_sleep";
		pinctrl-0 = <&i2c_2_active>;
		pinctrl-1 = <&i2c_2_sleep>;
		qcom,noise-rjct-scl = <3>;
		qcom,noise-rjct-sda = <3>;
		qcom,master-id = <86>;
		dmas = <&dma_blsp1 14 64 0x20000020 0x20>,
			<&dma_blsp1 15 32 0x20000020 0x20>;
		dma-names = "tx", "rx";
		status = "disabled";

		rt5616_codec@1b{
			compatible = "rt5616";
			reg = <0x1b>;
		};
		nau88c22_codec@1a{
			compatible = "nau88c22";
			reg = <0x1a>;
			gpios = <&tlmm_pinmux 42 0>;
		};
	};

	i2c_4: i2c@78b8000 { /* BLSP1 QUP4 */
		compatible = "qcom,i2c-msm-v2";
		#address-cells = <1>;
		#size-cells = <0>;
		reg-names = "qup_phys_addr";
		reg = <0x78b8000 0x600>;
		interrupt-names = "qup_irq";
		interrupts = <0 98 0>;
		qcom,clk-freq-out = <400000>;
		qcom,clk-freq-in  = <19200000>;
		clock-names = "iface_clk", "core_clk";
		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
			<&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;

		pinctrl-names = "i2c_active", "i2c_sleep";
		pinctrl-0 = <&i2c_4_active>;
		pinctrl-1 = <&i2c_4_sleep>;
		qcom,noise-rjct-scl = <0>;
		qcom,noise-rjct-sda = <0>;
		qcom,master-id = <86>;
		dmas = <&dma_blsp1 18 64 0x20000020 0x20>,
			<&dma_blsp1 19 32 0x20000020 0x20>;
		dma-names = "tx", "rx";
		status = "disabled";
	};

//high speed uart
/*
	blsp1_uart3: uart@78b1000 {
		compatible = "qcom,msm-hsuart-v14";
		reg = <0x78b1000 0x200>,
			<0x7884000 0x2b000>;
		reg-names = "core_mem", "bam_mem";
		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
		#address-cells = <0>;
		interrupt-parent = <&blsp1_uart3>;
		interrupts = <0 1 2>;
		#interrupt-cells = <1>;
		interrupt-map-mask = <0xffffffff>;
		interrupt-map = <0 &intc 0 119 0
				1 &intc 0 238 0
				2 &tlmm_pinmux 1 0>;

		qcom,inject-rx-on-wakeup;
		qcom,rx-char-to-inject = <0xFD>;

		qcom,bam-tx-ep-pipe-index = <4>;
		qcom,bam-rx-ep-pipe-index = <5>;
		qcom,master-id = <86>;
		clock-names = "core_clk", "iface_clk";
		clocks = <&clock_gcc clk_gcc_blsp1_uart3_apps_clk>,
				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
		pinctrl-names = "sleep", "default";
		pinctrl-0 = <&blsp1_uart3_sleep>;
		pinctrl-1 = <&blsp1_uart3_active>;
		qcom,msm-bus,name = "blsp1_uart3";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
				<86 512 0 0>,
				<86 512 500 800>;
		status = "disabled";
	};
*/
//low speed uart
//
//	blsp1_uart5_hs: uart@78b3000 { /* BLSP1 UART5 */
//		compatible = "qcom,msm-hsuart-v14";
//		reg = <0x78b3000 0x200>,
//			<0x7884000 0x23000>;
//		reg-names = "core_mem", "bam_mem";
//		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
//		#address-cells = <0>;
//		interrupt-parent = <&blsp1_uart5_hs>;
//		interrupts = <0 1 2>;
//		#interrupt-cells = <1>;
//		interrupt-map-mask = <0xffffffff>;
//		interrupt-map = <0 &intc 0 121 0
//				1 &intc 0 238 0
//				2 &tlmm_pinmux 9 0>;
//
//		qcom,inject-rx-on-wakeup;
//		qcom,rx-char-to-inject = <0xFD>;
//
//		qcom,bam-tx-ep-pipe-index = <8>;
//		qcom,bam-rx-ep-pipe-index = <9>;
//		qcom,master-id = <86>;
//		clock-names = "core_clk", "iface_clk";
//		clocks = <&clock_gcc clk_gcc_blsp1_uart5_apps_clk>,
//			<&clock_gcc clk_gcc_blsp1_ahb_clk>;
//		pinctrl-names = "sleep", "default";
//		pinctrl-0 = <&blsp1_uart5_sleep>;
//		pinctrl-1 = <&blsp1_uart5_active>;
//
//		qcom,msm-bus,name = "buart5";
//		qcom,msm-bus,num-cases = <2>;
//		qcom,msm-bus,num-paths = <1>;
//		qcom,msm-bus,vectors-KBps =
//				<86 512 0 0>,
//				<86 512 500 800>;
//		status = "disabled";
//	};
//
//end -->
	cnss_sdio: qcom,cnss-sdio {
		compatible = "qcom,cnss_sdio";
		reg = <0x87a00000 0x200000>;
		reg-names = "ramdump";
		subsys-name = "AR6320";
		vdd-wlan-supply = <&rome_vreg>;
		vdd-wlan-dsrc-supply = <&sdcard_ext_vreg>;
		vdd-wlan-io-supply = <&mdm9607_l11>;
		vdd-wlan-xtal-supply = <&mdm9607_l2>;
		status = "disabled";
	};

	usb_otg: usb@78d9000 {
		compatible = "qcom,hsusb-otg";
		reg = <0x78d9000 0x400>, <0x6c000 0x200>;
		reg-names = "core", "phy_csr";
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		interrupts = <0 134 0>, <0 140 0>;
		interrupt-names = "core_irq", "async_irq";

		hsusb_vdd_dig-supply = <&mdm9607_l9>;
		HSUSB_1p8-supply = <&mdm9607_l2>;
		HSUSB_3p3-supply = <&mdm9607_l4>;
		qcom,vdd-voltage-level = <0 1225000 1225000>;

		qcom,hsusb-otg-phy-init-seq =
			<0x44 0x80 0x38 0x81 0x24 0x82 0x13 0x83 0xffffffff>;

		qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
		qcom,hsusb-otg-mode = <3>; /* OTG mode */
		qcom,hsusb-otg-default-mode = <3>; /* peripheral mode */
		qcom,hsusb-otg-otg-control = <2>; /* PMIC control */
		qcom,usbid-gpio = <&tlmm_pinmux 42 0>;
		qcom,hsusb-log2-itc = <4>;
		qcom,dp-manual-pullup;
		qcom,boost-sysclk-with-streaming;
		qcom,phy-dvdd-always-on;
		qcom,hsusb-otg-lpm-on-dev-suspend;
		qcom,axi-prefetch-enable;
		qcom,hsusb-otg-mpm-dpsehv-int = <49>;
		qcom,hsusb-otg-mpm-dmsehv-int = <58>;
		qcom,hsusb-otg-delay-lpm;
		qcom,enable-phy-id-pullup;

		qcom,msm-bus,name = "usb2";
		qcom,msm-bus,num-cases = <3>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
				<87 512 0 0>,
				<87 512 80000 0>,
				<87 512 6000  6000>;
		clocks = <&clock_gcc clk_gcc_usb_hs_ahb_clk>,
			 <&clock_gcc clk_gcc_usb_hs_system_clk>,
			 <&clock_gcc clk_gcc_usb2a_phy_sleep_clk>,
			 <&clock_gcc clk_bimc_usb_a_clk>,
			 <&clock_gcc clk_pcnoc_usb_a_clk>,
			 <&clock_gcc clk_gcc_qusb2_phy_clk>,
			 <&clock_gcc clk_gcc_usb2_hs_phy_only_clk>,
			 <&clock_gcc clk_gcc_usb_hs_phy_cfg_ahb_clk>,
			 <&clock_gcc clk_xo_otg_clk>;
		clock-names = "iface_clk", "core_clk", "sleep_clk",
				"bimc_clk", "pcnoc_clk", "phy_reset_clk",
				"phy_por_clk", "phy_csr_clk", "xo";
		qcom,bus-clk-rate = <240000000 0 100000000
				     120000000 0  50000000>;
		qcom,max-nominal-sysclk-rate = <133330000>;
		qcom,max-svs-sysclk-rate = <69500000>;
		qcom,default-mode-svs;

		qcom,usbbam@78c4000 {
			compatible = "qcom,usb-bam-msm";
			reg = <0x78c4000 0x15000>;
			interrupt-parent = <&intc>;
			interrupts = <0 135 0>;
			qcom,bam-type = <1>;
			qcom,usb-bam-num-pipes = <2>;
			qcom,usb-bam-fifo-baseaddr = <0x08603800>;
			qcom,ignore-core-reset-ack;
			qcom,disable-clk-gating;
			qcom,reset-bam-on-disconnect;

			qcom,pipe0 {
				label = "hsusb-qdss-in-0";
				qcom,usb-bam-mem-type = <2>;
				qcom,dir = <1>;
				qcom,pipe-num = <0>;
				qcom,peer-bam = <0>;
				qcom,peer-bam-physical-address = <0x6084000>;
				qcom,src-bam-pipe-index = <0>;
				qcom,dst-bam-pipe-index = <0>;
				qcom,data-fifo-offset = <0x0>;
				qcom,data-fifo-size = <0x600>;
				qcom,descriptor-fifo-offset = <0x600>;
				qcom,descriptor-fifo-size = <0x200>;
			};
		};
	};

	android_usb: android_usb@086000c8 {
		compatible = "qcom,android-usb";
		reg = <0x086000c8 0xc8>;
		qcom,pm-qos-latency = <2 1001 12701>;
	};

	hsic: hsic@7c00000 {
		compatible = "qcom,hsic-peripheral";
		reg = <0x7c00000 0x352>,
		      <0x1100000 0x1200c>;
		interrupts = <0 141 0>, <0 142 0>;
		qcom,hsic-usb-core-id = <1>;
		vdd-supply = <&mdm9607_l9>;
		qcom,vdd-voltage-level = <0 1225000 1225000>;
		qcom,hsic-tlmm-init-seq =
			<0x12008 0x5 0x12004 0x5 0x12000 0x1>;
		qcom,hsic-disable-on-boot;

		clocks = <&clock_gcc clk_gcc_usb_hsic_ahb_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_system_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_io_cal_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_io_cal_sleep_clk>;
		clock-names = "iface_clk", "core_clk", "phy_clk",
				"cal_clk", "cal_sleep_clk";

		qcom,msm-bus,name = "hsic";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
				<85 512 0 0>,
				<85 512 6000  6000>;
		status = "disabled";
	};

	android_usb_hsic: android_usb-hsic {
		compatible = "qcom,android-usb";
		qcom,usb-core-id = <1>;
		status = "disabled";
	};

	hsic_host: hsic_host@7c00000 {
		compatible = "qcom,hsic-host";
		reg = <0x7c00000 0x352>,
		      <0x1100000 0x1200c>;
		interrupts = <0 141 0>, <0 142 0>;
		interrupt-names = "core_irq", "async_irq";
		hsic_vdd_dig-supply = <&mdm9607_l9>;
		hsic,vdd-voltage-level = <0 1225000 1225000>;
		qcom,hsic-tlmm-init-seq =
			<0x12008 0x5 0x12004 0x5 0x12000 0x1>;
		qcom,phy-susp-sof-workaround;
		qcom,disable-internal-clk-gating;

		clocks = <&clock_gcc clk_gcc_usb_hsic_ahb_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_system_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_io_cal_clk>,
			 <&clock_gcc clk_gcc_usb_hsic_io_cal_sleep_clk>;
		clock-names = "iface_clk", "core_clk", "phy_clk",
				"cal_clk", "inactivity_clk";

		qcom,msm-bus,name = "hsic";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
				<85 512 0 0>,
				<85 512 60000 800000>;
		status = "disabled";
	};

	qnand_1: nand@7980000 {
		compatible = "qcom,msm-nand";
		reg = <0x07980000 0x1000>,
		      <0x07984000 0x1a000>;
		reg-names = "nand_phys",
			    "bam_phys";
		qcom,reg-adjustment-offset = <0x4000>;

		interrupts = <0 132 0>;
		interrupt-names = "bam_irq";

		qcom,msm-bus,name = "qpic_nand";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;

		qcom,msm-bus,vectors-KBps =
			<91 512 0 0>,
			/* Voting for max b/w on PNOC bus for now */
			<91 512 400000 400000>;

		clock-names = "core_clk";
		clocks = <&clock_gcc clk_qpic_clk>;
		status = "disabled";
	};

/* Remove SDC1 by fanhang@2018.7.25 */
//	sdhc_1: sdhci@7824900 {
//		compatible = "qcom,sdhci-msm";
//		reg = <0x7824900 0x200>, <0x7824000 0x800>, <0x01111000 0x4>;
//		reg-names = "hc_mem", "core_mem", "tlmm_mem";
//
//		qcom,cpu-dma-latency-us = <701>;
//		qcom,bus-width = <4>;
//		gpios = <&tlmm_pinmux 16 0>, /* CLK */
//		      <&tlmm_pinmux 17 0>, /* CMD */
//		      <&tlmm_pinmux 15 0>, /* DATA0 */
//		      <&tlmm_pinmux 14 0>, /* DATA1 */
//		      <&tlmm_pinmux 13 0>, /* DATA2 */
//		      <&tlmm_pinmux 12 0>; /* DATA3 */
//		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
//
//		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
//			200000000>;
//
//		clock-names = "iface_clk", "core_clk";
//		clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
//		       <&clock_gcc clk_gcc_sdcc1_apps_clk>;
//
//		qcom,msm-bus,name = "sdhc1";
//		qcom,msm-bus,num-cases = <8>;
//		qcom,msm-bus,num-paths = <1>;
//		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
//			<78 512 1600 3200>,    /* 400 KB/s*/
//			<78 512 80000 160000>, /* 20 MB/s */
//			<78 512 100000 200000>, /* 25 MB/s */
//			<78 512 200000 400000>, /* 50 MB/s */
//			<78 512 400000 800000>, /* 100 MB/s */
//			<78 512 800000 800000>, /* 200 MB/s */
//			<78 512 2048000 4096000>; /* Max. bandwidth */
//			qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000
//			50000000 100000000 200000000 4294967295>;
//
//			#address-cells = <0>;
//			interrupt-parent = <&sdhc_1>;
//			interrupts = <0 1 2>;
//			#interrupt-cells = <1>;
//			interrupt-map-mask = <0xffffffff>;
//			interrupt-map = <0 &intc 0 123 0
//				1 &intc 0 138 0
//				2 &tlmm_pinmux 59 0x4>;
//			interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
//
//			qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50",
//					"DDR50","SDR104";
//
//			qcom,pm-qos-irq-type = "affine_irq";
//			qcom,pm-qos-irq-latency = <2 250>;
//
//			status = "disabled";
//	};

	 tsens: tsens@4a8000 {
		compatible = "qcom,mdm9607-tsens";
		reg = <0x4a8000 0x2000>,
			<0xa4000  0x1000>;
		reg-names = "tsens_physical", "tsens_eeprom_physical";
		interrupts = <0 184 0>;
		interrupt-names = "tsens-upper-lower";
		qcom,sensors = <5>;
		qcom,slope = <3000 3000 3000 3000 3000>;
		qcom,sensor-id = <0 1 2 3 4>;
		qcom,temp1-offset = <1 (-4) 4 (-3) (-4)>;
		qcom,temp2-offset = <1 (-2) 8 (-5) (-4)>;
	};

	wcd9xxx_intc: wcd9xxx-irq {
		compatible = "qcom,wcd9xxx-irq";
		interrupt-controller;
		#interrupt-cells = <1>;
		interrupt-parent = <&tlmm_pinmux>;
		qcom,gpio-connect = <&tlmm_pinmux 75 0>;
		interrupt-names = "cdc-int";
	};

	sound {
		compatible = "qcom,mdm9607-audio-tomtom";
		qcom,model = "mdm9607-tomtom-i2s-snd-card";

/*
		qcom,audio-routing =
			"RX_BIAS", "MCLK",
			"LDO_H", "MCLK",
			"AMIC2", "MIC BIAS2 External",
			"MIC BIAS2 External", "Headset Mic",
			"AMIC3", "MIC BIAS2 External",
			"MIC BIAS2 External", "ANCRight Headset Mic",
			"AMIC4", "MIC BIAS2 External",
			"MIC BIAS2 External", "ANCLeft Headset Mic",
			"AMIC5", "MIC BIAS1 External",
			"MIC BIAS1 External", "Handset Mic",
			"AMIC6", "MIC BIAS1 External",
			"MIC BIAS1 External", "Handset Mic",
			"DMIC1", "MIC BIAS1 External",
			"MIC BIAS1 External", "Digital Mic1",
			"DMIC3", "MIC BIAS3 External",
			"MIC BIAS3 External", "Digital Mic3";
*/

		qcom,codec-mclk-clk-freq = <12288000>;
		qcom,mi2s-interface-mode = "pri_mi2s_master", "sec_mi2s_master";
		qcom,auxpcm-interface-mode = "pri_pcm_master", "sec_pcm_master";
		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
				<&loopback>, <&hostless>, <&afe>, <&routing>,
				<&pcm_dtmf>, <&host_pcm>, <&compress>;
		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
				"msm-voip-dsp", "msm-pcm-voice",
				"msm-pcm-loopback", "msm-pcm-hostless",
				"msm-pcm-afe", "msm-pcm-routing",
				"msm-pcm-dtmf", "msm-voice-host-pcm",
				"msm-compress-dsp";
		asoc-cpu = <&dai_pri_auxpcm>, <&dai_sec_auxpcm>,
				<&mi2s_prim>, <&mi2s_sec>, <&dtmf_tx>,
				<&rx_capture_tx>, <&rx_playback_rx>,
				<&tx_capture_tx>, <&tx_playback_rx>,
				<&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
				<&afe_proxy_tx>, <&incall_record_rx>,
				<&incall_record_tx>, <&incall_music_rx>;
		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2",
				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
				"msm-dai-stub-dev.4", "msm-dai-stub-dev.5",
				"msm-dai-stub-dev.6", "msm-dai-stub-dev.7",
				"msm-dai-stub-dev.8", "msm-dai-q6-dev.224",
				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773";
		asoc-codec = <&stub_codec>;
		asoc-codec-names = "msm-stub-codec.1";
	};


	qcom,msm-adsp-loader {
		compatible = "qcom,adsp-loader";
		qcom,adsp-state = <0>;
		qcom,proc-img-to-load = "modem";
	};

	qcom,msm-audio-ion {
		compatible = "qcom,msm-audio-ion";
		qcom,scm-mp-enabled;
		memory-region = <&audio_mem>;
	};

	pcm0: qcom,msm-pcm {
		compatible = "qcom,msm-pcm-dsp";
		qcom,msm-pcm-dsp-id = <0>;
	};

	routing: qcom,msm-pcm-routing {
		compatible = "qcom,msm-pcm-routing";
	};

	pcm1: qcom,msm-pcm-low-latency {
		compatible = "qcom,msm-pcm-dsp";
		qcom,msm-pcm-dsp-id = <1>;
		qcom,msm-pcm-low-latency;
		qcom,latency-level = "ultra";
	};

	qcom,msm-compr-dsp {
		compatible = "qcom,msm-compr-dsp";
	};

	voip: qcom,msm-voip-dsp {
		compatible = "qcom,msm-voip-dsp";
	};

	voice: qcom,msm-pcm-voice {
		compatible = "qcom,msm-pcm-voice";
		qcom,destroy-cvd;
	};

	stub_codec: qcom,msm-stub-codec {
		compatible = "qcom,msm-stub-codec";
	};

	qcom,msm-dai-fe {
		compatible = "qcom,msm-dai-fe";
	};

	afe: qcom,msm-pcm-afe {
		compatible = "qcom,msm-pcm-afe";
	};

	hostless: qcom,msm-pcm-hostless {
		compatible = "qcom,msm-pcm-hostless";
	};

	host_pcm: qcom,msm-voice-host-pcm {
		compatible = "qcom,msm-voice-host-pcm";
	};

	loopback: qcom,msm-pcm-loopback {
		compatible = "qcom,msm-pcm-loopback";
	};

	compress: qcom,msm-compress-dsp {
		compatible = "qcom,msm-compress-dsp";
		qcom,adsp-version = "MDSP 2.8";
	};

	 qcom,msm-dai-stub {
		compatible = "qcom,msm-dai-stub";
		dtmf_tx: qcom,msm-dai-stub-dtmf-tx {
			compatible = "qcom,msm-dai-stub-dev";
			qcom,msm-dai-stub-dev-id = <4>;
		};

		rx_capture_tx: qcom,msm-dai-stub-host-rx-capture-tx {
			compatible = "qcom,msm-dai-stub-dev";
			qcom,msm-dai-stub-dev-id = <5>;
		};

		rx_playback_rx: qcom,msm-dai-stub-host-rx-playback-rx {
			compatible = "qcom,msm-dai-stub-dev";
			qcom,msm-dai-stub-dev-id = <6>;
	       };

		tx_capture_tx: qcom,msm-dai-stub-host-tx-capture-tx {
			compatible = "qcom,msm-dai-stub-dev";
			qcom,msm-dai-stub-dev-id = <7>;
		};

		tx_playback_rx: qcom,msm-dai-stub-host-tx-playback-rx {
			compatible = "qcom,msm-dai-stub-dev";
			qcom,msm-dai-stub-dev-id = <8>;
		};
	};

	qcom,msm-dai-q6 {
		compatible = "qcom,msm-dai-q6";
		afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <224>;
		};

		afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <225>;
		};

		afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <241>;
		};

		afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <240>;
		};

		incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <32771>;
		};

		incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <32772>;
		};

		incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
			compatible = "qcom,msm-dai-q6-dev";
			qcom,msm-dai-q6-dev-id = <32773>;
		};
	};

	pcm_dtmf: qcom,msm-pcm-dtmf {
		compatible = "qcom,msm-pcm-dtmf";
	};

	pcm_dsp_dtmf: qcom,msm-pcm-dsp-dtmf {
		compatible = "qcom,msm-pcm-dsp-dtmf";
	};

	pcm_dtmf_detect: qcom,msm-dtmf-detect {
		compatible = "qcom,msm-dtmf-detect";
	};

	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
...

This file has been truncated, please download it to see its full contents.

phy-msm-usb.c

C/C++
fibo_kernel/drivers/usb/phy/phy-msm-usb.c
/* Copyright (c) 2009-2017, 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
#include <linux/clk/msm-clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/irqchip/msm-mpm-irq.h>
#include <soc/qcom/scm.h>

#include <linux/usb.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/usb/gadget.h>
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/msm_ext_chg.h>
#include <linux/regulator/consumer.h>
#include <linux/qpnp/qpnp-adc.h>

#include <linux/msm-bus.h>

#define MSM_USB_BASE	(motg->regs)
#define MSM_USB_PHY_CSR_BASE (motg->phy_csr_regs)

#define DRIVER_NAME	"msm_otg"

#define CHG_RECHECK_DELAY	(jiffies + msecs_to_jiffies(2000))
#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
#define USB_PHY_3P3_VOL_MIN	3050000 /* uV */
#define USB_PHY_3P3_VOL_MAX	3300000 /* uV */
#define USB_PHY_3P3_HPM_LOAD	50000	/* uA */
#define USB_PHY_3P3_LPM_LOAD	4000	/* uA */

#define USB_PHY_1P8_VOL_MIN	1800000 /* uV */
#define USB_PHY_1P8_VOL_MAX	1800000 /* uV */
#define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
#define USB_PHY_1P8_LPM_LOAD	4000	/* uA */

#define USB_PHY_VDD_DIG_VOL_NONE	0 /*uV */
#define USB_PHY_VDD_DIG_VOL_MIN	1045000 /* uV */
#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */

#define USB_SUSPEND_DELAY_TIME	(500 * HZ/1000) /* 500 msec */

#define USB_DEFAULT_SYSTEM_CLOCK 80000000	/* 80 MHz */

#define PM_QOS_SAMPLE_SEC	2
#define PM_QOS_THRESHOLD	400

enum msm_otg_phy_reg_mode {
	USB_PHY_REG_OFF,
	USB_PHY_REG_ON,
	USB_PHY_REG_LPM_ON,
	USB_PHY_REG_LPM_OFF,
	USB_PHY_REG_3P3_ON,
	USB_PHY_REG_3P3_OFF,
};

static char *override_phy_init;
module_param(override_phy_init, charp, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(override_phy_init,
	"Override HSUSB PHY Init Settings");

unsigned int lpm_disconnect_thresh = 1000;
module_param(lpm_disconnect_thresh , uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(lpm_disconnect_thresh,
	"Delay before entering LPM on USB disconnect");

static bool floated_charger_enable;
module_param(floated_charger_enable , bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(floated_charger_enable,
	"Whether to enable floated charger");

/* by default debugging is enabled */
static unsigned int enable_dbg_log = 1;
module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(enable_dbg_log, "Debug buffer events");

/* Max current to be drawn for HVDCP charger */
static int hvdcp_max_current = IDEV_HVDCP_CHG_MAX;
module_param(hvdcp_max_current, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(hvdcp_max_current, "max current drawn for HVDCP charger");

/* Max current to be drawn for DCP charger */
static int dcp_max_current = IDEV_CHG_MAX;
module_param(dcp_max_current, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dcp_max_current, "max current drawn for DCP charger");

static DECLARE_COMPLETION(pmic_vbus_init);
static struct msm_otg *the_msm_otg;
static bool debug_bus_voting_enabled;

static struct regulator *hsusb_3p3;
static struct regulator *hsusb_1p8;
static struct regulator *hsusb_vdd;
static struct regulator *vbus_otg;
static struct power_supply *psy;

static int vdd_val[VDD_VAL_MAX];
static u32 bus_freqs[USB_NOC_NUM_VOTE][USB_NUM_BUS_CLOCKS]  /*bimc,snoc,pcnoc*/;
static char bus_clkname[USB_NUM_BUS_CLOCKS][20] = {"bimc_clk", "snoc_clk",
						"pcnoc_clk"};
static bool bus_clk_rate_set;
/*merge patch for am branch provided by hguan@qti.qualcomm.com 2019.04.1 zhouwentao Case Number:03911808*/
#ifdef FEATURE_USB_SLEEP_CTRL
bool odm_otg_resume = true;
static struct mutex otg_resume_mutex;
#endif
static bool odm_usbsleepen = false;//chenning modify gtusbsleepen =2,0 20191118

static void dbg_inc(unsigned *idx)
{
	*idx = (*idx + 1) & (DEBUG_MAX_MSG-1);
}

static void
msm_otg_dbg_log_event(struct usb_phy *phy, char *event, int d1, int d2)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	unsigned long flags;
	unsigned long long t;
	unsigned long nanosec;

	if (!enable_dbg_log)
		return;

	write_lock_irqsave(&motg->dbg_lock, flags);
	t = cpu_clock(smp_processor_id());
	nanosec = do_div(t, 1000000000)/1000;
	scnprintf(motg->buf[motg->dbg_idx], DEBUG_MSG_LEN,
			"[%5lu.%06lu]: %s :%d:%d",
			(unsigned long)t, nanosec, event, d1, d2);

	motg->dbg_idx++;
	motg->dbg_idx = motg->dbg_idx % DEBUG_MAX_MSG;
	write_unlock_irqrestore(&motg->dbg_lock, flags);
}

static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
{
	int rc = 0;

	if (init) {
		hsusb_3p3 = devm_regulator_get(motg->phy.dev, "HSUSB_3p3");
		if (IS_ERR(hsusb_3p3)) {
			dev_err(motg->phy.dev, "unable to get hsusb 3p3\n");
			return PTR_ERR(hsusb_3p3);
		}

		rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
				USB_PHY_3P3_VOL_MAX);
		if (rc) {
			dev_err(motg->phy.dev, "unable to set voltage level for"
					"hsusb 3p3\n");
			return rc;
		}
		hsusb_1p8 = devm_regulator_get(motg->phy.dev, "HSUSB_1p8");
		if (IS_ERR(hsusb_1p8)) {
			dev_err(motg->phy.dev, "unable to get hsusb 1p8\n");
			rc = PTR_ERR(hsusb_1p8);
			goto put_3p3_lpm;
		}
		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
				USB_PHY_1P8_VOL_MAX);
		if (rc) {
			dev_err(motg->phy.dev, "unable to set voltage level "
					"for hsusb 1p8\n");
			goto put_1p8;
		}

		return 0;
	}

put_1p8:
	regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
put_3p3_lpm:
	regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
	return rc;
}

static int msm_hsusb_config_vddcx(int high)
{
	struct msm_otg *motg = the_msm_otg;
	int max_vol = vdd_val[VDD_MAX];
	int min_vol;
	int ret;

	min_vol = vdd_val[!!high];
	ret = regulator_set_voltage(hsusb_vdd, min_vol, max_vol);
	if (ret) {
		pr_err("%s: unable to set the voltage for regulator "
			"HSUSB_VDDCX\n", __func__);
		return ret;
	}

	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
	msm_otg_dbg_log_event(&motg->phy, "CONFIG VDDCX", min_vol, max_vol);

	return ret;
}

static int msm_hsusb_ldo_enable(struct msm_otg *motg,
	enum msm_otg_phy_reg_mode mode)
{
	int ret = 0;

	if (IS_ERR(hsusb_1p8)) {
		pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
		return -ENODEV;
	}

	if (IS_ERR(hsusb_3p3)) {
		pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
		return -ENODEV;
	}

	switch (mode) {
	case USB_PHY_REG_ON:
		ret = regulator_set_optimum_mode(hsusb_1p8,
				USB_PHY_1P8_HPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set HPM of the regulator "
				"HSUSB_1p8\n", __func__);
			return ret;
		}

		ret = regulator_enable(hsusb_1p8);
		if (ret) {
			dev_err(motg->phy.dev, "%s: unable to enable the hsusb 1p8\n",
				__func__);
			regulator_set_optimum_mode(hsusb_1p8, 0);
			return ret;
		}

	/* fall through */
	case USB_PHY_REG_3P3_ON:
		ret = regulator_set_optimum_mode(hsusb_3p3,
				USB_PHY_3P3_HPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set HPM of the regulator "
				"HSUSB_3p3\n", __func__);
			if (mode == USB_PHY_REG_ON) {
				regulator_set_optimum_mode(hsusb_1p8, 0);
				regulator_disable(hsusb_1p8);
			}
			return ret;
		}

		ret = regulator_enable(hsusb_3p3);
		if (ret) {
			dev_err(motg->phy.dev, "%s: unable to enable the hsusb 3p3\n",
				__func__);
			regulator_set_optimum_mode(hsusb_3p3, 0);
			if (mode == USB_PHY_REG_ON) {
				regulator_set_optimum_mode(hsusb_1p8, 0);
				regulator_disable(hsusb_1p8);
			}
			return ret;
		}

		break;

	case USB_PHY_REG_OFF:
		ret = regulator_disable(hsusb_1p8);
		if (ret) {
			dev_err(motg->phy.dev, "%s: unable to disable the hsusb 1p8\n",
				__func__);
			return ret;
		}

		ret = regulator_set_optimum_mode(hsusb_1p8, 0);
		if (ret < 0)
			pr_err("%s: Unable to set LPM of the regulator "
				"HSUSB_1p8\n", __func__);

	/* fall through */
	case USB_PHY_REG_3P3_OFF:
		ret = regulator_disable(hsusb_3p3);
		if (ret) {
			dev_err(motg->phy.dev, "%s: unable to disable the hsusb 3p3\n",
				 __func__);
			return ret;
		}
		ret = regulator_set_optimum_mode(hsusb_3p3, 0);
		if (ret < 0)
			pr_err("%s: Unable to set LPM of the regulator "
				"HSUSB_3p3\n", __func__);

		break;

	case USB_PHY_REG_LPM_ON:
		ret = regulator_set_optimum_mode(hsusb_1p8,
				USB_PHY_1P8_LPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set LPM of the regulator: HSUSB_1p8\n",
				__func__);
			return ret;
		}

		ret = regulator_set_optimum_mode(hsusb_3p3,
				USB_PHY_3P3_LPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set LPM of the regulator: HSUSB_3p3\n",
				__func__);
			regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
			return ret;
		}

		break;

	case USB_PHY_REG_LPM_OFF:
		ret = regulator_set_optimum_mode(hsusb_1p8,
				USB_PHY_1P8_HPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set HPM of the regulator: HSUSB_1p8\n",
				__func__);
			return ret;
		}

		ret = regulator_set_optimum_mode(hsusb_3p3,
				USB_PHY_3P3_HPM_LOAD);
		if (ret < 0) {
			pr_err("%s: Unable to set HPM of the regulator: HSUSB_3p3\n",
				__func__);
			regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
			return ret;
		}

		break;

	default:
		pr_err("%s: Unsupported mode (%d).", __func__, mode);
		return -ENOTSUPP;
	}

	pr_debug("%s: USB reg mode (%d) (OFF/HPM/LPM)\n", __func__, mode);
	msm_otg_dbg_log_event(&motg->phy, "USB REG MODE", mode, ret);
	return ret < 0 ? ret : 0;
}

static int ulpi_read(struct usb_phy *phy, u32 reg)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	int cnt = 0;

	if (motg->pdata->emulation)
		return 0;

	if (motg->pdata->phy_type == QUSB_ULPI_PHY && reg > 0x3F) {
		pr_debug("%s: ULPI vendor-specific reg 0x%02x not supported\n",
			__func__, reg);
		return 0;
	}

	/* initiate read operation */
	writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
	       USB_ULPI_VIEWPORT);

	/* wait for completion */
	while (cnt < ULPI_IO_TIMEOUT_USEC) {
		if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
			break;
		udelay(1);
		cnt++;
	}

	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
		dev_err(phy->dev, "ulpi_read: timeout %08x\n",
			readl_relaxed(USB_ULPI_VIEWPORT));
		dev_err(phy->dev, "PORTSC: %08x USBCMD: %08x\n",
			readl_relaxed(USB_PORTSC), readl_relaxed(USB_USBCMD));
		return -ETIMEDOUT;
	}
	return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
}

static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	int cnt = 0;

	if (motg->pdata->emulation)
		return 0;

	if (motg->pdata->phy_type == QUSB_ULPI_PHY && reg > 0x3F) {
		pr_debug("%s: ULPI vendor-specific reg 0x%02x not supported\n",
			__func__, reg);
		return 0;
	}

	/* initiate write operation */
	writel_relaxed(ULPI_RUN | ULPI_WRITE |
	       ULPI_ADDR(reg) | ULPI_DATA(val),
	       USB_ULPI_VIEWPORT);

	/* wait for completion */
	while (cnt < ULPI_IO_TIMEOUT_USEC) {
		if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
			break;
		udelay(1);
		cnt++;
	}

	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
		dev_err(phy->dev, "ulpi_write: timeout\n");
		dev_err(phy->dev, "PORTSC: %08x USBCMD: %08x\n",
			readl_relaxed(USB_PORTSC), readl_relaxed(USB_USBCMD));
		return -ETIMEDOUT;
	}
	return 0;
}

static struct usb_phy_io_ops msm_otg_io_ops = {
	.read = ulpi_read,
	.write = ulpi_write,
};

static void ulpi_init(struct msm_otg *motg)
{
	struct msm_otg_platform_data *pdata = motg->pdata;
	int aseq[10];
	int *seq = NULL;

	if (override_phy_init) {
		pr_debug("%s(): HUSB PHY Init:%s\n", __func__,
				override_phy_init);
		get_options(override_phy_init, ARRAY_SIZE(aseq), aseq);
		seq = &aseq[1];
	} else {
		seq = pdata->phy_init_seq;
	}

	if (!seq)
		return;

	while (seq[0] >= 0) {
		if (override_phy_init)
			pr_debug("ulpi: write 0x%02x to 0x%02x\n",
					seq[0], seq[1]);

		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
				seq[0], seq[1]);
		msm_otg_dbg_log_event(&motg->phy, "ULPI WRITE", seq[0], seq[1]);
		ulpi_write(&motg->phy, seq[0], seq[1]);
		seq += 2;
	}
}

static int msm_otg_phy_clk_reset(struct msm_otg *motg)
{
	int ret;

	if (!motg->phy_reset_clk)
		return 0;

	if (motg->sleep_clk)
		clk_disable_unprepare(motg->sleep_clk);
	if (motg->phy_csr_clk)
		clk_disable_unprepare(motg->phy_csr_clk);

	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
	if (ret < 0) {
		pr_err("phy_reset_clk assert failed %d\n", ret);
		return ret;
	}
	/*
	 * As per databook, 10 usec delay is required between
	 * PHY POR assert and de-assert.
	 */
	usleep_range(10, 15);
	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
	if (ret < 0) {
		pr_err("phy_reset_clk de-assert failed %d\n", ret);
		return ret;
	}
	/*
	 * As per databook, it takes 75 usec for PHY to stabilize
	 * after the reset.
	 */
	usleep_range(80, 100);

	if (motg->phy_csr_clk)
		clk_prepare_enable(motg->phy_csr_clk);
	if (motg->sleep_clk)
		clk_prepare_enable(motg->sleep_clk);

	return 0;
}

static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
{
	int ret;

	if (assert) {
		/* Using asynchronous block reset to the hardware */
		dev_dbg(motg->phy.dev, "block_reset ASSERT\n");
		clk_disable_unprepare(motg->pclk);
		clk_disable_unprepare(motg->core_clk);
		ret = clk_reset(motg->core_clk, CLK_RESET_ASSERT);
		if (ret)
			dev_err(motg->phy.dev, "usb hs_clk assert failed\n");
	} else {
		dev_dbg(motg->phy.dev, "block_reset DEASSERT\n");
		ret = clk_reset(motg->core_clk, CLK_RESET_DEASSERT);
		ndelay(200);
		ret = clk_prepare_enable(motg->core_clk);
		WARN(ret, "USB core_clk enable failed\n");
		ret = clk_prepare_enable(motg->pclk);
		WARN(ret, "USB pclk enable failed\n");
		if (ret)
			dev_err(motg->phy.dev, "usb hs_clk deassert failed\n");
	}
	return ret;
}

static int msm_otg_phy_reset(struct msm_otg *motg)
{
	u32 val;
	int ret;
	struct msm_otg_platform_data *pdata = motg->pdata;

	/*
	 * AHB2AHB Bypass mode shouldn't be enable before doing
	 * async clock reset. If it is enable, disable the same.
	 */
	val = readl_relaxed(USB_AHBMODE);
	if (val & AHB2AHB_BYPASS) {
		pr_err("%s(): AHB2AHB_BYPASS SET: AHBMODE:%x\n",
						__func__, val);
		val &= ~AHB2AHB_BYPASS_BIT_MASK;
		writel_relaxed(val | AHB2AHB_BYPASS_CLEAR, USB_AHBMODE);
		pr_err("%s(): AHBMODE: %x\n", __func__,
				readl_relaxed(USB_AHBMODE));
	}

	ret = msm_otg_link_clk_reset(motg, 1);
	if (ret)
		return ret;

	msm_otg_phy_clk_reset(motg);

	/* wait for 1ms delay as suggested in HPG. */
	usleep_range(1000, 1200);

	ret = msm_otg_link_clk_reset(motg, 0);
	if (ret)
		return ret;

	if (pdata && pdata->enable_sec_phy)
		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
							USB_PHY_CTRL2);
	val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
	writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);

	dev_info(motg->phy.dev, "phy_reset: success\n");
	msm_otg_dbg_log_event(&motg->phy, "PHY RESET SUCCESS",
			motg->inputs, motg->phy.state);
	return 0;
}

#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
static int msm_otg_link_reset(struct msm_otg *motg)
{
	int cnt = 0;
	struct msm_otg_platform_data *pdata = motg->pdata;

	writel_relaxed(USBCMD_RESET, USB_USBCMD);
	while (cnt < LINK_RESET_TIMEOUT_USEC) {
		if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
			break;
		udelay(1);
		cnt++;
	}
	if (cnt >= LINK_RESET_TIMEOUT_USEC)
		return -ETIMEDOUT;

	/* select ULPI phy */
	writel_relaxed(0x80000000, USB_PORTSC);
	writel_relaxed(0x0, USB_AHBBURST);
	writel_relaxed(0x08, USB_AHBMODE);

	if (pdata && pdata->enable_sec_phy)
		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
								USB_PHY_CTRL2);
	return 0;
}

#define QUSB2PHY_PORT_POWERDOWN		0xB4
#define QUSB2PHY_PORT_UTMI_CTRL2	0xC4

static void msm_usb_phy_reset(struct msm_otg *motg)
{
	u32 val;
	int ret, *seq;

	switch (motg->pdata->phy_type) {
	case SNPS_PICO_PHY:
		/* Assert USB PHY_PON */
		val =  readl_relaxed(motg->usb_phy_ctrl_reg);
		val &= ~PHY_POR_BIT_MASK;
		val |= PHY_POR_ASSERT;
		writel_relaxed(val, motg->usb_phy_ctrl_reg);

		/* wait for minimum 10 microseconds as
		 * suggested in HPG.
		 */
		usleep_range(10, 15);

		/* Deassert USB PHY_PON */
		val =  readl_relaxed(motg->usb_phy_ctrl_reg);
		val &= ~PHY_POR_BIT_MASK;
		val |= PHY_POR_DEASSERT;
		writel_relaxed(val, motg->usb_phy_ctrl_reg);
		break;
	case QUSB_ULPI_PHY:
		ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
		if (ret) {
			pr_err("phy_reset_clk assert failed %d\n", ret);
			break;
		}

		/* need to delay 10us for PHY to reset */
		usleep_range(10, 20);

		ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
		if (ret) {
			pr_err("phy_reset_clk de-assert failed %d\n", ret);
			break;
		}

		/* Ensure that RESET operation is completed. */
		mb();

		writel_relaxed(0x23,
				motg->phy_csr_regs + QUSB2PHY_PORT_POWERDOWN);
		writel_relaxed(0x0,
				motg->phy_csr_regs + QUSB2PHY_PORT_UTMI_CTRL2);

		/* Program tuning parameters for PHY */
		seq = motg->pdata->phy_init_seq;
		if (seq) {
			while (seq[0] >= 0) {
				writel_relaxed(seq[1],
						motg->phy_csr_regs + seq[0]);
				seq += 2;
			}
		}

		/* ensure above writes are completed before re-enabling PHY */
		wmb();
		writel_relaxed(0x22,
				motg->phy_csr_regs + QUSB2PHY_PORT_POWERDOWN);
		break;
	case SNPS_FEMTO_PHY:
		if (!motg->phy_por_clk) {
			pr_err("phy_por_clk missing\n");
			break;
		}
		ret = clk_reset(motg->phy_por_clk, CLK_RESET_ASSERT);
		if (ret) {
			pr_err("phy_por_clk assert failed %d\n", ret);
			break;
		}
		/*
		 * The Femto PHY is POR reset in the following scenarios.
		 *
		 * 1. After overriding the parameter registers.
		 * 2. Low power mode exit from PHY retention.
		 *
		 * Ensure that SIDDQ is cleared before bringing the PHY
		 * out of reset.
		 *
		 */

		val = readb_relaxed(USB_PHY_CSR_PHY_CTRL_COMMON0);
		val &= ~SIDDQ;
		writeb_relaxed(val, USB_PHY_CSR_PHY_CTRL_COMMON0);

		/*
		 * As per databook, 10 usec delay is required between
		 * PHY POR assert and de-assert.
		 */
		usleep_range(10, 20);
		ret = clk_reset(motg->phy_por_clk, CLK_RESET_DEASSERT);
		if (ret) {
			pr_err("phy_por_clk de-assert failed %d\n", ret);
			break;
		}
		/*
		 * As per databook, it takes 75 usec for PHY to stabilize
		 * after the reset.
		 */
		usleep_range(80, 100);
		break;
	default:
		break;
	}
	/* Ensure that RESET operation is completed. */
	mb();
}

static int msm_otg_reset(struct usb_phy *phy)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	struct msm_otg_platform_data *pdata = motg->pdata;
	int ret;
	u32 val = 0;
	u32 ulpi_val = 0;

	msm_otg_dbg_log_event(&motg->phy, "USB RESET", phy->state,
			get_pm_runtime_counter(phy->dev));
	/*
	 * USB PHY and Link reset also reset the USB BAM.
	 * Thus perform reset operation only once to avoid
	 * USB BAM reset on other cases e.g. USB cable disconnections.
	 * If hardware reported error then it must be reset for recovery.
	 */
	if (motg->err_event_seen) {
		dev_info(phy->dev, "performing USB h/w reset for recovery\n");
	} else if (pdata->disable_reset_on_disconnect && motg->reset_counter) {
		return 0;
	}
	motg->reset_counter++;

	ret = msm_otg_phy_reset(motg);
	if (ret) {
		dev_err(phy->dev, "phy_reset failed\n");
		return ret;
	}

	ret = msm_otg_link_reset(motg);
	if (ret) {
		dev_err(phy->dev, "link reset failed\n");
		return ret;
	}

	msleep(100);

	/* Reset USB PHY after performing USB Link RESET */
	msm_usb_phy_reset(motg);

	/* Program USB PHY Override registers. */
	ulpi_init(motg);

	/*
	 * It is required to reset USB PHY after programming
	 * the USB PHY Override registers to get the new
	 * values into effect.
	 */
	msm_usb_phy_reset(motg);

	if (pdata->otg_control == OTG_PHY_CONTROL) {
		val = readl_relaxed(USB_OTGSC);
		if (pdata->mode == USB_OTG) {
			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
			val |= OTGSC_IDIE | OTGSC_BSVIE;
		} else if (pdata->mode == USB_PERIPHERAL) {
			ulpi_val = ULPI_INT_SESS_VALID;
			val |= OTGSC_BSVIE;
		}
		writel_relaxed(val, USB_OTGSC);
		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
	} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
		ulpi_write(phy, OTG_COMP_DISABLE,
			ULPI_SET(ULPI_PWR_CLK_MNG_REG));
		if (motg->phy_irq)
			writeb_relaxed(USB_PHY_ID_MASK,
				USB2_PHY_USB_PHY_INTERRUPT_MASK1);
	}

	if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED)
		writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU),
				USB_OTGSC);

	msm_otg_dbg_log_event(&motg->phy, "USB RESET DONE", phy->state,
			get_pm_runtime_counter(phy->dev));

	if (pdata->enable_axi_prefetch)
		writel_relaxed(readl_relaxed(USB_HS_APF_CTRL) | (APF_CTRL_EN),
							USB_HS_APF_CTRL);

	/*
	 * Disable USB BAM as block reset resets USB BAM registers.
	 */
	msm_usb_bam_enable(CI_CTRL, false);

	return 0;
}

static void msm_otg_kick_sm_work(struct msm_otg *motg)
{
	if (atomic_read(&motg->in_lpm))
		motg->resume_pending = true;

//+sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
#ifndef FEATURE_USB_SLEEP_CTRL
	if (atomic_read(&motg->pm_suspended) &&
			motg->phy.state != OTG_STATE_B_SUSPEND) {
		motg->sm_work_pending = true;
	} else
#endif
//-sunxuebin,ADD,2018-12-04,Merge FEATURE for fix usb lpm mode can not access usb bus and crash dump when wakeup by socket, etc.
	if (!motg->sm_work_pending) {
		/* process event only if previous one is not pending */
		queue_work(motg->otg_wq, &motg->sm_work);
	}
}

/*
 * UDC calls usb_phy_set_suspend() to notify during bus suspend/resume.
 * Update relevant state-machine inputs and queue sm_work.
 * LPM enter/exit doesn't happen directly from this routine.
 */

static int msm_otg_set_suspend(struct usb_phy *phy, int suspend)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);

	pr_debug("%s(%d) in %s state\n", __func__, suspend,
				usb_otg_state_string(phy->state));
	msm_otg_dbg_log_event(phy, "SET SUSPEND", suspend, phy->state);

	if (!(motg->caps & ALLOW_LPM_ON_DEV_SUSPEND))
		return 0;

	if (suspend) {
		/* called in suspend interrupt context */
		pr_debug("peripheral bus suspend\n");
		msm_otg_dbg_log_event(phy, "PERIPHERAL BUS SUSPEND",
				motg->inputs, phy->state);

		set_bit(A_BUS_SUSPEND, &motg->inputs);
	} else {
		/* host resume or remote-wakeup */
		pr_debug("peripheral bus resume\n");
		msm_otg_dbg_log_event(phy, "PERIPHERAL BUS RESUME",
				motg->inputs, phy->state);

		clear_bit(A_BUS_SUSPEND, &motg->inputs);
	}
	/* use kick_sm_work to handle race with pm_resume */
	msm_otg_kick_sm_work(motg);

	return 0;
}

static int msm_otg_bus_freq_set(struct msm_otg *motg, enum usb_noc_mode mode)
{
	int i, ret;
	long rate;

	for (i = 0; i < USB_NUM_BUS_CLOCKS; i++) {
		rate = bus_freqs[mode][i];
		if (!rate) {
			pr_debug("%s rate not available\n", bus_clkname[i]);
			continue;
		}

		ret = clk_set_rate(motg->bus_clks[i], rate);
		if (ret) {
			pr_err("%s set rate failed: %d\n", bus_clkname[i], ret);
			return ret;
		}
		pr_debug("%s set to %lu Hz\n", bus_clkname[i],
			 clk_get_rate(motg->bus_clks[i]));
		msm_otg_dbg_log_event(&motg->phy, "OTG BUS FREQ SET", i, rate);
	}

	bus_clk_rate_set = true;

	return 0;
}

static int msm_otg_bus_freq_get(struct msm_otg *motg)
{
	struct device *dev = motg->phy.dev;
	struct device_node *np = dev->of_node;
	int len = 0, i, count = USB_NUM_BUS_CLOCKS;

	if (!np)
		return -EINVAL;

	of_find_property(np, "qcom,bus-clk-rate", &len);
	/* SVS requires extra set of frequencies for perf_mode sysfs node */
	if (motg->default_noc_mode == USB_NOC_SVS_VOTE)
		count *= 2;

	if (!len || (len / sizeof(u32) != count)) {
		pr_err("Invalid bus rate:%d %u\n", len, motg->default_noc_mode);
		return -EINVAL;
	}
	of_property_read_u32_array(np, "qcom,bus-clk-rate", bus_freqs[0],
				   count);
	for (i = 0; i < USB_NUM_BUS_CLOCKS; i++) {
		if (bus_freqs[0][i] == 0) {
			motg->bus_clks[i] = NULL;
			pr_debug("%s not available\n", bus_clkname[i]);
			continue;
		}

		motg->bus_clks[i] = devm_clk_get(dev, bus_clkname[i]);
		if (IS_ERR(motg->bus_clks[i])) {
			pr_err("%s get failed\n", bus_clkname[i]);
			return PTR_ERR(motg->bus_clks[i]);
		}
	}
	return 0;
}

static void msm_otg_bus_clks_enable(struct msm_otg *motg)
{
	int i;
	int ret;

	if (!bus_clk_rate_set || motg->bus_clks_enabled)
		return;

	for (i = 0; i < USB_NUM_BUS_CLOCKS; i++) {
		if (motg->bus_clks[i] == NULL)
			continue;
		ret = clk_prepare_enable(motg->bus_clks[i]);
		if (ret) {
			pr_err("%s enable rate failed: %d\n", bus_clkname[i],
				ret);
			goto err_clk_en;
		}
	}
	motg->bus_clks_enabled = true;
	return;
err_clk_en:
	for (--i; i >= 0; --i) {
		if (motg->bus_clks[i] != NULL)
			clk_disable_unprepare(motg->bus_clks[i]);
	}
}

static void msm_otg_bus_clks_disable(struct msm_otg *motg)
{
	int i;

	if (!bus_clk_rate_set || !motg->bus_clks_enabled)
		return;

	for (i = 0; i < USB_NUM_BUS_CLOCKS; i++) {
		if (motg->bus_clks[i] != NULL)
			clk_disable_unprepare(motg->bus_clks[i]);
	}
	motg->bus_clks_enabled = false;
}

static void msm_otg_bus_vote(struct msm_otg *motg, enum usb_bus_vote vote)
{
	int ret;
	struct msm_otg_platform_data *pdata = motg->pdata;

	msm_otg_dbg_log_event(&motg->phy, "BUS VOTE", vote, motg->phy.state);
	/* Check if target allows min_vote to be same as no_vote */
	if (pdata->bus_scale_table &&
	    vote >= pdata->bus_scale_table->num_usecases)
		vote = USB_NO_PERF_VOTE;

	if (motg->bus_perf_client) {
		ret = msm_bus_scale_client_update_request(
			motg->bus_perf_client, vote);
		if (ret)
			dev_err(motg->phy.dev, "%s: Failed to vote (%d)\n"
				   "for bus bw %d\n", __func__, vote, ret);
	}

...

This file has been truncated, please download it to see its full contents.

iperf_fibo.zip

C/C++
iperf3 binaries cross-compiled to NL668
No preview (download only).

Credits

Victor Fragoso
16 projects • 72 followers
Field Application Engineer at Fibocom Wireless
Contact

Comments

Please log in or sign up to comment.