diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-07-28 10:12:45 +0200 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-07-28 10:12:45 +0200 |
commit | 740f41d3cbefe2068247852220226c2c3b287249 (patch) | |
tree | a8afb3f0e3f0b7d4574cbbfd2e8d780db6b4ae08 /drivers | |
parent | f2c8d7f591e28d3437155c7a6eae8c8d9e3fe552 (diff) | |
parent | 7c48b015100eeff0e1bbb766394f7beca23afb48 (diff) | |
download | u-boot-740f41d3cbefe2068247852220226c2c3b287249.tar.gz |
Merge branch 'u-boot-sunxi/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/sunxi_gpio.c | 102 | ||||
-rw-r--r-- | drivers/i2c/Makefile | 2 | ||||
-rw-r--r-- | drivers/i2c/mvtwsi.c | 88 | ||||
-rw-r--r-- | drivers/mmc/sunxi_mmc.c | 141 | ||||
-rw-r--r-- | drivers/net/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/sunxi_emac.c (renamed from drivers/net/sunxi_wemac.c) | 140 | ||||
-rw-r--r-- | drivers/power/Makefile | 2 | ||||
-rw-r--r-- | drivers/power/axp152.c | 97 | ||||
-rw-r--r-- | drivers/power/axp209.c | 167 |
10 files changed, 496 insertions, 246 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fb8dcd916b..aa11f15423 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -36,3 +36,4 @@ obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o obj-$(CONFIG_TCA642X) += tca642x.o oby-$(CONFIG_SX151X) += sx151x.o +obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c new file mode 100644 index 0000000000..0c50a8f332 --- /dev/null +++ b/drivers/gpio/sunxi_gpio.c @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net> + * + * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c: + * + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/gpio.h> + +static int sunxi_gpio_output(u32 pin, u32 val) +{ + u32 dat; + u32 bank = GPIO_BANK(pin); + u32 num = GPIO_NUM(pin); + struct sunxi_gpio *pio = BANK_TO_GPIO(bank); + + dat = readl(&pio->dat); + if (val) + dat |= 0x1 << num; + else + dat &= ~(0x1 << num); + + writel(dat, &pio->dat); + + return 0; +} + +static int sunxi_gpio_input(u32 pin) +{ + u32 dat; + u32 bank = GPIO_BANK(pin); + u32 num = GPIO_NUM(pin); + struct sunxi_gpio *pio = BANK_TO_GPIO(bank); + + dat = readl(&pio->dat); + dat >>= num; + + return dat & 0x1; +} + +int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT); + + return sunxi_gpio_input(gpio); +} + +int gpio_direction_output(unsigned gpio, int value) +{ + sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT); + + return sunxi_gpio_output(gpio, value); +} + +int gpio_get_value(unsigned gpio) +{ + return sunxi_gpio_input(gpio); +} + +int gpio_set_value(unsigned gpio, int value) +{ + return sunxi_gpio_output(gpio, value); +} + +int sunxi_name_to_gpio(const char *name) +{ + int group = 0; + int groupsize = 9 * 32; + long pin; + char *eptr; + if (*name == 'P' || *name == 'p') + name++; + if (*name >= 'A') { + group = *name - (*name > 'a' ? 'a' : 'A'); + groupsize = 32; + name++; + } + + pin = simple_strtol(name, &eptr, 10); + if (!*name || *eptr) + return -1; + if (pin < 0 || pin > groupsize || group >= 9) + return -1; + return group * 32 + pin; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 96bd45d853..416ea4f2c8 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o obj-$(CONFIG_DW_I2C) += designware_i2c.o -obj-$(CONFIG_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_I2C_MV) += mv_i2c.o obj-$(CONFIG_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o @@ -20,6 +19,7 @@ obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o +obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 5ba0e03862..ab3ffa0fc1 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -22,6 +22,8 @@ #include <asm/arch/orion5x.h> #elif defined(CONFIG_KIRKWOOD) #include <asm/arch/kirkwood.h> +#elif defined(CONFIG_SUNXI) +#include <asm/arch/i2c.h> #else #error Driver mvtwsi not supported by SoC or board #endif @@ -30,6 +32,20 @@ * TWSI register structure */ +#ifdef CONFIG_SUNXI + +struct mvtwsi_registers { + u32 slave_address; + u32 xtnd_slave_addr; + u32 data; + u32 control; + u32 status; + u32 baudrate; + u32 soft_reset; +}; + +#else + struct mvtwsi_registers { u32 slave_address; u32 data; @@ -43,6 +59,8 @@ struct mvtwsi_registers { u32 soft_reset; }; +#endif + /* * Control register fields */ @@ -220,11 +238,10 @@ static int twsi_stop(int status) /* * Reset controller. - * Called at end of i2c_init unsuccessful i2c transactions. * Controller reset also resets the baud rate and slave address, so - * re-establish them. + * they must be re-established afterwards. */ -static void twsi_reset(u8 baud_rate, u8 slave_address) +static void twsi_reset(struct i2c_adapter *adap) { /* ensure controller will be enabled by any twsi*() function */ twsi_control_flags = MVTWSI_CONTROL_TWSIEN; @@ -232,23 +249,17 @@ static void twsi_reset(u8 baud_rate, u8 slave_address) writel(0, &twsi->soft_reset); /* wait 2 ms -- this is what the Marvell LSP does */ udelay(20000); - /* set baud rate */ - writel(baud_rate, &twsi->baudrate); - /* set slave address even though we don't use it */ - writel(slave_address, &twsi->slave_address); - writel(0, &twsi->xtnd_slave_addr); - /* assert STOP but don't care for the result */ - (void) twsi_stop(0); } /* * I2C init called by cmd_i2c when doing 'i2c reset'. * Sets baud to the highest possible value not exceeding requested one. */ -void i2c_init(int requested_speed, int slaveadd) +static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int requested_speed) { - int tmp_speed, highest_speed, n, m; - int baud = 0x44; /* baudrate at controller reset */ + unsigned int tmp_speed, highest_speed, n, m; + unsigned int baud = 0x44; /* baudrate at controller reset */ /* use actual speed to collect progressively higher values */ highest_speed = 0; @@ -263,8 +274,21 @@ void i2c_init(int requested_speed, int slaveadd) } } } + writel(baud, &twsi->baudrate); + return 0; +} + +static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ /* reset controller */ - twsi_reset(baud, slaveadd); + twsi_reset(adap); + /* set speed */ + twsi_i2c_set_bus_speed(adap, speed); + /* set slave address even though we don't use it */ + writel(slaveadd, &twsi->slave_address); + writel(0, &twsi->xtnd_slave_addr); + /* assert STOP but don't care for the result */ + (void) twsi_stop(0); } /* @@ -294,7 +318,7 @@ static int i2c_begin(int expected_start_status, u8 addr) * I2C probe called by cmd_i2c when doing 'i2c probe'. * Begin read, nak data byte, end. */ -int i2c_probe(uchar chip) +static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip) { u8 dummy_byte; int status; @@ -320,12 +344,13 @@ int i2c_probe(uchar chip) * cmd_eeprom, so we have to choose here, and for the moment that'll be * a repeated start without a preceding stop. */ -int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the address bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -333,7 +358,7 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) /* begin i2c read to receive eeprom data bytes */ if (status == 0) status = i2c_begin( - MVTWSI_STATUS_REPEATED_START, (dev << 1) | 1); + MVTWSI_STATUS_REPEATED_START, (chip << 1) | 1); /* prepare ACK if at least one byte must be received */ if (length > 0) twsi_control_flags |= MVTWSI_CONTROL_ACK; @@ -355,12 +380,13 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c * Begin write, send address byte(s), send data bytes, end. */ -int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the eeprom adress bytes then data bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -374,21 +400,7 @@ int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) return status; } -/* - * Bus set routine: we only support bus 0. - */ -int i2c_set_bus_num(unsigned int bus) -{ - if (bus > 0) { - return -1; - } - return 0; -} - -/* - * Bus get routine: hard-return bus 0. - */ -unsigned int i2c_get_bus_num(void) -{ - return 0; -} +U_BOOT_I2C_ADAP_COMPLETE(twsi0, twsi_i2c_init, twsi_i2c_probe, + twsi_i2c_read, twsi_i2c_write, + twsi_i2c_set_bus_speed, + CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0) diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index eb7b1158d6..d4e574fe19 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -16,28 +16,6 @@ #include <asm/arch/cpu.h> #include <asm/arch/mmc.h> -struct sunxi_mmc_des { - u32 reserved1_1:1; - u32 dic:1; /* disable interrupt on completion */ - u32 last_des:1; /* 1-this data buffer is the last buffer */ - u32 first_des:1; /* 1-data buffer is the first buffer, - 0-data buffer contained in the next - descriptor is 1st buffer */ - u32 des_chain:1; /* 1-the 2nd address in the descriptor is the - next descriptor address */ - u32 end_of_ring:1; /* 1-last descriptor flag when using dual - data buffer in descriptor */ - u32 reserved1_2:24; - u32 card_err_sum:1; /* transfer error flag */ - u32 own:1; /* des owner:1-idma owns it, 0-host owns it */ -#define SDXC_DES_NUM_SHIFT 16 -#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) - u32 data_buf1_sz:16; - u32 data_buf2_sz:16; - u32 buf_addr_ptr1; - u32 buf_addr_ptr2; -}; - struct sunxi_mmc_host { unsigned mmc_no; uint32_t *mclkreg; @@ -189,6 +167,7 @@ static int mmc_core_init(struct mmc *mmc) /* Reset controller */ writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl); + udelay(1000); return 0; } @@ -204,6 +183,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) unsigned timeout_msecs = 2000; unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); + /* Always read / write data through the CPU */ + setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); + for (i = 0; i < (byte_cnt >> 2); i++) { while (readl(&mmchost->reg->status) & status_bit) { if (!timeout_msecs--) @@ -220,85 +202,6 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) return 0; } -static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data) -{ - struct sunxi_mmc_host *mmchost = mmc->priv; - unsigned byte_cnt = data->blocksize * data->blocks; - unsigned char *buff; - unsigned des_idx = 0; - unsigned buff_frag_num = - (byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT; - unsigned remain; - unsigned i, rval; - ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num); - - buff = data->flags & MMC_DATA_READ ? - (unsigned char *)data->dest : (unsigned char *)data->src; - remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1); - - flush_cache((unsigned long)buff, (unsigned long)byte_cnt); - for (i = 0; i < buff_frag_num; i++, des_idx++) { - memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des)); - pdes[des_idx].des_chain = 1; - pdes[des_idx].own = 1; - pdes[des_idx].dic = 1; - if (buff_frag_num > 1 && i != buff_frag_num - 1) - pdes[des_idx].data_buf1_sz = 0; /* 0 == max_len */ - else - pdes[des_idx].data_buf1_sz = remain; - - pdes[des_idx].buf_addr_ptr1 = - (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN; - if (i == 0) - pdes[des_idx].first_des = 1; - - if (i == buff_frag_num - 1) { - pdes[des_idx].dic = 0; - pdes[des_idx].last_des = 1; - pdes[des_idx].end_of_ring = 1; - pdes[des_idx].buf_addr_ptr2 = 0; - } else { - pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1]; - } - } - flush_cache((unsigned long)pdes, - sizeof(struct sunxi_mmc_des) * (des_idx + 1)); - - rval = readl(&mmchost->reg->gctrl); - /* Enable DMA */ - writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE, - &mmchost->reg->gctrl); - /* Reset iDMA */ - writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac); - /* Enable iDMA */ - writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE, - &mmchost->reg->dmac); - rval = readl(&mmchost->reg->idie) & - ~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ); - if (data->flags & MMC_DATA_WRITE) - rval |= SUNXI_MMC_IDIE_TXIRQ; - else - rval |= SUNXI_MMC_IDIE_RXIRQ; - writel(rval, &mmchost->reg->idie); - writel((u32) pdes, &mmchost->reg->dlba); - writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3), - &mmchost->reg->ftrglevel); - - return 0; -} - -static void mmc_enable_dma_accesses(struct mmc *mmc, int dma) -{ - struct sunxi_mmc_host *mmchost = mmc->priv; - - unsigned int gctrl = readl(&mmchost->reg->gctrl); - if (dma) - gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB; - else - gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB; - writel(gctrl, &mmchost->reg->gctrl); -} - static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs, unsigned int done_bit, const char *what) { @@ -327,7 +230,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, unsigned int timeout_msecs; int error = 0; unsigned int status = 0; - unsigned int usedma = 0; unsigned int bytecnt = 0; if (mmchost->fatal_err) @@ -378,20 +280,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, bytecnt = data->blocksize * data->blocks; debug("trans data %d bytes\n", bytecnt); -#if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD) - if (bytecnt > 64) { -#else - if (0) { -#endif - usedma = 1; - mmc_enable_dma_accesses(mmc, 1); - ret = mmc_trans_data_by_dma(mmc, data); - writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); - } else { - mmc_enable_dma_accesses(mmc, 0); - writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); - ret = mmc_trans_data_by_cpu(mmc, data); - } + writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); + ret = mmc_trans_data_by_cpu(mmc, data); if (ret) { error = readl(&mmchost->reg->rint) & \ SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT; @@ -405,7 +295,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, goto out; if (data) { - timeout_msecs = usedma ? 120 * bytecnt : 120; + timeout_msecs = 120; debug("cacl timeout %x msec\n", timeout_msecs); error = mmc_rint_wait(mmc, timeout_msecs, data->blocks > 1 ? @@ -442,23 +332,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, debug("mmc resp 0x%08x\n", cmd->response[0]); } out: - if (data && usedma) { - /* IDMASTAREG - * IDST[0] : idma tx int - * IDST[1] : idma rx int - * IDST[2] : idma fatal bus error - * IDST[4] : idma descriptor invalid - * IDST[5] : idma error summary - * IDST[8] : idma normal interrupt sumary - * IDST[9] : idma abnormal interrupt sumary - */ - status = readl(&mmchost->reg->idst); - writel(status, &mmchost->reg->idst); - writel(0, &mmchost->reg->idie); - writel(0, &mmchost->reg->dmac); - writel(readl(&mmchost->reg->gctrl) & ~SUNXI_MMC_GCTRL_DMA_ENABLE, - &mmchost->reg->gctrl); - } if (error < 0) { writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl); mmc_update_clk(mmc); diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6226cb259f..7cc6b6fc08 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o +obj-$(CONFIG_SUNXI_EMAC) += sunxi_emac.o obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_EP93XX) += ep93xx_eth.o obj-$(CONFIG_ETHOC) += ethoc.o @@ -51,7 +52,6 @@ obj-$(CONFIG_RTL8169) += rtl8169.o obj-$(CONFIG_SH_ETHER) += sh_eth.o obj-$(CONFIG_SMC91111) += smc91111.o obj-$(CONFIG_SMC911X) += smc911x.o -obj-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o diff --git a/drivers/net/sunxi_wemac.c b/drivers/net/sunxi_emac.c index 699a381582..5a06d68af7 100644 --- a/drivers/net/sunxi_wemac.c +++ b/drivers/net/sunxi_emac.c @@ -1,5 +1,5 @@ /* - * sunxi_wemac.c -- Allwinner A10 ethernet driver + * sunxi_emac.c -- Allwinner A10 ethernet driver * * (C) Copyright 2012, Stefan Roese <sr@denx.de> * @@ -7,16 +7,16 @@ */ #include <common.h> +#include <linux/err.h> #include <malloc.h> -#include <net.h> #include <miiphy.h> -#include <linux/err.h> +#include <net.h> #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> /* EMAC register */ -struct wemac_regs { +struct emac_regs { u32 ctl; /* 0x00 */ u32 tx_mode; /* 0x04 */ u32 tx_flow; /* 0x08 */ @@ -27,7 +27,7 @@ struct wemac_regs { u32 tx_pl1; /* 0x1c */ u32 tx_sta; /* 0x20 */ u32 tx_io_data; /* 0x24 */ - u32 tx_io_data1; /* 0x28 */ + u32 tx_io_data1;/* 0x28 */ u32 tx_tsvl0; /* 0x2c */ u32 tx_tsvh0; /* 0x30 */ u32 tx_tsvl1; /* 0x34 */ @@ -141,33 +141,33 @@ struct sunxi_sramc_regs { #define EMAC_MAC_IPGT 0x15 -#define EMAC_MAC_NBTB_IPG1 0xC +#define EMAC_MAC_NBTB_IPG1 0xc #define EMAC_MAC_NBTB_IPG2 0x12 #define EMAC_MAC_CW 0x37 -#define EMAC_MAC_RM 0xF +#define EMAC_MAC_RM 0xf #define EMAC_MAC_MFL 0x0600 /* Receive status */ -#define EMAC_CRCERR (1 << 4) -#define EMAC_LENERR (3 << 5) +#define EMAC_CRCERR (0x1 << 4) +#define EMAC_LENERR (0x3 << 5) #define DMA_CPU_TRRESHOLD 2000 -struct wemac_eth_dev { +struct emac_eth_dev { u32 speed; u32 duplex; u32 phy_configured; int link_printed; }; -struct wemac_rxhdr { +struct emac_rxhdr { s16 rx_len; u16 rx_status; }; -static void wemac_inblk_32bit(void *reg, void *data, int count) +static void emac_inblk_32bit(void *reg, void *data, int count) { int cnt = (count + 3) >> 2; @@ -181,7 +181,7 @@ static void wemac_inblk_32bit(void *reg, void *data, int count) } } -static void wemac_outblk_32bit(void *reg, void *data, int count) +static void emac_outblk_32bit(void *reg, void *data, int count) { int cnt = (count + 3) >> 2; @@ -194,14 +194,12 @@ static void wemac_outblk_32bit(void *reg, void *data, int count) } } -/* - * Read a word from phyxcer - */ -static int wemac_phy_read(const char *devname, unsigned char addr, +/* Read a word from phyxcer */ +static int emac_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { struct eth_device *dev = eth_get_dev_by_name(devname); - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -221,14 +219,12 @@ static int wemac_phy_read(const char *devname, unsigned char addr, return 0; } -/* - * Write a word to phyxcer - */ -static int wemac_phy_write(const char *devname, unsigned char addr, +/* Write a word to phyxcer */ +static int emac_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value) { struct eth_device *dev = eth_get_dev_by_name(devname); - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -250,7 +246,7 @@ static int wemac_phy_write(const char *devname, unsigned char addr, static void emac_setup(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; u32 reg_val; u16 phy_val; u32 duplex_flag; @@ -266,7 +262,7 @@ static void emac_setup(struct eth_device *dev) writel(EMAC_MAC_CTL0_SETUP, ®s->mac_ctl0); /* Set MAC CTL1 */ - wemac_phy_read(dev->name, 1, 0, &phy_val); + 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)); @@ -288,9 +284,9 @@ static void emac_setup(struct eth_device *dev) writel(EMAC_MAC_MFL, ®s->mac_maxf); } -static void wemac_reset(struct eth_device *dev) +static void emac_reset(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; debug("resetting device\n"); @@ -302,10 +298,10 @@ static void wemac_reset(struct eth_device *dev) udelay(200); } -static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) +static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; - struct wemac_eth_dev *priv = dev->priv; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_eth_dev *priv = dev->priv; u16 phy_reg; /* Init EMAC */ @@ -317,10 +313,7 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) /* Init MAC */ /* Soft reset MAC */ - clrbits_le32(®s->mac_ctl0, 1 << 15); - - /* Set MII clock */ - clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); + clrbits_le32(®s->mac_ctl0, 0x1 << 15); /* Clear RX counter */ writel(0x0, ®s->rx_fbc); @@ -336,14 +329,14 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) mdelay(1); - wemac_reset(dev); + emac_reset(dev); /* PHY POWER UP */ - wemac_phy_read(dev->name, 1, 0, &phy_reg); - wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11))); + emac_phy_read(dev->name, 1, 0, &phy_reg); + emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11))); mdelay(1); - wemac_phy_read(dev->name, 1, 0, &phy_reg); + emac_phy_read(dev->name, 1, 0, &phy_reg); priv->speed = miiphy_speed(dev->name, 0); priv->duplex = miiphy_duplex(dev->name, 0); @@ -357,11 +350,11 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) /* Set EMAC SPEED depend on PHY */ clrsetbits_le32(®s->mac_supp, 1 << 8, - ((phy_reg & (1 << 13)) >> 13) << 8); + ((phy_reg & (0x1 << 13)) >> 13) << 8); /* Set duplex depend on phy */ clrsetbits_le32(®s->mac_ctl1, 1 << 0, - ((phy_reg & (1 << 8)) >> 8) << 0); + ((phy_reg & (0x1 << 8)) >> 8) << 0); /* Enable RX/TX */ setbits_le32(®s->ctl, 0x7); @@ -369,15 +362,15 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) return 0; } -static void sunxi_wemac_eth_halt(struct eth_device *dev) +static void sunxi_emac_eth_halt(struct eth_device *dev) { /* Nothing to do here */ } -static int sunxi_wemac_eth_recv(struct eth_device *dev) +static int sunxi_emac_eth_recv(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; - struct wemac_rxhdr rxhdr; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_rxhdr rxhdr; u32 rxcount; u32 reg_val; int rx_len; @@ -386,8 +379,7 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) /* Check packet ready or not */ - /* - * Race warning: The first packet might arrive with + /* Race warning: The first packet might arrive with * the interrupts disabled, but the second will fix */ rxcount = readl(®s->rx_fbc); @@ -401,26 +393,25 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) reg_val = readl(®s->rx_io_data); if (reg_val != 0x0143414d) { /* Disable RX */ - clrbits_le32(®s->ctl, 1 << 2); + clrbits_le32(®s->ctl, 0x1 << 2); /* Flush RX FIFO */ - setbits_le32(®s->rx_ctl, 1 << 3); - while (readl(®s->rx_ctl) & (1 << 3)) + setbits_le32(®s->rx_ctl, 0x1 << 3); + while (readl(®s->rx_ctl) & (0x1 << 3)) ; /* Enable RX */ - setbits_le32(®s->ctl, 1 << 2); + setbits_le32(®s->ctl, 0x1 << 2); return 0; } - /* - * A packet ready now + /* A packet ready now * Get status/length */ good_packet = 1; - wemac_inblk_32bit(®s->rx_io_data, &rxhdr, sizeof(rxhdr)); + emac_inblk_32bit(®s->rx_io_data, &rxhdr, sizeof(rxhdr)); rx_len = rxhdr.rx_len; rx_status = rxhdr.rx_status; @@ -440,13 +431,13 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) printf("length error\n"); } - /* Move data from WEMAC */ + /* Move data from EMAC */ if (good_packet) { if (rx_len > DMA_CPU_TRRESHOLD) { printf("Received packet is too big (len=%d)\n", rx_len); } else { - wemac_inblk_32bit((void *)®s->rx_io_data, - NetRxPackets[0], rx_len); + emac_inblk_32bit((void *)®s->rx_io_data, + NetRxPackets[0], rx_len); /* Pass to upper layer */ NetReceive(NetRxPackets[0], rx_len); @@ -457,15 +448,15 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) return 0; } -static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len) +static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* Select channel 0 */ writel(0, ®s->tx_ins); /* Write packet */ - wemac_outblk_32bit((void *)®s->tx_io_data, packet, len); + emac_outblk_32bit((void *)®s->tx_io_data, packet, len); /* Set TX len */ writel(len, ®s->tx_pl0); @@ -476,50 +467,55 @@ static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len) return 0; } -int sunxi_wemac_initialize(void) +int sunxi_emac_initialize(void) { 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 wemac_eth_dev *priv; + struct emac_eth_dev *priv; int pin; dev = malloc(sizeof(*dev)); if (dev == NULL) return -ENOMEM; - priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev)); + 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 wemac_eth_dev)); + memset(priv, 0, sizeof(struct emac_eth_dev)); /* Map SRAM to EMAC */ setbits_le32(&sram->ctrl1, 0x5 << 2); /* Configure pin mux settings for MII Ethernet */ for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++) - sunxi_gpio_set_cfgpin(pin, 2); + sunxi_gpio_set_cfgpin(pin, SUNXI_GPA0_EMAC); /* Set up clock gating */ - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC); + setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC); + + /* Set MII clock */ + clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); - dev->iobase = SUNXI_EMAC_BASE; + dev->iobase = (int)regs; dev->priv = priv; - dev->init = sunxi_wemac_eth_init; - dev->halt = sunxi_wemac_eth_halt; - dev->send = sunxi_wemac_eth_send; - dev->recv = sunxi_wemac_eth_recv; - strcpy(dev->name, "wemac"); + 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"); eth_register(dev); - miiphy_register(dev->name, wemac_phy_read, wemac_phy_write); + miiphy_register(dev->name, emac_phy_read, emac_phy_write); return 0; } diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 53ff97d745..dc64e4d32b 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_AXP152_POWER) += axp152.o +obj-$(CONFIG_AXP209_POWER) += axp209.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/axp152.c b/drivers/power/axp152.c new file mode 100644 index 0000000000..fa4ea050a5 --- /dev/null +++ b/drivers/power/axp152.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2012 + * Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <i2c.h> +#include <axp152.h> + +enum axp152_reg { + AXP152_CHIP_VERSION = 0x3, + AXP152_DCDC2_VOLTAGE = 0x23, + AXP152_DCDC3_VOLTAGE = 0x27, + AXP152_DCDC4_VOLTAGE = 0x2B, + AXP152_LDO2_VOLTAGE = 0x2A, + AXP152_SHUTDOWN = 0x32, +}; + +#define AXP152_POWEROFF (1 << 7) + +static int axp152_write(enum axp152_reg reg, u8 val) +{ + return i2c_write(0x30, reg, 1, &val, 1); +} + +static int axp152_read(enum axp152_reg reg, u8 *val) +{ + return i2c_read(0x30, reg, 1, val, 1); +} + +static u8 axp152_mvolt_to_target(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp152_set_dcdc2(int mvolt) +{ + int rc; + u8 current, target; + + target = axp152_mvolt_to_target(mvolt, 700, 2275, 25); + + /* Do we really need to be this gentle? It has built-in voltage slope */ + while ((rc = axp152_read(AXP152_DCDC2_VOLTAGE, ¤t)) == 0 && + current != target) { + if (current < target) + current++; + else + current--; + rc = axp152_write(AXP152_DCDC2_VOLTAGE, current); + if (rc) + break; + } + return rc; +} + +int axp152_set_dcdc3(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25); + + return axp152_write(AXP152_DCDC3_VOLTAGE, target); +} + +int axp152_set_dcdc4(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25); + + return axp152_write(AXP152_DCDC4_VOLTAGE, target); +} + +int axp152_set_ldo2(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 100); + + return axp152_write(AXP152_LDO2_VOLTAGE, target); +} + +int axp152_init(void) +{ + u8 ver; + int rc; + + rc = axp152_read(AXP152_CHIP_VERSION, &ver); + if (rc) + return rc; + + if (ver != 0x05) + return -1; + + return 0; +} diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c new file mode 100644 index 0000000000..9798e5bf7c --- /dev/null +++ b/drivers/power/axp209.c @@ -0,0 +1,167 @@ +/* + * (C) Copyright 2012 + * Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <axp209.h> + +enum axp209_reg { + AXP209_POWER_STATUS = 0x00, + AXP209_CHIP_VERSION = 0x03, + AXP209_DCDC2_VOLTAGE = 0x23, + AXP209_DCDC3_VOLTAGE = 0x27, + AXP209_LDO24_VOLTAGE = 0x28, + AXP209_LDO3_VOLTAGE = 0x29, + AXP209_IRQ_STATUS5 = 0x4c, + AXP209_SHUTDOWN = 0x32, +}; + +#define AXP209_POWER_STATUS_ON_BY_DC (1 << 0) + +#define AXP209_IRQ5_PEK_UP (1 << 6) +#define AXP209_IRQ5_PEK_DOWN (1 << 5) + +#define AXP209_POWEROFF (1 << 7) + +static int axp209_write(enum axp209_reg reg, u8 val) +{ + return i2c_write(0x34, reg, 1, &val, 1); +} + +static int axp209_read(enum axp209_reg reg, u8 *val) +{ + return i2c_read(0x34, reg, 1, val, 1); +} + +static u8 axp209_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; +} + +int axp209_set_dcdc2(int mvolt) +{ + int rc; + u8 cfg, current; + + cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); + + /* Do we really need to be this gentle? It has built-in voltage slope */ + while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, ¤t)) == 0 && + current != cfg) { + if (current < cfg) + current++; + else + current--; + + rc = axp209_write(AXP209_DCDC2_VOLTAGE, current); + if (rc) + break; + } + + return rc; +} + +int axp209_set_dcdc3(int mvolt) +{ + u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); + + return axp209_write(AXP209_DCDC3_VOLTAGE, cfg); +} + +int axp209_set_ldo2(int mvolt) +{ + int rc; + u8 cfg, reg; + + cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100); + + rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); + if (rc) + return rc; + + /* LDO2 configuration is in upper 4 bits */ + reg = (reg & 0x0f) | (cfg << 4); + return axp209_write(AXP209_LDO24_VOLTAGE, reg); +} + +int axp209_set_ldo3(int mvolt) +{ + u8 cfg; + + if (mvolt == -1) + cfg = 0x80; /* determined by LDO3IN pin */ + else + cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); + + return axp209_write(AXP209_LDO3_VOLTAGE, cfg); +} + +int axp209_set_ldo4(int mvolt) +{ + int rc; + static const int vindex[] = { + 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, + 2700, 2800, 3000, 3100, 3200, 3300 + }; + u8 cfg, reg; + + /* Translate mvolt to register cfg value, requested <= selected */ + for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--); + + rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); + if (rc) + return rc; + + /* LDO4 configuration is in lower 4 bits */ + reg = (reg & 0xf0) | (cfg << 0); + return axp209_write(AXP209_LDO24_VOLTAGE, reg); +} + +int axp209_init(void) +{ + u8 ver; + int rc; + + rc = axp209_read(AXP209_CHIP_VERSION, &ver); + if (rc) + return rc; + + /* Low 4 bits is chip version */ + ver &= 0x0f; + + if (ver != 0x1) + return -1; + + return 0; +} + +int axp209_poweron_by_dc(void) +{ + u8 v; + + if (axp209_read(AXP209_POWER_STATUS, &v)) + return 0; + + return (v & AXP209_POWER_STATUS_ON_BY_DC); +} + +int axp209_power_button(void) +{ + u8 v; + + if (axp209_read(AXP209_IRQ_STATUS5, &v)) + return 0; + + axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN); + + return v & AXP209_IRQ5_PEK_DOWN; +} |