diff options
Diffstat (limited to 'drivers')
30 files changed, 693 insertions, 175 deletions
diff --git a/drivers/dma/keystone_nav.c b/drivers/dma/keystone_nav.c index 77707c2109..dfca75abdc 100644 --- a/drivers/dma/keystone_nav.c +++ b/drivers/dma/keystone_nav.c @@ -81,9 +81,6 @@ void qm_close(void) { u32 j; - if (qm_cfg == NULL) - return; - queue_close(qm_cfg->qpool_num); qm_cfg->mngr_cfg->link_ram_base0 = 0; @@ -105,9 +102,6 @@ void qm_push(struct qm_host_desc *hd, u32 qnum) { u32 regd; - if (!qm_cfg) - return; - cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4); regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1); writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh); @@ -127,9 +121,6 @@ struct qm_host_desc *qm_pop(u32 qnum) { u32 uhd; - if (!qm_cfg) - return NULL; - uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf; if (uhd) cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4); @@ -139,9 +130,6 @@ struct qm_host_desc *qm_pop(u32 qnum) struct qm_host_desc *qm_pop_from_free_pool(void) { - if (!qm_cfg) - return NULL; - return qm_pop(qm_cfg->qpool_num); } diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 811033b0b8..7bb1702bba 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -38,7 +38,7 @@ * generic value. */ #ifndef CONFIG_I2C_TIMEOUT -#define CONFIG_I2C_TIMEOUT 10000 +#define CONFIG_I2C_TIMEOUT 100000 #endif #define I2C_READ_BIT 1 diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index e7a15ba644..df8888550b 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -158,8 +158,7 @@ static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) * * Typical case is a Write of an addr followd by a Read. The * IBM FAQ does not cover this. On the last byte of the write - * we don't set the creg CHT bit, and on the first bytes of the - * read we set the RPST bit. + * we don't set the creg CHT bit but the RPST bit. * * It does not support address only transfers, there must be * a data part. If you want to write the address yourself, put @@ -247,6 +246,10 @@ static int _i2c_transfer(struct i2c_adapter *adap, if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt)) creg |= IIC_CNTL_CHT; + /* last part of address, prepare for repeated start on read */ + if (cmd_type && (ptr == addr) && ((tran + bc) == cnt)) + creg |= IIC_CNTL_RPST; + if (reading) { creg |= IIC_CNTL_READ; } else { @@ -286,6 +289,27 @@ static int _i2c_transfer(struct i2c_adapter *adap, /* Transfer aborted? */ if (status & IIC_EXTSTS_XFRA) result = IIC_NOK_XFRA; + /* Is bus free? + * If error happened during combined xfer + * IIC interface is usually stuck in some strange + * state without a valid stop condition. + * Brute, but working: generate stop, then soft reset. + */ + if ((status & IIC_EXTSTS_BCS_MASK) + != IIC_EXTSTS_BCS_FREE){ + u8 mdcntl = in_8(&i2c->mdcntl); + + /* Generate valid stop condition */ + out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST); + out_8(&i2c->directcntl, IIC_DIRCNTL_SCC); + udelay(10); + out_8(&i2c->directcntl, + IIC_DIRCNTL_SCC | IIC_DIRCNTL_SDAC); + out_8(&i2c->xtcntlss, 0); + + ppc4xx_i2c_init(adap, (mdcntl & IIC_MDCNTL_FSM) + ? 400000 : 100000, 0); + } } else if ( status & IIC_STS_PT) { result = IIC_NOK_TOUT; } @@ -314,8 +338,6 @@ static int _i2c_transfer(struct i2c_adapter *adap, cnt = data_len; tran = 0; reading = cmd_type; - if (reading) - creg = IIC_CNTL_RPST; } } return result; diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c index 50cebd622b..90ad116a98 100644 --- a/drivers/i2c/rcar_i2c.c +++ b/drivers/i2c/rcar_i2c.c @@ -119,10 +119,10 @@ rcar_i2c_raw_read(struct rcar_i2c *dev, u8 chip, uint addr) /* set slave address, receive */ writel((chip << 1) | 1, &dev->icmar); - /* clear status */ - writel(0, &dev->icmsr); /* start master receive */ writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr); + /* clear status */ + writel(0, &dev->icmsr); while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDR)) != (MSR_MAT | MSR_MDR)) diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 464cee16d1..461d7d8ec1 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -5,37 +5,39 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o +obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o +obj-$(CONFIG_DWMMC) += dw_mmc.o +obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o obj-$(CONFIG_GENERIC_MMC) += mmc.o obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o +obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o obj-$(CONFIG_MMC_SPI) += mmc_spi.o -obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o +obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o obj-$(CONFIG_MV_SDHCI) += mv_sdhci.o +obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o obj-$(CONFIG_MXC_MMC) += mxcmmc.o obj-$(CONFIG_MXS_MMC) += mxsmmc.o obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o -obj-$(CONFIG_SDHCI) += sdhci.o -obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o -obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o +obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_S3C_SDI) += s3c_sdi.o obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o +obj-$(CONFIG_SDHCI) += sdhci.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o +obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o -obj-$(CONFIG_DWMMC) += dw_mmc.o -obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o -obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o -obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o -obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o else obj-$(CONFIG_GENERIC_MMC) += mmc_write.o endif -obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o + diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index ef2cbf9e2f..ffb5284a00 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -611,7 +611,8 @@ static int omap_hsmmc_getcd(struct mmc *mmc) if (cd_gpio < 0) return 1; - return gpio_get_value(cd_gpio); + /* NOTE: assumes card detect signal is active-low */ + return !gpio_get_value(cd_gpio); } static int omap_hsmmc_getwp(struct mmc *mmc) @@ -624,6 +625,7 @@ static int omap_hsmmc_getwp(struct mmc *mmc) if (wp_gpio < 0) return 0; + /* NOTE: assumes write protect signal is active-high */ return gpio_get_value(wp_gpio); } #endif diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c index 9499290bba..60e898cd7c 100644 --- a/drivers/net/fm/memac.c +++ b/drivers/net/fm/memac.c @@ -37,7 +37,8 @@ static void memac_enable_mac(struct fsl_enet_mac *mac) { struct memac *regs = mac->base; - setbits_be32(®s->command_config, MEMAC_CMD_CFG_RXTX_EN); + setbits_be32(®s->command_config, + MEMAC_CMD_CFG_RXTX_EN | MEMAC_CMD_CFG_NO_LEN_CHK); } static void memac_disable_mac(struct fsl_enet_mac *mac) @@ -93,11 +94,16 @@ static void memac_set_interface_mode(struct fsl_enet_mac *mac, if_mode &= ~IF_MODE_MASK; if_mode |= (IF_MODE_GMII); break; + case PHY_INTERFACE_MODE_XGMII: + if_mode &= ~IF_MODE_MASK; + if_mode |= IF_MODE_XGMII; + break; default: break; } - /* Enable automatic speed selection */ - if_mode |= IF_MODE_EN_AUTO; + /* Enable automatic speed selection for Non-XGMII */ + if (type != PHY_INTERFACE_MODE_XGMII) + if_mode |= IF_MODE_EN_AUTO; if (type == PHY_INTERFACE_MODE_RGMII) { if_mode &= ~IF_MODE_EN_AUTO; diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c index 5f910c2cdd..a155d8930b 100644 --- a/drivers/net/fm/memac_phy.c +++ b/drivers/net/fm/memac_phy.c @@ -71,6 +71,8 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr, u32 c45 = 1; if (dev_addr == MDIO_DEVAD_NONE) { + if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME)) + return 0xffff; c45 = 0; /* clause 22 */ dev_addr = regnum & 0x1f; clrbits_be32(®s->mdio_stat, MDIO_STAT_ENC); @@ -137,9 +139,12 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info) * is zero, so MDIO clock is disabled. * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to * be properly initialized. + * NEG bit default should be '1' as per FMAN-v3 RM, but on platform + * like T2080QDS, this bit default is '0', which leads to MDIO failure + * on XAUI PHY, so set this bit definitely. */ setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat, - MDIO_STAT_CLKDIV(258)); + MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG); return mdio_register(bus); } diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index c8681d0223..bedab1d606 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -315,7 +315,7 @@ int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); -#ifdef CONFIG_K2E_EVM +#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) /* Map RX packet flow priority to 0 */ writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP); #endif @@ -400,6 +400,9 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) keystone2_net_serdes_setup(); + if (sys_has_mdio) + keystone2_mdio_reset(mdio_bus); + keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1, eth_priv->sgmii_link_type); @@ -582,7 +585,7 @@ static void keystone2_net_serdes_setup(void) &ks2_serdes_sgmii_156p25mhz, CONFIG_KSNET_SERDES_LANES_PER_SGMII); -#ifdef CONFIG_SOC_K2E +#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, &ks2_serdes_sgmii_156p25mhz, CONFIG_KSNET_SERDES_LANES_PER_SGMII); diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index d2ecadc890..9437c3bbcc 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -276,6 +276,57 @@ static int m88e1111s_config(struct phy_device *phydev) return 0; } +/** + * m88e1518_phy_writebits - write bits to a register + */ +void m88e1518_phy_writebits(struct phy_device *phydev, + u8 reg_num, u16 offset, u16 len, u16 data) +{ + u16 reg, mask; + + if ((len + offset) >= 16) + mask = 0 - (1 << offset); + else + mask = (1 << (len + offset)) - (1 << offset); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, reg_num); + + reg &= ~mask; + reg |= data << offset; + + phy_write(phydev, MDIO_DEVAD_NONE, reg_num, reg); +} + +static int m88e1518_config(struct phy_device *phydev) +{ + /* + * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 + * /88E1514 Rev A0, Errata Section 3.1 + */ + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); /* page 0xff */ + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); + phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); + phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); /* reg page 0 */ + phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); /* reg page 18 */ + /* Write HWCFG_MODE = SGMII to Copper */ + m88e1518_phy_writebits(phydev, 20, 0, 3, 1); + + /* Phy reset */ + m88e1518_phy_writebits(phydev, 20, 15, 1, 1); + phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); /* reg page 18 */ + udelay(100); + } + + return m88e1111s_config(phydev); +} + /* Marvell 88E1118 */ static int m88e1118_config(struct phy_device *phydev) { @@ -493,7 +544,7 @@ static struct phy_driver M88E1518_driver = { .uid = 0x1410dd1, .mask = 0xffffff0, .features = PHY_GBIT_FEATURES, - .config = &m88e1111s_config, + .config = &m88e1518_config, .startup = &m88e1011s_startup, .shutdown = &genphy_shutdown, }; diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index b097c1a56f..5959672370 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -187,6 +187,7 @@ static int smc911x_send(struct eth_device *dev, void *packet, int length) static void smc911x_halt(struct eth_device *dev) { smc911x_reset(dev); + smc911x_handle_mac_address(dev); } static int smc911x_rx(struct eth_device *dev) diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c index 538f11e3eb..9526faa4af 100644 --- a/drivers/net/uli526x.c +++ b/drivers/net/uli526x.c @@ -548,7 +548,7 @@ static int uli526x_rx_packet(struct eth_device *dev) rdes0 = le32_to_cpu(rxptr->rdes0); #ifdef RX_DEBUG - printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0); + printf("%s(): rxptr->rdes0=%x\n", __FUNCTION__, rxptr->rdes0); #endif if (!(rdes0 & 0x80000000)) { /* packet owner check */ if ((rdes0 & 0x300) != 0x300) { diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e69de29bb2..1ec7c0e59a 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -0,0 +1,47 @@ +config AXP221_POWER + boolean "axp221 pmic support" + depends on MACH_SUN6I + default y + ---help--- + Say y here to enable support for the axp221 pmic found on most sun6i + (A31) boards. + +config AXP221_DLDO1_VOLT + int "axp221 dldo1 voltage" + depends on AXP221_POWER + default -1 + ---help--- + Set the voltage (mV) to program the axp221 dldo1 at, set to -1 to + disable dldo1. + +config AXP221_DLDO4_VOLT + int "axp221 dldo4 voltage" + depends on AXP221_POWER + default -1 + ---help--- + Set the voltage (mV) to program the axp221 dldo4 at, set to -1 to + disable dldo4. + +config AXP221_ALDO1_VOLT + int "axp221 aldo1 voltage" + depends on AXP221_POWER + default -1 + ---help--- + Set the voltage (mV) to program the axp221 aldo1 at, set to -1 to + disable aldo1. + +config AXP221_ALDO2_VOLT + int "axp221 aldo2 voltage" + depends on AXP221_POWER + default -1 + ---help--- + Set the voltage (mV) to program the axp221 aldo2 at, set to -1 to + disable aldo2. + +config AXP221_ALDO3_VOLT + int "axp221 aldo3 voltage" + depends on AXP221_POWER + default -1 + ---help--- + Set the voltage (mV) to program the axp221 aldo3 at, set to -1 to + disable aldo3. diff --git a/drivers/power/Makefile b/drivers/power/Makefile index dc64e4d32b..04bd996cad 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_AXP152_POWER) += axp152.o obj-$(CONFIG_AXP209_POWER) += axp209.o +obj-$(CONFIG_AXP221_POWER) += axp221.o obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o obj-$(CONFIG_FTPMU010_POWER) += ftpmu010.o obj-$(CONFIG_TPS6586X_POWER) += tps6586x.o diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c new file mode 100644 index 0000000000..941193a19d --- /dev/null +++ b/drivers/power/axp221.c @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <asm/arch/p2wi.h> +#include <axp221.h> + +static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +static int axp221_setbits(u8 reg, u8 bits) +{ + int ret; + u8 val; + + ret = p2wi_read(reg, &val); + if (ret) + return ret; + + val |= bits; + return p2wi_write(reg, val); +} + +int axp221_set_dcdc1(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100); + + ret = p2wi_write(AXP221_DCDC1_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DCDC1_EN); +} + +int axp221_set_dcdc2(unsigned int mvolt) +{ + u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); + + return p2wi_write(AXP221_DCDC2_CTRL, cfg); +} + +int axp221_set_dcdc3(unsigned int mvolt) +{ + u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20); + + return p2wi_write(AXP221_DCDC3_CTRL, cfg); +} + +int axp221_set_dcdc4(unsigned int mvolt) +{ + u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); + + return p2wi_write(AXP221_DCDC4_CTRL, cfg); +} + +int axp221_set_dcdc5(unsigned int mvolt) +{ + u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50); + + return p2wi_write(AXP221_DCDC5_CTRL, cfg); +} + +int axp221_set_dldo1(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_DLDO1_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO1_EN); +} + +int axp221_set_dldo2(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_DLDO2_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO2_EN); +} + +int axp221_set_dldo3(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_DLDO3_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO3_EN); +} + +int axp221_set_dldo4(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_DLDO4_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO4_EN); +} + +int axp221_set_aldo1(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_ALDO1_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO1_EN); +} + +int axp221_set_aldo2(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_ALDO2_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO2_EN); +} + +int axp221_set_aldo3(unsigned int mvolt) +{ + int ret; + u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); + + ret = p2wi_write(AXP221_ALDO3_CTRL, cfg); + if (ret) + return ret; + + return axp221_setbits(AXP221_OUTPUT_CTRL3, + AXP221_OUTPUT_CTRL3_ALDO3_EN); +} + +int axp221_init(void) +{ + u8 axp_chip_id; + int ret; + + p2wi_init(); + ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, + AXP221_INIT_DATA); + if (ret) + return ret; + + ret = p2wi_read(AXP221_CHIP_ID, &axp_chip_id); + if (ret) + return ret; + + if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17)) + return -ENODEV; + + return 0; +} diff --git a/drivers/power/power_spi.c b/drivers/power/power_spi.c index fb455a0061..1e554461f3 100644 --- a/drivers/power/power_spi.c +++ b/drivers/power/power_spi.c @@ -17,27 +17,14 @@ static struct spi_slave *slave; -void pmic_spi_free(struct spi_slave *slave) -{ - if (slave) - spi_free_slave(slave); -} - -struct spi_slave *pmic_spi_probe(struct pmic *p) -{ - return spi_setup_slave(p->bus, - p->hw.spi.cs, - p->hw.spi.clk, - p->hw.spi.mode); -} - static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write) { u32 pmic_tx, pmic_rx; u32 tmp; if (!slave) { - slave = pmic_spi_probe(p); + slave = spi_setup_slave(p->bus, p->hw.spi.cs, p->hw.spi.clk, + p->hw.spi.mode); if (!slave) return -1; @@ -54,25 +41,25 @@ static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write) tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, - pmic_spi_flags)) { - spi_release_bus(slave); - return -1; - } + pmic_spi_flags)) + goto err; if (write) { pmic_tx = p->hw.spi.prepare_tx(reg, val, 0); tmp = cpu_to_be32(pmic_tx); if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx, - pmic_spi_flags)) { - spi_release_bus(slave); - return -1; - } + pmic_spi_flags)) + goto err; } spi_release_bus(slave); *val = cpu_to_be32(pmic_rx); return 0; + +err: + spi_release_bus(slave); + return -1; } int pmic_reg_write(struct pmic *p, u32 reg, u32 val) diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c index 3f3d415213..6046efb51f 100644 --- a/drivers/serial/serial_uniphier.c +++ b/drivers/serial/serial_uniphier.c @@ -5,7 +5,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include <common.h> +#include <linux/serial_reg.h> #include <asm/io.h> #include <asm/errno.h> #include <dm/device.h> @@ -37,17 +37,6 @@ struct uniphier_serial { #define thr rbr -/* - * These are the definitions for the Line Control Register - */ -#define UART_LCR_WLS_8 0x03 /* 8 bit character length */ - -/* - * These are the definitions for the Line Status Register - */ -#define UART_LSR_DR 0x01 /* Data ready */ -#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ - struct uniphier_serial_private_data { struct uniphier_serial __iomem *membase; }; @@ -62,7 +51,7 @@ static int uniphier_serial_setbrg(struct udevice *dev, int baudrate) const unsigned int mode_x_div = 16; unsigned int divisor; - writeb(UART_LCR_WLS_8, &port->lcr); + writeb(UART_LCR_WLEN8, &port->lcr); divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index e69de29bb2..b4a9442703 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -0,0 +1,46 @@ +config USB_ARCH_HAS_HCD + def_bool y + +config USB + bool "Support for Host-side USB" + depends on USB_ARCH_HAS_HCD + ---help--- + Universal Serial Bus (USB) is a specification for a serial bus + subsystem which offers higher speeds and more features than the + traditional PC serial port. The bus supplies power to peripherals + and allows for hot swapping. Up to 127 USB peripherals can be + connected to a single USB host in a tree structure. + + The USB host is the root of the tree, the peripherals are the + leaves and the inner nodes are special USB devices called hubs. + Most PCs now have USB host ports, used to connect peripherals + such as scanners, keyboards, mice, modems, cameras, disks, + flash memory, network links, and printers to the PC. + + Say Y here if your computer has a host-side USB port and you want + to use USB devices. You then need to say Y to at least one of the + Host Controller Driver (HCD) options below. Choose a USB 1.1 + controller, such as "UHCI HCD support" or "OHCI HCD support", + and "EHCI HCD (USB 2.0) support" except for older systems that + do not have USB 2.0 support. It doesn't normally hurt to select + them all if you are not certain. + + If your system has a device-side USB port, used in the peripheral + side of the USB protocol, see the "USB Gadget" framework instead. + + After choosing your HCD, then select drivers for the USB peripherals + you'll be using. You may want to check out the information provided + in <file:Documentation/usb/> and especially the links given in + <file:Documentation/usb/usb-help.txt>. + +if USB + +source "drivers/usb/host/Kconfig" + +config USB_STORAGE + bool "USB Mass Storage support" + ---help--- + Say Y here if you want to connect USB mass storage devices to your + board's USB port. + +endif diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile index 94551c4c0c..e6ae9f1e52 100644 --- a/drivers/usb/eth/Makefile +++ b/drivers/usb/eth/Makefile @@ -5,8 +5,6 @@ # new USB host ethernet layer dependencies obj-$(CONFIG_USB_HOST_ETHER) += usb_ether.o -ifdef CONFIG_USB_ETHER_ASIX -obj-y += asix.o -endif +obj-$(CONFIG_USB_ETHER_ASIX) += asix.o obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 2efd5a4d5b..70bb550fa4 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o ifdef CONFIG_USB_GADGET obj-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o obj-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o +obj-$(CONFIG_USB_GADGET_S3C_UDC_OTG_PHY) += s3c_udc_otg_phy.o obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o obj-$(CONFIG_CI_UDC) += ci_udc.o obj-$(CONFIG_THOR_FUNCTION) += f_thor.o diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c index b9816dfe30..7653f03949 100644 --- a/drivers/usb/gadget/s3c_udc_otg.c +++ b/drivers/usb/gadget/s3c_udc_otg.c @@ -31,7 +31,6 @@ #include <asm/io.h> #include <asm/mach-types.h> -#include <asm/arch/gpio.h> #include "regs-otg.h" #include <usb/lin_gadget_compat.h> @@ -105,7 +104,7 @@ static void stop_activity(struct s3c_udc *dev, struct usb_gadget_driver *driver); static int udc_enable(struct s3c_udc *dev); static void udc_set_address(struct s3c_udc *dev, unsigned char address); -static void reconfig_usbd(void); +static void reconfig_usbd(struct s3c_udc *dev); static void set_max_pktsize(struct s3c_udc *dev, enum usb_device_speed speed); static void nuke(struct s3c_ep *ep, int status); static int s3c_udc_set_halt(struct usb_ep *_ep, int value); @@ -146,68 +145,14 @@ static struct usb_ep_ops s3c_ep_ops = { void __iomem *regs_otg; struct s3c_usbotg_reg *reg; -struct s3c_usbotg_phy *phy; -static unsigned int usb_phy_ctrl; bool dfu_usb_get_reset(void) { return !!(readl(®->gintsts) & INT_RESET); } -void otg_phy_init(struct s3c_udc *dev) -{ - dev->pdata->phy_control(1); - - /*USB PHY0 Enable */ - printf("USB PHY0 Enable\n"); - - /* Enable PHY */ - writel(readl(usb_phy_ctrl) | USB_PHY_CTRL_EN0, usb_phy_ctrl); - - if (dev->pdata->usb_flags == PHY0_SLEEP) /* C210 Universal */ - writel((readl(&phy->phypwr) - &~(PHY_0_SLEEP | OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); - else /* C110 GONI */ - writel((readl(&phy->phypwr) &~(OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); - - if (s5p_cpu_id == 0x4412) - writel((readl(&phy->phyclk) & ~(EXYNOS4X12_ID_PULLUP0 | - EXYNOS4X12_COMMON_ON_N0)) | EXYNOS4X12_CLK_SEL_24MHZ, - &phy->phyclk); /* PLL 24Mhz */ - else - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) | - CLK_SEL_24MHZ, &phy->phyclk); /* PLL 24Mhz */ - - writel((readl(&phy->rstcon) &~(LINK_SW_RST | PHYLNK_SW_RST)) - | PHY_SW_RST0, &phy->rstcon); - udelay(10); - writel(readl(&phy->rstcon) - &~(PHY_SW_RST0 | LINK_SW_RST | PHYLNK_SW_RST), &phy->rstcon); - udelay(10); -} - -void otg_phy_off(struct s3c_udc *dev) -{ - /* reset controller just in case */ - writel(PHY_SW_RST0, &phy->rstcon); - udelay(20); - writel(readl(&phy->phypwr) &~PHY_SW_RST0, &phy->rstcon); - udelay(20); - - writel(readl(&phy->phypwr) | OTG_DISABLE_0 | ANALOG_PWRDOWN - | FORCE_SUSPEND_0, &phy->phypwr); - - writel(readl(usb_phy_ctrl) &~USB_PHY_CTRL_EN0, usb_phy_ctrl); - - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)), - &phy->phyclk); - - udelay(10000); - - dev->pdata->phy_control(0); -} +__weak void otg_phy_init(struct s3c_udc *dev) {} +__weak void otg_phy_off(struct s3c_udc *dev) {} /***********************************************************/ @@ -270,7 +215,7 @@ static int udc_enable(struct s3c_udc *dev) debug_cond(DEBUG_SETUP != 0, "%s: %p\n", __func__, dev); otg_phy_init(dev); - reconfig_usbd(); + reconfig_usbd(dev); debug_cond(DEBUG_SETUP != 0, "S3C USB 2.0 OTG Controller Core Initialized : 0x%x\n", @@ -451,15 +396,17 @@ static void stop_activity(struct s3c_udc *dev, udc_reinit(dev); } -static void reconfig_usbd(void) +static void reconfig_usbd(struct s3c_udc *dev) { /* 2. Soft-reset OTG Core and then unreset again. */ int i; unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); + uint32_t dflt_gusbcfg; debug("Reseting OTG controller\n"); - writel(0<<15 /* PHY Low Power Clock sel*/ + dflt_gusbcfg = + 0<<15 /* PHY Low Power Clock sel*/ |1<<14 /* Non-Periodic TxFIFO Rewind Enable*/ |0x5<<10 /* Turnaround time*/ |0<<9 | 0<<8 /* [0:HNP disable,1:HNP enable][ 0:SRP disable*/ @@ -468,8 +415,12 @@ static void reconfig_usbd(void) |0<<6 /* 0: high speed utmi+, 1: full speed serial*/ |0<<4 /* 0: utmi+, 1:ulpi*/ |1<<3 /* phy i/f 0:8bit, 1:16bit*/ - |0x7<<0, /* HS/FS Timeout**/ - ®->gusbcfg); + |0x7<<0; /* HS/FS Timeout**/ + + if (dev->pdata->usb_gusbcfg) + dflt_gusbcfg = dev->pdata->usb_gusbcfg; + + writel(dflt_gusbcfg, ®->gusbcfg); /* 3. Put the OTG device core in the disconnected state.*/ uTemp = readl(®->dctl); @@ -854,9 +805,7 @@ int s3c_udc_probe(struct s3c_plat_otg_data *pdata) dev->pdata = pdata; - phy = (struct s3c_usbotg_phy *)pdata->regs_phy; reg = (struct s3c_usbotg_reg *)pdata->regs_otg; - usb_phy_ctrl = pdata->usb_phy_ctrl; /* regs_otg = (void *)pdata->regs_otg; */ diff --git a/drivers/usb/gadget/s3c_udc_otg_phy.c b/drivers/usb/gadget/s3c_udc_otg_phy.c new file mode 100644 index 0000000000..f13cb8910a --- /dev/null +++ b/drivers/usb/gadget/s3c_udc_otg_phy.c @@ -0,0 +1,101 @@ +/* + * drivers/usb/gadget/s3c_udc_otg.c + * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers + * + * Copyright (C) 2008 for Samsung Electronics + * + * BSP Support for Samsung's UDC driver + * available at: + * git://git.kernel.org/pub/scm/linux/kernel/git/kki_ap/linux-2.6-samsung.git + * + * State machine bugfixes: + * Marek Szyprowski <m.szyprowski@samsung.com> + * + * Ported to u-boot: + * Marek Szyprowski <m.szyprowski@samsung.com> + * Lukasz Majewski <l.majewski@samsumg.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/errno.h> +#include <linux/list.h> +#include <malloc.h> + +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> + +#include <asm/byteorder.h> +#include <asm/unaligned.h> +#include <asm/io.h> + +#include <asm/mach-types.h> + +#include "regs-otg.h" +#include <usb/lin_gadget_compat.h> + +#include <usb/s3c_udc.h> + +void otg_phy_init(struct s3c_udc *dev) +{ + unsigned int usb_phy_ctrl = dev->pdata->usb_phy_ctrl; + struct s3c_usbotg_phy *phy = + (struct s3c_usbotg_phy *)dev->pdata->regs_phy; + + dev->pdata->phy_control(1); + + /* USB PHY0 Enable */ + printf("USB PHY0 Enable\n"); + + /* Enable PHY */ + writel(readl(usb_phy_ctrl) | USB_PHY_CTRL_EN0, usb_phy_ctrl); + + if (dev->pdata->usb_flags == PHY0_SLEEP) /* C210 Universal */ + writel((readl(&phy->phypwr) + &~(PHY_0_SLEEP | OTG_DISABLE_0 | ANALOG_PWRDOWN) + &~FORCE_SUSPEND_0), &phy->phypwr); + else /* C110 GONI */ + writel((readl(&phy->phypwr) &~(OTG_DISABLE_0 | ANALOG_PWRDOWN) + &~FORCE_SUSPEND_0), &phy->phypwr); + + if (s5p_cpu_id == 0x4412) + writel((readl(&phy->phyclk) & ~(EXYNOS4X12_ID_PULLUP0 | + EXYNOS4X12_COMMON_ON_N0)) | EXYNOS4X12_CLK_SEL_24MHZ, + &phy->phyclk); /* PLL 24Mhz */ + else + writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) | + CLK_SEL_24MHZ, &phy->phyclk); /* PLL 24Mhz */ + + writel((readl(&phy->rstcon) &~(LINK_SW_RST | PHYLNK_SW_RST)) + | PHY_SW_RST0, &phy->rstcon); + udelay(10); + writel(readl(&phy->rstcon) + &~(PHY_SW_RST0 | LINK_SW_RST | PHYLNK_SW_RST), &phy->rstcon); + udelay(10); +} + +void otg_phy_off(struct s3c_udc *dev) +{ + unsigned int usb_phy_ctrl = dev->pdata->usb_phy_ctrl; + struct s3c_usbotg_phy *phy = + (struct s3c_usbotg_phy *)dev->pdata->regs_phy; + + /* reset controller just in case */ + writel(PHY_SW_RST0, &phy->rstcon); + udelay(20); + writel(readl(&phy->phypwr) &~PHY_SW_RST0, &phy->rstcon); + udelay(20); + + writel(readl(&phy->phypwr) | OTG_DISABLE_0 | ANALOG_PWRDOWN + | FORCE_SUSPEND_0, &phy->phypwr); + + writel(readl(usb_phy_ctrl) &~USB_PHY_CTRL_EN0, usb_phy_ctrl); + + writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)), + &phy->phyclk); + + udelay(10000); + + dev->pdata->phy_control(0); +} diff --git a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c index 4f69b22a25..9c54b462c4 100644 --- a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c @@ -551,7 +551,7 @@ static int s3c_udc_irq(int irq, void *_dev) debug_cond(DEBUG_ISR, "\t\tOTG core got reset (%d)!!\n", reset_available); - reconfig_usbd(); + reconfig_usbd(dev); dev->ep0state = WAIT_FOR_SETUP; reset_available = 0; s3c_udc_pre_setup(); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig new file mode 100644 index 0000000000..30d1457638 --- /dev/null +++ b/drivers/usb/host/Kconfig @@ -0,0 +1,56 @@ +# +# USB Host Controller Drivers +# +comment "USB Host Controller Drivers" + +config USB_XHCI_HCD + bool "xHCI HCD (USB 3.0) support" + ---help--- + The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 + "SuperSpeed" host controller hardware. + +config USB_XHCI + bool + default USB_XHCI_HCD + ---help--- + TODO: rename after most boards switch to Kconfig + +if USB_XHCI_HCD + +endif + +config USB_EHCI_HCD + bool "EHCI HCD (USB 2.0) support" + ---help--- + The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 + "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. + If your USB host controller supports USB 2.0, you will likely want to + configure this Host Controller Driver. + + EHCI controllers are packaged with "companion" host controllers (OHCI + or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports + will connect to EHCI if the device is high speed, otherwise they + connect to a companion controller. If you configure EHCI, you should + probably configure the OHCI (for NEC and some other vendors) USB Host + Controller Driver or UHCI (for Via motherboards) Host Controller + Driver too. + + You may want to read <file:Documentation/usb/ehci.txt>. + +config USB_EHCI + bool + default USB_EHCI_HCD + ---help--- + TODO: rename after most boards switch to Kconfig + +if USB_EHCI_HCD + +config USB_EHCI_UNIPHIER + bool "Support for Panasonic UniPhier on-chip EHCI USB controller" + depends on ARCH_UNIPHIER + default y + ---help--- + Enables support for the on-chip EHCI controller on Panasonic + UniPhier SoCs. + +endif diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1c3592914d..c11b551620 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o +obj-$(CONFIG_USB_EHCI_UNIPHIER) += ehci-uniphier.o obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o diff --git a/drivers/usb/host/ehci-rmobile.c b/drivers/usb/host/ehci-rmobile.c index b4330876f8..7fe79efc17 100644 --- a/drivers/usb/host/ehci-rmobile.c +++ b/drivers/usb/host/ehci-rmobile.c @@ -13,18 +13,18 @@ #include "ehci.h" #if defined(CONFIG_R8A7740) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { +static u32 usb_base_address[] = { 0xC6700000 }; #elif defined(CONFIG_R8A7790) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { +static u32 usb_base_address[] = { 0xEE080000, /* USB0 (EHCI) */ 0xEE0A0000, /* USB1 */ 0xEE0C0000, /* USB2 */ }; #elif defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \ defined(CONFIG_R8A7794) -static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = { +static u32 usb_base_address[] = { 0xEE080000, /* USB0 (EHCI) */ 0xEE0C0000, /* USB1 */ }; @@ -53,7 +53,7 @@ int ehci_hcd_stop(int index) if (!i) printf("error : ehci(%d) reset failed.\n", index); - if (index == (CONFIG_USB_MAX_CONTROLLER_COUNT - 1)) + if (index == (ARRAY_SIZE(usb_base_address) - 1)) setbits_le32(SMSTPCR7, SMSTPCR703); return 0; diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 4befd57454..cc9a8fa71e 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -10,16 +10,14 @@ */ #include <asm/arch/clock.h> +#include <asm/arch/cpu.h> #include <asm/gpio.h> #include <asm/io.h> #include <common.h> #include "ehci.h" -#define SUNXI_USB1_IO_BASE 0x01c14000 -#define SUNXI_USB2_IO_BASE 0x01c1c000 - #define SUNXI_USB_PMU_IRQ_ENABLE 0x800 -#define SUNXI_USB_CSR 0x01c13404 +#define SUNXI_USB_CSR 0x404 #define SUNXI_USB_PASSBY_EN 1 #define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10) @@ -32,25 +30,28 @@ static struct sunxi_ehci_hcd { int usb_rst_mask; int ahb_clk_mask; int gpio_vbus; - void *csr; int irq; int id; } sunxi_echi_hcd[] = { { - .usb_rst_mask = CCM_USB_CTRL_PHY1_RST, + .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK, .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0, - .gpio_vbus = CONFIG_SUNXI_USB_VBUS0_GPIO, - .csr = (void *)SUNXI_USB_CSR, +#ifndef CONFIG_MACH_SUN6I .irq = 39, +#else + .irq = 72, +#endif .id = 1, }, #if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) { - .usb_rst_mask = CCM_USB_CTRL_PHY2_RST, + .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1, - .gpio_vbus = CONFIG_SUNXI_USB_VBUS1_GPIO, - .csr = (void *)SUNXI_USB_CSR, +#ifndef CONFIG_MACH_SUN6I .irq = 40, +#else + .irq = 74, +#endif .id = 2, } #endif @@ -60,19 +61,32 @@ static int enabled_hcd_count; static void *get_io_base(int hcd_id) { - if (hcd_id == 1) - return (void *)SUNXI_USB1_IO_BASE; - else if (hcd_id == 2) - return (void *)SUNXI_USB2_IO_BASE; - else + switch (hcd_id) { + case 0: + return (void *)SUNXI_USB0_BASE; + case 1: + return (void *)SUNXI_USB1_BASE; + case 2: + return (void *)SUNXI_USB2_BASE; + default: return NULL; + } +} + +static int get_vbus_gpio(int hcd_id) +{ + switch (hcd_id) { + case 1: return sunxi_name_to_gpio(CONFIG_USB1_VBUS_PIN); + case 2: return sunxi_name_to_gpio(CONFIG_USB2_VBUS_PIN); + } + return -1; } static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci, int addr, int data, int len) { int j = 0, usbc_bit = 0; - void *dest = sunxi_ehci->csr; + void *dest = get_io_base(0) + SUNXI_USB_CSR; usbc_bit = 1 << (sunxi_ehci->id * 2); for (j = 0; j < len; j++) { @@ -105,7 +119,7 @@ static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci) usb_phy_write(sunxi_ehci, 0x20, 0x14, 5); /* threshold adjustment disconnect */ -#ifdef CONFIG_MACH_SUN4I +#if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN6I usb_phy_write(sunxi_ehci, 0x2a, 3, 2); #else usb_phy_write(sunxi_ehci, 0x2a, 2, 2); @@ -138,22 +152,30 @@ static void sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci) setbits_le32(&ccm->usb_clk_cfg, sunxi_ehci->usb_rst_mask); setbits_le32(&ccm->ahb_gate0, sunxi_ehci->ahb_clk_mask); +#ifdef CONFIG_MACH_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, sunxi_ehci->ahb_clk_mask); +#endif sunxi_usb_phy_init(sunxi_ehci); sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN); - gpio_direction_output(sunxi_ehci->gpio_vbus, 1); + if (sunxi_ehci->gpio_vbus != -1) + gpio_direction_output(sunxi_ehci->gpio_vbus, 1); } static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - gpio_direction_output(sunxi_ehci->gpio_vbus, 0); + if (sunxi_ehci->gpio_vbus != -1) + gpio_direction_output(sunxi_ehci->gpio_vbus, 0); sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN); +#ifdef CONFIG_MACH_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, sunxi_ehci->ahb_clk_mask); +#endif clrbits_le32(&ccm->ahb_gate0, sunxi_ehci->ahb_clk_mask); clrbits_le32(&ccm->usb_clk_cfg, sunxi_ehci->usb_rst_mask); } @@ -165,13 +187,17 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct sunxi_ehci_hcd *sunxi_ehci = &sunxi_echi_hcd[index]; int err; + sunxi_ehci->gpio_vbus = get_vbus_gpio(sunxi_ehci->id); + /* enable common PHY only once */ if (index == 0) setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - err = gpio_request(sunxi_ehci->gpio_vbus, "ehci_vbus"); - if (err) - return err; + if (sunxi_ehci->gpio_vbus != -1) { + err = gpio_request(sunxi_ehci->gpio_vbus, "ehci_vbus"); + if (err) + return err; + } sunxi_ehci_enable(sunxi_ehci); @@ -197,9 +223,11 @@ int ehci_hcd_stop(int index) sunxi_ehci_disable(sunxi_ehci); - err = gpio_free(sunxi_ehci->gpio_vbus); - if (err) - return err; + if (sunxi_ehci->gpio_vbus != -1) { + err = gpio_free(sunxi_ehci->gpio_vbus); + if (err) + return err; + } /* disable common PHY only once, for the last enabled hcd */ if (enabled_hcd_count == 1) diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c new file mode 100644 index 0000000000..77f6c9d9d1 --- /dev/null +++ b/drivers/usb/host/ehci-uniphier.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 Panasonic Corporation + * Author: Masahiro Yamada <yamada.m@jp.panasonic.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <usb.h> +#include <asm/arch/ehci-uniphier.h> +#include "ehci.h" + +/* + * Create the appropriate control structures to manage + * a new EHCI host controller. + */ +int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, + struct ehci_hcor **hcor) +{ + struct ehci_hccr *cr; + struct ehci_hcor *or; + + uniphier_ehci_reset(index, 0); + + cr = (struct ehci_hccr *)(uniphier_ehci_platdata[index].base); + or = (void *)cr + HC_LENGTH(ehci_readl(&cr->cr_capbase)); + + *hccr = cr; + *hcor = or; + + return 0; +} + +int ehci_hcd_stop(int index) +{ + uniphier_ehci_reset(index, 1); + + return 0; +} diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 433e703da8..79aecd414e 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -47,9 +47,9 @@ struct ehci_hcor { uint32_t or_usbcmd; #define CMD_PARK (1 << 11) /* enable "park" */ #define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */ -#define CMD_ASE (1 << 5) /* async schedule enable */ #define CMD_LRESET (1 << 7) /* partial reset */ -#define CMD_IAAD (1 << 5) /* "doorbell" interrupt */ +#define CMD_IAAD (1 << 6) /* "doorbell" interrupt */ +#define CMD_ASE (1 << 5) /* async schedule enable */ #define CMD_PSE (1 << 4) /* periodic schedule enable */ #define CMD_RESET (1 << 1) /* reset HC not bus */ #define CMD_RUN (1 << 0) /* start/stop HC */ diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 6aa50cb4f9..a347e13d7d 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1160,10 +1160,19 @@ static void video_putc(struct stdio_dev *dev, const char c) static void video_puts(struct stdio_dev *dev, const char *s) { + int flush = cfb_do_flush_cache; int count = strlen(s); + /* temporarily disable cache flush */ + cfb_do_flush_cache = 0; + while (count--) video_putc(dev, *s++); + + if (flush) { + cfb_do_flush_cache = flush; + flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); + } } /* |