Merge "cnss: Provide API to CLD Driver to control SPDT GPIO"
This commit is contained in:
commit
fad851b94a
6 changed files with 528 additions and 28 deletions
|
@ -29,6 +29,9 @@ Optional properties:
|
|||
has exclusive access to UART.
|
||||
- vdd-wlan-io-supply: phandle to the 1.8V IO regulator for QCA6174
|
||||
- vdd-wlan-xtal-supply: phandle to the 1.8V XTAL regulator for QCA6174
|
||||
- vdd-wlan-xtal-aon-supply: phandle to the LDO-4 regulator. This is needed
|
||||
on platforms where XTAL regulator depends on
|
||||
always on regulator in VDDmin.
|
||||
- vdd-wlan-core-supply: phandle to the 1.3V CORE regulator for QCA6174
|
||||
- vdd-wlan-sp2t-supply: phandle to the 2.7V SP2T regulator for QCA6174
|
||||
- qcom,wlan-smmu-iova-address: I/O virtual address range as <start length>
|
||||
|
@ -39,6 +42,8 @@ Optional properties:
|
|||
- reg-names: Names of the memory regions defined in reg entry
|
||||
- wlan-bootstrap-gpio: WLAN_BOOTSTRAP GPIO signal specified by QCA6174
|
||||
which should be drived depending on platforms
|
||||
- qcom,is-dual-wifi-enabled: Boolean property to control wlan enable(wlan-en)
|
||||
gpio on dual-wifi platforms.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -382,3 +382,45 @@ int cnss_common_set_wlan_mac_address(
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_common_set_wlan_mac_address);
|
||||
|
||||
int cnss_power_up(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (cnss_get_dev_bus_type(dev)) {
|
||||
case CNSS_BUS_PCI:
|
||||
ret = cnss_pcie_power_up(dev);
|
||||
break;
|
||||
case CNSS_BUS_SDIO:
|
||||
ret = cnss_sdio_power_up(dev);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid Bus Type\n", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_power_up);
|
||||
|
||||
int cnss_power_down(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (cnss_get_dev_bus_type(dev)) {
|
||||
case CNSS_BUS_PCI:
|
||||
ret = cnss_pcie_power_down(dev);
|
||||
break;
|
||||
case CNSS_BUS_SDIO:
|
||||
ret = cnss_sdio_power_down(dev);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid Bus Type\n", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_power_down);
|
||||
|
|
|
@ -37,4 +37,8 @@ int cnss_sdio_set_wlan_mac_address(const u8 *in, uint32_t len);
|
|||
|
||||
u8 *cnss_pci_get_wlan_mac_address(uint32_t *num);
|
||||
u8 *cnss_sdio_get_wlan_mac_address(uint32_t *num);
|
||||
int cnss_sdio_power_up(struct device *dev);
|
||||
int cnss_sdio_power_down(struct device *dev);
|
||||
int cnss_pcie_power_up(struct device *dev);
|
||||
int cnss_pcie_power_down(struct device *dev);
|
||||
#endif /* _NET_CNSS_COMMON_H_ */
|
||||
|
|
|
@ -109,6 +109,7 @@ static struct cnss_fw_files FW_FILES_DEFAULT = {
|
|||
#define WLAN_VREG_NAME "vdd-wlan"
|
||||
#define WLAN_VREG_IO_NAME "vdd-wlan-io"
|
||||
#define WLAN_VREG_XTAL_NAME "vdd-wlan-xtal"
|
||||
#define WLAN_VREG_XTAL_AON_NAME "vdd-wlan-xtal-aon"
|
||||
#define WLAN_VREG_CORE_NAME "vdd-wlan-core"
|
||||
#define WLAN_VREG_SP2T_NAME "vdd-wlan-sp2t"
|
||||
#define WLAN_SWREG_NAME "wlan-soc-swreg"
|
||||
|
@ -181,6 +182,7 @@ struct cnss_wlan_vreg_info {
|
|||
struct regulator *ant_switch;
|
||||
struct regulator *wlan_reg_io;
|
||||
struct regulator *wlan_reg_xtal;
|
||||
struct regulator *wlan_reg_xtal_aon;
|
||||
struct regulator *wlan_reg_core;
|
||||
struct regulator *wlan_reg_sp2t;
|
||||
bool state;
|
||||
|
@ -221,6 +223,10 @@ struct index_file {
|
|||
u8 file_name[13];
|
||||
};
|
||||
|
||||
struct cnss_dual_wifi {
|
||||
bool is_dual_wifi_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_mac_addr - Structure to hold WLAN MAC Address
|
||||
* @mac_addr: MAC address
|
||||
|
@ -298,6 +304,7 @@ static struct cnss_data {
|
|||
int wlan_bootstrap_gpio;
|
||||
atomic_t auto_suspended;
|
||||
bool monitor_wake_intr;
|
||||
struct cnss_dual_wifi dual_wifi_info;
|
||||
} *penv;
|
||||
|
||||
static unsigned int pcie_link_down_panic;
|
||||
|
@ -334,6 +341,15 @@ static int cnss_wlan_vreg_on(struct cnss_wlan_vreg_info *vreg_info)
|
|||
}
|
||||
}
|
||||
|
||||
if (vreg_info->wlan_reg_xtal_aon) {
|
||||
ret = regulator_enable(vreg_info->wlan_reg_xtal_aon);
|
||||
if (ret) {
|
||||
pr_err("%s: wlan_reg_xtal_aon enable failed\n",
|
||||
__func__);
|
||||
goto error_enable_reg_xtal_aon;
|
||||
}
|
||||
}
|
||||
|
||||
if (vreg_info->wlan_reg_xtal) {
|
||||
ret = regulator_enable(vreg_info->wlan_reg_xtal);
|
||||
if (ret) {
|
||||
|
@ -382,6 +398,9 @@ error_enable_reg_sp2t:
|
|||
if (vreg_info->wlan_reg_xtal)
|
||||
regulator_disable(vreg_info->wlan_reg_xtal);
|
||||
error_enable_reg_xtal:
|
||||
if (vreg_info->wlan_reg_xtal_aon)
|
||||
regulator_disable(vreg_info->wlan_reg_xtal_aon);
|
||||
error_enable_reg_xtal_aon:
|
||||
if (vreg_info->wlan_reg_io)
|
||||
regulator_disable(vreg_info->wlan_reg_io);
|
||||
error_enable_reg_io:
|
||||
|
@ -433,6 +452,15 @@ static int cnss_wlan_vreg_off(struct cnss_wlan_vreg_info *vreg_info)
|
|||
}
|
||||
}
|
||||
|
||||
if (vreg_info->wlan_reg_xtal_aon) {
|
||||
ret = regulator_disable(vreg_info->wlan_reg_xtal_aon);
|
||||
if (ret) {
|
||||
pr_err("%s: wlan_reg_xtal_aon disable failed\n",
|
||||
__func__);
|
||||
goto error_disable;
|
||||
}
|
||||
}
|
||||
|
||||
if (vreg_info->wlan_reg_io) {
|
||||
ret = regulator_disable(vreg_info->wlan_reg_io);
|
||||
if (ret) {
|
||||
|
@ -553,6 +581,11 @@ static void cnss_wlan_gpio_set(struct cnss_wlan_gpio_info *info, bool state)
|
|||
return;
|
||||
}
|
||||
|
||||
if (state == WLAN_EN_LOW && penv->dual_wifi_info.is_dual_wifi_enabled) {
|
||||
pr_debug("%s Dual WiFi enabled\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_value(info->num, state);
|
||||
info->state = state;
|
||||
|
||||
|
@ -583,6 +616,89 @@ static int cnss_pinctrl_init(struct cnss_wlan_gpio_info *gpio_info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void cnss_disable_xtal_ldo(struct platform_device *pdev)
|
||||
{
|
||||
struct cnss_wlan_vreg_info *info = &penv->vreg_info;
|
||||
|
||||
if (info->wlan_reg_xtal) {
|
||||
regulator_disable(info->wlan_reg_xtal);
|
||||
regulator_put(info->wlan_reg_xtal);
|
||||
}
|
||||
|
||||
if (info->wlan_reg_xtal_aon) {
|
||||
regulator_disable(info->wlan_reg_xtal_aon);
|
||||
regulator_put(info->wlan_reg_xtal_aon);
|
||||
}
|
||||
}
|
||||
|
||||
static int cnss_enable_xtal_ldo(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cnss_wlan_vreg_info *info = &penv->vreg_info;
|
||||
|
||||
if (!of_get_property(pdev->dev.of_node,
|
||||
WLAN_VREG_XTAL_AON_NAME "-supply", NULL))
|
||||
goto enable_xtal;
|
||||
|
||||
info->wlan_reg_xtal_aon = regulator_get(&pdev->dev,
|
||||
WLAN_VREG_XTAL_AON_NAME);
|
||||
if (IS_ERR(info->wlan_reg_xtal_aon)) {
|
||||
ret = PTR_ERR(info->wlan_reg_xtal_aon);
|
||||
pr_err("%s: XTAL AON Regulator get failed err:%d\n", __func__,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(info->wlan_reg_xtal_aon);
|
||||
if (ret) {
|
||||
pr_err("%s: VREG_XTAL_ON enable failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
enable_xtal:
|
||||
|
||||
if (!of_get_property(pdev->dev.of_node,
|
||||
WLAN_VREG_XTAL_NAME "-supply", NULL))
|
||||
goto out_disable_xtal_aon;
|
||||
|
||||
info->wlan_reg_xtal = regulator_get(&pdev->dev, WLAN_VREG_XTAL_NAME);
|
||||
|
||||
if (IS_ERR(info->wlan_reg_xtal)) {
|
||||
ret = PTR_ERR(info->wlan_reg_xtal);
|
||||
pr_err("%s XTAL Regulator get failed err:%d\n", __func__, ret);
|
||||
goto out_disable_xtal_aon;
|
||||
}
|
||||
|
||||
ret = regulator_set_voltage(info->wlan_reg_xtal, WLAN_VREG_XTAL_MIN,
|
||||
WLAN_VREG_XTAL_MAX);
|
||||
if (ret) {
|
||||
pr_err("%s: Set wlan_vreg_xtal failed!\n", __func__);
|
||||
goto out_put_xtal;
|
||||
}
|
||||
|
||||
ret = regulator_enable(info->wlan_reg_xtal);
|
||||
if (ret) {
|
||||
pr_err("%s: Enable wlan_vreg_xtal failed!\n", __func__);
|
||||
goto out_put_xtal;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_put_xtal:
|
||||
if (info->wlan_reg_xtal)
|
||||
regulator_put(info->wlan_reg_xtal);
|
||||
|
||||
out_disable_xtal_aon:
|
||||
if (info->wlan_reg_xtal_aon)
|
||||
regulator_disable(info->wlan_reg_xtal_aon);
|
||||
|
||||
end:
|
||||
if (info->wlan_reg_xtal_aon)
|
||||
regulator_put(info->wlan_reg_xtal_aon);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cnss_wlan_get_resources(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -660,27 +776,8 @@ static int cnss_wlan_get_resources(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (of_get_property(pdev->dev.of_node,
|
||||
WLAN_VREG_XTAL_NAME"-supply", NULL)) {
|
||||
vreg_info->wlan_reg_xtal =
|
||||
regulator_get(&pdev->dev, WLAN_VREG_XTAL_NAME);
|
||||
if (!IS_ERR(vreg_info->wlan_reg_xtal)) {
|
||||
ret = regulator_set_voltage(vreg_info->wlan_reg_xtal,
|
||||
WLAN_VREG_XTAL_MIN, WLAN_VREG_XTAL_MAX);
|
||||
if (ret) {
|
||||
pr_err("%s: Set wlan_vreg_xtal failed!\n",
|
||||
__func__);
|
||||
goto err_reg_xtal_set;
|
||||
}
|
||||
|
||||
ret = regulator_enable(vreg_info->wlan_reg_xtal);
|
||||
if (ret) {
|
||||
pr_err("%s: Enable wlan_vreg_xtal failed!\n",
|
||||
__func__);
|
||||
goto err_reg_xtal_enable;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cnss_enable_xtal_ldo(pdev))
|
||||
goto err_reg_xtal_enable;
|
||||
|
||||
if (of_get_property(pdev->dev.of_node,
|
||||
WLAN_VREG_SP2T_NAME"-supply", NULL)) {
|
||||
|
@ -850,13 +947,10 @@ err_reg_sp2t_enable:
|
|||
err_reg_sp2t_set:
|
||||
if (vreg_info->wlan_reg_sp2t)
|
||||
regulator_put(vreg_info->wlan_reg_sp2t);
|
||||
if (vreg_info->wlan_reg_xtal)
|
||||
regulator_disable(vreg_info->wlan_reg_xtal);
|
||||
|
||||
cnss_disable_xtal_ldo(pdev);
|
||||
|
||||
err_reg_xtal_enable:
|
||||
err_reg_xtal_set:
|
||||
if (vreg_info->wlan_reg_xtal)
|
||||
regulator_put(vreg_info->wlan_reg_xtal);
|
||||
if (vreg_info->wlan_reg_io)
|
||||
regulator_disable(vreg_info->wlan_reg_io);
|
||||
|
||||
|
@ -901,6 +995,8 @@ static void cnss_wlan_release_resources(void)
|
|||
regulator_put(vreg_info->wlan_reg_sp2t);
|
||||
if (vreg_info->wlan_reg_xtal)
|
||||
regulator_put(vreg_info->wlan_reg_xtal);
|
||||
if (vreg_info->wlan_reg_xtal_aon)
|
||||
regulator_put(vreg_info->wlan_reg_xtal_aon);
|
||||
if (vreg_info->wlan_reg_io)
|
||||
regulator_put(vreg_info->wlan_reg_io);
|
||||
regulator_put(vreg_info->wlan_reg);
|
||||
|
@ -1864,6 +1960,13 @@ void cnss_schedule_recovery_work(void)
|
|||
}
|
||||
EXPORT_SYMBOL(cnss_schedule_recovery_work);
|
||||
|
||||
static inline void __cnss_disable_irq(void *data)
|
||||
{
|
||||
struct pci_dev *pdev = data;
|
||||
|
||||
disable_irq(pdev->irq);
|
||||
}
|
||||
|
||||
void cnss_pci_events_cb(struct msm_pcie_notify *notify)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -1887,6 +1990,7 @@ void cnss_pci_events_cb(struct msm_pcie_notify *notify)
|
|||
spin_unlock_irqrestore(&pci_link_down_lock, flags);
|
||||
|
||||
pr_err("PCI link down, schedule recovery\n");
|
||||
__cnss_disable_irq(notify->user);
|
||||
schedule_work(&cnss_pci_recovery_work);
|
||||
break;
|
||||
|
||||
|
@ -2813,6 +2917,9 @@ static int cnss_probe(struct platform_device *pdev)
|
|||
|
||||
penv->subsys_handle = subsystem_get(penv->subsysdesc.name);
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,is-dual-wifi-enabled"))
|
||||
penv->dual_wifi_info.is_dual_wifi_enabled = true;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
|
||||
&ramdump_size) == 0) {
|
||||
penv->ramdump_addr = dma_alloc_coherent(&pdev->dev,
|
||||
|
@ -3364,6 +3471,326 @@ void cnss_runtime_exit(struct device *dev)
|
|||
pm_runtime_set_active(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_runtime_exit);
|
||||
|
||||
static void __cnss_set_pcie_monitor_intr(struct device *dev, bool val)
|
||||
{
|
||||
penv->monitor_wake_intr = val;
|
||||
}
|
||||
|
||||
static void __cnss_set_auto_suspend(struct device *dev, int val)
|
||||
{
|
||||
atomic_set(&penv->auto_suspended, val);
|
||||
}
|
||||
|
||||
static int __cnss_resume_link(struct device *dev, u32 flags)
|
||||
{
|
||||
int ret;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
u8 bus_num = cnss_get_pci_dev_bus_number(pdev);
|
||||
|
||||
ret = cnss_msm_pcie_pm_control(MSM_PCIE_RESUME, bus_num, pdev, flags);
|
||||
if (ret)
|
||||
pr_err("%s: PCIe link resume failed with flags:%d bus_num:%d\n",
|
||||
__func__, flags, bus_num);
|
||||
|
||||
penv->pcie_link_state = PCIE_LINK_UP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cnss_suspend_link(struct device *dev, u32 flags)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
u8 bus_num = cnss_get_pci_dev_bus_number(pdev);
|
||||
int ret;
|
||||
|
||||
if (!penv->pcie_link_state)
|
||||
return 0;
|
||||
|
||||
ret = cnss_msm_pcie_pm_control(MSM_PCIE_SUSPEND, bus_num, pdev, flags);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to suspend link\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
penv->pcie_link_state = PCIE_LINK_DOWN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cnss_pcie_recover_config(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cnss_msm_pcie_recover_config(to_pci_dev(dev));
|
||||
if (ret)
|
||||
pr_err("%s: PCIe Recover config failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cnss_event_reg(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct msm_pcie_register_event *event_reg;
|
||||
|
||||
event_reg = &penv->event_reg;
|
||||
|
||||
event_reg->events = MSM_PCIE_EVENT_LINKDOWN |
|
||||
MSM_PCIE_EVENT_WAKEUP;
|
||||
event_reg->user = to_pci_dev(dev);
|
||||
event_reg->mode = MSM_PCIE_TRIGGER_CALLBACK;
|
||||
event_reg->callback = cnss_pci_events_cb;
|
||||
event_reg->options = MSM_PCIE_CONFIG_NO_RECOVERY;
|
||||
|
||||
ret = cnss_msm_pcie_register_event(event_reg);
|
||||
if (ret)
|
||||
pr_err("%s: PCIe event register failed! %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __cnss_event_dereg(struct device *dev)
|
||||
{
|
||||
cnss_msm_pcie_deregister_event(&penv->event_reg);
|
||||
}
|
||||
|
||||
static struct pci_dev *__cnss_get_pcie_dev(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct pci_dev *pdev = penv->pdev;
|
||||
|
||||
if (pdev)
|
||||
return pdev;
|
||||
|
||||
ret = pci_register_driver(&cnss_wlan_pci_driver);
|
||||
if (ret) {
|
||||
pr_err("%s: pci re-registration failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdev = penv->pdev;
|
||||
|
||||
return pdev;
|
||||
}
|
||||
|
||||
static int __cnss_pcie_power_up(struct device *dev)
|
||||
{
|
||||
struct cnss_wlan_vreg_info *vreg_info;
|
||||
struct cnss_wlan_gpio_info *gpio_info;
|
||||
int ret;
|
||||
|
||||
vreg_info = &penv->vreg_info;
|
||||
gpio_info = &penv->gpio_info;
|
||||
|
||||
ret = cnss_wlan_vreg_set(vreg_info, VREG_ON);
|
||||
if (ret) {
|
||||
pr_err("%s: WLAN VREG ON Failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(POWER_ON_DELAY);
|
||||
|
||||
if (penv->wlan_bootstrap_gpio > 0) {
|
||||
gpio_set_value(penv->wlan_bootstrap_gpio, WLAN_BOOTSTRAP_HIGH);
|
||||
msleep(WLAN_BOOTSTRAP_DELAY);
|
||||
}
|
||||
|
||||
cnss_wlan_gpio_set(gpio_info, WLAN_EN_HIGH);
|
||||
msleep(WLAN_ENABLE_DELAY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cnss_pcie_power_down(struct device *dev)
|
||||
{
|
||||
struct cnss_wlan_vreg_info *vreg_info;
|
||||
struct cnss_wlan_gpio_info *gpio_info;
|
||||
int ret;
|
||||
|
||||
vreg_info = &penv->vreg_info;
|
||||
gpio_info = &penv->gpio_info;
|
||||
|
||||
cnss_wlan_gpio_set(gpio_info, WLAN_EN_LOW);
|
||||
|
||||
if (penv->wlan_bootstrap_gpio > 0)
|
||||
gpio_set_value(penv->wlan_bootstrap_gpio, WLAN_BOOTSTRAP_LOW);
|
||||
|
||||
ret = cnss_wlan_vreg_set(vreg_info, VREG_OFF);
|
||||
if (ret)
|
||||
pr_err("%s: Failed to turn off 3.3V regulator\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cnss_suspend_link_state(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int link_ind;
|
||||
|
||||
if (!penv->pcie_link_state) {
|
||||
pr_debug("%s: Link is already suspended\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
link_ind = penv->pcie_link_down_ind;
|
||||
|
||||
if (!link_ind)
|
||||
pci_save_state(pdev);
|
||||
|
||||
penv->saved_state = link_ind ? NULL : cnss_pci_store_saved_state(pdev);
|
||||
|
||||
ret = link_ind ? __cnss_suspend_link(dev, PM_OPTIONS_SUSPEND_LINK_DOWN)
|
||||
: __cnss_suspend_link(dev, PM_OPTIONS);
|
||||
if (ret) {
|
||||
pr_err("%s: Link Suspend failed in state:%s\n", __func__,
|
||||
link_ind ? "LINK_DOWN" : "LINK_ACTIVE");
|
||||
return ret;
|
||||
}
|
||||
|
||||
penv->pcie_link_state = PCIE_LINK_DOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cnss_restore_pci_config_space(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (penv->saved_state)
|
||||
ret = cnss_pci_load_and_free_saved_state(pdev,
|
||||
&penv->saved_state);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cnss_resume_link_state(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
int link_ind;
|
||||
|
||||
if (penv->pcie_link_state) {
|
||||
pr_debug("%s: Link is already in active state\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
link_ind = penv->pcie_link_down_ind;
|
||||
|
||||
ret = link_ind ? __cnss_resume_link(dev, PM_OPTIONS_RESUME_LINK_DOWN) :
|
||||
__cnss_resume_link(dev, PM_OPTIONS);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Resume Link failed in link state:%s\n", __func__,
|
||||
link_ind ? "LINK_DOWN" : "LINK_ACTIVE");
|
||||
return ret;
|
||||
}
|
||||
|
||||
penv->pcie_link_state = PCIE_LINK_UP;
|
||||
|
||||
ret = link_ind ? __cnss_pcie_recover_config(dev) :
|
||||
__cnss_restore_pci_config_space(dev);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Link Recovery Config Failed link_state:%s\n",
|
||||
__func__, link_ind ? "LINK_DOWN" : "LINK_ACTIVE");
|
||||
penv->pcie_link_state = PCIE_LINK_DOWN;
|
||||
return ret;
|
||||
}
|
||||
|
||||
penv->pcie_link_down_ind = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cnss_pcie_power_up(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (!penv) {
|
||||
pr_err("%s: platform data is NULL\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = __cnss_pcie_power_up(dev);
|
||||
if (ret) {
|
||||
pr_err("%s: Power UP Failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pdev = __cnss_get_pcie_dev(dev);
|
||||
if (!pdev) {
|
||||
pr_err("%s: PCIe Dev is NULL\n", __func__);
|
||||
goto power_down;
|
||||
}
|
||||
|
||||
ret = __cnss_event_reg(dev);
|
||||
|
||||
if (ret)
|
||||
pr_err("%s: PCIe event registration failed\n", __func__);
|
||||
|
||||
ret = __cnss_resume_link_state(dev);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Link Bring Up Failed\n", __func__);
|
||||
goto event_dereg;
|
||||
}
|
||||
|
||||
__cnss_set_pcie_monitor_intr(dev, true);
|
||||
|
||||
return ret;
|
||||
|
||||
event_dereg:
|
||||
__cnss_event_dereg(dev);
|
||||
power_down:
|
||||
__cnss_pcie_power_down(dev);
|
||||
pr_err("%s: Device Power Up Failed Fatal Error!\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __cnss_vote_bus_width(struct device *dev, uint32_t option)
|
||||
{
|
||||
if (penv->bus_client)
|
||||
msm_bus_scale_client_update_request(penv->bus_client, option);
|
||||
}
|
||||
|
||||
int cnss_pcie_power_down(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (!penv) {
|
||||
pr_err("%s: Invalid Platform data\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!pdev) {
|
||||
pr_err("%s: Invalid Pdev, Cut Power to device\n", __func__);
|
||||
__cnss_pcie_power_down(dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
__cnss_vote_bus_width(dev, CNSS_BUS_WIDTH_NONE);
|
||||
__cnss_event_dereg(dev);
|
||||
|
||||
ret = __cnss_suspend_link_state(dev);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Suspend Link failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
__cnss_set_pcie_monitor_intr(dev, false);
|
||||
__cnss_set_auto_suspend(dev, 0);
|
||||
|
||||
ret = __cnss_pcie_power_down(dev);
|
||||
if (ret)
|
||||
pr_err("%s: Power Down Failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_init(cnss_initialize);
|
||||
module_exit(cnss_exit);
|
||||
|
||||
|
|
|
@ -49,8 +49,6 @@
|
|||
#define CNSS_DUMP_NAME "CNSS_WLAN"
|
||||
#define CNSS_PINCTRL_SLEEP_STATE "sleep"
|
||||
#define CNSS_PINCTRL_ACTIVE_STATE "active"
|
||||
#define PINCTRL_SLEEP 0
|
||||
#define PINCTRL_ACTIVE 1
|
||||
|
||||
struct cnss_sdio_regulator {
|
||||
struct regulator *wlan_io;
|
||||
|
@ -673,6 +671,15 @@ static int cnss_set_pinctrl_state(struct cnss_sdio_data *pdata, bool state)
|
|||
pinctrl_select_state(info->pinctrl, info->sleep);
|
||||
}
|
||||
|
||||
int cnss_sdio_configure_spdt(bool state)
|
||||
{
|
||||
if (!cnss_pdata)
|
||||
return -ENODEV;
|
||||
|
||||
return cnss_set_pinctrl_state(cnss_pdata, state);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_sdio_configure_spdt);
|
||||
|
||||
/**
|
||||
* cnss_sdio_wlan_register_driver() - cnss wlan register API
|
||||
* @driver: sdio wlan driver interface from wlan driver.
|
||||
|
@ -1168,6 +1175,16 @@ u8 *cnss_sdio_get_wlan_mac_address(uint32_t *num)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int cnss_sdio_power_down(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cnss_sdio_power_up(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cnss_sdio_dt_match[] = {
|
||||
{.compatible = "qcom,cnss_sdio"},
|
||||
{}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#ifdef CONFIG_CNSS
|
||||
#define CNSS_MAX_FILE_NAME 20
|
||||
#define PINCTRL_SLEEP 0
|
||||
#define PINCTRL_ACTIVE 1
|
||||
|
||||
enum cnss_bus_width_type {
|
||||
CNSS_BUS_WIDTH_NONE,
|
||||
|
@ -242,4 +244,7 @@ extern void cnss_common_schedule_recovery_work(struct device *dev);
|
|||
extern int cnss_common_set_wlan_mac_address(struct device *dev, const u8 *in,
|
||||
uint32_t len);
|
||||
extern u8 *cnss_common_get_wlan_mac_address(struct device *dev, uint32_t *num);
|
||||
extern int cnss_power_up(struct device *dev);
|
||||
extern int cnss_power_down(struct device *dev);
|
||||
extern int cnss_sdio_configure_spdt(bool state);
|
||||
#endif /* _NET_CNSS_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue