diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/ahci.c | 50 | ||||
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 22 | ||||
-rw-r--r-- | drivers/input/cros_ec_keyb.c | 16 | ||||
-rw-r--r-- | drivers/misc/i2c_eeprom.c | 1 | ||||
-rw-r--r-- | drivers/mmc/mvebu_mmc.c | 103 | ||||
-rw-r--r-- | drivers/mtd/nand/omap_gpmc.c | 3 |
6 files changed, 111 insertions, 84 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index c9a3beb79b..37d2d2a28e 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -137,6 +137,33 @@ static void sunxi_dma_init(volatile u8 *port_mmio) } #endif +int ahci_reset(u32 base) +{ + int i = 1000; + u32 host_ctl_reg = base + HOST_CTL; + u32 tmp = readl(host_ctl_reg); /* global controller reset */ + + if ((tmp & HOST_RESET) == 0) + writel_with_flush(tmp | HOST_RESET, host_ctl_reg); + + /* + * reset must complete within 1 second, or + * the hardware should be considered fried. + */ + do { + udelay(1000); + tmp = readl(host_ctl_reg); + i--; + } while ((i > 0) && (tmp & HOST_RESET)); + + if (i == 0) { + printf("controller reset failed (0x%x)\n", tmp); + return -1; + } + + return 0; +} + static int ahci_host_init(struct ahci_probe_ent *probe_ent) { #ifndef CONFIG_SCSI_AHCI_PLAT @@ -156,23 +183,9 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) cap_save &= ((1 << 28) | (1 << 17)); cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */ - /* global controller reset */ - tmp = readl(mmio + HOST_CTL); - if ((tmp & HOST_RESET) == 0) - writel_with_flush(tmp | HOST_RESET, mmio + HOST_CTL); - - /* reset must complete within 1 second, or - * the hardware should be considered fried. - */ - i = 1000; - do { - udelay(1000); - tmp = readl(mmio + HOST_CTL); - if (!i--) { - debug("controller reset failed (0x%x)\n", tmp); - return -1; - } - } while (tmp & HOST_RESET); + ret = ahci_reset(probe_ent->mmio_base); + if (ret) + return ret; writel_with_flush(HOST_AHCI_EN, mmio + HOST_CTL); writel(cap_save, mmio + HOST_CAP); @@ -997,12 +1010,11 @@ static int ata_io_flush(u8 port) } -void scsi_bus_reset(void) +__weak void scsi_bus_reset(void) { /*Not implement*/ } - void scsi_print_error(ccb * pccb) { /*The ahci error info can be read in the ahci driver*/ diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 021b2fe511..fc5ee35a1a 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -402,17 +402,6 @@ int bus_i2c_write(void *base, uchar chip, uint addr, int alen, return ret; } -struct i2c_parms { - void *base; - void *idle_bus_data; - int (*idle_bus_fn)(void *p); -}; - -struct sram_data { - unsigned curr_i2c_bus; - struct i2c_parms i2c_data[3]; -}; - static void * const i2c_bases[] = { #if defined(CONFIG_MX25) (void *)IMX_I2C_BASE, @@ -439,6 +428,17 @@ static void * const i2c_bases[] = { #endif }; +struct i2c_parms { + void *base; + void *idle_bus_data; + int (*idle_bus_fn)(void *p); +}; + +struct sram_data { + unsigned curr_i2c_bus; + struct i2c_parms i2c_data[ARRAY_SIZE(i2c_bases)]; +}; + void *i2c_get_base(struct i2c_adapter *adap) { return i2c_bases[adap->hwadapnr]; diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c index 47502b1763..49ee7b2c9b 100644 --- a/drivers/input/cros_ec_keyb.c +++ b/drivers/input/cros_ec_keyb.c @@ -18,6 +18,8 @@ DECLARE_GLOBAL_DATA_PTR; enum { KBC_MAX_KEYS = 8, /* Maximum keys held down at once */ + KBC_REPEAT_RATE_MS = 30, + KBC_REPEAT_DELAY_MS = 240, }; static struct keyb { @@ -26,8 +28,6 @@ static struct keyb { struct key_matrix matrix; /* The key matrix layer */ int key_rows; /* Number of keyboard rows */ int key_cols; /* Number of keyboard columns */ - unsigned int repeat_delay_ms; /* Time before autorepeat starts */ - unsigned int repeat_rate_ms; /* Autorepeat rate in ms */ int ghost_filter; /* 1 to enable ghost filter, else 0 */ int inited; /* 1 if keyboard is ready */ } config; @@ -188,8 +188,8 @@ static int cros_ec_keyb_decode_fdt(const void *blob, int node, * Get keyboard rows and columns - at present we are limited to * 8 columns by the protocol (one byte per row scan) */ - config->key_rows = fdtdec_get_int(blob, node, "google,key-rows", 0); - config->key_cols = fdtdec_get_int(blob, node, "google,key-columns", 0); + config->key_rows = fdtdec_get_int(blob, node, "keypad,num-rows", 0); + config->key_cols = fdtdec_get_int(blob, node, "keypad,num-columns", 0); if (!config->key_rows || !config->key_cols || config->key_rows * config->key_cols / 8 > CROS_EC_KEYSCAN_COLS) { @@ -197,10 +197,6 @@ static int cros_ec_keyb_decode_fdt(const void *blob, int node, config->key_rows, config->key_cols); return -1; } - config->repeat_delay_ms = fdtdec_get_int(blob, node, - "google,repeat-delay-ms", 0); - config->repeat_rate_ms = fdtdec_get_int(blob, node, - "google,repeat-rate-ms", 0); config->ghost_filter = fdtdec_get_bool(blob, node, "google,ghost-filter"); return 0; @@ -232,8 +228,8 @@ static int cros_ec_init_keyboard(struct stdio_dev *dev) } if (cros_ec_keyb_decode_fdt(blob, node, &config)) return -1; - input_set_delays(&config.input, config.repeat_delay_ms, - config.repeat_rate_ms); + input_set_delays(&config.input, KBC_REPEAT_DELAY_MS, + KBC_REPEAT_RATE_MS); if (key_matrix_init(&config.matrix, config.key_rows, config.key_cols, config.ghost_filter)) { debug("%s: cannot init key matrix\n", __func__); diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index d0548ecc4e..814134a2cb 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <linux/err.h> #include <dm.h> #include <i2c.h> #include <i2c_eeprom.h> diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index 9f98c3f37c..8ca09042d8 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -1,7 +1,7 @@ /* * Marvell MMC/SD/SDIO driver * - * (C) Copyright 2012 + * (C) Copyright 2012-2014 * Marvell Semiconductor <www.marvell.com> * Written-by: Maen Suleiman, Gerald Kerma * @@ -23,6 +23,8 @@ DECLARE_GLOBAL_DATA_PTR; #define MVEBU_TARGET_DRAM 0 +#define TIMEOUT_DELAY 5*CONFIG_SYS_HZ /* wait 5 seconds */ + static void mvebu_mmc_write(u32 offs, u32 val) { writel(val, CONFIG_SYS_MMC_BASE + (offs)); @@ -63,37 +65,47 @@ static int mvebu_mmc_setup_data(struct mmc_data *data) static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - int timeout = 10; + ulong start; ushort waittype = 0; ushort resptype = 0; ushort xfertype = 0; ushort resp_indx = 0; - debug("cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n", - cmd->cmdidx, cmd->resp_type, cmd->cmdarg); - - udelay(10*1000); + debug("%s: cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n", + DRIVER_NAME, cmd->cmdidx, cmd->resp_type, cmd->cmdarg); debug("%s: cmd %d (hw state 0x%04x)\n", DRIVER_NAME, cmd->cmdidx, mvebu_mmc_read(SDIO_HW_STATE)); - /* Checking if card is busy */ - while ((mvebu_mmc_read(SDIO_HW_STATE) & CARD_BUSY)) { - if (timeout == 0) { - printf("%s: card busy!\n", DRIVER_NAME); - return -1; - } - timeout--; - udelay(1000); + /* + * Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE + * register is sometimes not set before a while when some + * "unusual" data block sizes are used (such as with the SWITCH + * command), even despite the fact that the XFER_DONE interrupt + * was raised. And if another data transfer starts before + * this bit comes to good sense (which eventually happens by + * itself) then the new transfer simply fails with a timeout. + */ + if (!(mvebu_mmc_read(SDIO_HW_STATE) & CMD_FIFO_EMPTY)) { + ushort hw_state, count = 0; + + start = get_timer(0); + do { + hw_state = mvebu_mmc_read(SDIO_HW_STATE); + if ((get_timer(0) - start) > TIMEOUT_DELAY) { + printf("%s : FIFO_EMPTY bit missing\n", + DRIVER_NAME); + break; + } + count++; + } while (!(hw_state & CMD_FIFO_EMPTY)); + debug("%s *** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n", + DRIVER_NAME, hw_state, count, (get_timer(0) - (start))); } - /* Set up for a data transfer if we have one */ - if (data) { - int err = mvebu_mmc_setup_data(data); - - if (err) - return err; - } + /* Clear status */ + mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); resptype = SDIO_CMD_INDEX(cmd->cmdidx); @@ -119,6 +131,14 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } if (data) { + int err = mvebu_mmc_setup_data(data); + + if (err) { + debug("%s: command DATA error :%x\n", + DRIVER_NAME, err); + return err; + } + resptype |= SDIO_CMD_DATA_PRESENT | SDIO_CMD_CHECK_DATACRC16; xfertype |= SDIO_XFER_MODE_HW_WR_DATA_EN; if (data->flags & MMC_DATA_READ) { @@ -138,17 +158,10 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, /* Setting Xfer mode */ mvebu_mmc_write(SDIO_XFER_MODE, xfertype); - mvebu_mmc_write(SDIO_NOR_INTR_STATUS, ~SDIO_NOR_CARD_INT); - mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); - /* Sending command */ mvebu_mmc_write(SDIO_CMD, resptype); - mvebu_mmc_write(SDIO_NOR_INTR_EN, SDIO_POLL_MASK); - mvebu_mmc_write(SDIO_ERR_INTR_EN, SDIO_POLL_MASK); - - /* Waiting for completion */ - timeout = 1000000; + start = get_timer(0); while (!((mvebu_mmc_read(SDIO_NOR_INTR_STATUS)) & waittype)) { if (mvebu_mmc_read(SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) { @@ -156,21 +169,20 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, DRIVER_NAME, cmd->cmdidx, mvebu_mmc_read(SDIO_ERR_INTR_STATUS)); if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & - (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) + (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) { + debug("%s: command READ timed out\n", + DRIVER_NAME); return TIMEOUT; + } + debug("%s: command READ error\n", DRIVER_NAME); return COMM_ERR; } - timeout--; - udelay(1); - if (timeout <= 0) { - printf("%s: command timed out\n", DRIVER_NAME); + if ((get_timer(0) - start) > TIMEOUT_DELAY) { + debug("%s: command timed out\n", DRIVER_NAME); return TIMEOUT; } } - if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & - (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) - return TIMEOUT; /* Handling response */ if (cmd->resp_type & MMC_RSP_136) { @@ -204,6 +216,11 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, cmd->response[1] = ((response[0] & 0xfc00) >> 10); cmd->response[2] = 0; cmd->response[3] = 0; + } else { + cmd->response[0] = 0; + cmd->response[1] = 0; + cmd->response[2] = 0; + cmd->response[3] = 0; } debug("%s: resp[0x%x] ", DRIVER_NAME, cmd->resp_type); @@ -213,6 +230,10 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, debug("[0x%x] ", cmd->response[3]); debug("\n"); + if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & + (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) + return TIMEOUT; + return 0; } @@ -251,9 +272,8 @@ static void mvebu_mmc_set_clk(unsigned int clock) if (m > MVEBU_MMC_BASE_DIV_MAX) m = MVEBU_MMC_BASE_DIV_MAX; mvebu_mmc_write(SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX); + debug("%s: clock (%d) div : %d\n", DRIVER_NAME, clock, m); } - - udelay(10*1000); } static void mvebu_mmc_set_bus(unsigned int bus) @@ -293,7 +313,6 @@ static void mvebu_mmc_set_bus(unsigned int bus) "high-speed" : ""); mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg); - udelay(10*1000); } static void mvebu_mmc_set_ios(struct mmc *mmc) @@ -355,7 +374,7 @@ static void mvebu_window_setup(void) static int mvebu_mmc_initialize(struct mmc *mmc) { - debug("%s: mvebu_mmc_initialize", DRIVER_NAME); + debug("%s: mvebu_mmc_initialize\n", DRIVER_NAME); /* * Setting host parameters @@ -384,8 +403,6 @@ static int mvebu_mmc_initialize(struct mmc *mmc) /* SW reset */ mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW); - udelay(10*1000); - return 0; } diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 93829a40b6..459904d81c 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -368,8 +368,9 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, uint32_t error_loc[ELM_MAX_ERROR_COUNT]; enum bch_level bch_type; uint32_t i, ecc_flag = 0; - uint8_t count, err = 0; + uint8_t count; uint32_t byte_pos, bit_pos; + int err = 0; /* check calculated ecc */ for (i = 0; i < ecc->bytes && !ecc_flag; i++) { |