]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/spi/mxc_spi.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / spi / mxc_spi.c
index 2fa748608f2bfe25046dd5f6c75e6fb860799850..5bed858787f610a9c9a46bb2214665a51d60a9e9 100644 (file)
 
 #error "i.MX27 CSPI not supported due to drastic differences in register definitions" \
 "See linux mxc_spi driver from Freescale for details."
-
-#elif defined(CONFIG_MX31)
-
-#define MXC_CSPICTRL_EN                (1 << 0)
-#define MXC_CSPICTRL_MODE      (1 << 1)
-#define MXC_CSPICTRL_XCH       (1 << 2)
-#define MXC_CSPICTRL_SMC       (1 << 3)
-#define MXC_CSPICTRL_POL       (1 << 4)
-#define MXC_CSPICTRL_PHA       (1 << 5)
-#define MXC_CSPICTRL_SSCTL     (1 << 6)
-#define MXC_CSPICTRL_SSPOL     (1 << 7)
-#define MXC_CSPICTRL_CHIPSELECT(x)     (((x) & 0x3) << 24)
-#define MXC_CSPICTRL_BITCOUNT(x)       (((x) & 0x1f) << 8)
-#define MXC_CSPICTRL_DATARATE(x)       (((x) & 0x7) << 16)
-#define MXC_CSPICTRL_TC                (1 << 8)
-#define MXC_CSPICTRL_RXOVF     (1 << 6)
-#define MXC_CSPICTRL_MAXBITS   0x1f
-
-#define MXC_CSPIPERIOD_32KHZ   (1 << 15)
-#define MAX_SPI_BYTES  4
-
-static unsigned long spi_bases[] = {
-       0x43fa4000,
-       0x50010000,
-       0x53f84000,
-};
-
-#elif defined(CONFIG_MX51)
-
-#define MXC_CSPICTRL_EN                (1 << 0)
-#define MXC_CSPICTRL_MODE      (1 << 1)
-#define MXC_CSPICTRL_XCH       (1 << 2)
-#define MXC_CSPICTRL_CHIPSELECT(x)     (((x) & 0x3) << 12)
-#define MXC_CSPICTRL_BITCOUNT(x)       (((x) & 0xfff) << 20)
-#define MXC_CSPICTRL_PREDIV(x) (((x) & 0xF) << 12)
-#define MXC_CSPICTRL_POSTDIV(x)        (((x) & 0xF) << 8)
-#define MXC_CSPICTRL_SELCHAN(x)        (((x) & 0x3) << 18)
-#define MXC_CSPICTRL_MAXBITS   0xfff
-#define MXC_CSPICTRL_TC                (1 << 7)
-#define MXC_CSPICTRL_RXOVF     (1 << 6)
-
-#define MXC_CSPIPERIOD_32KHZ   (1 << 15)
-#define MAX_SPI_BYTES  32
-
-/* Bit position inside CTRL register to be associated with SS */
-#define MXC_CSPICTRL_CHAN      18
-
-/* Bit position inside CON register to be associated with SS */
-#define MXC_CSPICON_POL                4
-#define MXC_CSPICON_PHA                0
-#define MXC_CSPICON_SSPOL      12
-
-static unsigned long spi_bases[] = {
-       CSPI1_BASE_ADDR,
-       CSPI2_BASE_ADDR,
-       CSPI3_BASE_ADDR,
-};
-
-#elif defined(CONFIG_MX35)
-
-#define MXC_CSPICTRL_EN                (1 << 0)
-#define MXC_CSPICTRL_MODE      (1 << 1)
-#define MXC_CSPICTRL_XCH       (1 << 2)
-#define MXC_CSPICTRL_SMC       (1 << 3)
-#define MXC_CSPICTRL_POL       (1 << 4)
-#define MXC_CSPICTRL_PHA       (1 << 5)
-#define MXC_CSPICTRL_SSCTL     (1 << 6)
-#define MXC_CSPICTRL_SSPOL     (1 << 7)
-#define MXC_CSPICTRL_CHIPSELECT(x)     (((x) & 0x3) << 12)
-#define MXC_CSPICTRL_BITCOUNT(x)       (((x) & 0xfff) << 20)
-#define MXC_CSPICTRL_DATARATE(x)       (((x) & 0x7) << 16)
-#define MXC_CSPICTRL_TC                (1 << 7)
-#define MXC_CSPICTRL_RXOVF     (1 << 6)
-#define MXC_CSPICTRL_MAXBITS   0xfff
-
-#define MXC_CSPIPERIOD_32KHZ   (1 << 15)
-#define MAX_SPI_BYTES  4
+#endif
 
 static unsigned long spi_bases[] = {
-       0x43fa4000,
-       0x50010000,
+       MXC_SPI_BASE_ADDRESSES
 };
 
-#else
-#error "Unsupported architecture"
-#endif
-
 #define OUT    MXC_GPIO_DIRECTION_OUT
 
 #define reg_read readl
@@ -129,7 +48,7 @@ struct mxc_spi_slave {
        struct spi_slave slave;
        unsigned long   base;
        u32             ctrl_reg;
-#if defined(CONFIG_MX51)
+#if defined(MXC_ECSPI)
        u32             cfg_reg;
 #endif
        int             gpio;
@@ -167,7 +86,7 @@ u32 get_cspi_div(u32 div)
        return i;
 }
 
-#if defined(CONFIG_MX31) || defined(CONFIG_MX35)
+#ifdef MXC_CSPI
 static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
                unsigned int max_hz, unsigned int mode)
 {
@@ -177,7 +96,7 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
 
        clk_src = mxc_get_clock(MXC_CSPI_CLK);
 
-       div = clk_src / max_hz;
+       div = DIV_ROUND_UP(clk_src, max_hz);
        div = get_cspi_div(div);
 
        debug("clk %d Hz, div %d, real clk %d Hz\n",
@@ -204,7 +123,7 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
 }
 #endif
 
-#if defined(CONFIG_MX51)
+#ifdef MXC_ECSPI
 static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
                unsigned int max_hz, unsigned int mode)
 {
@@ -218,17 +137,21 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
                return -1;
        }
 
-       reg_ctrl = reg_read(&regs->ctrl);
-
-       /* Reset spi */
-       reg_write(&regs->ctrl, 0);
-       reg_write(&regs->ctrl, (reg_ctrl | 0x1));
+       /*
+        * Reset SPI and set all CSs to master mode, if toggling
+        * between slave and master mode we might see a glitch
+        * on the clock line
+        */
+       reg_ctrl = MXC_CSPICTRL_MODE_MASK;
+       reg_write(&regs->ctrl, reg_ctrl);
+       reg_ctrl |=  MXC_CSPICTRL_EN;
+       reg_write(&regs->ctrl, reg_ctrl);
 
        /*
         * The following computation is taken directly from Freescale's code.
         */
        if (clk_src > max_hz) {
-               pre_div = clk_src / max_hz;
+               pre_div = DIV_ROUND_UP(clk_src, max_hz);
                if (pre_div > 16) {
                        post_div = pre_div / 16;
                        pre_div = 15;
@@ -255,9 +178,6 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
        reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
                MXC_CSPICTRL_POSTDIV(post_div);
 
-       /* always set to master mode */
-       reg_ctrl |= 1 << (cs + 4);
-
        /* We need to disable SPI before changing registers */
        reg_ctrl &= ~MXC_CSPICTRL_EN;
 
@@ -316,7 +236,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
                MXC_CSPICTRL_BITCOUNT(bitlen - 1);
 
        reg_write(&regs->ctrl, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
-#ifdef CONFIG_MX51
+#ifdef MXC_ECSPI
        reg_write(&regs->cfg, mxcs->cfg_reg);
 #endif
 
@@ -468,7 +388,7 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
        if (cs > 3) {
                mxcs->gpio = cs >> 8;
                cs &= 3;
-               ret = gpio_direction_output(mxcs->gpio, 0);
+               ret = gpio_direction_output(mxcs->gpio, !(mxcs->ss_pol));
                if (ret) {
                        printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
                        return -EINVAL;
@@ -489,12 +409,14 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        if (bus >= ARRAY_SIZE(spi_bases))
                return NULL;
 
-       mxcs = malloc(sizeof(struct mxc_spi_slave));
+       mxcs = spi_alloc_slave(struct mxc_spi_slave, bus, cs);
        if (!mxcs) {
                puts("mxc_spi: SPI Slave not allocated !\n");
                return NULL;
        }
 
+       mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
+
        ret = decode_cs(mxcs, cs);
        if (ret < 0) {
                free(mxcs);
@@ -503,10 +425,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
        cs = ret;
 
-       mxcs->slave.bus = bus;
-       mxcs->slave.cs = cs;
        mxcs->base = spi_bases[bus];
-       mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
 
        ret = spi_cfg_mxc(mxcs, cs, max_hz, mode);
        if (ret) {