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

Commit a898fa4b authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3-msm: consolidate DBM driver



Currently the DBM module registers a separate platform driver that
probes the DBM device separately than that of the dwc3-msm device
and driver. Since DBM is useless outside of dwc3-msm, it need not
be an independent driver and can be consolidated into the dwc3-msm
module directly. This eliminates a possible probe deferral in case
the devices probe in a certain order. Reassign the DT bindings to
the dwc3-msm node itself.

Change-Id: I5ec8820398fdfce626e15f2e75027fc02b4e5da5
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent cae02e55
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
MSM DBM (Device Bus Manager)

Required properties :
- compatible : must be one of "qcom,usb-dbm-1p4", or "qcom,usb-dbm-1p5"
- reg : offset and length of the register set in the memory map.

Optional properties :
- qcom,reset-ep-after-lpm-resume: If present, dbm requires ep reset after
	going to lpm

Example MSM DBM (Device Bus Manager) device node :
	dbm_1p4: dbm@f92f8000 {
		compatible = "qcom,usb-dbm-1p4";
		reg = <0xf92f8000 0x1000>;
	};
+4 −1
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ Optional properties :
  regulator node to the USB controller.
- qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for
		TX fifo allocation in bytes
- qcom,usb-dbm : phandle for the DBM device
- qcom,lpm-to-suspend-delay-ms: Indicates timeout (in milliseconds) to release wakeup source
  after USB is kept into LPM.
- qcom,ext-hub-reset-gpio: This corresponds to gpio which is used for HUB reset.
@@ -82,6 +81,10 @@ Optional properties :
- qcom,smmu-s1-bypass: If present, configure SMMU to bypass stage 1 translation.
- qcom,no-vbus-vote-with-type-C: If present, then do not try to get and enable VBUS
	regulator in type-C host mode from dwc3-msm driver.
- qcom,dbm-version: If present, specifies DBM version. Currently "1.4" or "1.5"
	are supported. If omitted, assume HW supports "1.5".
- qcom,reset-ep-after-lpm-resume: If present, dbm requires ep reset after
	going to lpm

Sub nodes:
- Sub node for "DWC3- USB3 controller".
+23 −90
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#include "dbm.h"

/* USB DBM Hardware registers */

#define DBM_REG_OFFSET		0xF8000

enum dbm_reg {
	DBM_EP_CFG,
	DBM_DATA_FIFO,
@@ -55,9 +58,7 @@ struct dbm_reg_data {
struct dbm {
	void __iomem *base;
	const struct dbm_reg_data *reg_table;

	struct device		*dev;
	struct list_head	head;
	struct device *mdwc_dev;

	int dbm_num_eps;
	u8 ep_num_mapping[DBM_1_5_NUM_EP];
@@ -110,8 +111,6 @@ static const struct dbm_reg_data dbm_1_5_regtable[] = {
	[DBM_DATA_FIFO_SIZE_EN]	= { 0x0204, 0x0 },
};

static LIST_HEAD(dbm_list);

/**
 * Write register masked field with debug info.
 *
@@ -518,103 +517,37 @@ bool dbm_l1_lpm_interrupt(struct dbm *dbm)
	return !dbm->is_1p4;
}

static const struct of_device_id msm_dbm_id_table[] = {
	{ .compatible = "qcom,usb-dbm-1p4", .data = &dbm_1_4_regtable },
	{ .compatible = "qcom,usb-dbm-1p5", .data = &dbm_1_5_regtable },
	{ },
};
MODULE_DEVICE_TABLE(of, msm_dbm_id_table);

static int msm_dbm_probe(struct platform_device *pdev)
struct dbm *dwc3_init_dbm(struct device *dev, void __iomem *base)
{
	struct device_node *node = pdev->dev.of_node;
	const struct of_device_id *match;
	const char *dbm_ver;
	int ret;
	struct dbm *dbm;
	struct resource *res;

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

	match = of_match_node(msm_dbm_id_table, node);
	if (!match) {
		dev_err(&pdev->dev, "Unsupported DBM module\n");
		return -ENODEV;
	if (!dev->of_node) {
		dev_dbg(dev, "device does not have a device node entry\n");
		return ERR_PTR(-EINVAL);
	}
	dbm->reg_table = match->data;

	if (!strcmp(match->compatible, "qcom,usb-dbm-1p4")) {
	dbm = devm_kzalloc(dev, sizeof(*dbm), GFP_KERNEL);
	if (!dbm)
		return ERR_PTR(-ENOMEM);

	ret = of_property_read_string(dev->of_node, "qcom,dbm-version",
			&dbm_ver);
	if (!ret && !strcmp(dbm_ver, "1.4")) {
		dbm->reg_table = dbm_1_4_regtable;
		dbm->dbm_num_eps = DBM_1_4_NUM_EP;
		dbm->is_1p4 = true;
	} else {
		/* default to v1.5 register layout */
		dbm->reg_table = dbm_1_5_regtable;
		dbm->dbm_num_eps = DBM_1_5_NUM_EP;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "missing memory base resource\n");
		return -ENODEV;
	}

	dbm->base = devm_ioremap_nocache(&pdev->dev, res->start,
		resource_size(res));
	if (!dbm->base) {
		dev_err(&pdev->dev, "ioremap failed\n");
		return -ENOMEM;
	}

	dbm->dbm_reset_ep_after_lpm = of_property_read_bool(node,
	dbm->base = base + DBM_REG_OFFSET;
	dbm->mdwc_dev = dev;
	dbm->dbm_reset_ep_after_lpm = of_property_read_bool(dev->of_node,
			"qcom,reset-ep-after-lpm-resume");

	dbm->dev = &pdev->dev;

	platform_set_drvdata(pdev, dbm);

	list_add_tail(&dbm->head, &dbm_list);

	return 0;
}

static struct platform_driver msm_dbm_driver = {
	.probe		= msm_dbm_probe,
	.driver = {
		.name	= "msm-usb-dbm",
		.of_match_table = of_match_ptr(msm_dbm_id_table),
	},
};

module_platform_driver(msm_dbm_driver);

static struct dbm *of_usb_find_dbm(struct device_node *node)
{
	struct dbm  *dbm;

	list_for_each_entry(dbm, &dbm_list, head) {
		if (node != dbm->dev->of_node)
			continue;
		return dbm;
	}
	return ERR_PTR(-ENODEV);
}

struct dbm *usb_get_dbm_by_phandle(struct device *dev, const char *phandle)
{
	struct device_node *node;

	if (!dev->of_node) {
		dev_dbg(dev, "device does not have a device node entry\n");
		return ERR_PTR(-EINVAL);
	}

	node = of_parse_phandle(dev->of_node, phandle, 0);
	if (!node) {
		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
			dev->of_node->full_name);
		return ERR_PTR(-ENODEV);
	}

	return of_usb_find_dbm(node);
}

MODULE_DESCRIPTION("MSM USB DBM driver");
MODULE_LICENSE("GPL v2");
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@

struct dbm;

struct dbm *usb_get_dbm_by_phandle(struct device *dev, const char *phandle);
struct dbm *dwc3_init_dbm(struct device *dev, void __iomem *base);

int dbm_soft_reset(struct dbm *dbm, bool enter_reset);
int dbm_ep_config(struct dbm  *dbm, u8 usb_ep, u8 bam_pipe, bool producer,
+12 −17
Original line number Diff line number Diff line
@@ -3346,18 +3346,14 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		}
	}

	if (of_get_property(pdev->dev.of_node, "qcom,usb-dbm", NULL)) {
		mdwc->dbm = usb_get_dbm_by_phandle(&pdev->dev, "qcom,usb-dbm");
	mdwc->dbm = dwc3_init_dbm(&pdev->dev, mdwc->base);
	if (IS_ERR(mdwc->dbm)) {
			dev_err(&pdev->dev, "unable to get dbm device\n");
			ret = -EPROBE_DEFER;
			goto err;
		dev_warn(&pdev->dev, "unable to init dbm device, skipping...\n");
		mdwc->dbm = NULL;
	}
		/*
		 * Add power event if the dbm indicates coming out of L1
		 * by interrupt
		 */
		if (dbm_l1_lpm_interrupt(mdwc->dbm)) {

	/* Add power event if the dbm indicates coming out of L1 by interrupt */
	if (mdwc->dbm && dbm_l1_lpm_interrupt(mdwc->dbm)) {
		if (!mdwc->wakeup_irq[PWR_EVNT_IRQ].irq) {
			dev_err(&pdev->dev,
				"need pwr_event_irq exiting L1\n");
@@ -3365,7 +3361,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
			goto err;
		}
	}
	}

	ext_hub_reset_gpio = of_get_named_gpio(node,
					"qcom,ext-hub-reset-gpio", 0);