diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/qcom/clock-apq8016.c | 21 | ||||
| -rw-r--r-- | drivers/clk/qcom/clock-apq8096.c | 7 | ||||
| -rw-r--r-- | drivers/clk/qcom/clock-qcs404.c | 25 | ||||
| -rw-r--r-- | drivers/gpio/msm_gpio.c | 20 | ||||
| -rw-r--r-- | drivers/gpio/qcom_pmic_gpio.c | 273 | ||||
| -rw-r--r-- | drivers/mmc/msm_sdhci.c | 69 | ||||
| -rw-r--r-- | drivers/phy/qcom/msm8916-usbh-phy.c | 4 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-apq8016.c | 34 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-apq8096.c | 21 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-ipq4019.c | 5 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-qcom.c | 12 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-qcs404.c | 64 | ||||
| -rw-r--r-- | drivers/pinctrl/qcom/pinctrl-sdm845.c | 5 | ||||
| -rw-r--r-- | drivers/serial/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/serial/serial_msm.c | 62 | ||||
| -rw-r--r-- | drivers/usb/dwc3/dwc3-generic.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-msm.c | 22 | 
17 files changed, 495 insertions, 181 deletions
| diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index c0ce570edc7..e6647f7c41d 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -13,6 +13,7 @@  #include <errno.h>  #include <asm/io.h>  #include <linux/bitops.h> +#include <dt-bindings/clock/qcom,gcc-msm8916.h>  #include "clock-qcom.h" @@ -102,20 +103,20 @@ static const struct bcr_regs uart2_regs = {  };  /* UART: 115200 */ -static int clk_init_uart(struct msm_clk_priv *priv) +int apq8016_clk_init_uart(phys_addr_t base)  {  	/* Enable AHB clock */ -	clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk); +	clk_enable_vote_clk(base, &gcc_blsp1_ahb_clk);  	/* 7372800 uart block clock @ GPLL0 */ -	clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625, +	clk_rcg_set_rate_mnd(base, &uart2_regs, 1, 144, 15625,  			     CFG_CLK_SRC_GPLL0, 16);  	/* Vote for gpll0 clock */ -	clk_enable_gpll0(priv->base, &gpll0_vote_clk); +	clk_enable_gpll0(base, &gpll0_vote_clk);  	/* Enable core clk */ -	clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); +	clk_enable_cbc(base + BLSP1_UART2_APPS_CBCR);  	return 0;  } @@ -125,14 +126,14 @@ static ulong apq8016_clk_set_rate(struct clk *clk, ulong rate)  	struct msm_clk_priv *priv = dev_get_priv(clk->dev);  	switch (clk->id) { -	case 0: /* SDC1 */ +	case GCC_SDCC1_APPS_CLK: /* SDC1 */  		return clk_init_sdc(priv, 0, rate);  		break; -	case 1: /* SDC2 */ +	case GCC_SDCC2_APPS_CLK: /* SDC2 */  		return clk_init_sdc(priv, 1, rate);  		break; -	case 4: /* UART2 */ -		return clk_init_uart(priv); +	case GCC_BLSP1_UART2_APPS_CLK: /* UART2 */ +		return apq8016_clk_init_uart(priv->base);  		break;  	default:  		return 0; @@ -145,7 +146,7 @@ static struct msm_clk_data apq8016_clk_data = {  static const struct udevice_id gcc_apq8016_of_match[] = {  	{ -		.compatible = "qcom,gcc-apq8016", +		.compatible = "qcom,gcc-msm8916",  		.data = (ulong)&apq8016_clk_data,  	},  	{ } diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index cf1a347309a..a4731613c5e 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -13,6 +13,7 @@  #include <errno.h>  #include <asm/io.h>  #include <linux/bitops.h> +#include <dt-bindings/clock/qcom,gcc-msm8996.h>  #include "clock-qcom.h" @@ -107,10 +108,10 @@ static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate)  	struct msm_clk_priv *priv = dev_get_priv(clk->dev);  	switch (clk->id) { -	case 0: /* SDC1 */ +	case GCC_SDCC1_APPS_CLK: /* SDC1 */  		return clk_init_sdc(priv, rate);  		break; -	case 4: /*UART2*/ +	case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/  		return clk_init_uart(priv);  	default:  		return 0; @@ -123,7 +124,7 @@ static struct msm_clk_data apq8096_clk_data = {  static const struct udevice_id gcc_apq8096_of_match[] = {  	{ -		.compatible = "qcom,gcc-apq8096", +		.compatible = "qcom,gcc-msm8996",  		.data = (ulong)&apq8096_clk_data,  	},  	{ } diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index f5b35280392..958312b8884 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -193,24 +193,18 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate)  	switch (clk->id) {  	case GCC_BLSP1_UART2_APPS_CLK: -		/* UART: 115200 */ +		/* UART: 1843200Hz for a fixed 115200 baudrate (19200000 * (12/125)) */  		clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 0, 12, 125,  				     CFG_CLK_SRC_CXO, 16);  		clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); -		break; -	case GCC_BLSP1_AHB_CLK: -		clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk); -		break; +		return 1843200;  	case GCC_SDCC1_APPS_CLK:  		/* SDCC1: 200MHz */  		clk_rcg_set_rate_mnd(priv->base, &sdc_regs, 7, 0, 0,  				     CFG_CLK_SRC_GPLL0, 8);  		clk_enable_gpll0(priv->base, &gpll0_vote_clk);  		clk_enable_cbc(priv->base + SDCC_APPS_CBCR(1)); -		break; -	case GCC_SDCC1_AHB_CLK: -		clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1)); -		break; +		return rate;  	case GCC_ETH_RGMII_CLK:  		if (rate == 250000000)  			clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 0, 0, @@ -224,11 +218,15 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate)  		else if (rate == 5000000)  			clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 1, 50,  					     CFG_CLK_SRC_GPLL1, 8); -		break; -	default: -		return 0; +		return rate;  	} +	/* There is a bug only seeming to affect this board where the MMC driver somehow calls +	 * clk_set_rate() on a clock with id 0 which is associated with the qcom_clk device. +	 * The only clock with ID 0 is the xo_board clock which should not be associated with +	 * this device... +	 */ +	log_debug("Unknown clock id %ld\n", clk->id);  	return 0;  } @@ -305,6 +303,9 @@ static int qcs404_clk_enable(struct clk *clk)  		clk_rcg_set_rate(priv->base, &blsp1_qup4_i2c_apps_regs, 0,  				 CFG_CLK_SRC_CXO);  		break; +	case GCC_SDCC1_AHB_CLK: +		clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1)); +		break;  	default:  		return 0;  	} diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index 80cd28bb231..5e57b0cbde7 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -39,6 +39,10 @@ static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)  {  	struct msm_gpio_bank *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(priv->pin_data, gpio)) +		return 0; +  	/* Disable OE bit */  	clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),  			GPIO_OE_MASK, GPIO_OE_DISABLE); @@ -50,6 +54,10 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value)  {  	struct msm_gpio_bank *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(priv->pin_data, gpio)) +		return 0; +  	value = !!value;  	/* set value */  	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); @@ -62,6 +70,10 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,  {  	struct msm_gpio_bank *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(priv->pin_data, gpio)) +		return 0; +  	value = !!value;  	/* set value */  	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); @@ -76,6 +88,10 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio)  {  	struct msm_gpio_bank *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(priv->pin_data, gpio)) +		return 0; +  	return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN);  } @@ -83,6 +99,10 @@ static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio)  {  	struct msm_gpio_bank *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(priv->pin_data, gpio)) +		return 0; +  	if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE)  		return GPIOF_OUTPUT; diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 6167c841167..14a8210522b 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -7,10 +7,14 @@  #include <common.h>  #include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h>  #include <log.h>  #include <power/pmic.h>  #include <spmi/spmi.h>  #include <asm/io.h> +#include <stdlib.h>  #include <asm/gpio.h>  #include <linux/bitops.h> @@ -64,27 +68,34 @@  #define REG_EN_CTL             0x46  #define REG_EN_CTL_ENABLE      (1 << 7) -struct qcom_gpio_bank { +/** + * pmic_gpio_match_data - platform specific configuration + * + * @PMIC_MATCH_READONLY: treat all GPIOs as readonly, don't attempt to configure them. + * This is a workaround for an unknown bug on some platforms where trying to write the + * GPIO configuration registers causes the board to hang. + */ +enum pmic_gpio_quirks { +	QCOM_PMIC_QUIRK_READONLY = (1 << 0), +}; + +struct qcom_pmic_gpio_data {  	uint32_t pid; /* Peripheral ID on SPMI bus */  	bool     lv_mv_type; /* If subtype is GPIO_LV(0x10) or GPIO_MV(0x11) */ +	u32 pin_count; +	struct udevice *pmic; /* Reference to pmic device for read/write */  }; -static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset, -				   bool input, int value) +/* dev can be the GPIO or pinctrl device */ +static int _qcom_gpio_set_direction(struct udevice *dev, u32 offset, bool input, int value)  { -	struct qcom_gpio_bank *priv = dev_get_priv(dev); -	uint32_t gpio_base = priv->pid + REG_OFFSET(offset); -	uint32_t reg_ctl_val; -	int ret; - -	/* Disable the GPIO */ -	ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, -			      REG_EN_CTL_ENABLE, 0); -	if (ret < 0) -		return ret; +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	u32 gpio_base = plat->pid + REG_OFFSET(offset); +	u32 reg_ctl_val; +	int ret = 0;  	/* Select the mode and output */ -	if (priv->lv_mv_type) { +	if (plat->lv_mv_type) {  		if (input)  			reg_ctl_val = REG_CTL_LV_MV_MODE_INPUT;  		else @@ -96,20 +107,43 @@ static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset,  			reg_ctl_val = REG_CTL_MODE_INOUT | !!value;  	} -	ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, reg_ctl_val); +	ret = pmic_reg_write(plat->pmic, gpio_base + REG_CTL, reg_ctl_val);  	if (ret < 0)  		return ret; -	if (priv->lv_mv_type && !input) { -		ret = pmic_reg_write(dev->parent, +	if (plat->lv_mv_type && !input) { +		ret = pmic_reg_write(plat->pmic,  				     gpio_base + REG_LV_MV_OUTPUT_CTL,  				     !!value << REG_LV_MV_OUTPUT_CTL_SHIFT);  		if (ret < 0)  			return ret;  	} +	return 0; +} + +static int qcom_gpio_set_direction(struct udevice *dev, unsigned int offset, +				   bool input, int value) +{ +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	uint32_t gpio_base = plat->pid + REG_OFFSET(offset); +	ulong quirks = dev_get_driver_data(dev); +	int ret = 0; + +	/* Some PMICs don't like their GPIOs being configured */ +	if (quirks & QCOM_PMIC_QUIRK_READONLY) +		return 0; + +	/* Disable the GPIO */ +	ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, +			      REG_EN_CTL_ENABLE, 0); +	if (ret < 0) +		return ret; + +	_qcom_gpio_set_direction(dev, offset, input, value); +  	/* Set the right pull (no pull) */ -	ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL, +	ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_PULL_CTL,  			     REG_DIG_PULL_NO_PU);  	if (ret < 0)  		return ret; @@ -117,13 +151,13 @@ static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset,  	/* Configure output pin drivers if needed */  	if (!input) {  		/* Select the VIN - VIN0, pin is input so it doesn't matter */ -		ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_VIN_CTL, +		ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_VIN_CTL,  				     REG_DIG_VIN_VIN0);  		if (ret < 0)  			return ret;  		/* Set the right dig out control */ -		ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL, +		ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_OUT_CTL,  				     REG_DIG_OUT_CTL_CMOS |  				     REG_DIG_OUT_CTL_DRIVE_L);  		if (ret < 0) @@ -148,15 +182,15 @@ static int qcom_gpio_direction_output(struct udevice *dev, unsigned offset,  static int qcom_gpio_get_function(struct udevice *dev, unsigned offset)  { -	struct qcom_gpio_bank *priv = dev_get_priv(dev); -	uint32_t gpio_base = priv->pid + REG_OFFSET(offset); +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	uint32_t gpio_base = plat->pid + REG_OFFSET(offset);  	int reg; -	reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL); +	reg = pmic_reg_read(plat->pmic, gpio_base + REG_CTL);  	if (reg < 0)  		return reg; -	if (priv->lv_mv_type) { +	if (plat->lv_mv_type) {  		switch (reg & REG_CTL_LV_MV_MODE_MASK) {  		case REG_CTL_LV_MV_MODE_INPUT:  			return GPIOF_INPUT; @@ -181,11 +215,11 @@ static int qcom_gpio_get_function(struct udevice *dev, unsigned offset)  static int qcom_gpio_get_value(struct udevice *dev, unsigned offset)  { -	struct qcom_gpio_bank *priv = dev_get_priv(dev); -	uint32_t gpio_base = priv->pid + REG_OFFSET(offset); +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	uint32_t gpio_base = plat->pid + REG_OFFSET(offset);  	int reg; -	reg = pmic_reg_read(dev->parent, gpio_base + REG_STATUS); +	reg = pmic_reg_read(plat->pmic, gpio_base + REG_STATUS);  	if (reg < 0)  		return reg; @@ -195,11 +229,11 @@ static int qcom_gpio_get_value(struct udevice *dev, unsigned offset)  static int qcom_gpio_set_value(struct udevice *dev, unsigned offset,  			       int value)  { -	struct qcom_gpio_bank *priv = dev_get_priv(dev); -	uint32_t gpio_base = priv->pid + REG_OFFSET(offset); +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	uint32_t gpio_base = plat->pid + REG_OFFSET(offset);  	/* Set the output value of the gpio */ -	if (priv->lv_mv_type) +	if (plat->lv_mv_type)  		return pmic_clrsetbits(dev->parent,  				       gpio_base + REG_LV_MV_OUTPUT_CTL,  				       REG_LV_MV_OUTPUT_CTL_MASK, @@ -209,71 +243,104 @@ static int qcom_gpio_set_value(struct udevice *dev, unsigned offset,  				       REG_CTL_OUTPUT_MASK, !!value);  } +static int qcom_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, +			   struct ofnode_phandle_args *args) +{ +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + +	if (args->args_count < 1) +		return -EINVAL; + +	/* GPIOs in DT are 1-based */ +	desc->offset = args->args[0] - 1; +	if (desc->offset >= uc_priv->gpio_count) +		return -EINVAL; + +	if (args->args_count < 2) +		return 0; + +	desc->flags = gpio_flags_xlate(args->args[1]); + +	return 0; +} +  static const struct dm_gpio_ops qcom_gpio_ops = {  	.direction_input	= qcom_gpio_direction_input,  	.direction_output	= qcom_gpio_direction_output,  	.get_value		= qcom_gpio_get_value,  	.set_value		= qcom_gpio_set_value,  	.get_function		= qcom_gpio_get_function, +	.xlate			= qcom_gpio_xlate,  }; +static int qcom_gpio_bind(struct udevice *dev) +{ + +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	ulong quirks = dev_get_driver_data(dev); +	struct udevice *child; +	struct driver *drv; +	int ret; + +	drv = lists_driver_lookup_name("qcom_pmic_pinctrl"); +	if (!drv) { +		log_warning("Cannot find driver '%s'\n", "qcom_pmic_pinctrl"); +		return -ENOENT; +	} + +	/* Bind the GPIO driver as a child of the PMIC. */ +	ret = device_bind_with_driver_data(dev, drv, +					   dev->name, +					   quirks, dev_ofnode(dev), &child); +	if (ret) +		return log_msg_ret("bind", ret); + +	dev_set_plat(child, plat); + +	return 0; +} +  static int qcom_gpio_probe(struct udevice *dev)  { -	struct qcom_gpio_bank *priv = dev_get_priv(dev); -	int reg; +	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); +	struct ofnode_phandle_args args; +	int val, ret;  	u64 pid; +	plat->pmic = dev->parent; +  	pid = dev_read_addr(dev);  	if (pid == FDT_ADDR_T_NONE)  		return log_msg_ret("bad address", -EINVAL); -	priv->pid = pid; +	plat->pid = pid;  	/* Do a sanity check */ -	reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); -	if (reg != REG_TYPE_VAL) +	val = pmic_reg_read(plat->pmic, plat->pid + REG_TYPE); +	if (val != REG_TYPE_VAL)  		return log_msg_ret("bad type", -ENXIO); -	reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); -	if (reg != REG_SUBTYPE_GPIO_4CH && reg != REG_SUBTYPE_GPIOC_4CH && -	    reg != REG_SUBTYPE_GPIO_LV && reg != REG_SUBTYPE_GPIO_MV) +	val = pmic_reg_read(plat->pmic, plat->pid + REG_SUBTYPE); +	if (val != REG_SUBTYPE_GPIO_4CH && val != REG_SUBTYPE_GPIOC_4CH && +	    val != REG_SUBTYPE_GPIO_LV && val != REG_SUBTYPE_GPIO_MV)  		return log_msg_ret("bad subtype", -ENXIO); -	priv->lv_mv_type = reg == REG_SUBTYPE_GPIO_LV || -			   reg == REG_SUBTYPE_GPIO_MV; - -	return 0; -} - -/* - * Parse basic GPIO count specified via the gpio-ranges property - * as specified in Linux devicetrees - * Returns < 0 on error, otherwise gpio count - */ -static int qcom_gpio_of_parse_ranges(struct udevice *dev) -{ -	int ret; -	struct ofnode_phandle_args args; +	plat->lv_mv_type = val == REG_SUBTYPE_GPIO_LV || +			   val == REG_SUBTYPE_GPIO_MV; +	/* +	 * Parse basic GPIO count specified via the gpio-ranges property +	 * as specified in upstream devicetrees +	 */  	ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges",  					     NULL, 3, 0, &args);  	if (ret)  		return log_msg_ret("gpio-ranges", ret); -	return args.args[2]; -} - -static int qcom_gpio_of_to_plat(struct udevice *dev) -{ -	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); -	int ret; - -	ret = qcom_gpio_of_parse_ranges(dev); -	if (ret > 0) -		uc_priv->gpio_count = ret; -	else -		return ret; +	plat->pin_count = args.args[2]; +	uc_priv->gpio_count = plat->pin_count;  	uc_priv->bank_name = "pmic";  	return 0; @@ -282,7 +349,7 @@ static int qcom_gpio_of_to_plat(struct udevice *dev)  static const struct udevice_id qcom_gpio_ids[] = {  	{ .compatible = "qcom,pm8916-gpio" },  	{ .compatible = "qcom,pm8994-gpio" },	/* 22 GPIO's */ -	{ .compatible = "qcom,pm8998-gpio" }, +	{ .compatible = "qcom,pm8998-gpio", .data = QCOM_PMIC_QUIRK_READONLY },  	{ .compatible = "qcom,pms405-gpio" },  	{ }  }; @@ -291,9 +358,75 @@ U_BOOT_DRIVER(qcom_pmic_gpio) = {  	.name	= "qcom_pmic_gpio",  	.id	= UCLASS_GPIO,  	.of_match = qcom_gpio_ids, -	.of_to_plat = qcom_gpio_of_to_plat, -	.probe	= qcom_gpio_probe, +	.bind	= qcom_gpio_bind, +	.probe = qcom_gpio_probe,  	.ops	= &qcom_gpio_ops, -	.priv_auto	= sizeof(struct qcom_gpio_bank), +	.plat_auto = sizeof(struct qcom_pmic_gpio_data), +	.flags = DM_FLAG_ALLOC_PDATA, +}; + +static const struct pinconf_param qcom_pmic_pinctrl_conf_params[] = { +	{ "output-high", PIN_CONFIG_OUTPUT_ENABLE, 1 }, +	{ "output-low", PIN_CONFIG_OUTPUT, 0 }, +}; + +static int qcom_pmic_pinctrl_get_pins_count(struct udevice *dev) +{ +	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + +	return plat->pin_count; +} + +static const char *qcom_pmic_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector) +{ +	static char name[8]; + +	/* DT indexes from 1 */ +	snprintf(name, sizeof(name), "gpio%u", selector + 1); + +	return name; +} + +static int qcom_pmic_pinctrl_pinconf_set(struct udevice *dev, unsigned int selector, +					 unsigned int param, unsigned int arg) +{ +	/* We only support configuring the pin as an output, either low or high */ +	return _qcom_gpio_set_direction(dev, selector, false, +					param == PIN_CONFIG_OUTPUT_ENABLE); +} + +static const char *qcom_pmic_pinctrl_get_function_name(struct udevice *dev, unsigned int selector) +{ +	if (!selector) +		return "normal"; +	return NULL; +} + +static int qcom_pmic_pinctrl_generic_get_functions_count(struct udevice *dev) +{ +	return 1; +} + +static int qcom_pmic_pinctrl_generic_pinmux_set_mux(struct udevice *dev, unsigned int selector, +						    unsigned int func_selector) +{ +	return 0; +} + +struct pinctrl_ops qcom_pmic_pinctrl_ops = { +	.get_pins_count = qcom_pmic_pinctrl_get_pins_count, +	.get_pin_name = qcom_pmic_pinctrl_get_pin_name, +	.set_state = pinctrl_generic_set_state, +	.pinconf_num_params = ARRAY_SIZE(qcom_pmic_pinctrl_conf_params), +	.pinconf_params = qcom_pmic_pinctrl_conf_params, +	.pinconf_set = qcom_pmic_pinctrl_pinconf_set, +	.get_function_name = qcom_pmic_pinctrl_get_function_name, +	.get_functions_count = qcom_pmic_pinctrl_generic_get_functions_count, +	.pinmux_set = qcom_pmic_pinctrl_generic_pinmux_set_mux,  }; +U_BOOT_DRIVER(qcom_pmic_pinctrl) = { +	.name	= "qcom_pmic_pinctrl", +	.id	= UCLASS_PINCTRL, +	.ops	= &qcom_pmic_pinctrl_ops, +}; diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index fe1e754bfde..059cb3da77c 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -44,6 +44,7 @@ struct msm_sdhc_plat {  struct msm_sdhc {  	struct sdhci_host host;  	void *base; +	struct clk_bulk clks;  };  struct msm_sdhc_variant_info { @@ -54,35 +55,57 @@ DECLARE_GLOBAL_DATA_PTR;  static int msm_sdc_clk_init(struct udevice *dev)  { -	int node = dev_of_offset(dev); -	uint clk_rate = fdtdec_get_uint(gd->fdt_blob, node, "clock-frequency", -					400000); -	uint clkd[2]; /* clk_id and clk_no */ -	int clk_offset; -	struct udevice *clk_dev; -	struct clk clk; -	int ret; +	struct msm_sdhc *prv = dev_get_priv(dev); +	ofnode node = dev_ofnode(dev); +	ulong clk_rate; +	int ret, i = 0, n_clks; +	const char *clk_name; -	ret = fdtdec_get_int_array(gd->fdt_blob, node, "clock", clkd, 2); +	ret = ofnode_read_u32(node, "clock-frequency", (uint *)(&clk_rate));  	if (ret) -		return ret; - -	clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]); -	if (clk_offset < 0) -		return clk_offset; +		clk_rate = 400000; -	ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev); -	if (ret) +	ret = clk_get_bulk(dev, &prv->clks); +	if (ret) { +		log_warning("Couldn't get mmc clocks: %d\n", ret);  		return ret; +	} -	clk.id = clkd[1]; -	ret = clk_request(clk_dev, &clk); -	if (ret < 0) +	ret = clk_enable_bulk(&prv->clks); +	if (ret) { +		log_warning("Couldn't enable mmc clocks: %d\n", ret);  		return ret; +	} -	ret = clk_set_rate(&clk, clk_rate); -	if (ret < 0) -		return ret; +	/* If clock-names is unspecified, then the first clock is the core clock */ +	if (!ofnode_get_property(node, "clock-names", &n_clks)) { +		if (!clk_set_rate(&prv->clks.clks[0], clk_rate)) { +			log_warning("Couldn't set core clock rate: %d\n", ret); +			return -EINVAL; +		} +	} + +	/* Find the index of the "core" clock */ +	while (i < n_clks) { +		ofnode_read_string_index(node, "clock-names", i, &clk_name); +		if (!strcmp(clk_name, "core")) +			break; +		i++; +	} + +	if (i >= prv->clks.count) { +		log_warning("Couldn't find core clock (index %d but only have %d clocks)\n", i, +		       prv->clks.count); +		return -EINVAL; +	} + +	/* The clock is already enabled by the clk_bulk above */ +	clk_rate = clk_set_rate(&prv->clks.clks[i], clk_rate); +	/* If we get a rate of 0 then something has probably gone wrong. */ +	if (clk_rate == 0 || IS_ERR((void *)clk_rate)) { +		log_warning("Couldn't set MMC core clock rate: %dE\n", clk_rate ? (int)PTR_ERR((void *)clk_rate) : 0); +		return -EINVAL; +	}  	return 0;  } @@ -187,6 +210,8 @@ static int msm_sdc_remove(struct udevice *dev)  	if (!var_info->mci_removed)  		writel(0, priv->base + SDCC_MCI_HC_MODE); +	clk_release_bulk(&priv->clks); +  	return 0;  } diff --git a/drivers/phy/qcom/msm8916-usbh-phy.c b/drivers/phy/qcom/msm8916-usbh-phy.c index 7c9d030a4d8..f52046f7cb0 100644 --- a/drivers/phy/qcom/msm8916-usbh-phy.c +++ b/drivers/phy/qcom/msm8916-usbh-phy.c @@ -74,7 +74,7 @@ static int msm_phy_probe(struct udevice *dev)  {  	struct msm_phy_priv *priv = dev_get_priv(dev); -	priv->regs = dev_remap_addr(dev); +	priv->regs = dev_remap_addr(dev_get_parent(dev));  	if (!priv->regs)  		return -EINVAL; @@ -96,7 +96,7 @@ static struct phy_ops msm_phy_ops = {  };  static const struct udevice_id msm_phy_ids[] = { -	{ .compatible = "qcom,apq8016-usbphy" }, +	{ .compatible = "qcom,usb-hs-phy-msm8916" },  	{ }  }; diff --git a/drivers/pinctrl/qcom/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c index 8149ffd83cc..db0e2124684 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8016.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c @@ -14,22 +14,22 @@  #define MAX_PIN_NAME_LEN 32  static char pin_name[MAX_PIN_NAME_LEN] __section(".data");  static const char * const msm_pinctrl_pins[] = { -	"SDC1_CLK", -	"SDC1_CMD", -	"SDC1_DATA", -	"SDC2_CLK", -	"SDC2_CMD", -	"SDC2_DATA", -	"QDSD_CLK", -	"QDSD_CMD", -	"QDSD_DATA0", -	"QDSD_DATA1", -	"QDSD_DATA2", -	"QDSD_DATA3", +	"sdc1_clk", +	"sdc1_cmd", +	"sdc1_data", +	"sdc2_clk", +	"sdc2_cmd", +	"sdc2_data", +	"qdsd_clk", +	"qdsd_cmd", +	"qdsd_data0", +	"qdsd_data1", +	"qdsd_data2", +	"qdsd_data3",  };  static const struct pinctrl_function msm_pinctrl_functions[] = { -	{"blsp1_uart", 2}, +	{"blsp_uart2", 2},  };  static const char *apq8016_get_function_name(struct udevice *dev, @@ -42,7 +42,7 @@ static const char *apq8016_get_pin_name(struct udevice *dev,  					unsigned int selector)  {  	if (selector < 122) { -		snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); +		snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);  		return pin_name;  	} else {  		return msm_pinctrl_pins[selector - 122]; @@ -55,7 +55,10 @@ static unsigned int apq8016_get_function_mux(unsigned int selector)  }  static const struct msm_pinctrl_data apq8016_data = { -	.pin_data = { .pin_count = 133, }, +	.pin_data = { +		.pin_count = 133, +		.special_pins_start = 122, +	},  	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),  	.get_function_name = apq8016_get_function_name,  	.get_function_mux = apq8016_get_function_mux, @@ -73,4 +76,5 @@ U_BOOT_DRIVER(pinctrl_apq8016) = {  	.of_match	= msm_pinctrl_ids,  	.ops		= &msm_pinctrl_ops,  	.bind		= msm_pinctrl_bind, +	.flags		= DM_FLAG_PRE_RELOC,  }; diff --git a/drivers/pinctrl/qcom/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c index d64ab1ff7be..880df8fe3c7 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8096.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c @@ -14,13 +14,13 @@  #define MAX_PIN_NAME_LEN 32  static char pin_name[MAX_PIN_NAME_LEN] __section(".data");  static const char * const msm_pinctrl_pins[] = { -	"SDC1_CLK", -	"SDC1_CMD", -	"SDC1_DATA", -	"SDC2_CLK", -	"SDC2_CMD", -	"SDC2_DATA", -	"SDC1_RCLK", +	"sdc1_clk", +	"sdc1_cmd", +	"sdc1_data", +	"sdc2_clk", +	"sdc2_cmd", +	"sdc2_data", +	"sdc1_rclk",  };  static const struct pinctrl_function msm_pinctrl_functions[] = { @@ -37,7 +37,7 @@ static const char *apq8096_get_pin_name(struct udevice *dev,  					unsigned int selector)  {  	if (selector < 150) { -		snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); +		snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);  		return pin_name;  	} else {  		return msm_pinctrl_pins[selector - 150]; @@ -50,7 +50,10 @@ static unsigned int apq8096_get_function_mux(unsigned int selector)  }  static const struct msm_pinctrl_data apq8096_data = { -	.pin_data = { .pin_count = 157, }, +	.pin_data = { +		.pin_count = 157, +		.special_pins_start = 150, +	},  	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),  	.get_function_name = apq8096_get_function_name,  	.get_function_mux = apq8096_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 2d99f99e1e4..74c04ab87cd 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -46,7 +46,10 @@ static unsigned int ipq4019_get_function_mux(unsigned int selector)  }  static const struct msm_pinctrl_data ipq4019_data = { -	.pin_data = { .pin_count = 100, }, +	.pin_data = { +		.pin_count = 100, +		.special_pins_start = 100, /* There are no special pins */ +	},  	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),  	.get_function_name = ipq4019_get_function_name,  	.get_function_mux = ipq4019_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c index dc3d8c4d903..ee0624df296 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -16,6 +16,7 @@  #include <asm/gpio.h>  #include <dm/pinctrl.h>  #include <linux/bitops.h> +#include <linux/bug.h>  #include <mach/gpio.h>  #include "pinctrl-qcom.h" @@ -83,6 +84,10 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector,  {  	struct msm_pinctrl_priv *priv = dev_get_priv(dev); +	/* Always NOP for special pins, assume they're in the correct state */ +	if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) +		return 0; +  	clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),  			TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE,  			priv->data->get_function_mux(func_selector) << 2); @@ -94,6 +99,10 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector,  {  	struct msm_pinctrl_priv *priv = dev_get_priv(dev); +	/* Always NOP for special pins */ +	if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) +		return 0; +  	switch (param) {  	case PIN_CONFIG_DRIVE_STRENGTH:  		argument = (argument / 2) - 1; @@ -136,6 +145,9 @@ int msm_pinctrl_bind(struct udevice *dev)  	const char *name;  	int ret; +	if (!data->pin_data.special_pins_start) +		dev_warn(dev, "Special pins start index not defined!\n"); +  	drv = lists_driver_lookup_name("pinctrl_qcom");  	if (!drv)  		return -ENOENT; diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index ac00afa2a1f..3a2d4685997 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -10,20 +10,24 @@  #include "pinctrl-qcom.h" +#define NORTH	0x00300000 +#define SOUTH	0x00000000 +#define EAST	0x06b00000 +  #define MAX_PIN_NAME_LEN 32  static char pin_name[MAX_PIN_NAME_LEN] __section(".data");  static const char * const msm_pinctrl_pins[] = { -	"SDC1_RCLK", -	"SDC1_CLK", -	"SDC1_CMD", -	"SDC1_DATA", -	"SDC2_CLK", -	"SDC2_CMD", -	"SDC2_DATA", +	"sdc1_rclk", +	"sdc1_clk", +	"sdc1_cmd", +	"sdc1_data", +	"sdc2_clk", +	"sdc2_cmd", +	"sdc2_data",  };  static const struct pinctrl_function msm_pinctrl_functions[] = { -	{"blsp_uart2", 1}, +	{"gpio", 0},  	{"rgmii_int", 1},  	{"rgmii_ck", 1},  	{"rgmii_tx", 1}, @@ -37,6 +41,40 @@ static const struct pinctrl_function msm_pinctrl_functions[] = {  	{"blsp_i2c_scl_a2", 3},  	{"blsp_i2c3", 2},  	{"blsp_i2c4", 1}, +	{"blsp_uart_tx_a2", 1}, +	{"blsp_uart_rx_a2", 1}, +}; + +static const unsigned int qcs404_pin_offsets[] = { +	[0] = SOUTH,    [1] = SOUTH,    [2] = SOUTH,    [3] = SOUTH,    [4] = SOUTH, +	[5] = SOUTH,   [6] = SOUTH,   [7] = SOUTH,   [8] = SOUTH,    [9] = SOUTH, +	[10] = SOUTH,   [11] = SOUTH,   [12] = SOUTH,  [13] = SOUTH,  [14] = SOUTH, +	[15] = SOUTH,  [16] = SOUTH,  [17] = NORTH,  [18] = NORTH,  [19] = NORTH, +	[20] = NORTH,  [21] = SOUTH,  [22] = NORTH,  [23] = NORTH,  [24] = NORTH, +	[25] = NORTH,  [26] = EAST,  [27] = EAST,   [28] = EAST,   [29] = EAST, +	[30] = NORTH,   [31] = NORTH,  [32] = NORTH,  [33] = NORTH,  [34] = SOUTH, +	[35] = SOUTH,  [36] = NORTH,  [37] = NORTH,  [38] = NORTH,  [39] = EAST, +	[40] = EAST,  [41] = EAST,   [42] = EAST,   [43] = EAST,   [44] = EAST, +	[45] = EAST,   [46] = EAST,   [47] = EAST,   [48] = EAST,   [49] = EAST, +	[50] = EAST,  [51] = EAST,  [52] = EAST,  [53] = EAST,  [54] = EAST, +	[55] = EAST,  [56] = EAST,  [57] = EAST,  [58] = EAST,  [59] = EAST, +	[60] = NORTH,  [61] = NORTH,  [62] = NORTH,  [63] = NORTH,  [64] = NORTH, +	[65] = NORTH,  [66] = NORTH,  [67] = NORTH,  [68] = NORTH,  [69] = NORTH, +	[70] = NORTH,   [71] = NORTH,   [72] = NORTH,   [73] = NORTH,   [74] = NORTH, +	[75] = NORTH,   [76] = NORTH,   [77] = NORTH,   [78] = EAST,   [79] = EAST, +	[80] = EAST,  [81] = EAST,  [82] = NORTH,  [83] = NORTH,  [84] = NORTH, +	[85] = NORTH,   [86] = EAST,   [87] = EAST,   [88] = EAST,   [89] = EAST, +	[90] = EAST,  [91] = EAST,  [92] = EAST,  [93] = EAST,  [94] = EAST, +	[95] = EAST,  [96] = EAST,  [97] = EAST,  [98] = EAST,  [99] = EAST, +	[100] = EAST, [101] = EAST, [102] = EAST, [103] = EAST, [104] = EAST, +	[105] = EAST, [106] = EAST, [107] = EAST, [108] = EAST, [109] = EAST, +	[110] = EAST, [111] = EAST, [112] = EAST, [113] = EAST, [114] = EAST, +	[115] = EAST, [116] = EAST, [117] = NORTH, [118] = NORTH, [119] = EAST, +	/* +	 * There's 126 pins but the last ones are special and have non-standard registers +	 * so we leave them out here. The pinctrl and GPIO drivers both currently ignore +	 * these pins. +	 */  };  static const char *qcs404_get_function_name(struct udevice *dev, @@ -49,7 +87,7 @@ static const char *qcs404_get_pin_name(struct udevice *dev,  				       unsigned int selector)  {  	if (selector < 120) { -		snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); +		snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);  		return pin_name;  	} else {  		return msm_pinctrl_pins[selector - 120]; @@ -61,8 +99,12 @@ static unsigned int qcs404_get_function_mux(unsigned int selector)  	return msm_pinctrl_functions[selector].val;  } -static struct msm_pinctrl_data qcs404_data = { -	.pin_data = { .pin_count = 126, }, +static const struct msm_pinctrl_data qcs404_data = { +	.pin_data = { +		.pin_count = 126, +		.pin_offsets = qcs404_pin_offsets, +		.special_pins_start = 120, +	},  	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),  	.get_function_name = qcs404_get_function_name,  	.get_function_mux = qcs404_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index 9f0f4085ce2..76bd8c4ef41 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -75,10 +75,11 @@ static unsigned int sdm845_get_function_mux(unsigned int selector)  	return msm_pinctrl_functions[selector].val;  } -static struct msm_pinctrl_data sdm845_data = { +static const struct msm_pinctrl_data sdm845_data = {  	.pin_data = {  		.pin_offsets = sdm845_pin_offsets, -		.pin_count = ARRAY_SIZE(sdm845_pin_offsets), +		.pin_count = 154, +		.special_pins_start = 150,  	},  	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),  	.get_function_name = sdm845_get_function_name, diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 26460c4e0ca..fbd351a4785 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -319,6 +319,14 @@ config DEBUG_UART_S5P  	  will need to provide parameters to make this work. The driver will  	  be available until the real driver-model serial is running. +config DEBUG_UART_MSM +	bool "Qualcomm QUP UART debug" +	depends on ARCH_SNAPDRAGON +	help +	  Select this to enable a debug UART using the serial_msm driver. You +	  will need to provide parameters to make this work. The driver will +	  be available until the real driver-model serial is running. +  config DEBUG_UART_MSM_GENI  	bool "Qualcomm snapdragon"  	depends on ARCH_SNAPDRAGON diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index f4d96313b93..ac4280c6c4c 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -160,29 +160,14 @@ static int msm_uart_clk_init(struct udevice *dev)  {  	uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),  					"clock-frequency", 115200); -	uint clkd[2]; /* clk_id and clk_no */ -	int clk_offset; -	struct udevice *clk_dev;  	struct clk clk;  	int ret; -	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "clock", -				   clkd, 2); -	if (ret) -		return ret; - -	clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]); -	if (clk_offset < 0) -		return clk_offset; - -	ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev); -	if (ret) -		return ret; - -	clk.id = clkd[1]; -	ret = clk_request(clk_dev, &clk); -	if (ret < 0) +	ret = clk_get_by_name(dev, "core", &clk); +	if (ret < 0) { +		pr_warn("%s: Failed to get clock: %d\n", __func__, ret);  		return ret; +	}  	ret = clk_set_rate(&clk, clk_rate);  	if (ret < 0) @@ -218,7 +203,6 @@ static int msm_serial_probe(struct udevice *dev)  	if (ret)  		return ret; -	pinctrl_select_state(dev, "uart");  	uart_dm_init(priv);  	return 0; @@ -251,4 +235,42 @@ U_BOOT_DRIVER(serial_msm) = {  	.priv_auto	= sizeof(struct msm_serial_data),  	.probe = msm_serial_probe,  	.ops	= &msm_serial_ops, +	.flags = DM_FLAG_PRE_RELOC,  }; + +#ifdef CONFIG_DEBUG_UART_MSM + +static struct msm_serial_data init_serial_data = { +	.base = CONFIG_VAL(DEBUG_UART_BASE), +	.clk_rate = 7372800, +}; + +#include <debug_uart.h> + +/* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ +//int apq8016_clk_init_uart(phys_addr_t gcc_base); + +static inline void _debug_uart_init(void) +{ +	/* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ +	//apq8016_clk_init_uart(0x1800000); +	uart_dm_init(&init_serial_data); +} + +static inline void _debug_uart_putc(int ch) +{ +	struct msm_serial_data *priv = &init_serial_data; + +	while (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) && +	       !(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY)) +		; + +	writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR); + +	writel(1, priv->base + UARTDM_NCF_TX); +	writel(ch, priv->base + UARTDM_TF); +} + +DEBUG_UART_FUNCS + +#endif diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 6fb2de8a5ac..a379a0002e7 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -21,6 +21,7 @@  #include <linux/usb/ch9.h>  #include <linux/usb/gadget.h>  #include <malloc.h> +#include <power/regulator.h>  #include <usb.h>  #include "core.h"  #include "gadget.h" @@ -47,6 +48,7 @@ struct dwc3_generic_priv {  struct dwc3_generic_host_priv {  	struct xhci_ctrl xhci_ctrl;  	struct dwc3_generic_priv gen_priv; +	struct udevice *vbus_supply;  };  static int dwc3_generic_probe(struct udevice *dev, @@ -240,11 +242,24 @@ static int dwc3_generic_host_probe(struct udevice *dev)  	if (rc)  		return rc; +	rc = device_get_supply_regulator(dev, "vbus-supply", &priv->vbus_supply); +	if (rc) +		debug("%s: No vbus regulator found: %d\n", dev->name, rc); + +	/* Only returns an error if regulator is valid and failed to enable due to a driver issue */ +	rc = regulator_set_enable_if_allowed(priv->vbus_supply, true); +	if (rc) +		return rc; +  	hccr = (struct xhci_hccr *)priv->gen_priv.base;  	hcor = (struct xhci_hcor *)(priv->gen_priv.base +  			HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); -	return xhci_register(dev, hccr, hcor); +	rc = xhci_register(dev, hccr, hcor); +	if (rc) +		regulator_set_enable_if_allowed(priv->vbus_supply, false); + +	return rc;  }  static int dwc3_generic_host_remove(struct udevice *dev) @@ -252,9 +267,12 @@ static int dwc3_generic_host_remove(struct udevice *dev)  	struct dwc3_generic_host_priv *priv = dev_get_priv(dev);  	int rc; -	rc = xhci_deregister(dev); +	/* This function always returns 0 */ +	xhci_deregister(dev); + +	rc = regulator_set_enable_if_allowed(priv->vbus_supply, false);  	if (rc) -		return rc; +		debug("%s: Failed to disable vbus regulator: %d\n", dev->name, rc);  	return dwc3_generic_remove(dev, &priv->gen_priv);  } diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index dd0d153500c..98fe7bc3bcb 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -9,6 +9,7 @@  #include <common.h>  #include <dm.h> +#include <dm/lists.h>  #include <errno.h>  #include <usb.h>  #include <usb/ehci-ci.h> @@ -119,6 +120,24 @@ static int ehci_usb_of_to_plat(struct udevice *dev)  	return 0;  } +static int ehci_usb_of_bind(struct udevice *dev) +{ +	ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev)); +	ofnode phy_node; + +	if (!ofnode_valid(ulpi_node)) +		return 0; + +	phy_node = ofnode_first_subnode(ulpi_node); +	if (!ofnode_valid(phy_node)) { +		printf("%s: ulpi subnode with no phy\n", __func__); +		return -ENOENT; +	} + +	return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy", +					  phy_node, NULL); +} +  #if defined(CONFIG_CI_UDC)  /* Little quirk that MSM needs with Chipidea controller   * Must reinit phy after reset @@ -132,7 +151,7 @@ void ci_init_after_reset(struct ehci_ctrl *ctrl)  #endif  static const struct udevice_id ehci_usb_ids[] = { -	{ .compatible = "qcom,ehci-host", }, +	{ .compatible = "qcom,ci-hdrc", },  	{ }  }; @@ -141,6 +160,7 @@ U_BOOT_DRIVER(usb_ehci) = {  	.id	= UCLASS_USB,  	.of_match = ehci_usb_ids,  	.of_to_plat = ehci_usb_of_to_plat, +	.bind = ehci_usb_of_bind,  	.probe = ehci_usb_probe,  	.remove = ehci_usb_remove,  	.ops	= &ehci_usb_ops, | 
