summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2015-05-04 17:50:20 -0400
committerTom Rini <trini@konsulko.com>2015-05-04 17:50:20 -0400
commit622da1c36aee9c39075f2109848228a5737925c0 (patch)
treee08cd8d033fd09e415d603bab26691d776365adb /drivers
parent281239ad9dc2a695a53ab34dda44cdbe31c69122 (diff)
parentfd01ae1384a67c354eb53fc8a4c1e0d519014ae8 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/axp_gpio.c186
-rw-r--r--drivers/gpio/sunxi_gpio.c104
-rw-r--r--drivers/mmc/sunxi_mmc.c10
-rw-r--r--drivers/net/sunxi_emac.c260
-rw-r--r--drivers/power/axp209.c64
-rw-r--r--drivers/power/axp221.c236
-rw-r--r--drivers/usb/host/ehci-sunxi.c46
-rw-r--r--drivers/usb/musb-new/musb_regs.h5
-rw-r--r--drivers/usb/musb-new/musb_uboot.c6
-rw-r--r--drivers/usb/musb-new/sunxi.c43
-rw-r--r--drivers/video/sunxi_display.c29
12 files changed, 543 insertions, 447 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fb40e09020..ba9efe8d54 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -7,6 +7,7 @@
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_DM_GPIO) += gpio-uclass.o
+obj-$(CONFIG_AXP_GPIO) += axp_gpio.o
endif
/* TODO(sjg@chromium.org): Only tegra supports driver model in SPL */
ifdef CONFIG_TEGRA_GPIO
diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
new file mode 100644
index 0000000000..2e97cc39d6
--- /dev/null
+++ b/drivers/gpio/axp_gpio.c
@@ -0,0 +1,186 @@
+/*
+ * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * X-Powers AXP Power Management ICs gpio driver
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pmic_bus.h>
+#include <asm/gpio.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <errno.h>
+
+#ifdef CONFIG_AXP152_POWER
+#include <axp152.h>
+#elif defined CONFIG_AXP209_POWER
+#include <axp209.h>
+#elif defined CONFIG_AXP221_POWER
+#include <axp221.h>
+#else
+#error Unknown AXP model
+#endif
+
+static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
+
+static u8 axp_get_gpio_ctrl_reg(unsigned pin)
+{
+ switch (pin) {
+ case 0: return AXP_GPIO0_CTRL;
+ case 1: return AXP_GPIO1_CTRL;
+#ifdef AXP_GPIO2_CTRL
+ case 2: return AXP_GPIO2_CTRL;
+#endif
+#ifdef AXP_GPIO3_CTRL
+ case 3: return AXP_GPIO3_CTRL;
+#endif
+ }
+ return 0;
+}
+
+static int axp_gpio_direction_input(struct udevice *dev, unsigned pin)
+{
+ u8 reg;
+
+ switch (pin) {
+#ifndef CONFIG_AXP152_POWER /* NA on axp152 */
+ case SUNXI_GPIO_AXP0_VBUS_DETECT:
+ return 0;
+#endif
+ default:
+ reg = axp_get_gpio_ctrl_reg(pin);
+ if (reg == 0)
+ return -EINVAL;
+
+ return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT);
+ }
+}
+
+static int axp_gpio_direction_output(struct udevice *dev, unsigned pin,
+ int val)
+{
+ __maybe_unused int ret;
+ u8 reg;
+
+ switch (pin) {
+#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */
+ case SUNXI_GPIO_AXP0_VBUS_ENABLE:
+ ret = pmic_bus_clrbits(AXP221_MISC_CTRL,
+ AXP221_MISC_CTRL_N_VBUSEN_FUNC);
+ if (ret)
+ return ret;
+
+ return axp_gpio_set_value(dev, pin, val);
+#endif
+ default:
+ reg = axp_get_gpio_ctrl_reg(pin);
+ if (reg == 0)
+ return -EINVAL;
+
+ return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH :
+ AXP_GPIO_CTRL_OUTPUT_LOW);
+ }
+}
+
+static int axp_gpio_get_value(struct udevice *dev, unsigned pin)
+{
+ u8 reg, val, mask;
+ int ret;
+
+ switch (pin) {
+#ifndef CONFIG_AXP152_POWER /* NA on axp152 */
+ case SUNXI_GPIO_AXP0_VBUS_DETECT:
+ ret = pmic_bus_read(AXP_POWER_STATUS, &val);
+ mask = AXP_POWER_STATUS_VBUS_PRESENT;
+ break;
+#endif
+#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */
+ case SUNXI_GPIO_AXP0_VBUS_ENABLE:
+ ret = pmic_bus_read(AXP221_VBUS_IPSOUT, &val);
+ mask = AXP221_VBUS_IPSOUT_DRIVEBUS;
+ break;
+#endif
+ default:
+ reg = axp_get_gpio_ctrl_reg(pin);
+ if (reg == 0)
+ return -EINVAL;
+
+ ret = pmic_bus_read(AXP_GPIO_STATE, &val);
+ mask = 1 << (pin + AXP_GPIO_STATE_OFFSET);
+ }
+ if (ret)
+ return ret;
+
+ return (val & mask) ? 1 : 0;
+}
+
+static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val)
+{
+ u8 reg;
+
+ switch (pin) {
+#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */
+ case SUNXI_GPIO_AXP0_VBUS_ENABLE:
+ if (val)
+ return pmic_bus_setbits(AXP221_VBUS_IPSOUT,
+ AXP221_VBUS_IPSOUT_DRIVEBUS);
+ else
+ return pmic_bus_clrbits(AXP221_VBUS_IPSOUT,
+ AXP221_VBUS_IPSOUT_DRIVEBUS);
+#endif
+ default:
+ reg = axp_get_gpio_ctrl_reg(pin);
+ if (reg == 0)
+ return -EINVAL;
+
+ return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH :
+ AXP_GPIO_CTRL_OUTPUT_LOW);
+ }
+}
+
+static const struct dm_gpio_ops gpio_axp_ops = {
+ .direction_input = axp_gpio_direction_input,
+ .direction_output = axp_gpio_direction_output,
+ .get_value = axp_gpio_get_value,
+ .set_value = axp_gpio_set_value,
+};
+
+static int gpio_axp_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ /* Tell the uclass how many GPIOs we have */
+ uc_priv->bank_name = strdup(SUNXI_GPIO_AXP0_PREFIX);
+ uc_priv->gpio_count = SUNXI_GPIO_AXP0_GPIO_COUNT;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_axp) = {
+ .name = "gpio_axp",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_axp_ops,
+ .probe = gpio_axp_probe,
+};
+
+int axp_gpio_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = pmic_bus_init();
+ if (ret)
+ return ret;
+
+ /* There is no devicetree support for the axp yet, so bind directly */
+ ret = device_bind_driver(dm_root(), "gpio_axp", "AXP-gpio", &dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index cf5c62463e..f9881308f4 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -15,15 +15,10 @@
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
+#include <asm/arch/gpio.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <dm/device-internal.h>
-#ifdef CONFIG_AXP209_POWER
-#include <axp209.h>
-#endif
-#ifdef CONFIG_AXP221_POWER
-#include <axp221.h>
-#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -79,10 +74,6 @@ int gpio_free(unsigned gpio)
int gpio_direction_input(unsigned gpio)
{
-#ifdef AXP_GPIO
- if (gpio >= SUNXI_GPIO_AXP0_START)
- return axp_gpio_direction_input(gpio - SUNXI_GPIO_AXP0_START);
-#endif
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
return 0;
@@ -90,11 +81,6 @@ int gpio_direction_input(unsigned gpio)
int gpio_direction_output(unsigned gpio, int value)
{
-#ifdef AXP_GPIO
- if (gpio >= SUNXI_GPIO_AXP0_START)
- return axp_gpio_direction_output(gpio - SUNXI_GPIO_AXP0_START,
- value);
-#endif
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
return sunxi_gpio_output(gpio, value);
@@ -102,36 +88,14 @@ int gpio_direction_output(unsigned gpio, int value)
int gpio_get_value(unsigned gpio)
{
-#ifdef AXP_GPIO
- if (gpio >= SUNXI_GPIO_AXP0_START)
- return axp_gpio_get_value(gpio - SUNXI_GPIO_AXP0_START);
-#endif
return sunxi_gpio_input(gpio);
}
int gpio_set_value(unsigned gpio, int value)
{
-#ifdef AXP_GPIO
- if (gpio >= SUNXI_GPIO_AXP0_START)
- return axp_gpio_set_value(gpio - SUNXI_GPIO_AXP0_START, value);
-#endif
return sunxi_gpio_output(gpio, value);
}
-int sunxi_name_to_gpio_bank(const char *name)
-{
- int group = 0;
-
- if (*name == 'P' || *name == 'p')
- name++;
- if (*name >= 'A') {
- group = *name - (*name > 'a' ? 'a' : 'A');
- return group;
- }
-
- return -1;
-}
-
int sunxi_name_to_gpio(const char *name)
{
int group = 0;
@@ -139,21 +103,6 @@ int sunxi_name_to_gpio(const char *name)
long pin;
char *eptr;
-#ifdef AXP_GPIO
- if (strncasecmp(name, "AXP0-", 5) == 0) {
- name += 5;
- if (strcmp(name, "VBUS-DETECT") == 0)
- return SUNXI_GPIO_AXP0_START +
- SUNXI_GPIO_AXP0_VBUS_DETECT;
- if (strcmp(name, "VBUS-ENABLE") == 0)
- return SUNXI_GPIO_AXP0_START +
- SUNXI_GPIO_AXP0_VBUS_ENABLE;
- pin = simple_strtol(name, &eptr, 10);
- if (!*name || *eptr)
- return -1;
- return SUNXI_GPIO_AXP0_START + pin;
- }
-#endif
if (*name == 'P' || *name == 'p')
name++;
if (*name >= 'A') {
@@ -171,7 +120,44 @@ int sunxi_name_to_gpio(const char *name)
}
#endif
+int sunxi_name_to_gpio_bank(const char *name)
+{
+ int group = 0;
+
+ if (*name == 'P' || *name == 'p')
+ name++;
+ if (*name >= 'A') {
+ group = *name - (*name > 'a' ? 'a' : 'A');
+ return group;
+ }
+
+ return -1;
+}
+
#ifdef CONFIG_DM_GPIO
+/* TODO(sjg@chromium.org): Remove this function and use device tree */
+int sunxi_name_to_gpio(const char *name)
+{
+ unsigned int gpio;
+ int ret;
+#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
+ char lookup[8];
+
+ if (strcasecmp(name, "AXP0-VBUS-DETECT") == 0) {
+ sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
+ SUNXI_GPIO_AXP0_VBUS_DETECT);
+ name = lookup;
+ } else if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) {
+ sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
+ SUNXI_GPIO_AXP0_VBUS_ENABLE);
+ name = lookup;
+ }
+#endif
+ ret = gpio_lookup_name(name, NULL, NULL, &gpio);
+
+ return ret ? ret : gpio;
+}
+
static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
@@ -249,10 +235,11 @@ static char *gpio_bank_name(int bank)
{
char *name;
- name = malloc(2);
+ name = malloc(3);
if (name) {
- name[0] = 'A' + bank;
- name[1] = '\0';
+ name[0] = 'P';
+ name[1] = 'A' + bank;
+ name[2] = '\0';
}
return name;
@@ -310,7 +297,14 @@ static int gpio_sunxi_bind(struct udevice *parent)
}
static const struct udevice_id sunxi_gpio_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-pinctrl" },
+ { .compatible = "allwinner,sun5i-a10s-pinctrl" },
+ { .compatible = "allwinner,sun5i-a13-pinctrl" },
+ { .compatible = "allwinner,sun6i-a31-pinctrl" },
+ { .compatible = "allwinner,sun6i-a31s-pinctrl" },
{ .compatible = "allwinner,sun7i-a20-pinctrl" },
+ { .compatible = "allwinner,sun8i-a23-pinctrl" },
+ { .compatible = "allwinner,sun9i-a80-pinctrl" },
{ }
};
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 22335452c5..c4300f25fd 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -9,6 +9,7 @@
*/
#include <common.h>
+#include <errno.h>
#include <malloc.h>
#include <mmc.h>
#include <asm/io.h>
@@ -37,7 +38,7 @@ static int sunxi_mmc_getcd_gpio(int sdc_no)
case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN);
case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN);
}
- return -1;
+ return -EINVAL;
}
static int mmc_resource_init(int sdc_no)
@@ -72,7 +73,7 @@ static int mmc_resource_init(int sdc_no)
mmchost->mmc_no = sdc_no;
cd_pin = sunxi_mmc_getcd_gpio(sdc_no);
- if (cd_pin != -1) {
+ if (cd_pin >= 0) {
ret = gpio_request(cd_pin, "mmc_cd");
if (!ret)
ret = gpio_direction_input(cd_pin);
@@ -151,8 +152,7 @@ static int mmc_clk_io_on(int sdc_no)
/* config ahb clock */
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
- defined(CONFIG_MACH_SUN9I)
+#ifdef CONFIG_SUNXI_GEN_SUN6I
/* unassert reset */
setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
#endif
@@ -425,7 +425,7 @@ static int sunxi_mmc_getcd(struct mmc *mmc)
int cd_pin;
cd_pin = sunxi_mmc_getcd_gpio(mmchost->mmc_no);
- if (cd_pin == -1)
+ if (cd_pin < 0)
return 1;
return !gpio_get_value(cd_pin);
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 7b31f8c1da..e939bf2108 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <linux/err.h>
#include <malloc.h>
#include <miiphy.h>
@@ -153,13 +154,16 @@ struct sunxi_sramc_regs {
#define EMAC_CRCERR (0x1 << 4)
#define EMAC_LENERR (0x3 << 5)
-#define DMA_CPU_TRRESHOLD 2000
+#define EMAC_RX_BUFSIZE 2000
struct emac_eth_dev {
- u32 speed;
- u32 duplex;
- u32 phy_configured;
+ struct emac_regs *regs;
+ struct mii_dev *bus;
+ struct phy_device *phydev;
int link_printed;
+#ifdef CONFIG_DM_ETH
+ uchar rx_buf[EMAC_RX_BUFSIZE];
+#endif
};
struct emac_rxhdr {
@@ -195,11 +199,10 @@ static void emac_outblk_32bit(void *reg, void *data, int count)
}
/* Read a word from phyxcer */
-static int emac_phy_read(const char *devname, unsigned char addr,
- unsigned char reg, unsigned short *value)
+static int emac_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
{
- struct eth_device *dev = eth_get_dev_by_name(devname);
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_eth_dev *priv = bus->priv;
+ struct emac_regs *regs = priv->regs;
/* issue the phy address and reg */
writel(addr << 8 | reg, &regs->mac_madr);
@@ -213,18 +216,16 @@ static int emac_phy_read(const char *devname, unsigned char addr,
/* push down the phy io line */
writel(0x0, &regs->mac_mcmd);
- /* and write data */
- *value = readl(&regs->mac_mrdd);
-
- return 0;
+ /* And read data */
+ return readl(&regs->mac_mrdd);
}
/* Write a word to phyxcer */
-static int emac_phy_write(const char *devname, unsigned char addr,
- unsigned char reg, unsigned short value)
+static int emac_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+ u16 value)
{
- struct eth_device *dev = eth_get_dev_by_name(devname);
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_eth_dev *priv = bus->priv;
+ struct emac_regs *regs = priv->regs;
/* issue the phy address and reg */
writel(addr << 8 | reg, &regs->mac_madr);
@@ -244,12 +245,44 @@ static int emac_phy_write(const char *devname, unsigned char addr,
return 0;
}
-static void emac_setup(struct eth_device *dev)
+static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev)
+{
+ int ret, mask = 0xffffffff;
+
+#ifdef CONFIG_PHY_ADDR
+ mask = 1 << CONFIG_PHY_ADDR;
+#endif
+
+ priv->bus = mdio_alloc();
+ if (!priv->bus) {
+ printf("Failed to allocate MDIO bus\n");
+ return -ENOMEM;
+ }
+
+ priv->bus->read = emac_mdio_read;
+ priv->bus->write = emac_mdio_write;
+ priv->bus->priv = priv;
+ strcpy(priv->bus->name, "emac");
+
+ ret = mdio_register(priv->bus);
+ if (ret)
+ return ret;
+
+ priv->phydev = phy_find_by_mask(priv->bus, mask,
+ PHY_INTERFACE_MODE_MII);
+ if (!priv->phydev)
+ return -ENODEV;
+
+ phy_connect_dev(priv->phydev, dev);
+ phy_config(priv->phydev);
+
+ return 0;
+}
+
+static void emac_setup(struct emac_eth_dev *priv)
{
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_regs *regs = priv->regs;
u32 reg_val;
- u16 phy_val;
- u32 duplex_flag;
/* Set up TX */
writel(EMAC_TX_SETUP, &regs->tx_mode);
@@ -262,12 +295,8 @@ static void emac_setup(struct eth_device *dev)
writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
/* Set MAC CTL1 */
- emac_phy_read(dev->name, 1, 0, &phy_val);
- debug("PHY SETUP, reg 0 value: %x\n", phy_val);
- duplex_flag = !!(phy_val & (1 << 8));
-
reg_val = 0;
- if (duplex_flag)
+ if (priv->phydev->duplex == DUPLEX_FULL)
reg_val = (0x1 << 0);
writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
@@ -284,9 +313,9 @@ static void emac_setup(struct eth_device *dev)
writel(EMAC_MAC_MFL, &regs->mac_maxf);
}
-static void emac_reset(struct eth_device *dev)
+static void emac_reset(struct emac_eth_dev *priv)
{
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_regs *regs = priv->regs;
debug("resetting device\n");
@@ -298,11 +327,10 @@ static void emac_reset(struct eth_device *dev)
udelay(200);
}
-static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)
+static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
{
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
- struct emac_eth_dev *priv = dev->priv;
- u16 phy_reg;
+ struct emac_regs *regs = priv->regs;
+ int ret;
/* Init EMAC */
@@ -320,41 +348,44 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)
udelay(1);
/* Set up EMAC */
- emac_setup(dev);
+ emac_setup(priv);
- writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
- dev->enetaddr[2], &regs->mac_a1);
- writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
- dev->enetaddr[5], &regs->mac_a0);
+ writel(enetaddr[0] << 16 | enetaddr[1] << 8 | enetaddr[2],
+ &regs->mac_a1);
+ writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5],
+ &regs->mac_a0);
mdelay(1);
- emac_reset(dev);
+ emac_reset(priv);
/* PHY POWER UP */
- emac_phy_read(dev->name, 1, 0, &phy_reg);
- emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11)));
- mdelay(1);
-
- emac_phy_read(dev->name, 1, 0, &phy_reg);
-
- priv->speed = miiphy_speed(dev->name, 0);
- priv->duplex = miiphy_duplex(dev->name, 0);
+ ret = phy_startup(priv->phydev);
+ if (ret) {
+ printf("Could not initialize PHY %s\n",
+ priv->phydev->dev->name);
+ return ret;
+ }
/* Print link status only once */
if (!priv->link_printed) {
printf("ENET Speed is %d Mbps - %s duplex connection\n",
- priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+ priv->phydev->speed,
+ priv->phydev->duplex ? "FULL" : "HALF");
priv->link_printed = 1;
}
/* Set EMAC SPEED depend on PHY */
- clrsetbits_le32(&regs->mac_supp, 1 << 8,
- ((phy_reg & (0x1 << 13)) >> 13) << 8);
+ if (priv->phydev->speed == SPEED_100)
+ setbits_le32(&regs->mac_supp, 1 << 8);
+ else
+ clrbits_le32(&regs->mac_supp, 1 << 8);
/* Set duplex depend on phy */
- clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
- ((phy_reg & (0x1 << 8)) >> 8) << 0);
+ if (priv->phydev->duplex == DUPLEX_FULL)
+ setbits_le32(&regs->mac_ctl1, 1 << 0);
+ else
+ clrbits_le32(&regs->mac_ctl1, 1 << 0);
/* Enable RX/TX */
setbits_le32(&regs->ctl, 0x7);
@@ -362,14 +393,9 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd)
return 0;
}
-static void sunxi_emac_eth_halt(struct eth_device *dev)
-{
- /* Nothing to do here */
-}
-
-static int sunxi_emac_eth_recv(struct eth_device *dev)
+static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet)
{
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_regs *regs = priv->regs;
struct emac_rxhdr rxhdr;
u32 rxcount;
u32 reg_val;
@@ -387,7 +413,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)
/* Had one stuck? */
rxcount = readl(&regs->rx_fbc);
if (!rxcount)
- return 0;
+ return -EAGAIN;
}
reg_val = readl(&regs->rx_io_data);
@@ -403,7 +429,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)
/* Enable RX */
setbits_le32(&regs->ctl, 0x1 << 2);
- return 0;
+ return -EAGAIN;
}
/* A packet ready now
@@ -433,24 +459,21 @@ static int sunxi_emac_eth_recv(struct eth_device *dev)
/* Move data from EMAC */
if (good_packet) {
- if (rx_len > DMA_CPU_TRRESHOLD) {
+ if (rx_len > EMAC_RX_BUFSIZE) {
printf("Received packet is too big (len=%d)\n", rx_len);
- } else {
- emac_inblk_32bit((void *)&regs->rx_io_data,
- net_rx_packets[0], rx_len);
-
- /* Pass to upper layer */
- net_process_received_packet(net_rx_packets[0], rx_len);
- return rx_len;
+ return -EMSGSIZE;
}
+ emac_inblk_32bit((void *)&regs->rx_io_data, packet, rx_len);
+ return rx_len;
}
- return 0;
+ return -EIO; /* Bad packet */
}
-static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len)
+static int _sunxi_emac_eth_send(struct emac_eth_dev *priv, void *packet,
+ int len)
{
- struct emac_regs *regs = (struct emac_regs *)dev->iobase;
+ struct emac_regs *regs = priv->regs;
/* Select channel 0 */
writel(0, &regs->tx_ins);
@@ -467,31 +490,15 @@ static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len)
return 0;
}
-int sunxi_emac_initialize(void)
+static void sunxi_emac_board_setup(struct emac_eth_dev *priv)
{
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_sramc_regs *sram =
(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
- struct emac_regs *regs =
- (struct emac_regs *)SUNXI_EMAC_BASE;
- struct eth_device *dev;
- struct emac_eth_dev *priv;
+ struct emac_regs *regs = priv->regs;
int pin;
- dev = malloc(sizeof(*dev));
- if (dev == NULL)
- return -ENOMEM;
-
- priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev));
- if (!priv) {
- free(dev);
- return -ENOMEM;
- }
-
- memset(dev, 0, sizeof(*dev));
- memset(priv, 0, sizeof(struct emac_eth_dev));
-
/* Map SRAM to EMAC */
setbits_le32(&sram->ctrl1, 0x5 << 2);
@@ -504,18 +511,77 @@ int sunxi_emac_initialize(void)
/* Set MII clock */
clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
+}
+
+static int sunxi_emac_eth_start(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+
+ return _sunxi_emac_eth_init(dev->priv, pdata->enetaddr);
+}
+
+static int sunxi_emac_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct emac_eth_dev *priv = dev_get_priv(dev);
- dev->iobase = (int)regs;
- dev->priv = priv;
- dev->init = sunxi_emac_eth_init;
- dev->halt = sunxi_emac_eth_halt;
- dev->send = sunxi_emac_eth_send;
- dev->recv = sunxi_emac_eth_recv;
- strcpy(dev->name, "emac");
+ return _sunxi_emac_eth_send(priv, packet, length);
+}
+
+static int sunxi_emac_eth_recv(struct udevice *dev, uchar **packetp)
+{
+ struct emac_eth_dev *priv = dev_get_priv(dev);
+ int rx_len;
- eth_register(dev);
+ rx_len = _sunxi_emac_eth_recv(priv, priv->rx_buf);
+ *packetp = priv->rx_buf;
- miiphy_register(dev->name, emac_phy_read, emac_phy_write);
+ return rx_len;
+}
+
+static void sunxi_emac_eth_stop(struct udevice *dev)
+{
+ /* Nothing to do here */
+}
+
+static int sunxi_emac_eth_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct emac_eth_dev *priv = dev_get_priv(dev);
+
+ priv->regs = (struct emac_regs *)pdata->iobase;
+ sunxi_emac_board_setup(priv);
+
+ return sunxi_emac_init_phy(priv, dev);
+}
+
+static const struct eth_ops sunxi_emac_eth_ops = {
+ .start = sunxi_emac_eth_start,
+ .send = sunxi_emac_eth_send,
+ .recv = sunxi_emac_eth_recv,
+ .stop = sunxi_emac_eth_stop,
+};
+
+static int sunxi_emac_eth_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+
+ pdata->iobase = dev_get_addr(dev);
return 0;
}
+
+static const struct udevice_id sunxi_emac_eth_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-emac" },
+ { }
+};
+
+U_BOOT_DRIVER(eth_sunxi_emac) = {
+ .name = "eth_sunxi_emac",
+ .id = UCLASS_ETH,
+ .of_match = sunxi_emac_eth_ids,
+ .ofdata_to_platdata = sunxi_emac_eth_ofdata_to_platdata,
+ .probe = sunxi_emac_eth_probe,
+ .ops = &sunxi_emac_eth_ops,
+ .priv_auto_alloc_size = sizeof(struct emac_eth_dev),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c
index 1d7be4991a..5161bc1472 100644
--- a/drivers/power/axp209.c
+++ b/drivers/power/axp209.c
@@ -155,67 +155,3 @@ int axp209_power_button(void)
return v & AXP209_IRQ5_PEK_DOWN;
}
-
-static u8 axp209_get_gpio_ctrl_reg(unsigned int pin)
-{
- switch (pin) {
- case 0: return AXP209_GPIO0_CTRL;
- case 1: return AXP209_GPIO1_CTRL;
- case 2: return AXP209_GPIO2_CTRL;
- case 3: return AXP209_GPIO3_CTRL;
- }
- return 0;
-}
-
-int axp_gpio_direction_input(unsigned int pin)
-{
- if (pin == SUNXI_GPIO_AXP0_VBUS_DETECT)
- return 0;
-
- u8 reg = axp209_get_gpio_ctrl_reg(pin);
- /* GPIO3 is "special" */
- u8 val = (pin == 3) ? AXP209_GPIO3_INPUT : AXP209_GPIO_INPUT;
-
- return axp209_write(reg, val);
-}
-
-int axp_gpio_direction_output(unsigned int pin, unsigned int val)
-{
- u8 reg = axp209_get_gpio_ctrl_reg(pin);
-
- if (val) {
- val = (pin == 3) ? AXP209_GPIO3_OUTPUT_HIGH :
- AXP209_GPIO_OUTPUT_HIGH;
- } else {
- val = (pin == 3) ? AXP209_GPIO3_OUTPUT_LOW :
- AXP209_GPIO_OUTPUT_LOW;
- }
-
- return axp209_write(reg, val);
-}
-
-int axp_gpio_get_value(unsigned int pin)
-{
- u8 val, mask;
- int rc;
-
- if (pin == SUNXI_GPIO_AXP0_VBUS_DETECT) {
- rc = axp209_read(AXP209_POWER_STATUS, &val);
- mask = AXP209_POWER_STATUS_VBUS_USABLE;
- } else if (pin == 3) {
- rc = axp209_read(AXP209_GPIO3_CTRL, &val);
- mask = 1;
- } else {
- rc = axp209_read(AXP209_GPIO_STATE, &val);
- mask = 1 << (pin + 4);
- }
- if (rc)
- return rc;
-
- return (val & mask) ? 1 : 0;
-}
-
-int axp_gpio_set_value(unsigned int pin, unsigned int val)
-{
- return axp_gpio_direction_output(pin, val);
-}
diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
index dc3a7f19bd..7bbaec87e4 100644
--- a/drivers/power/axp221.c
+++ b/drivers/power/axp221.c
@@ -12,50 +12,10 @@
#include <common.h>
#include <errno.h>
-#include <asm/arch/p2wi.h>
-#include <asm/arch/rsb.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/pmic_bus.h>
#include <axp221.h>
-/*
- * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
- * used sofar) but uses the rsb bus. These functions abstract this.
- */
-static int pmic_bus_init(void)
-{
-#ifdef CONFIG_MACH_SUN6I
- p2wi_init();
- return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
- AXP221_INIT_DATA);
-#else
- int ret;
-
- ret = rsb_init();
- if (ret)
- return ret;
-
- return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
-#endif
-}
-
-static int pmic_bus_read(const u8 addr, u8 *data)
-{
-#ifdef CONFIG_MACH_SUN6I
- return p2wi_read(addr, data);
-#else
- return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
-#endif
-}
-
-static int pmic_bus_write(const u8 addr, u8 data)
-{
-#ifdef CONFIG_MACH_SUN6I
- return p2wi_write(addr, data);
-#else
- return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
-#endif
-}
-
static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
{
if (mvolt < min)
@@ -66,52 +26,26 @@ static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
return (mvolt - min) / div;
}
-static int axp221_setbits(u8 reg, u8 bits)
-{
- int ret;
- u8 val;
-
- ret = pmic_bus_read(reg, &val);
- if (ret)
- return ret;
-
- val |= bits;
- return pmic_bus_write(reg, val);
-}
-
-static int axp221_clrbits(u8 reg, u8 bits)
-{
- int ret;
- u8 val;
-
- ret = pmic_bus_read(reg, &val);
- if (ret)
- return ret;
-
- val &= ~bits;
- return pmic_bus_write(reg, val);
-}
-
int axp221_set_dcdc1(unsigned int mvolt)
{
int ret;
u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC1_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC1_EN);
ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
if (ret)
return ret;
- ret = axp221_setbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
+ ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC1_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC1_EN);
}
int axp221_set_dcdc2(unsigned int mvolt)
@@ -120,15 +54,15 @@ int axp221_set_dcdc2(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC2_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC2_EN);
ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC2_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC2_EN);
}
int axp221_set_dcdc3(unsigned int mvolt)
@@ -137,15 +71,15 @@ int axp221_set_dcdc3(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC3_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC3_EN);
ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC3_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC3_EN);
}
int axp221_set_dcdc4(unsigned int mvolt)
@@ -154,15 +88,15 @@ int axp221_set_dcdc4(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC4_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC4_EN);
ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC4_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC4_EN);
}
int axp221_set_dcdc5(unsigned int mvolt)
@@ -171,15 +105,15 @@ int axp221_set_dcdc5(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC5_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC5_EN);
ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_DCDC5_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_DCDC5_EN);
}
int axp221_set_dldo1(unsigned int mvolt)
@@ -188,15 +122,15 @@ int axp221_set_dldo1(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO1_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO1_EN);
ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO1_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO1_EN);
}
int axp221_set_dldo2(unsigned int mvolt)
@@ -205,15 +139,15 @@ int axp221_set_dldo2(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO2_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO2_EN);
ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO2_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO2_EN);
}
int axp221_set_dldo3(unsigned int mvolt)
@@ -222,15 +156,15 @@ int axp221_set_dldo3(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO3_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO3_EN);
ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO3_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO3_EN);
}
int axp221_set_dldo4(unsigned int mvolt)
@@ -239,15 +173,15 @@ int axp221_set_dldo4(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO4_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO4_EN);
ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL2,
- AXP221_OUTPUT_CTRL2_DLDO4_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
+ AXP221_OUTPUT_CTRL2_DLDO4_EN);
}
int axp221_set_aldo1(unsigned int mvolt)
@@ -256,15 +190,15 @@ int axp221_set_aldo1(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_ALDO1_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_ALDO1_EN);
ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_ALDO1_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_ALDO1_EN);
}
int axp221_set_aldo2(unsigned int mvolt)
@@ -273,15 +207,15 @@ int axp221_set_aldo2(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_ALDO2_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_ALDO2_EN);
ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL1,
- AXP221_OUTPUT_CTRL1_ALDO2_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
+ AXP221_OUTPUT_CTRL1_ALDO2_EN);
}
int axp221_set_aldo3(unsigned int mvolt)
@@ -290,15 +224,15 @@ int axp221_set_aldo3(unsigned int mvolt)
u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL3,
- AXP221_OUTPUT_CTRL3_ALDO3_EN);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3,
+ AXP221_OUTPUT_CTRL3_ALDO3_EN);
ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL3,
- AXP221_OUTPUT_CTRL3_ALDO3_EN);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL3,
+ AXP221_OUTPUT_CTRL3_ALDO3_EN);
}
int axp221_set_eldo(int eldo_num, unsigned int mvolt)
@@ -325,13 +259,13 @@ int axp221_set_eldo(int eldo_num, unsigned int mvolt)
}
if (mvolt == 0)
- return axp221_clrbits(AXP221_OUTPUT_CTRL2, bits);
+ return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, bits);
ret = pmic_bus_write(addr, cfg);
if (ret)
return ret;
- return axp221_setbits(AXP221_OUTPUT_CTRL2, bits);
+ return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, bits);
}
int axp221_init(void)
@@ -385,67 +319,3 @@ int axp221_get_sid(unsigned int *sid)
return 0;
}
-
-int axp_gpio_direction_input(unsigned int pin)
-{
- switch (pin) {
- case SUNXI_GPIO_AXP0_VBUS_DETECT:
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-int axp_gpio_direction_output(unsigned int pin, unsigned int val)
-{
- int ret;
-
- switch (pin) {
- case SUNXI_GPIO_AXP0_VBUS_ENABLE:
- ret = axp221_clrbits(AXP221_MISC_CTRL,
- AXP221_MISC_CTRL_N_VBUSEN_FUNC);
- if (ret)
- return ret;
-
- return axp_gpio_set_value(pin, val);
- default:
- return -EINVAL;
- }
-}
-
-int axp_gpio_get_value(unsigned int pin)
-{
- int ret;
- u8 val;
-
- switch (pin) {
- case SUNXI_GPIO_AXP0_VBUS_DETECT:
- ret = pmic_bus_read(AXP221_POWER_STATUS, &val);
- if (ret)
- return ret;
-
- return !!(val & AXP221_POWER_STATUS_VBUS_AVAIL);
- default:
- return -EINVAL;
- }
-}
-
-int axp_gpio_set_value(unsigned int pin, unsigned int val)
-{
- int ret;
-
- switch (pin) {
- case SUNXI_GPIO_AXP0_VBUS_ENABLE:
- if (val)
- ret = axp221_setbits(AXP221_VBUS_IPSOUT,
- AXP221_VBUS_IPSOUT_DRIVEBUS);
- else
- ret = axp221_clrbits(AXP221_VBUS_IPSOUT,
- AXP221_VBUS_IPSOUT_DRIVEBUS);
-
- if (ret)
- return ret;
- }
-
- return 0;
-}
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
index eda9f698d9..0edb6438cb 100644
--- a/drivers/usb/host/ehci-sunxi.c
+++ b/drivers/usb/host/ehci-sunxi.c
@@ -1,7 +1,8 @@
/*
- * Copyright (C) 2014 Roman Byshko
+ * Sunxi ehci glue
*
- * Roman Byshko <rbyshko@gmail.com>
+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com>
*
* Based on code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -9,23 +10,32 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#include <asm/arch/usbc.h>
#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/usb_phy.h>
+#include <asm/io.h>
#include "ehci.h"
int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
struct ehci_hcor **hcor)
{
- int err;
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ int ahb_gate_offset;
- err = sunxi_usbc_request_resources(index + 1);
- if (err)
- return err;
+ ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
+ AHB_GATE_OFFSET_USB_EHCI0;
+ setbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset);
+#endif
- sunxi_usbc_enable(index + 1);
- sunxi_usbc_vbus_enable(index + 1);
+ sunxi_usb_phy_init(index + 1);
+ sunxi_usb_phy_power_on(index + 1);
- *hccr = sunxi_usbc_get_io_base(index + 1);
+ if (index == 0)
+ *hccr = (void *)SUNXI_USB1_BASE;
+ else
+ *hccr = (void *)SUNXI_USB2_BASE;
*hcor = (struct ehci_hcor *)((uint32_t) *hccr
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
@@ -39,8 +49,18 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
int ehci_hcd_stop(int index)
{
- sunxi_usbc_vbus_disable(index + 1);
- sunxi_usbc_disable(index + 1);
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ int ahb_gate_offset;
- return sunxi_usbc_free_resources(index + 1);
+ sunxi_usb_phy_power_off(index + 1);
+ sunxi_usb_phy_exit(index + 1);
+
+ ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
+ AHB_GATE_OFFSET_USB_EHCI0;
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ clrbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset);
+#endif
+ clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
+
+ return 0;
}
diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h
index 27e4ed4ec6..90288c4694 100644
--- a/drivers/usb/musb-new/musb_regs.h
+++ b/drivers/usb/musb-new/musb_regs.h
@@ -458,8 +458,13 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
static inline u8 musb_read_configdata(void __iomem *mbase)
{
+#ifdef CONFIG_MACH_SUN8I_A33
+ /* <Sigh> allwinner saves a reg, and we need to hardcode this */
+ return 0xde;
+#else
musb_writeb(mbase, MUSB_INDEX, 0);
return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
+#endif
}
static inline u16 musb_read_hwvers(void __iomem *mbase)
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 7d90ebc1f5..d1ee5f8d06 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -1,7 +1,7 @@
#include <common.h>
#include <watchdog.h>
#ifdef CONFIG_ARCH_SUNXI
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
#endif
#include <asm/errno.h>
#include <linux/usb/ch9.h>
@@ -195,12 +195,12 @@ int usb_reset_root_port(void)
* when clearing reset on low-speed devices, temporary disable
* squelch detection to work around this.
*/
- sunxi_usbc_enable_squelch_detect(0, 0);
+ sunxi_usb_phy_enable_squelch_detect(0, 0);
#endif
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
#ifdef CONFIG_ARCH_SUNXI
- sunxi_usbc_enable_squelch_detect(0, 1);
+ sunxi_usb_phy_enable_squelch_detect(0, 1);
#endif
host->isr(0, host);
host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index c9a6a16b89..e8a3a23aa4 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -22,8 +22,9 @@
*/
#include <common.h>
#include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
#include <asm/arch/gpio.h>
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
#include <asm-generic/gpio.h>
#include "linux-compat.h"
#include "musb_core.h"
@@ -213,43 +214,57 @@ static void sunxi_musb_enable(struct musb *musb)
if (is_host_enabled(musb)) {
/* port power on */
- sunxi_usbc_vbus_enable(0);
+ sunxi_usb_phy_power_on(0);
}
}
static void sunxi_musb_disable(struct musb *musb)
{
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
pr_debug("%s():\n", __func__);
/* Put the controller back in a pristane state for "usb reset" */
if (musb->is_active) {
- sunxi_usbc_disable(0);
- sunxi_usbc_enable(0);
+ sunxi_usb_phy_exit(0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
+ clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+
+ mdelay(10);
+
+ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
+ sunxi_usb_phy_init(0);
musb->is_active = 0;
}
}
static int sunxi_musb_init(struct musb *musb)
{
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
int err;
pr_debug("%s():\n", __func__);
- err = sunxi_usbc_request_resources(0);
- if (err)
- return err;
-
if (is_host_enabled(musb)) {
- err = sunxi_usbc_vbus_detect(0);
+ err = sunxi_usb_phy_vbus_detect(0);
if (err) {
eprintf("Error: A charger is plugged into the OTG\n");
- sunxi_usbc_free_resources(0);
return -EIO;
}
}
musb->isr = sunxi_musb_interrupt;
- sunxi_usbc_enable(0);
+
+ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
+ sunxi_usb_phy_init(0);
USBC_ConfigFIFO_Base();
USBC_EnableDpDmPullUp(musb->mregs);
@@ -273,10 +288,10 @@ static int sunxi_musb_exit(struct musb *musb)
USBC_DisableDpDmPullUp(musb->mregs);
USBC_DisableIdPullUp(musb->mregs);
- sunxi_usbc_vbus_disable(0);
- sunxi_usbc_disable(0);
+ sunxi_usb_phy_power_off(0);
+ sunxi_usb_phy_exit(0);
- return sunxi_usbc_free_resources(0);
+ return 0;
}
const struct musb_platform_ops sunxi_musb_ops = {
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
index d2341b0e36..48dbdf5795 100644
--- a/drivers/video/sunxi_display.c
+++ b/drivers/video/sunxi_display.c
@@ -84,7 +84,7 @@ static int sunxi_hdmi_hpd_detect(int hpd_delay)
CCM_HDMI_CTRL_PLL3);
/* Set ahb gating to pass */
-#ifdef CONFIG_MACH_SUN6I
+#ifdef CONFIG_SUNXI_GEN_SUN6I
setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
#endif
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
@@ -113,7 +113,7 @@ static void sunxi_hdmi_shutdown(void)
clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
-#ifdef CONFIG_MACH_SUN6I
+#ifdef CONFIG_SUNXI_GEN_SUN6I
clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
#endif
clock_set_pll3(0);
@@ -404,7 +404,7 @@ static void sunxi_composer_init(void)
sunxi_frontend_init();
-#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+#ifdef CONFIG_SUNXI_GEN_SUN6I
/* Reset off */
setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
#endif
@@ -549,7 +549,7 @@ static void sunxi_lcdc_init(void)
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
/* Reset off */
-#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+#ifdef CONFIG_SUNXI_GEN_SUN6I
setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
#else
setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
@@ -600,19 +600,19 @@ static void sunxi_lcdc_panel_enable(void)
* white while the lcd inits.
*/
pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
- if (pin != -1) {
+ if (pin >= 0) {
gpio_request(pin, "lcd_backlight_enable");
gpio_direction_output(pin, 0);
}
pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
- if (pin != -1) {
+ if (pin >= 0) {
gpio_request(pin, "lcd_backlight_pwm");
gpio_direction_output(pin, PWM_OFF);
}
reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
- if (reset_pin != -1) {
+ if (reset_pin >= 0) {
gpio_request(reset_pin, "lcd_reset");
gpio_direction_output(reset_pin, 0); /* Assert reset */
}
@@ -620,12 +620,12 @@ static void sunxi_lcdc_panel_enable(void)
/* Give the backlight some time to turn off and power up the panel. */
mdelay(40);
pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
- if (pin != -1) {
+ if (pin >= 0) {
gpio_request(pin, "lcd_power");
gpio_direction_output(pin, 1);
}
- if (reset_pin != -1)
+ if (reset_pin >= 0)
gpio_direction_output(reset_pin, 1); /* De-assert reset */
}
@@ -640,11 +640,11 @@ static void sunxi_lcdc_backlight_enable(void)
mdelay(40);
pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
- if (pin != -1)
+ if (pin >= 0)
gpio_direction_output(pin, 1);
pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
- if (pin != -1)
+ if (pin >= 0)
gpio_direction_output(pin, PWM_ON);
}
@@ -942,11 +942,14 @@ static void sunxi_vga_enable(void)
static void sunxi_drc_init(void)
{
-#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
+#ifdef CONFIG_SUNXI_GEN_SUN6I
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
/* On sun6i the drc must be clocked even when in pass-through mode */
+#ifdef CONFIG_MACH_SUN8I_A33
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
+#endif
setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
#endif
@@ -958,7 +961,7 @@ static void sunxi_vga_external_dac_enable(void)
int pin;
pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
- if (pin != -1) {
+ if (pin >= 0) {
gpio_request(pin, "vga_enable");
gpio_direction_output(pin, 1);
}