Hardware components | ||||||
![]() |
| × | 1 |
This documentation has the objective to teach how to use an USB to Ethernet adapter on NL688-LA dev-board using Open Linux. This means that you can just plug the USB/ETH adapter on the OTG port and connect and Ethernet Cable to use the NL668 as an router to provide internet access to any device.
The main advantage of this process is because the OpenLinux can dismiss the necessity to use an external MCU or MPU, so you can use the NL668 as an Standalone solution for your project.
This documentation assumes that you already has an Fibocom's OpenLinux SDK done setup and you already made your first Hello World app. So, if you didn't setup it yet, you can access the documentation on this link:
https://www.hackster.io/victorffs/nl668-la-openlinux-quickstart-c40508
2. Requirements- NL668-LA Module (or any NL668 series module)
- Linux Operating System (can be a virtual machine)
- VSCode
- Fibocom's OpenLinux SDK Done Setup
- USB to OTG cable
- USB to Ethernet Adapter*
*I'm using an HP DHC-CT101 Adapter because reliability and ease to be found at any webstore or physical store (brazilian market for my case). But you can use any other converter just swapping the driver configuration in a few steps forward.
3. Identify your correct USB DriverYou need to identify the correct USB driver for your USB to ETH adapter. The brand name and model doesn't guarantee that this is the same driver name for the device.
What really matters is the internal ethernet chipset in your adapter, so you need to check it to get the right driver.
Plug the adapter in your PC, run lsusb in terminal and check the identified driver name:
lsusb
In this case I'm using an HP DHC-CT101 adapter, but the correct driver that Linux is using is the Realtek RTL8153 because the internal chipset of the adapter. So, we will use this driver on the OpenLinux kernel.
Check here another example with another adapter:
In this other case, the identified driver is DM9601. This should be the selected driver on OpenLinux kernel if we were to use this other adapter.
So, repeat the same on your PC and get the driver name.
4. Select the Menuconfig driversOpen your VSCode with the right SDK selected, set the crosstools and execute make menuconfig.
source fibo_crosstools/fibo-crosstool-env-init
cd fibo_kernel/
make menuconfig
Press Forward Slash "/" on your keyboard to access the search option and type the name of your ethernet driver. Input a partial name, like RTL815 or RTL81 if you can't find it by the full name:
You could just press the number of the result (#2 in this case) to be forwarded to the selection menu, change the driver option to Y and replace the saved file in the fibo_kernel right folder.
But unfortunately, after some tests, I've identified some compiling issues using the menuconfig generated file depending the version of your SDK. So, I recommend you to set the driver manually.
To set the driver manually, use the driver symbol, dependencies and selects reported on menuconfig and add the word CONFIG_ before it and the option =y after it. The result should be like this:
CONFIG_USB_RTL8152=y
CONFIG_NETDEVICES=y
CONFIG_USB_NET_DRIVERS=y
CONFIG_MII=y
Now, open fibo_kernel/arch/arm/configs/mdm9607-perf_defconfig, edit lines from 266 to 271 changing the config =n to =y as below:
Now go to the end of the file, add the config settings for your adapter driver and save it:
We will need to do some kernel customizations. You can follow the steps bellow to edit, or just replace the right files according to the attached files in this tutorial and go to step 6.
5.1. Set USB PhyOpen fibo_kernel/drivers/usb/phy/phy-msm-usb.c to edit as described bellow:
Edit the line 1782 changing the #if 0 to #if 1 :
Edit the line 2056 to remove the comment:
And finally edit the line 2079 to remove the comment too:
Now save the file.
5.2 Set USB OTG modeWe need to change the settings in kernel file to enable the USB_OTG.
Open the file fibo_kernel/arch/arm/boot/dts/fibocom/nl668-cn-12/mdm9607.dtsi , edit the lines from 552 to 555 as below and save it:
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>;
Open the fibo_kernel/drivers/platform/msm/gpio-usbdetect.c and comment some lines as described below;
TIP: Select multiple lines and press Shift + / to comment
#1
#2
#3
#4
#5
The iperf is an application to check the performance between 2 devices inside an network connection. It can be very useful to measure the performance of your project.
Fortunately we already have an iperf compiled binary compatible with NL668 (attached in the project). So, we will just put in the right folders of our SDK to enable to use.
Extract the iperf_fibo.zip and move the /usr/bin/iperf3 to folder /fibo_rootfs/usr/bin:
Now do the same but moving the /usr/lib/libiperf.so.0 to the /fibo_rootfs/usr/lib/
Your SDK with customizations for USB/Ethernet adapter is already done. Compile the files and flash in to your module.
make
adb devices
adb shell sys_reboot bootloader
fastboot devices
fastboot flash aboot target/appsboot.mbn
fastboot flash boot target/mdm9607-boot.img
fastboot flash system target/mdm9607-sysfs.ubi
fastboot reboot
Notice that after fastboot reboot the module won't be found as an ADB device by your PC. We will talk about this on next step.
8. DevKit SetupNow that your module already has the right firmware, turn off your dev kit and lets's start to connect the peripherals and jumpers.
The ADP Board has 2 USB headers. During the kernel configuration we have setup the module as an USB-OTG Host. The USB-to-USB interface now will be an OTG Interface and it's where you will plug the USB OTG Cable + USB To Ethernet adapter. While the other port (USB to Serial) now will be used to communicate with our computer.
Connect the USB OTG Adapter in the left one (1) and the USB to PC cable in the right (2).
As any OTG device, our adapter will need an power supply. Fortunately you can just enable the on-board power connecting jumpers on OTG_VBUS (3) and VDD_EXT (4) to allow USB header to provide it own power supply to external device.
After connect everything, your setup should be like this:
Plug the power adapter in EVB and turn on your module (press the PWRKEY in ADP board).
When connect the USB to PC cable, the module will provide you 2 new serial interfaces in your PC:
- /dev/ttyUSB0: for AT commands
- /dev/ ttyUSB1: for Debug and OpenLinux terminal
Now open your terminal and access the OpenLinux terminal using any terminal emulator.
minicom -D /dev/ttyUSB1 -b 115200
// OR
screen /dev/ttyUSB1 115200
Use the credentials below to login:
login: root
password: oelinux123
And use lsusb to check if your USB to Ethernet adapter was identified:
lsusb
The Vendor ID and Device ID from Device 002 is exactly the same one that we saw before when we were getting the driver name on PC. This means that our driver was loaded correctly.
10. Starting Connection and DHCPLet's use our module as an router via Ethernet. Connect the Ethernet Cable to your computer, access the OpenLinux terminal via USB and input the commands below:
dsi_netctrl_test dmnet 1 & //Dial
dnsmasq -i bridge0 --no-resolv --no-poll --dhcp-range=192.168.225.2,192.168.225.2,10h --dhcp-option=option:dns-server,8.8.8.8,114.114.114.114 & //Start DHCP service
iptables -t nat -A POSTROUTING -o rmnet_data0 -j MASQUERADE //Set routing forwarding rules
iptables -t filter -F //Delete filter rule
iptables -t filter -nvL //Check the rule table to ensure that the data forwarded to bridge0 will not be filtered out
Open your PC terminal and check your connection using ifconfig:
ifconfig
Congratulations! Now you can navigate on web using LTE connection.
If you have followed the step 6, you should have the iperf3 already installed in your module. Let set our NL668 as an iperf3 server and use our PC as an client:
In OpenLinux terminal execute the command:
iperf3 -s
Now, go to your PC terminal, install the iperf with apt-get and then execute the iperf client request.
sudo apt-get install iperf3
iperf3 -c 192.168.225.1 -P 10 -t 30
Obs.: The iperf3 will start 10 process (parameter -P) to send and receive TCP data. The total network bandwidth should be shared between all the started process, so you can consider as a result the SUM at 2 last lines.
12. Reflashing any Firwmare (EXTRA)You probably noticed that there is now how to connect to ADB and because this you should be thinking about how reflash your firmware.
There is 2 ways to get back to fastboot and allow you to re-flash your module.
12.1 sys_rebootAccess the openlinux terminal and input the following command:
sys_reboot bootloader
Then your module will reset an you will see the debug log (from fastboot booting):
Now swap the USB cable from USB-To-Serial port to USB-to-USB port and you will able to use fastboot normally as the same after send adb shell sys_reboot bootloader
12.2 Terminal + ESCIf you have any issue to access the OpenLinux terminal (if you are stuck in a bootloop for example) you can open the serial interface (ttyUSB1) before power on the module, and so power on while pressing the ESC button.
The module will detect the ESC button interruption and start the bootloader mode.
Don't forget to swap the USB cabble from USB-to-Serial port to USB-to-USB port.
13. Uploading file using Ethernet (EXTRA)One other advantage to have the ADB is the capability to send files via USB using ADB push, but unfortunately you wont be able to do this because the ADB is not enabled.
If you need to send any file to your module I recommend you to use the http server Python module. With an unique command line you will be sharing all the content of the terminal selected folder.
Here is an example about how to proceed:
- Create a folder
- Put the file that you want to upload inside the folder
- Open an terminal inside the folder and run the command bellow:
python3 -m http.server
- Access your NL668 module and use wget to download the file from your PC. Example:
wget http://192.168.225.2:8000/example.txt
/* 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");
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
/*
* 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.
/* 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.
Comments
Please log in or sign up to comment.