Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ff075a6 authored by Yue Ma's avatar Yue Ma Committed by Gerrit - the friendly Code Review server
Browse files

cnss2: Add bus layer



Bus layer is a shim layer for potential buses (PCIe, USB and SDIO)
of WLAN devices. It abstracts all the bus related APIs for common
files of the driver so that it can help make them bus independent.

Change-Id: I06e19a26d34168fe0fcc65229a4519b868cd97c1
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
Signed-off-by: default avatarRajasekaran Kalidoss <rkalidos@codeaurora.org>
parent e84e34c0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
obj-$(CONFIG_CNSS2) += cnss2.o

cnss2-y := main.o
cnss2-y += bus.o
cnss2-y += debug.o
cnss2-y += pci.o
cnss2-y += power.o
+164 −0
Original line number Diff line number Diff line
/* Copyright (c) 2018, 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 "bus.h"
#include "debug.h"
#include "pci.h"

enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
{
	if (!dev)
		return CNSS_BUS_NONE;

	if (!dev->bus)
		return CNSS_BUS_NONE;

	if (memcmp(dev->bus->name, "pci", 3) == 0)
		return CNSS_BUS_PCI;
	else
		return CNSS_BUS_NONE;
}

enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id)
{
	switch (device_id) {
	case QCA6174_DEVICE_ID:
	case QCA6290_EMULATION_DEVICE_ID:
	case QCA6290_DEVICE_ID:
		return CNSS_BUS_PCI;
	default:
		cnss_pr_err("Unknown device_id: 0x%lx\n", device_id);
		return CNSS_BUS_NONE;
	}
}

int cnss_bus_init(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_init(plat_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

void cnss_bus_deinit(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		cnss_pci_deinit(plat_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return;
	}
}

int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_load_m3(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_alloc_fw_mem(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_get_wake_msi(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_force_fw_assert_hdlr(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return -EINVAL;
	}
}

void cnss_bus_fw_boot_timeout_hdlr(unsigned long data)
{
	struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data;

	if (!plat_priv)
		return;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_fw_boot_timeout_hdlr(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return;
	}
}

void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv)
{
	if (!plat_priv)
		return;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_collect_dump_info(plat_priv->bus_priv);
	default:
		cnss_pr_err("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return;
	}
}
+39 −0
Original line number Diff line number Diff line
/* Copyright (c) 2018, 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.
 */

#ifndef _CNSS_BUS_H
#define _CNSS_BUS_H

#include "main.h"

#define QCA6174_VENDOR_ID		0x168C
#define QCA6174_DEVICE_ID		0x003E
#define QCA6174_REV_ID_OFFSET		0x08
#define QCA6174_REV3_VERSION		0x5020000
#define QCA6174_REV3_2_VERSION		0x5030000
#define QCA6290_VENDOR_ID		0x17CB
#define QCA6290_DEVICE_ID		0x1100
#define QCA6290_EMULATION_VENDOR_ID	0x168C
#define QCA6290_EMULATION_DEVICE_ID	0xABCD

enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
int cnss_bus_init(struct cnss_plat_data *plat_priv);
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
void cnss_bus_fw_boot_timeout_hdlr(unsigned long data);
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv);

#endif /* _CNSS_BUS_H */
+12 −93
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <soc/qcom/subsystem_notif.h>

#include "main.h"
#include "bus.h"
#include "debug.h"
#include "pci.h"

@@ -37,7 +38,6 @@
#define FW_READY_TIMEOUT		20000
#define FW_ASSERT_TIMEOUT		5000
#define CNSS_EVENT_PENDING		2989
#define WAKE_MSI_NAME			"WAKE"

static struct cnss_plat_data *plat_env;

@@ -87,20 +87,6 @@ struct cnss_driver_event {
	void *data;
};

static enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
{
	if (!dev)
		return CNSS_BUS_NONE;

	if (!dev->bus)
		return CNSS_BUS_NONE;

	if (memcmp(dev->bus->name, "pci", 3) == 0)
		return CNSS_BUS_PCI;
	else
		return CNSS_BUS_NONE;
}

static void cnss_set_plat_priv(struct platform_device *plat_dev,
			       struct cnss_plat_data *plat_priv)
{
@@ -274,23 +260,6 @@ int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap)
}
EXPORT_SYMBOL(cnss_get_platform_cap);

int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
{
	int ret = 0;
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
	void *bus_priv = cnss_bus_dev_to_bus_priv(dev);

	if (!plat_priv)
		return -ENODEV;

	ret = cnss_pci_get_bar_info(bus_priv, &info->va, &info->pa);
	if (ret)
		return ret;

	return 0;
}
EXPORT_SYMBOL(cnss_get_soc_info);

void cnss_request_pm_qos(struct device *dev, u32 qos_val)
{
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
@@ -506,24 +475,6 @@ int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
}
EXPORT_SYMBOL(cnss_set_fw_log_mode);

u32 cnss_get_wake_msi(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	int ret, num_vectors;
	u32 user_base_data, base_vector;

	ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
					   WAKE_MSI_NAME, &num_vectors,
					   &user_base_data, &base_vector);

	if (ret) {
		cnss_pr_err("WAKE MSI is not valid\n");
		return 0;
	}

	return user_base_data;
}

static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
@@ -541,7 +492,7 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
	if (ret)
		goto out;

	ret = cnss_pci_load_m3(plat_priv->bus_priv);
	ret = cnss_bus_load_m3(plat_priv);
	if (ret)
		goto out;

@@ -1483,7 +1434,7 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
			cnss_pr_err("Failed to complete RDDM, err = %d\n", ret);
			break;
		}
		cnss_pci_collect_dump_info(pci_priv);
		cnss_bus_collect_dump_info(plat_priv);
		break;
	case CNSS_REASON_DEFAULT:
	case CNSS_REASON_TIMEOUT:
@@ -1590,28 +1541,6 @@ void cnss_schedule_recovery(struct device *dev,
}
EXPORT_SYMBOL(cnss_schedule_recovery);

static int cnss_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	int ret;

	ret = cnss_pci_set_mhi_state(plat_priv->bus_priv,
				     CNSS_MHI_TRIGGER_RDDM);
	if (ret) {
		cnss_pr_err("Failed to trigger RDDM, err = %d\n", ret);
		cnss_schedule_recovery(&pci_priv->pci_dev->dev,
				       CNSS_REASON_DEFAULT);
		return 0;
	}

	if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
		mod_timer(&plat_priv->fw_boot_timer,
			  jiffies + msecs_to_jiffies(FW_ASSERT_TIMEOUT));
	}

	return 0;
}

int cnss_force_fw_assert(struct device *dev)
{
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
@@ -1639,17 +1568,6 @@ int cnss_force_fw_assert(struct device *dev)
}
EXPORT_SYMBOL(cnss_force_fw_assert);

void fw_boot_timeout(unsigned long data)
{
	struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	cnss_pr_err("Timeout waiting for FW ready indication!\n");

	cnss_schedule_recovery(&pci_priv->pci_dev->dev,
			       CNSS_REASON_TIMEOUT);
}

static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv,
				     void *data)
{
@@ -1746,7 +1664,7 @@ static void cnss_driver_event_work(struct work_struct *work)
			ret = cnss_wlfw_server_exit(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_REQUEST_MEM:
			ret = cnss_pci_alloc_fw_mem(plat_priv->bus_priv);
			ret = cnss_bus_alloc_fw_mem(plat_priv);
			if (ret)
				break;
			ret = cnss_wlfw_respond_mem_send_sync(plat_priv);
@@ -1775,7 +1693,7 @@ static void cnss_driver_event_work(struct work_struct *work)
							event->data);
			break;
		case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
			ret = cnss_force_fw_assert_hdlr(plat_priv);
			ret = cnss_bus_force_fw_assert_hdlr(plat_priv);
			break;
		case CNSS_DRIVER_EVENT_POWER_UP:
			ret = cnss_power_up_hdlr(plat_priv);
@@ -2232,6 +2150,7 @@ static int cnss_probe(struct platform_device *plat_dev)

	plat_priv->plat_dev = plat_dev;
	plat_priv->device_id = device_id->driver_data;
	plat_priv->bus_type = cnss_get_bus_type(plat_priv->device_id);
	cnss_set_plat_priv(plat_dev, plat_priv);
	platform_set_drvdata(plat_dev, plat_priv);

@@ -2244,14 +2163,14 @@ static int cnss_probe(struct platform_device *plat_dev)
		if (ret)
			goto free_res;

		ret = cnss_pci_init(plat_priv);
		ret = cnss_bus_init(plat_priv);
		if (ret)
			goto power_off;
	}

	ret = cnss_register_esoc(plat_priv);
	if (ret)
		goto deinit_pci;
		goto deinit_bus;

	ret = cnss_register_bus_scale(plat_priv);
	if (ret)
@@ -2274,7 +2193,7 @@ static int cnss_probe(struct platform_device *plat_dev)
		goto deinit_qmi;

	setup_timer(&plat_priv->fw_boot_timer,
		    fw_boot_timeout, (unsigned long)plat_priv);
		    cnss_bus_fw_boot_timeout_hdlr, (unsigned long)plat_priv);

	register_pm_notifier(&cnss_pm_notifier);

@@ -2300,9 +2219,9 @@ unreg_bus_scale:
	cnss_unregister_bus_scale(plat_priv);
unreg_esoc:
	cnss_unregister_esoc(plat_priv);
deinit_pci:
deinit_bus:
	if (!test_bit(SKIP_DEVICE_BOOT, &quirks))
		cnss_pci_deinit(plat_priv);
		cnss_bus_deinit(plat_priv);
power_off:
	if (!test_bit(SKIP_DEVICE_BOOT, &quirks))
		cnss_power_off_device(plat_priv);
@@ -2329,7 +2248,7 @@ static int cnss_remove(struct platform_device *plat_dev)
	cnss_remove_sysfs(plat_priv);
	cnss_unregister_bus_scale(plat_priv);
	cnss_unregister_esoc(plat_priv);
	cnss_pci_deinit(plat_priv);
	cnss_bus_deinit(plat_priv);
	cnss_put_resources(plat_priv);
	platform_set_drvdata(plat_dev, NULL);
	plat_env = NULL;
+1 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ struct cnss_pin_connect_result {
struct cnss_plat_data {
	struct platform_device *plat_dev;
	void *bus_priv;
	enum cnss_dev_bus_type bus_type;
	struct cnss_vreg_info *vreg_info;
	struct cnss_pinctrl_info pinctrl_info;
	struct cnss_subsys_info subsys_info;
Loading