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

Commit 1eef60bf authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Add bus layer"

parents e5020c20 5ff075a6
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