diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 5 | ||||
-rw-r--r-- | drivers/mmc/atmel_mci.h | 48 | ||||
-rw-r--r-- | drivers/mmc/gen_atmel_mci.c | 353 | ||||
-rw-r--r-- | drivers/mmc/omap3_mmc.c | 68 | ||||
-rw-r--r-- | drivers/mmc/omap3_mmc.h | 9 | ||||
-rw-r--r-- | drivers/mmc/s5p_mmc.c | 36 | ||||
-rw-r--r-- | drivers/mtd/onenand/samsung.c | 6 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
-rw-r--r-- | drivers/rtc/at91sam9_rtt.c | 100 | ||||
-rw-r--r-- | drivers/serial/Makefile | 2 | ||||
-rw-r--r-- | drivers/serial/serial_s5p.c | 10 | ||||
-rw-r--r-- | drivers/spi/atmel_spi.c | 13 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/mb86r0xgdc.c | 186 |
15 files changed, 754 insertions, 86 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 528ca2e..07d395d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -29,7 +29,7 @@ COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o COBJS-$(CONFIG_MX31_GPIO) += mx31_gpio.o COBJS-$(CONFIG_PCA953X) += pca953x.o -COBJS-$(CONFIG_S5PC1XX) += s5p_gpio.o +COBJS-$(CONFIG_S5P) += s5p_gpio.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 8dfd8a3..6603d74 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -25,12 +25,13 @@ include $(TOPDIR)/config.mk LIB := $(obj)libmmc.a -COBJS-$(CONFIG_GENERIC_MMC) += mmc.o COBJS-$(CONFIG_ATMEL_MCI) += atmel_mci.o COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o -COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o +COBJS-$(CONFIG_GENERIC_MMC) += mmc.o +COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o +COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o diff --git a/drivers/mmc/atmel_mci.h b/drivers/mmc/atmel_mci.h index 5b4f5c9..823a77d 100644 --- a/drivers/mmc/atmel_mci.h +++ b/drivers/mmc/atmel_mci.h @@ -22,7 +22,45 @@ #ifndef __CPU_AT32AP_ATMEL_MCI_H__ #define __CPU_AT32AP_ATMEL_MCI_H__ -/* Atmel MultiMedia Card Interface (MCI) registers */ +#ifndef __ASSEMBLY__ + +/* + * Structure for struct SoC access. + * Names starting with '_' are fillers. + */ +typedef struct atmel_mci { + /* reg Offset */ + u32 cr; /* 0x00 */ + u32 mr; /* 0x04 */ + u32 dtor; /* 0x08 */ + u32 sdcr; /* 0x0c */ + u32 argr; /* 0x10 */ + u32 cmdr; /* 0x14 */ + u32 _18; /* 0x18 */ + u32 _1c; /* 0x1c */ + u32 rspr; /* 0x20 */ + u32 rspr1; /* 0x24 */ + u32 rspr2; /* 0x28 */ + u32 rspr3; /* 0x2c */ + u32 rdr; /* 0x30 */ + u32 tdr; /* 0x34 */ + u32 _38; /* 0x38 */ + u32 _3c; /* 0x3c */ + u32 sr; /* 0x40 */ + u32 ier; /* 0x44 */ + u32 idr; /* 0x48 */ + u32 imr; /* 0x4c */ +} atmel_mci_t; + +#endif /* __ASSEMBLY__ */ + +/* + * NOTICE: Use of registers offsets is depreciated. + * These defines will be removed once the old driver + * is taken out of commision. + * + * Atmel MultiMedia Card Interface (MCI) registers + */ #define MMCI_CR 0x0000 #define MMCI_MR 0x0004 #define MMCI_DTOR 0x0008 @@ -192,7 +230,13 @@ << MMCI_##name##_OFFSET)) \ | MMCI_BF(name,value)) -/* Register access macros */ +/* + * NOTICE: Use of registers offsets is depreciated. + * These defines will be removed once the old driver + * is taken out of commision. + * + * Register access macros + */ #define mmci_readl(reg) \ readl((void *)MMCI_BASE + MMCI_##reg) #define mmci_writel(reg,value) \ diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c new file mode 100644 index 0000000..fa4df99 --- /dev/null +++ b/drivers/mmc/gen_atmel_mci.c @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2010 + * Rob Emanuele <rob@emanuele.us> + * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de> + * + * Original Driver: + * Copyright (C) 2004-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mmc.h> +#include <part.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h> +#include "atmel_mci.h" + +#ifndef CONFIG_SYS_MMC_CLK_OD +# define CONFIG_SYS_MMC_CLK_OD 150000 +#endif + +#define MMC_DEFAULT_BLKLEN 512 + +#if defined(CONFIG_ATMEL_MCI_PORTB) +# define MCI_BUS 1 +#else +# define MCI_BUS 0 +#endif + +static int initialized = 0; + +/* + * Print command and status: + * + * - always when DEBUG is defined + * - on command errors + */ +static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) +{ + printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n", + cmdr, cmdr&0x3F, arg, status, msg); +} + +/* Setup for MCI Clock and Block Size */ +static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) +{ + atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + u32 bus_hz = get_mci_clk_rate(); + u32 clkdiv = 255; + + debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n", + bus_hz, hz, blklen); + if (hz > 0) { + /* find lowest clkdiv yielding a rate <= than requested */ + for (clkdiv=0; clkdiv<255; clkdiv++) { + if ((bus_hz / (clkdiv+1) / 2) <= hz) + break; + } + } + printf("mci: setting clock %u Hz, block size %u\n", + (bus_hz / (clkdiv+1)) / 2, blklen); + + blklen &= 0xfffc; + /* On some platforms RDPROOF and WRPROOF are ignored */ + writel((MMCI_BF(CLKDIV, clkdiv) + | MMCI_BF(BLKLEN, blklen) + | MMCI_BIT(RDPROOF) + | MMCI_BIT(WRPROOF)), &mci->mr); + initialized = 1; +} + +/* Return the CMDR with flags for a given command and data packet */ +static u32 mci_encode_cmd( + struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags) +{ + u32 cmdr = 0; + + /* Default Flags for Errors */ + *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) | + MMCI_BIT(RINDE) | MMCI_BIT(RTOE)); + + /* Default Flags for the Command */ + cmdr |= MMCI_BIT(MAXLAT); + + if (data) { + cmdr |= MMCI_BF(TRCMD, 1); + if (data->blocks > 1) + cmdr |= MMCI_BF(TRTYP, 1); + if (data->flags & MMC_DATA_READ) + cmdr |= MMCI_BIT(TRDIR); + } + + if (cmd->resp_type & MMC_RSP_CRC) + *error_flags |= MMCI_BIT(RCRCE); + if (cmd->resp_type & MMC_RSP_136) + cmdr |= MMCI_BF(RSPTYP, 2); + else if (cmd->resp_type & MMC_RSP_BUSY) + cmdr |= MMCI_BF(RSPTYP, 3); + else if (cmd->resp_type & MMC_RSP_PRESENT) + cmdr |= MMCI_BF(RSPTYP, 1); + + return cmdr | MMCI_BF(CMDNB, cmd->cmdidx); +} + +/* Entered into function pointer in mci_send_cmd */ +static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags) +{ + u32 status; + + do { + status = readl(&mci->sr); + if (status & (error_flags | MMCI_BIT(OVRE))) + goto io_fail; + } while (!(status & MMCI_BIT(RXRDY))); + + if (status & MMCI_BIT(RXRDY)) { + *data = readl(&mci->rdr); + status = 0; + } +io_fail: + return status; +} + +/* Entered into function pointer in mci_send_cmd */ +static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags) +{ + u32 status; + + do { + status = readl(&mci->sr); + if (status & (error_flags | MMCI_BIT(UNRE))) + goto io_fail; + } while (!(status & MMCI_BIT(TXRDY))); + + if (status & MMCI_BIT(TXRDY)) { + writel(*data, &mci->tdr); + status = 0; + } +io_fail: + return status; +} + +/* + * Entered into mmc structure during driver init + * + * Sends a command out on the bus and deals with the block data. + * Takes the mmc pointer, a command pointer, and an optional data pointer. + */ +static int +mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +{ + atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + u32 cmdr; + u32 error_flags = 0; + u32 status; + + if (!initialized) { + puts ("MCI not initialized!\n"); + return COMM_ERR; + } + + /* Figure out the transfer arguments */ + cmdr = mci_encode_cmd(cmd, data, &error_flags); + + /* Send the command */ + writel(cmd->cmdarg, &mci->argr); + writel(cmdr, &mci->cmdr); + +#ifdef DEBUG + dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG"); +#endif + + /* Wait for the command to complete */ + while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY))); + + if (status & error_flags) { + dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed"); + return COMM_ERR; + } + + /* Copy the response to the response buffer */ + if (cmd->resp_type & MMC_RSP_136) { + cmd->response[0] = readl(&mci->rspr); + cmd->response[1] = readl(&mci->rspr1); + cmd->response[2] = readl(&mci->rspr2); + cmd->response[3] = readl(&mci->rspr3); + } else + cmd->response[0] = readl(&mci->rspr); + + /* transfer all of the blocks */ + if (data) { + u32 word_count, block_count; + u32* ioptr; + u32 sys_blocksize, dummy, i; + u32 (*mci_data_op) + (atmel_mci_t *mci, u32* data, u32 error_flags); + + if (data->flags & MMC_DATA_READ) { + mci_data_op = mci_data_read; + sys_blocksize = mmc->read_bl_len; + ioptr = (u32*)data->dest; + } else { + mci_data_op = mci_data_write; + sys_blocksize = mmc->write_bl_len; + ioptr = (u32*)data->src; + } + + status = 0; + for (block_count = 0; + block_count < data->blocks && !status; + block_count++) { + word_count = 0; + do { + status = mci_data_op(mci, ioptr, error_flags); + word_count++; + ioptr++; + } while (!status && word_count < (data->blocksize/4)); +#ifdef DEBUG + if (data->flags & MMC_DATA_READ) + { + printf("Read Data:\n"); + print_buffer(0, data->dest, 1, + word_count*4, 0); + } +#endif +#ifdef DEBUG + if (!status && word_count < (sys_blocksize / 4)) + printf("filling rest of block...\n"); +#endif + /* fill the rest of a full block */ + while (!status && word_count < (sys_blocksize / 4)) { + status = mci_data_op(mci, &dummy, + error_flags); + word_count++; + } + if (status) { + dump_cmd(cmdr, cmd->cmdarg, status, + "Data Transfer Failed"); + return COMM_ERR; + } + } + + /* Wait for Transfer End */ + i = 0; + do { + status = readl(&mci->sr); + + if (status & error_flags) { + dump_cmd(cmdr, cmd->cmdarg, status, + "DTIP Wait Failed"); + return COMM_ERR; + } + i++; + } while ((status & MMCI_BIT(DTIP)) && i < 10000); + if (status & MMCI_BIT(DTIP)) { + dump_cmd(cmdr, cmd->cmdarg, status, + "XFER DTIP never unset, ignoring"); + } + } + + return 0; +} + +/* Entered into mmc structure during driver init */ +static void mci_set_ios(struct mmc *mmc) +{ + atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + int busw = (mmc->bus_width == 4) ? 1 : 0; + + /* Set the clock speed */ + mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN); + + /* + * set the bus width and select slot for this interface + * there is no capability for multiple slots on the same interface yet + * Bitfield SCDBUS needs to be expanded to 2 bits for 8-bit buses + */ + writel(MMCI_BF(SCDBUS, busw) | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr); +} + +/* Entered into mmc structure during driver init */ +static int mci_init(struct mmc *mmc) +{ + atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + + /* Initialize controller */ + writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */ + writel(MMCI_BIT(PWSDIS), &mci->cr); /* disable power save */ + writel(MMCI_BIT(MCIEN), &mci->cr); /* enable mci */ + + /* Initial Time-outs */ + writel(0x5f, &mci->dtor); + /* Disable Interrupts */ + writel(~0UL, &mci->idr); + + /* Set default clocks and blocklen */ + mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); + + return 0; +} + +/* + * This is the only exported function + * + * Call it with the MCI register base address + */ +int atmel_mci_init(void *regs) +{ + struct mmc *mmc = malloc(sizeof(struct mmc)); + + if (!mmc) + return -1; + strcpy(mmc->name, "mci"); + mmc->priv = regs; + mmc->send_cmd = mci_send_cmd; + mmc->set_ios = mci_set_ios; + mmc->init = mci_init; + + /* need to be able to pass these in on a board by board basis */ + mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->host_caps = MMC_MODE_4BIT; + /* + * min and max frequencies determined by + * max and min of clock divider + */ + mmc->f_min = get_mci_clk_rate() / (2*256); + mmc->f_max = get_mci_clk_rate() / (2*1); + + mmc_register(mmc); + + return 0; +} diff --git a/drivers/mmc/omap3_mmc.c b/drivers/mmc/omap3_mmc.c index 9506cca..15d41e5 100644 --- a/drivers/mmc/omap3_mmc.c +++ b/drivers/mmc/omap3_mmc.c @@ -33,7 +33,7 @@ #include "omap3_mmc.h" -const unsigned short mmc_transspeed_val[15][4] = { +static const unsigned short mmc_transspeed_val[15][4] = { {CLKD(10, 1), CLKD(10, 10), CLKD(10, 100), CLKD(10, 1000)}, {CLKD(12, 1), CLKD(12, 10), CLKD(12, 100), CLKD(12, 1000)}, {CLKD(13, 1), CLKD(13, 10), CLKD(13, 100), CLKD(13, 1000)}, @@ -51,7 +51,7 @@ const unsigned short mmc_transspeed_val[15][4] = { {CLKD(80, 1), CLKD(80, 10), CLKD(80, 100), CLKD(80, 1000)} }; -mmc_card_data cur_card_data; +static mmc_card_data cur_card_data; static block_dev_desc_t mmc_blk_dev; static hsmmc_t *mmc_base = (hsmmc_t *)OMAP_HSMMC1_BASE; @@ -80,7 +80,7 @@ block_dev_desc_t *mmc_get_dev(int dev) return (block_dev_desc_t *) &mmc_blk_dev; } -unsigned char mmc_board_init(void) +static unsigned char mmc_board_init(void) { #if defined(CONFIG_TWL4030_POWER) twl4030_power_mmc_init(); @@ -114,7 +114,7 @@ unsigned char mmc_board_init(void) return 1; } -void mmc_init_stream(void) +static void mmc_init_stream(void) { writel(readl(&mmc_base->con) | INIT_INITSTREAM, &mmc_base->con); @@ -129,7 +129,7 @@ void mmc_init_stream(void) writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con); } -unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) +static unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) { unsigned int val; @@ -158,7 +158,7 @@ unsigned char mmc_clock_config(unsigned int iclk, unsigned short clk_div) return 1; } -unsigned char mmc_init_setup(void) +static unsigned char mmc_init_setup(void) { unsigned int reg_val; @@ -192,7 +192,7 @@ unsigned char mmc_init_setup(void) return 1; } -unsigned char mmc_send_cmd(unsigned int cmd, unsigned int arg, +static unsigned char mmc_send_cmd(unsigned int cmd, unsigned int arg, unsigned int *response) { unsigned int mmc_stat; @@ -228,7 +228,7 @@ unsigned char mmc_send_cmd(unsigned int cmd, unsigned int arg, return 1; } -unsigned char mmc_read_data(unsigned int *output_buf) +static unsigned char mmc_read_data(unsigned int *output_buf) { unsigned int mmc_stat; unsigned int read_count = 0; @@ -269,7 +269,7 @@ unsigned char mmc_read_data(unsigned int *output_buf) return 1; } -unsigned char mmc_detect_card(mmc_card_data *mmc_card_cur) +static unsigned char mmc_detect_card(mmc_card_data *mmc_card_cur) { unsigned char err; unsigned int argument = 0; @@ -380,7 +380,7 @@ unsigned char mmc_detect_card(mmc_card_data *mmc_card_cur) return 1; } -unsigned char mmc_read_cardsize(mmc_card_data *mmc_dev_data, +static unsigned char mmc_read_cardsize(mmc_card_data *mmc_dev_data, mmc_csd_reg_t *cur_csd) { mmc_extended_csd_reg_t ext_csd; @@ -434,45 +434,48 @@ unsigned char mmc_read_cardsize(mmc_card_data *mmc_dev_data, return 1; } -unsigned char omap_mmc_read_sect(unsigned int start_sec, unsigned int num_bytes, - mmc_card_data *mmc_c, - unsigned long *output_buf) +static unsigned long mmc_bread(int dev_num, unsigned long blknr, + lbaint_t blkcnt, void *dst) { unsigned char err; unsigned int argument; unsigned int resp[4]; - unsigned int num_sec_val = - (num_bytes + (MMCSD_SECTOR_SIZE - 1)) / MMCSD_SECTOR_SIZE; + unsigned int *output_buf = dst; unsigned int sec_inc_val; + lbaint_t i; - if (num_sec_val == 0) - return 1; + if (blkcnt == 0) + return 0; - if (mmc_c->mode == SECTOR_MODE) { - argument = start_sec; + if (cur_card_data.mode == SECTOR_MODE) { + argument = blknr; sec_inc_val = 1; } else { - argument = start_sec * MMCSD_SECTOR_SIZE; + argument = blknr * MMCSD_SECTOR_SIZE; sec_inc_val = MMCSD_SECTOR_SIZE; } - while (num_sec_val) { + for (i = 0; i < blkcnt; i++) { err = mmc_send_cmd(MMC_CMD17, argument, resp); - if (err != 1) - return err; + if (err != 1) { + printf("mmc: CMD17 failed, status = %08x\n", err); + break; + } - err = mmc_read_data((unsigned int *) output_buf); - if (err != 1) - return err; + err = mmc_read_data(output_buf); + if (err != 1) { + printf("mmc: read failed, status = %08x\n", err); + break; + } output_buf += (MMCSD_SECTOR_SIZE / 4); argument += sec_inc_val; - num_sec_val--; } - return 1; + + return i; } -unsigned char configure_mmc(mmc_card_data *mmc_card_cur) +static unsigned char configure_mmc(mmc_card_data *mmc_card_cur) { unsigned char ret_val; unsigned int argument; @@ -541,13 +544,6 @@ unsigned char configure_mmc(mmc_card_data *mmc_card_cur) return 1; } -unsigned long mmc_bread(int dev_num, unsigned long blknr, lbaint_t blkcnt, - void *dst) -{ - omap_mmc_read_sect(blknr, (blkcnt * MMCSD_SECTOR_SIZE), &cur_card_data, - (unsigned long *) dst); - return 1; -} int mmc_legacy_init(int dev) { diff --git a/drivers/mmc/omap3_mmc.h b/drivers/mmc/omap3_mmc.h index cbb3dc3..e4d263c 100644 --- a/drivers/mmc/omap3_mmc.h +++ b/drivers/mmc/omap3_mmc.h @@ -230,13 +230,4 @@ typedef union { mmc_csd_reg_t Card_CSD; } mmc_resp_t; -extern mmc_card_data mmc_dev; - -unsigned char mmc_lowlevel_init(void); -unsigned char mmc_send_command(unsigned int cmd, unsigned int arg, - unsigned int *response); -unsigned char mmc_setup_clock(unsigned int iclk, unsigned short clkd); -unsigned char mmc_set_opendrain(unsigned char state); -unsigned char mmc_read_data(unsigned int *output_buf); - #endif /* MMC_H */ diff --git a/drivers/mmc/s5p_mmc.c b/drivers/mmc/s5p_mmc.c index 669b1d0..1fd425c 100644 --- a/drivers/mmc/s5p_mmc.c +++ b/drivers/mmc/s5p_mmc.c @@ -23,12 +23,6 @@ #include <asm/io.h> #include <asm/arch/mmc.h> -#ifdef DEBUG_S5P_HSMMC -#define dbg(x...) printf(x) -#else -#define dbg(x...) do { } while (0) -#endif - /* support 4 mmc hosts */ struct mmc mmc_dev[4]; struct mmc_host mmc_host[4]; @@ -36,18 +30,14 @@ struct mmc_host mmc_host[4]; static inline struct s5p_mmc *s5p_get_base_mmc(int dev_index) { unsigned long offset = dev_index * sizeof(struct s5p_mmc); - - if (cpu_is_s5pc100()) - return (struct s5p_mmc *)(S5PC100_MMC_BASE + offset); - else - return (struct s5p_mmc *)(S5PC110_MMC_BASE + offset); + return (struct s5p_mmc *)(samsung_get_base_mmc() + offset); } static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data) { unsigned char ctrl; - dbg("data->dest: %08x\n", (u32)data->dest); + debug("data->dest: %08x\n", (u32)data->dest); writel((u32)data->dest, &host->reg->sysad); /* * DMASEL[4:3] @@ -128,7 +118,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (data) mmc_prepare_data(host, data); - dbg("cmd->arg: %08x\n", cmd->cmdarg); + debug("cmd->arg: %08x\n", cmd->cmdarg); writel(cmd->cmdarg, &host->reg->argument); if (data) @@ -165,7 +155,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (data) flags |= (1 << 5); - dbg("cmd: %d\n", cmd->cmdidx); + debug("cmd: %d\n", cmd->cmdidx); writew((cmd->cmdidx << 8) | flags, &host->reg->cmdreg); @@ -186,11 +176,11 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (mask & (1 << 16)) { /* Timeout Error */ - dbg("timeout: %08x cmd %d\n", mask, cmd->cmdidx); + debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx); return TIMEOUT; } else if (mask & (1 << 15)) { /* Error Interrupt */ - dbg("error: %08x cmd %d\n", mask, cmd->cmdidx); + debug("error: %08x cmd %d\n", mask, cmd->cmdidx); return -1; } @@ -206,7 +196,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, cmd->response[i] |= readb(offset - 1); } - dbg("cmd->resp[%d]: %08x\n", + debug("cmd->resp[%d]: %08x\n", i, cmd->response[i]); } } else if (cmd->resp_type & MMC_RSP_BUSY) { @@ -223,10 +213,10 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } cmd->response[0] = readl(&host->reg->rspreg0); - dbg("cmd->resp[0]: %08x\n", cmd->response[0]); + debug("cmd->resp[0]: %08x\n", cmd->response[0]); } else { cmd->response[0] = readl(&host->reg->rspreg0); - dbg("cmd->resp[0]: %08x\n", cmd->response[0]); + debug("cmd->resp[0]: %08x\n", cmd->response[0]); } } @@ -242,11 +232,11 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, return -1; } else if (mask & (1 << 3)) { /* DMA Interrupt */ - dbg("DMA end\n"); + debug("DMA end\n"); break; } else if (mask & (1 << 1)) { /* Transfer Complete */ - dbg("r/w is done\n"); + debug("r/w is done\n"); break; } } @@ -288,7 +278,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) div = 2; else div = 1; - dbg("div: %d\n", div); + debug("div: %d\n", div); div >>= 1; /* @@ -325,7 +315,7 @@ static void mmc_set_ios(struct mmc *mmc) unsigned char ctrl; unsigned long val; - dbg("set_ios: bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock); + debug("bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock); /* * SELCLKPADDS[17:16] diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index f2be687..20b4912 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -67,7 +67,7 @@ do { \ #define MAP_01 (0x1 << 24) #define MAP_10 (0x2 << 24) #define MAP_11 (0x3 << 24) -#elif defined(CONFIG_S5PC1XX) +#elif defined(CONFIG_S5P) #define MAP_00 (0x0 << 26) #define MAP_01 (0x1 << 26) #define MAP_10 (0x2 << 26) @@ -121,7 +121,7 @@ static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) { return (fba << 12) | (fpa << 6) | (fsa << 4); } -#elif defined(CONFIG_S5PC1XX) +#elif defined(CONFIG_S5P) static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) { return (fba << 13) | (fpa << 7) | (fsa << 5); @@ -614,7 +614,7 @@ void s3c_onenand_init(struct mtd_info *mtd) #if defined(CONFIG_S3C64XX) onenand->base = (void *)0x70100000; onenand->ahb_addr = (void *)0x20000000; -#elif defined(CONFIG_S5PC1XX) +#elif defined(CONFIG_S5P) onenand->base = (void *)0xE7100000; onenand->ahb_addr = (void *)0xB0000000; #endif diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 772a49a..98734db 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)librtc.a +COBJS-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o COBJS-$(CONFIG_RTC_BFIN) += bfin_rtc.o COBJS-y += date.o COBJS-$(CONFIG_RTC_DS12887) += ds12887.o diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c new file mode 100644 index 0000000..de8e30d --- /dev/null +++ b/drivers/rtc/at91sam9_rtt.c @@ -0,0 +1,100 @@ +/* + * (C) Copyright 2010 + * Reinhard Meyer, reinhard.meyer@emk-elektronik.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Date & Time support for the internal Real-time Timer + * of AT91SAM9260 and compatibles. + * Compatible with the LinuX rtc driver workaround: + * The RTT cannot be written to, but only reset. + * The actual time is the sum of RTT and one of + * the four GPBR registers. + * + * The at91sam9260 has 4 GPBR (0-3). + * For their typical use see at91_gpbr.h ! + * + * make sure u-boot and kernel use the same GPBR ! + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> +#include <asm/arch/io.h> +#include <asm/arch/at91_rtt.h> +#include <asm/arch/at91_gpbr.h> + +#if defined(CONFIG_CMD_DATE) + +int rtc_get (struct rtc_time *tmp) +{ + at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE; + at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE; + ulong tim; + ulong tim2; + ulong off; + + do { + tim = readl(&rtt->vr); + tim2 = readl(&rtt->vr); + } while (tim!=tim2); + off = readl(&gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); + /* off==0 means time is invalid, but we ignore that */ + to_tm (tim+off, tmp); + return 0; +} + +int rtc_set (struct rtc_time *tmp) +{ + at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE; + at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE; + ulong tim; + + tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + /* clear alarm, set prescaler to 32768, clear counter */ + writel(32768+AT91_RTT_RTTRST, &rtt->mr); + writel(~0, &rtt->ar); + writel(tim, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); + /* wait for counter clear to happen, takes less than a 1/32768th second */ + while (readl(&rtt->vr) != 0) + ; + return 0; +} + +void rtc_reset (void) +{ + at91_rtt_t *rtt = (at91_rtt_t *) AT91_RTT_BASE; + at91_gpbr_t *gpbr = (at91_gpbr_t *) AT91_GPR_BASE; + + /* clear alarm, set prescaler to 32768, clear counter */ + writel(32768+AT91_RTT_RTTRST, &rtt->mr); + writel(~0, &rtt->ar); + writel(0, &gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); + /* wait for counter clear to happen, takes less than a 1/32768th second */ + while (readl(&rtt->vr) != 0) + ; +} + +#endif diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index c731bfb..6d45a8e 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -36,7 +36,7 @@ COBJS-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o COBJS-$(CONFIG_SYS_NS16550) += ns16550.o COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o COBJS-$(CONFIG_S3C64XX) += s3c64xx.o -COBJS-$(CONFIG_S5PC1XX) += serial_s5p.o +COBJS-$(CONFIG_S5P) += serial_s5p.o COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial.o COBJS-$(CONFIG_CLPS7111_SERIAL) += serial_clps7111.o COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index e0d4e80..7709664 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -30,11 +30,7 @@ static inline struct s5p_uart *s5p_get_base_uart(int dev_index) { u32 offset = dev_index * sizeof(struct s5p_uart); - - if (cpu_is_s5pc100()) - return (struct s5p_uart *)(S5PC100_UART_BASE + offset); - else - return (struct s5p_uart *)(S5PC110_UART_BASE + offset); + return (struct s5p_uart *)(samsung_get_base_uart() + offset); } /* @@ -67,11 +63,11 @@ void serial_setbrg_dev(const int dev_index) { DECLARE_GLOBAL_DATA_PTR; struct s5p_uart *const uart = s5p_get_base_uart(dev_index); - u32 pclk = get_pclk(); + u32 uclk = get_uart_clk(dev_index); u32 baudrate = gd->baudrate; u32 val; - val = pclk / baudrate; + val = uclk / baudrate; writel(val / 16 - 1, &uart->ubrdiv); writew(udivslot[val % 16], &uart->udivslot); diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 317c0b4..d0de931 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -43,7 +43,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, u32 csrx; void *regs; - if (cs > 3 || !spi_cs_is_valid(bus, cs)) + if (!spi_cs_is_valid(bus, cs)) return NULL; switch (bus) { @@ -168,8 +168,17 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, * somewhat quirky, and it doesn't really buy us much anyway * in the context of U-Boot. */ - if (flags & SPI_XFER_BEGIN) + if (flags & SPI_XFER_BEGIN) { spi_cs_activate(slave); + /* + * sometimes the RDR is not empty when we get here, + * in theory that should not happen, but it DOES happen. + * Read it here to be on the safe side. + * That also clears the OVRES flag. Required if the + * following loop exits due to OVRES! + */ + spi_readl(as, RDR); + } for (len_tx = 0, len_rx = 0; len_rx < len; ) { status = spi_readl(as, SR); diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 7d84fc7..4be82e7 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -32,6 +32,7 @@ COBJS-$(CONFIG_S6E63D6) += s6e63d6.o COBJS-$(CONFIG_VIDEO_AMBA) += amba.o COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o +COBJS-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o COBJS-$(CONFIG_SED156X) += sed156x.o diff --git a/drivers/video/mb86r0xgdc.c b/drivers/video/mb86r0xgdc.c new file mode 100644 index 0000000..3bdc1db --- /dev/null +++ b/drivers/video/mb86r0xgdc.c @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2010 + * Matthias Weisser <weisserm@arcor.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * mb86r0xgdc.c - Graphic interface for Fujitsu MB86R0x integrated graphic + * controller. + */ + +#include <common.h> + +#include <malloc.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <video_fb.h> +#include "videomodes.h" + +/* + * 4MB (at the end of system RAM) + */ +#define VIDEO_MEM_SIZE 0x400000 + +#define FB_SYNC_CLK_INV (1<<16) /* pixel clock inverted */ + +/* + * Graphic Device + */ +static GraphicDevice mb86r0x; + +static void dsp_init(struct mb86r0x_gdc_dsp *dsp, char *modestr, + u32 *videomem) +{ + struct ctfb_res_modes var_mode; + u32 dcm1, dcm2, dcm3; + u16 htp, hdp, hdb, hsp, vtr, vsp, vdp; + u8 hsw, vsw; + u32 l2m, l2em, l2oa0, l2da0, l2oa1, l2da1; + u16 l2dx, l2dy, l2wx, l2wy, l2ww, l2wh; + unsigned long div; + int bpp; + u32 i; + + bpp = video_get_params(&var_mode, modestr); + + if (bpp == 0) { + var_mode.xres = 640; + var_mode.yres = 480; + var_mode.pixclock = 39721; /* 25MHz */ + var_mode.left_margin = 48; + var_mode.right_margin = 16; + var_mode.upper_margin = 33; + var_mode.lower_margin = 10; + var_mode.hsync_len = 96; + var_mode.vsync_len = 2; + var_mode.sync = 0; + var_mode.vmode = 0; + bpp = 15; + } + + /* Fill memory with white */ + for (i = 0; i < var_mode.xres * var_mode.yres / 2; i++) + *videomem++ = 0xFFFFFFFF; + + mb86r0x.winSizeX = var_mode.xres; + mb86r0x.winSizeY = var_mode.yres; + + /* LCD base clock is ~ 660MHZ. We do calculations in kHz */ + div = 660000 / (1000000000L / var_mode.pixclock); + if (div > 64) + div = 64; + if (0 == div) + div = 1; + + dcm1 = (div - 1) << 8; + dcm2 = 0x00000000; + if (var_mode.sync & FB_SYNC_CLK_INV) + dcm3 = 0x00000100; + else + dcm3 = 0x00000000; + + htp = var_mode.left_margin + var_mode.xres + + var_mode.hsync_len + var_mode.right_margin; + hdp = var_mode.xres; + hdb = var_mode.xres; + hsp = var_mode.xres + var_mode.right_margin; + hsw = var_mode.hsync_len; + + vsw = var_mode.vsync_len; + vtr = var_mode.upper_margin + var_mode.yres + + var_mode.vsync_len + var_mode.lower_margin; + vsp = var_mode.yres + var_mode.lower_margin; + vdp = var_mode.yres; + + l2m = ((var_mode.yres - 1) << (0)) | + (((var_mode.xres * 2) / 64) << (16)) | + ((1) << (31)); + + l2em = (1 << 0) | (1 << 1); + + l2oa0 = mb86r0x.frameAdrs; + l2da0 = mb86r0x.frameAdrs; + l2oa1 = mb86r0x.frameAdrs; + l2da1 = mb86r0x.frameAdrs; + l2dx = 0; + l2dy = 0; + l2wx = 0; + l2wy = 0; + l2ww = var_mode.xres; + l2wh = var_mode.yres - 1; + + writel(dcm1, &dsp->dcm1); + writel(dcm2, &dsp->dcm2); + writel(dcm3, &dsp->dcm3); + + writew(htp, &dsp->htp); + writew(hdp, &dsp->hdp); + writew(hdb, &dsp->hdb); + writew(hsp, &dsp->hsp); + writeb(hsw, &dsp->hsw); + + writeb(vsw, &dsp->vsw); + writew(vtr, &dsp->vtr); + writew(vsp, &dsp->vsp); + writew(vdp, &dsp->vdp); + + writel(l2m, &dsp->l2m); + writel(l2em, &dsp->l2em); + writel(l2oa0, &dsp->l2oa0); + writel(l2da0, &dsp->l2da0); + writel(l2oa1, &dsp->l2oa1); + writel(l2da1, &dsp->l2da1); + writew(l2dx, &dsp->l2dx); + writew(l2dy, &dsp->l2dy); + writew(l2wx, &dsp->l2wx); + writew(l2wy, &dsp->l2wy); + writew(l2ww, &dsp->l2ww); + writew(l2wh, &dsp->l2wh); + + writel(dcm1 | (1 << 18) | (1 << 31), &dsp->dcm1); +} + +void *video_hw_init(void) +{ + struct mb86r0x_gdc *gdc = (struct mb86r0x_gdc *) MB86R0x_GDC_BASE; + GraphicDevice *pGD = &mb86r0x; + char *s; + u32 *vid; + + memset(pGD, 0, sizeof(GraphicDevice)); + + pGD->gdfIndex = GDF_15BIT_555RGB; + pGD->gdfBytesPP = 2; + pGD->memSize = VIDEO_MEM_SIZE; + pGD->frameAdrs = PHYS_SDRAM + PHYS_SDRAM_SIZE - VIDEO_MEM_SIZE; + + vid = (u32 *)pGD->frameAdrs; + + s = getenv("videomode"); + if (s != NULL) + dsp_init(&gdc->dsp0, s, vid); + + s = getenv("videomode1"); + if (s != NULL) + dsp_init(&gdc->dsp1, s, vid); + + return pGD; +} |