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

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

Merge "usb: dwc3-msm: add support for ep specific-reset"

parents 936b41d4 07ce836f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -4,6 +4,10 @@ Required properties :
- compatible : should be "qcom,usb-dbm-<dbm version number>"
- 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";
+12 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2014, 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
@@ -147,7 +147,7 @@ static int soft_reset(bool reset)
 * @enter_reset - should we enter a reset state or get out of it.
 *
 */
static int dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
static int ep_soft_reset(u8 dbm_ep, bool enter_reset)
{
	pr_debug("%s\n", __func__);

@@ -196,7 +196,7 @@ static int ep_config(u8 usb_ep, u8 bam_pipe, bool producer, bool disable_wb,
	}

	/* First, reset the dbm endpoint */
	dbm_ep_soft_reset(dbm_ep, 0);
	ep_soft_reset(dbm_ep, 0);

	/* Set ioc bit for dbm_ep if needed */
	msm_dbm_write_reg_field(dbm_data->base, DBM_DBG_CNFG,
@@ -248,13 +248,13 @@ static int ep_unconfig(u8 usb_ep)
	msm_dbm_write_reg(dbm_data->base, DBM_EP_CFG(dbm_ep), data);

	/* Reset the dbm endpoint */
	dbm_ep_soft_reset(dbm_ep, true);
	ep_soft_reset(dbm_ep, true);
	/*
	 * 10 usec delay is required before deasserting DBM endpoint reset
	 * according to hardware programming guide.
	 */
	udelay(10);
	dbm_ep_soft_reset(dbm_ep, false);
	ep_soft_reset(dbm_ep, false);

	return 0;
}
@@ -336,6 +336,11 @@ static void set_speed(bool speed)
	msm_dbm_write_reg(dbm_data->base, DBM_GEN_CFG, speed >> 2);
}

static bool reset_ep_after_lpm(void)
{
	return false;
}

static void enable(void) {}


@@ -384,6 +389,8 @@ static int msm_dbm_probe(struct platform_device *pdev)
	dbm->data_fifo_config = data_fifo_config;
	dbm->set_speed = set_speed;
	dbm->enable = enable;
	dbm->ep_soft_reset = ep_soft_reset;
	dbm->reset_ep_after_lpm = reset_ep_after_lpm;

	platform_set_drvdata(pdev, dbm);

+19 −5
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ struct dbm_data {

	int dbm_num_eps;
	u8 ep_num_mapping[DBM_1_5_NUM_EP];
	bool dbm_reset_ep_after_lpm;
};

static struct dbm_data *dbm_data;
@@ -147,12 +148,12 @@ static int soft_reset(bool reset)
 * @enter_reset - should we enter a reset state or get out of it.
 *
 */
static int dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
static int ep_soft_reset(u8 dbm_ep, bool enter_reset)
{
	pr_debug("%s\n", __func__);

	if (dbm_ep >= dbm_data->dbm_num_eps) {
		pr_err("%s: Invalid DBM ep index\n", __func__);
		pr_err("Invalid DBM ep index %d\n", dbm_ep);
		return -ENODEV;
	}

@@ -202,7 +203,7 @@ static int ep_config(u8 usb_ep, u8 bam_pipe, bool producer, bool disable_wb,
	}

	/* First, reset the dbm endpoint */
	dbm_ep_soft_reset(dbm_ep, 0);
	ep_soft_reset(dbm_ep, 0);

	/* Set ioc bit for dbm_ep if needed */
	msm_dbm_write_reg_field(dbm_data->base, DBM_DBG_CNFG,
@@ -254,13 +255,13 @@ static int ep_unconfig(u8 usb_ep)
	msm_dbm_write_reg(dbm_data->base, DBM_EP_CFG(dbm_ep), data);

	/* Reset the dbm endpoint */
	dbm_ep_soft_reset(dbm_ep, true);
	ep_soft_reset(dbm_ep, true);
	/*
	 * 10 usec delay is required before deasserting DBM endpoint reset
	 * according to hardware programming guide.
	 */
	udelay(10);
	dbm_ep_soft_reset(dbm_ep, false);
	ep_soft_reset(dbm_ep, false);

	return 0;
}
@@ -339,9 +340,17 @@ static void enable(void)
	msm_dbm_write_reg(dbm_data->base, DBM_DATA_FIFO_SIZE_EN, 0x000000FF);
}

static bool reset_ep_after_lpm(void)
{
	return dbm_data->dbm_reset_ep_after_lpm;
}



static int msm_dbm_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *node = pdev->dev.of_node;
	struct dbm *dbm;
	struct resource *res;
	int ret = 0;
@@ -374,6 +383,9 @@ static int msm_dbm_probe(struct platform_device *pdev)
		goto free_dbm_data;
	}

	dbm_data->dbm_reset_ep_after_lpm = of_property_read_bool(node,
			"qcom,reset-ep-after-lpm-resume");

	dbm->dev = dev;

	dbm->soft_reset = soft_reset;
@@ -384,6 +396,8 @@ static int msm_dbm_probe(struct platform_device *pdev)
	dbm->data_fifo_config = data_fifo_config;
	dbm->set_speed = set_speed;
	dbm->enable = enable;
	dbm->ep_soft_reset = ep_soft_reset;
	dbm->reset_ep_after_lpm = reset_ep_after_lpm;

	platform_set_drvdata(pdev, dbm);

+40 −13
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, 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
@@ -84,6 +84,12 @@ struct dbm {
	/* Enable DBM */
	void (*enable)(void);

	/* Reset a USB DBM ep */
	int (*ep_soft_reset)(u8 dbm_ep, bool enter_reset);

	/* Check whether the USB DBM requires ep reset after lpm suspend */
	bool (*reset_ep_after_lpm)(void);

};

struct dbm *usb_get_dbm_by_phandle(struct device *dev,
@@ -92,23 +98,30 @@ int usb_add_dbm(struct dbm *x);



#define CHECK_DBM_PTR_INT(dbm) do {					   \
	if (!(dbm)) {							   \
#define CHECK_DBM_PTR_INT(dbm, func) do {				   \
	if (!(dbm) || !((dbm)->func)) {					   \
		pr_err("Can't call %s, dbp pointer == NULL\n", __func__);  \
		return -EPERM;						   \
	}								   \
} while (0)

#define CHECK_DBM_PTR_VOID(dbm) do {				   \
	if (!(dbm)) {							   \
#define CHECK_DBM_PTR_VOID(dbm, func) do {				   \
	if (!(dbm) || !((dbm)->func)) {					   \
		pr_err("Can't call %s, dbp pointer == NULL\n", __func__);  \
		return;							   \
	}								   \
} while (0)

#define CHECK_DBM_PTR_BOOL(dbm, func, ret) do {				   \
	if (!(dbm) || !((dbm)->func)) {					   \
		pr_err("Can't call %s, dbp pointer == NULL\n", __func__);  \
		return ret;						   \
	}								   \
} while (0)

static inline int dbm_soft_reset(struct dbm *dbm, bool enter_reset)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, soft_reset);
	return dbm->soft_reset(enter_reset);
}

@@ -116,7 +129,7 @@ static inline int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe,
			bool producer, bool disable_wb, bool internal_mem,
			bool ioc)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, ep_config);
	return dbm->ep_config(usb_ep, bam_pipe, producer, disable_wb,
				  internal_mem, ioc);

@@ -124,41 +137,55 @@ static inline int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe,

static inline int dbm_ep_unconfig(struct dbm *dbm, u8 usb_ep)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, ep_unconfig);
	return dbm->ep_unconfig(usb_ep);
}

static inline int dbm_get_num_of_eps_configured(struct dbm *dbm)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, get_num_of_eps_configured);
	return dbm->get_num_of_eps_configured();
}

static inline int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo,
					u32 addr_hi, int size)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, event_buffer_config);
	return dbm->event_buffer_config(addr_lo, addr_hi, size);
}

static inline int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num,
				phys_addr_t addr, u32 size, u8 dst_pipe_idx)
{
	CHECK_DBM_PTR_INT(dbm);
	CHECK_DBM_PTR_INT(dbm, data_fifo_config);
	return dbm->data_fifo_config(dep_num, addr, size, dst_pipe_idx);
}

static inline void dbm_set_speed(struct dbm *dbm, bool speed)
{
	CHECK_DBM_PTR_VOID(dbm);
	CHECK_DBM_PTR_VOID(dbm, set_speed);
	dbm->set_speed(speed);
}

static inline void dbm_enable(struct dbm *dbm)
{
	CHECK_DBM_PTR_VOID(dbm);
	CHECK_DBM_PTR_VOID(dbm, enable);
	dbm->enable();
}

static inline int dbm_ep_soft_reset(struct dbm *dbm, u8 dbm_ep,
					bool enter_reset)
{
	CHECK_DBM_PTR_INT(dbm, ep_soft_reset);
	return dbm->ep_soft_reset(dbm_ep, enter_reset);
}


static inline bool dbm_reset_ep_after_lpm(struct dbm *dbm)
{
	/* Default (backward compatible) setting is false */
	CHECK_DBM_PTR_BOOL(dbm, reset_ep_after_lpm, false);
	return dbm->reset_ep_after_lpm();
}

#endif /* __DBM_H */