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

Commit 37a842d3 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'usb-ci-v4.3-rc1' of...

Merge tag 'usb-ci-v4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next

Peter writes:

USB: chipidea updates for v4.3-rc1

The main changes are adding several system interfaces for
tuning performance, and each vendors can adjust them according
to their design configurations.

Others are tiny improvements, like more well siTD supports,
USB_DEVICE_A_HNP_SUPPORT supports, etc.
parents a3fbedf9 96625ead
Loading
Loading
Loading
Loading
+20 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,21 @@ Optional properties:
  argument that indicate usb controller index
  argument that indicate usb controller index
- disable-over-current: (FSL only) disable over current detect
- disable-over-current: (FSL only) disable over current detect
- external-vbus-divider: (FSL only) enables off-chip resistor divider for Vbus
- external-vbus-divider: (FSL only) enables off-chip resistor divider for Vbus
- itc-setting: interrupt threshold control register control, the setting
  should be aligned with ITC bits at register USBCMD.
- ahb-burst-config: it is vendor dependent, the required value should be
  aligned with AHBBRST at SBUSCFG, the range is from 0x0 to 0x7. This
  property is used to change AHB burst configuration, check the chipidea
  spec for meaning of each value. If this property is not existed, it
  will use the reset value.
- tx-burst-size-dword: it is vendor dependent, the tx burst size in dword
  (4 bytes), This register represents the maximum length of a the burst
  in 32-bit words while moving data from system memory to the USB
  bus, changing this value takes effect only the SBUSCFG.AHBBRST is 0.
- rx-burst-size-dword: it is vendor dependent, the rx burst size in dword
  (4 bytes), This register represents the maximum length of a the burst
  in 32-bit words while moving data from the USB bus to system memory,
  changing this value takes effect only the SBUSCFG.AHBBRST is 0.


Example:
Example:


@@ -41,4 +56,9 @@ Example:
		phys = <&usb_phy0>;
		phys = <&usb_phy0>;
		phy-names = "usb-phy";
		phy-names = "usb-phy";
		vbus-supply = <&reg_usb0_vbus>;
		vbus-supply = <&reg_usb0_vbus>;
		gadget-itc-setting = <0x4>; /* 4 micro-frames */
		 /* Incremental burst of unspecified length */
		ahb-burst-config = <0x0>;
		tx-burst-size-dword = <0x10>; /* 64 bytes */
		rx-burst-size-dword = <0x10>;
	};
	};
+12 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,9 @@
#define VERSION		      (0xF << 25)
#define VERSION		      (0xF << 25)
#define CIVERSION	      (0x7 << 29)
#define CIVERSION	      (0x7 << 29)


/* SBUSCFG */
#define AHBBRST_MASK		0x7

/* HCCPARAMS */
/* HCCPARAMS */
#define HCCPARAMS_LEN         BIT(17)
#define HCCPARAMS_LEN         BIT(17)


@@ -53,6 +56,15 @@
#define DEVICEADDR_USBADRA    BIT(24)
#define DEVICEADDR_USBADRA    BIT(24)
#define DEVICEADDR_USBADR     (0x7FUL << 25)
#define DEVICEADDR_USBADR     (0x7FUL << 25)


/* TTCTRL */
#define TTCTRL_TTHA_MASK	(0x7fUL << 24)
/* Set non-zero value for internal TT Hub address representation */
#define TTCTRL_TTHA		(0x7fUL << 24)

/* BURSTSIZE */
#define RX_BURST_MASK		0xff
#define TX_BURST_MASK		0xff00

/* PORTSC */
/* PORTSC */
#define PORTSC_CCS            BIT(0)
#define PORTSC_CCS            BIT(0)
#define PORTSC_CSC            BIT(1)
#define PORTSC_CSC            BIT(1)
+4 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,8 @@ enum ci_hw_regs {
	OP_USBINTR,
	OP_USBINTR,
	OP_DEVICEADDR,
	OP_DEVICEADDR,
	OP_ENDPTLISTADDR,
	OP_ENDPTLISTADDR,
	OP_TTCTRL,
	OP_BURSTSIZE,
	OP_PORTSC,
	OP_PORTSC,
	OP_DEVLC,
	OP_DEVLC,
	OP_OTGSC,
	OP_OTGSC,
@@ -429,4 +431,6 @@ u8 hw_port_test_get(struct ci_hdrc *ci);
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
				u32 value, unsigned int timeout_ms);
				u32 value, unsigned int timeout_ms);


void ci_platform_configure(struct ci_hdrc *ci);

#endif	/* __DRIVERS_USB_CHIPIDEA_CI_H */
#endif	/* __DRIVERS_USB_CHIPIDEA_CI_H */
+11 −6
Original line number Original line Diff line number Diff line
@@ -29,26 +29,31 @@ struct ci_hdrc_imx_platform_flag {
};
};


static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
		CI_HDRC_DISABLE_STREAMING,
};
};


static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
	.flags = CI_HDRC_IMX28_WRITE_FIX |
	.flags = CI_HDRC_IMX28_WRITE_FIX |
		CI_HDRC_TURN_VBUS_EARLY_ON,
		CI_HDRC_TURN_VBUS_EARLY_ON |
		CI_HDRC_DISABLE_STREAMING,
};
};


static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
		CI_HDRC_TURN_VBUS_EARLY_ON,
		CI_HDRC_TURN_VBUS_EARLY_ON |
		CI_HDRC_DISABLE_STREAMING,
};
};


static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
		CI_HDRC_TURN_VBUS_EARLY_ON,
		CI_HDRC_TURN_VBUS_EARLY_ON |
		CI_HDRC_DISABLE_HOST_STREAMING,
};
};


static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
	.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
		CI_HDRC_TURN_VBUS_EARLY_ON,
		CI_HDRC_TURN_VBUS_EARLY_ON |
		CI_HDRC_DISABLE_HOST_STREAMING,
};
};


static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
@@ -104,7 +109,7 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
	misc_pdev = of_find_device_by_node(args.np);
	misc_pdev = of_find_device_by_node(args.np);
	of_node_put(args.np);
	of_node_put(args.np);


	if (!misc_pdev)
	if (!misc_pdev || !platform_get_drvdata(misc_pdev))
		return ERR_PTR(-EPROBE_DEFER);
		return ERR_PTR(-EPROBE_DEFER);


	data->dev = &misc_pdev->dev;
	data->dev = &misc_pdev->dev;
@@ -126,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
	struct ci_hdrc_platform_data pdata = {
	struct ci_hdrc_platform_data pdata = {
		.name		= dev_name(&pdev->dev),
		.name		= dev_name(&pdev->dev),
		.capoffset	= DEF_CAPOFFSET,
		.capoffset	= DEF_CAPOFFSET,
		.flags		= CI_HDRC_DISABLE_STREAMING,
		.flags		= CI_HDRC_SET_NON_ZERO_TTHA,
	};
	};
	int ret;
	int ret;
	const struct of_device_id *of_id =
	const struct of_device_id *of_id =
+101 −12
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@
#include <linux/of.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/ehci_def.h>


#include "ci.h"
#include "ci.h"
#include "udc.h"
#include "udc.h"
@@ -84,6 +85,8 @@ static const u8 ci_regs_nolpm[] = {
	[OP_USBINTR]		= 0x08U,
	[OP_USBINTR]		= 0x08U,
	[OP_DEVICEADDR]		= 0x14U,
	[OP_DEVICEADDR]		= 0x14U,
	[OP_ENDPTLISTADDR]	= 0x18U,
	[OP_ENDPTLISTADDR]	= 0x18U,
	[OP_TTCTRL]		= 0x1CU,
	[OP_BURSTSIZE]		= 0x20U,
	[OP_PORTSC]		= 0x44U,
	[OP_PORTSC]		= 0x44U,
	[OP_DEVLC]		= 0x84U,
	[OP_DEVLC]		= 0x84U,
	[OP_OTGSC]		= 0x64U,
	[OP_OTGSC]		= 0x64U,
@@ -106,6 +109,8 @@ static const u8 ci_regs_lpm[] = {
	[OP_USBINTR]		= 0x08U,
	[OP_USBINTR]		= 0x08U,
	[OP_DEVICEADDR]		= 0x14U,
	[OP_DEVICEADDR]		= 0x14U,
	[OP_ENDPTLISTADDR]	= 0x18U,
	[OP_ENDPTLISTADDR]	= 0x18U,
	[OP_TTCTRL]		= 0x1CU,
	[OP_BURSTSIZE]		= 0x20U,
	[OP_PORTSC]		= 0x44U,
	[OP_PORTSC]		= 0x44U,
	[OP_DEVLC]		= 0x84U,
	[OP_DEVLC]		= 0x84U,
	[OP_OTGSC]		= 0xC4U,
	[OP_OTGSC]		= 0xC4U,
@@ -118,7 +123,7 @@ static const u8 ci_regs_lpm[] = {
	[OP_ENDPTCTRL]		= 0xECU,
	[OP_ENDPTCTRL]		= 0xECU,
};
};


static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
static void hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
{
{
	int i;
	int i;


@@ -134,7 +139,6 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
			 ? ci_regs_lpm[OP_ENDPTCTRL]
			 ? ci_regs_lpm[OP_ENDPTCTRL]
			 : ci_regs_nolpm[OP_ENDPTCTRL]);
			 : ci_regs_nolpm[OP_ENDPTCTRL]);


	return 0;
}
}


static enum ci_revision ci_get_revision(struct ci_hdrc *ci)
static enum ci_revision ci_get_revision(struct ci_hdrc *ci)
@@ -403,6 +407,55 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
	return ret;
	return ret;
}
}



/**
 * ci_platform_configure: do controller configure
 * @ci: the controller
 *
 */
void ci_platform_configure(struct ci_hdrc *ci)
{
	bool is_device_mode, is_host_mode;

	is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
	is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;

	if (is_device_mode &&
		(ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING))
		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);

	if (is_host_mode &&
		(ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING))
		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);

	if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
		if (ci->hw_bank.lpm)
			hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
		else
			hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
	}

	if (ci->platdata->flags & CI_HDRC_SET_NON_ZERO_TTHA)
		hw_write(ci, OP_TTCTRL, TTCTRL_TTHA_MASK, TTCTRL_TTHA);

	hw_write(ci, OP_USBCMD, 0xff0000, ci->platdata->itc_setting << 16);

	if (ci->platdata->flags & CI_HDRC_OVERRIDE_AHB_BURST)
		hw_write_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK,
			ci->platdata->ahb_burst_config);

	/* override burst size, take effect only when ahb_burst_config is 0 */
	if (!hw_read_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK)) {
		if (ci->platdata->flags & CI_HDRC_OVERRIDE_TX_BURST)
			hw_write(ci, OP_BURSTSIZE, TX_BURST_MASK,
			ci->platdata->tx_burst_size << __ffs(TX_BURST_MASK));

		if (ci->platdata->flags & CI_HDRC_OVERRIDE_RX_BURST)
			hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK,
				ci->platdata->rx_burst_size);
	}
}

/**
/**
 * hw_controller_reset: do controller reset
 * hw_controller_reset: do controller reset
 * @ci: the controller
 * @ci: the controller
@@ -447,16 +500,6 @@ int hw_device_reset(struct ci_hdrc *ci)
		ci->platdata->notify_event(ci,
		ci->platdata->notify_event(ci,
			CI_HDRC_CONTROLLER_RESET_EVENT);
			CI_HDRC_CONTROLLER_RESET_EVENT);


	if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);

	if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
		if (ci->hw_bank.lpm)
			hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
		else
			hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
	}

	/* USBMODE should be configured step by step */
	/* USBMODE should be configured step by step */
	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC);
	hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC);
@@ -469,6 +512,8 @@ int hw_device_reset(struct ci_hdrc *ci)
		return -ENODEV;
		return -ENODEV;
	}
	}


	ci_platform_configure(ci);

	return 0;
	return 0;
}
}


@@ -606,6 +651,50 @@ static int ci_get_platdata(struct device *dev,
	if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
	if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
		platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
		platdata->flags |= CI_HDRC_FORCE_FULLSPEED;


	platdata->itc_setting = 1;
	if (of_find_property(dev->of_node, "itc-setting", NULL)) {
		ret = of_property_read_u32(dev->of_node, "itc-setting",
			&platdata->itc_setting);
		if (ret) {
			dev_err(dev,
				"failed to get itc-setting\n");
			return ret;
		}
	}

	if (of_find_property(dev->of_node, "ahb-burst-config", NULL)) {
		ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
			&platdata->ahb_burst_config);
		if (ret) {
			dev_err(dev,
				"failed to get ahb-burst-config\n");
			return ret;
		}
		platdata->flags |= CI_HDRC_OVERRIDE_AHB_BURST;
	}

	if (of_find_property(dev->of_node, "tx-burst-size-dword", NULL)) {
		ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword",
			&platdata->tx_burst_size);
		if (ret) {
			dev_err(dev,
				"failed to get tx-burst-size-dword\n");
			return ret;
		}
		platdata->flags |= CI_HDRC_OVERRIDE_TX_BURST;
	}

	if (of_find_property(dev->of_node, "rx-burst-size-dword", NULL)) {
		ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword",
			&platdata->rx_burst_size);
		if (ret) {
			dev_err(dev,
				"failed to get rx-burst-size-dword\n");
			return ret;
		}
		platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
	}

	return 0;
	return 0;
}
}


Loading