153736baaSDirk Behme /*
277b8d048SJagan Teki * Copyright (C) 2016 Jagan Teki <jteki@openedev.com>
377b8d048SJagan Teki * Christophe Ricard <christophe.ricard@gmail.com>
477b8d048SJagan Teki *
553736baaSDirk Behme * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
653736baaSDirk Behme *
753736baaSDirk Behme * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
853736baaSDirk Behme * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
953736baaSDirk Behme *
1053736baaSDirk Behme * Copyright (C) 2007 Atmel Corporation
1153736baaSDirk Behme *
1253736baaSDirk Behme * Parts taken from linux/drivers/spi/omap2_mcspi.c
1353736baaSDirk Behme * Copyright (C) 2005, 2006 Nokia Corporation
1453736baaSDirk Behme *
1553736baaSDirk Behme * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
1653736baaSDirk Behme *
171a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
1853736baaSDirk Behme */
1953736baaSDirk Behme
2053736baaSDirk Behme #include <common.h>
2177b8d048SJagan Teki #include <dm.h>
2253736baaSDirk Behme #include <spi.h>
2353736baaSDirk Behme #include <malloc.h>
2453736baaSDirk Behme #include <asm/io.h>
2553736baaSDirk Behme
2677b8d048SJagan Teki DECLARE_GLOBAL_DATA_PTR;
2777b8d048SJagan Teki
28682c1723SJagan Teki #if defined(CONFIG_AM33XX) || defined(CONFIG_AM43XX)
29682c1723SJagan Teki #define OMAP3_MCSPI1_BASE 0x48030100
30682c1723SJagan Teki #define OMAP3_MCSPI2_BASE 0x481A0100
31682c1723SJagan Teki #else
32682c1723SJagan Teki #define OMAP3_MCSPI1_BASE 0x48098000
33682c1723SJagan Teki #define OMAP3_MCSPI2_BASE 0x4809A000
34682c1723SJagan Teki #define OMAP3_MCSPI3_BASE 0x480B8000
35682c1723SJagan Teki #define OMAP3_MCSPI4_BASE 0x480BA000
36682c1723SJagan Teki #endif
37682c1723SJagan Teki
385f89a15eSMartin Hejnfelt #define OMAP4_MCSPI_REG_OFFSET 0x100
395f89a15eSMartin Hejnfelt
405f89a15eSMartin Hejnfelt struct omap2_mcspi_platform_config {
415f89a15eSMartin Hejnfelt unsigned int regs_offset;
425f89a15eSMartin Hejnfelt };
435f89a15eSMartin Hejnfelt
44682c1723SJagan Teki /* per-register bitmasks */
45682c1723SJagan Teki #define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
46682c1723SJagan Teki #define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2)
47682c1723SJagan Teki #define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE BIT(0)
48682c1723SJagan Teki #define OMAP3_MCSPI_SYSCONFIG_SOFTRESET BIT(1)
49682c1723SJagan Teki
50682c1723SJagan Teki #define OMAP3_MCSPI_SYSSTATUS_RESETDONE BIT(0)
51682c1723SJagan Teki
52682c1723SJagan Teki #define OMAP3_MCSPI_MODULCTRL_SINGLE BIT(0)
53682c1723SJagan Teki #define OMAP3_MCSPI_MODULCTRL_MS BIT(2)
54682c1723SJagan Teki #define OMAP3_MCSPI_MODULCTRL_STEST BIT(3)
55682c1723SJagan Teki
56682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_PHA BIT(0)
57682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_POL BIT(1)
58682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_CLKD_MASK GENMASK(5, 2)
59682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_EPOL BIT(6)
60682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_WL_MASK GENMASK(11, 7)
61682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY BIT(12)
62682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY BIT(13)
63682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_TRM_MASK GENMASK(13, 12)
64682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_DMAW BIT(14)
65682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_DMAR BIT(15)
66682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_DPE0 BIT(16)
67682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_DPE1 BIT(17)
68682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_IS BIT(18)
69682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_TURBO BIT(19)
70682c1723SJagan Teki #define OMAP3_MCSPI_CHCONF_FORCE BIT(20)
71682c1723SJagan Teki
72682c1723SJagan Teki #define OMAP3_MCSPI_CHSTAT_RXS BIT(0)
73682c1723SJagan Teki #define OMAP3_MCSPI_CHSTAT_TXS BIT(1)
74682c1723SJagan Teki #define OMAP3_MCSPI_CHSTAT_EOT BIT(2)
75682c1723SJagan Teki
76682c1723SJagan Teki #define OMAP3_MCSPI_CHCTRL_EN BIT(0)
77682c1723SJagan Teki #define OMAP3_MCSPI_CHCTRL_DIS (0 << 0)
78682c1723SJagan Teki
79682c1723SJagan Teki #define OMAP3_MCSPI_WAKEUPENABLE_WKEN BIT(0)
8077b8d048SJagan Teki #define MCSPI_PINDIR_D0_IN_D1_OUT 0
8177b8d048SJagan Teki #define MCSPI_PINDIR_D0_OUT_D1_IN 1
82682c1723SJagan Teki
83682c1723SJagan Teki #define OMAP3_MCSPI_MAX_FREQ 48000000
84611c9ba2SDavid Dueck #define SPI_WAIT_TIMEOUT 10
8553736baaSDirk Behme
86682c1723SJagan Teki /* OMAP3 McSPI registers */
87682c1723SJagan Teki struct mcspi_channel {
88682c1723SJagan Teki unsigned int chconf; /* 0x2C, 0x40, 0x54, 0x68 */
89682c1723SJagan Teki unsigned int chstat; /* 0x30, 0x44, 0x58, 0x6C */
90682c1723SJagan Teki unsigned int chctrl; /* 0x34, 0x48, 0x5C, 0x70 */
91682c1723SJagan Teki unsigned int tx; /* 0x38, 0x4C, 0x60, 0x74 */
92682c1723SJagan Teki unsigned int rx; /* 0x3C, 0x50, 0x64, 0x78 */
93682c1723SJagan Teki };
94682c1723SJagan Teki
95682c1723SJagan Teki struct mcspi {
96682c1723SJagan Teki unsigned char res1[0x10];
97682c1723SJagan Teki unsigned int sysconfig; /* 0x10 */
98682c1723SJagan Teki unsigned int sysstatus; /* 0x14 */
99682c1723SJagan Teki unsigned int irqstatus; /* 0x18 */
100682c1723SJagan Teki unsigned int irqenable; /* 0x1C */
101682c1723SJagan Teki unsigned int wakeupenable; /* 0x20 */
102682c1723SJagan Teki unsigned int syst; /* 0x24 */
103682c1723SJagan Teki unsigned int modulctrl; /* 0x28 */
104682c1723SJagan Teki struct mcspi_channel channel[4];
105682c1723SJagan Teki /* channel0: 0x2C - 0x3C, bus 0 & 1 & 2 & 3 */
106682c1723SJagan Teki /* channel1: 0x40 - 0x50, bus 0 & 1 */
107682c1723SJagan Teki /* channel2: 0x54 - 0x64, bus 0 & 1 */
108682c1723SJagan Teki /* channel3: 0x68 - 0x78, bus 0 */
109682c1723SJagan Teki };
110682c1723SJagan Teki
11177b8d048SJagan Teki struct omap3_spi_priv {
11241bccb81SJagan Teki #ifndef CONFIG_DM_SPI
11341bccb81SJagan Teki struct spi_slave slave;
11441bccb81SJagan Teki #endif
115682c1723SJagan Teki struct mcspi *regs;
11677b8d048SJagan Teki unsigned int cs;
117682c1723SJagan Teki unsigned int freq;
118682c1723SJagan Teki unsigned int mode;
11977b8d048SJagan Teki unsigned int wordlen;
12077b8d048SJagan Teki unsigned int pin_dir:1;
121682c1723SJagan Teki };
122682c1723SJagan Teki
omap3_spi_write_chconf(struct omap3_spi_priv * priv,int val)12377b8d048SJagan Teki static void omap3_spi_write_chconf(struct omap3_spi_priv *priv, int val)
12477b8d048SJagan Teki {
12577b8d048SJagan Teki writel(val, &priv->regs->channel[priv->cs].chconf);
12677b8d048SJagan Teki /* Flash post writes to make immediate effect */
12777b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chconf);
12877b8d048SJagan Teki }
12977b8d048SJagan Teki
omap3_spi_set_enable(struct omap3_spi_priv * priv,int enable)13077b8d048SJagan Teki static void omap3_spi_set_enable(struct omap3_spi_priv *priv, int enable)
13177b8d048SJagan Teki {
13277b8d048SJagan Teki writel(enable, &priv->regs->channel[priv->cs].chctrl);
13377b8d048SJagan Teki /* Flash post writes to make immediate effect */
13477b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chctrl);
13577b8d048SJagan Teki }
13677b8d048SJagan Teki
omap3_spi_write(struct omap3_spi_priv * priv,unsigned int len,const void * txp,unsigned long flags)13777b8d048SJagan Teki static int omap3_spi_write(struct omap3_spi_priv *priv, unsigned int len,
13877b8d048SJagan Teki const void *txp, unsigned long flags)
13977b8d048SJagan Teki {
14077b8d048SJagan Teki ulong start;
14177b8d048SJagan Teki int i, chconf;
14277b8d048SJagan Teki
14377b8d048SJagan Teki chconf = readl(&priv->regs->channel[priv->cs].chconf);
14477b8d048SJagan Teki
14577b8d048SJagan Teki /* Enable the channel */
14677b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
14777b8d048SJagan Teki
14877b8d048SJagan Teki chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
14977b8d048SJagan Teki chconf |= (priv->wordlen - 1) << 7;
15077b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
15177b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_FORCE;
15277b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
15377b8d048SJagan Teki
15477b8d048SJagan Teki for (i = 0; i < len; i++) {
15577b8d048SJagan Teki /* wait till TX register is empty (TXS == 1) */
15677b8d048SJagan Teki start = get_timer(0);
15777b8d048SJagan Teki while (!(readl(&priv->regs->channel[priv->cs].chstat) &
15877b8d048SJagan Teki OMAP3_MCSPI_CHSTAT_TXS)) {
15977b8d048SJagan Teki if (get_timer(start) > SPI_WAIT_TIMEOUT) {
16077b8d048SJagan Teki printf("SPI TXS timed out, status=0x%08x\n",
16177b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chstat));
16277b8d048SJagan Teki return -1;
16377b8d048SJagan Teki }
16477b8d048SJagan Teki }
16577b8d048SJagan Teki /* Write the data */
16677b8d048SJagan Teki unsigned int *tx = &priv->regs->channel[priv->cs].tx;
16777b8d048SJagan Teki if (priv->wordlen > 16)
16877b8d048SJagan Teki writel(((u32 *)txp)[i], tx);
16977b8d048SJagan Teki else if (priv->wordlen > 8)
17077b8d048SJagan Teki writel(((u16 *)txp)[i], tx);
17177b8d048SJagan Teki else
17277b8d048SJagan Teki writel(((u8 *)txp)[i], tx);
17377b8d048SJagan Teki }
17477b8d048SJagan Teki
17577b8d048SJagan Teki /* wait to finish of transfer */
17677b8d048SJagan Teki while ((readl(&priv->regs->channel[priv->cs].chstat) &
17777b8d048SJagan Teki (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
17877b8d048SJagan Teki (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS))
17977b8d048SJagan Teki ;
18077b8d048SJagan Teki
18177b8d048SJagan Teki /* Disable the channel otherwise the next immediate RX will get affected */
18277b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
18377b8d048SJagan Teki
18477b8d048SJagan Teki if (flags & SPI_XFER_END) {
18577b8d048SJagan Teki
18677b8d048SJagan Teki chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
18777b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
18877b8d048SJagan Teki }
18977b8d048SJagan Teki return 0;
19077b8d048SJagan Teki }
19177b8d048SJagan Teki
omap3_spi_read(struct omap3_spi_priv * priv,unsigned int len,void * rxp,unsigned long flags)19277b8d048SJagan Teki static int omap3_spi_read(struct omap3_spi_priv *priv, unsigned int len,
19377b8d048SJagan Teki void *rxp, unsigned long flags)
19477b8d048SJagan Teki {
19577b8d048SJagan Teki int i, chconf;
19677b8d048SJagan Teki ulong start;
19777b8d048SJagan Teki
19877b8d048SJagan Teki chconf = readl(&priv->regs->channel[priv->cs].chconf);
19977b8d048SJagan Teki
20077b8d048SJagan Teki /* Enable the channel */
20177b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
20277b8d048SJagan Teki
20377b8d048SJagan Teki chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
20477b8d048SJagan Teki chconf |= (priv->wordlen - 1) << 7;
20577b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
20677b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_FORCE;
20777b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
20877b8d048SJagan Teki
20977b8d048SJagan Teki writel(0, &priv->regs->channel[priv->cs].tx);
21077b8d048SJagan Teki
21177b8d048SJagan Teki for (i = 0; i < len; i++) {
21277b8d048SJagan Teki start = get_timer(0);
21377b8d048SJagan Teki /* Wait till RX register contains data (RXS == 1) */
21477b8d048SJagan Teki while (!(readl(&priv->regs->channel[priv->cs].chstat) &
21577b8d048SJagan Teki OMAP3_MCSPI_CHSTAT_RXS)) {
21677b8d048SJagan Teki if (get_timer(start) > SPI_WAIT_TIMEOUT) {
21777b8d048SJagan Teki printf("SPI RXS timed out, status=0x%08x\n",
21877b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chstat));
21977b8d048SJagan Teki return -1;
22077b8d048SJagan Teki }
22177b8d048SJagan Teki }
22277b8d048SJagan Teki
22377b8d048SJagan Teki /* Disable the channel to prevent furher receiving */
22477b8d048SJagan Teki if (i == (len - 1))
22577b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
22677b8d048SJagan Teki
22777b8d048SJagan Teki /* Read the data */
22877b8d048SJagan Teki unsigned int *rx = &priv->regs->channel[priv->cs].rx;
22977b8d048SJagan Teki if (priv->wordlen > 16)
23077b8d048SJagan Teki ((u32 *)rxp)[i] = readl(rx);
23177b8d048SJagan Teki else if (priv->wordlen > 8)
23277b8d048SJagan Teki ((u16 *)rxp)[i] = (u16)readl(rx);
23377b8d048SJagan Teki else
23477b8d048SJagan Teki ((u8 *)rxp)[i] = (u8)readl(rx);
23577b8d048SJagan Teki }
23677b8d048SJagan Teki
23777b8d048SJagan Teki if (flags & SPI_XFER_END) {
23877b8d048SJagan Teki chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
23977b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
24077b8d048SJagan Teki }
24177b8d048SJagan Teki
24277b8d048SJagan Teki return 0;
24377b8d048SJagan Teki }
24477b8d048SJagan Teki
24577b8d048SJagan Teki /*McSPI Transmit Receive Mode*/
omap3_spi_txrx(struct omap3_spi_priv * priv,unsigned int len,const void * txp,void * rxp,unsigned long flags)24677b8d048SJagan Teki static int omap3_spi_txrx(struct omap3_spi_priv *priv, unsigned int len,
24777b8d048SJagan Teki const void *txp, void *rxp, unsigned long flags)
24877b8d048SJagan Teki {
24977b8d048SJagan Teki ulong start;
25077b8d048SJagan Teki int chconf, i = 0;
25177b8d048SJagan Teki
25277b8d048SJagan Teki chconf = readl(&priv->regs->channel[priv->cs].chconf);
25377b8d048SJagan Teki
25477b8d048SJagan Teki /*Enable SPI channel*/
25577b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
25677b8d048SJagan Teki
25777b8d048SJagan Teki /*set TRANSMIT-RECEIVE Mode*/
25877b8d048SJagan Teki chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
25977b8d048SJagan Teki chconf |= (priv->wordlen - 1) << 7;
26077b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_FORCE;
26177b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
26277b8d048SJagan Teki
26377b8d048SJagan Teki /*Shift in and out 1 byte at time*/
26477b8d048SJagan Teki for (i=0; i < len; i++){
26577b8d048SJagan Teki /* Write: wait for TX empty (TXS == 1)*/
26677b8d048SJagan Teki start = get_timer(0);
26777b8d048SJagan Teki while (!(readl(&priv->regs->channel[priv->cs].chstat) &
26877b8d048SJagan Teki OMAP3_MCSPI_CHSTAT_TXS)) {
26977b8d048SJagan Teki if (get_timer(start) > SPI_WAIT_TIMEOUT) {
27077b8d048SJagan Teki printf("SPI TXS timed out, status=0x%08x\n",
27177b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chstat));
27277b8d048SJagan Teki return -1;
27377b8d048SJagan Teki }
27477b8d048SJagan Teki }
27577b8d048SJagan Teki /* Write the data */
27677b8d048SJagan Teki unsigned int *tx = &priv->regs->channel[priv->cs].tx;
27777b8d048SJagan Teki if (priv->wordlen > 16)
27877b8d048SJagan Teki writel(((u32 *)txp)[i], tx);
27977b8d048SJagan Teki else if (priv->wordlen > 8)
28077b8d048SJagan Teki writel(((u16 *)txp)[i], tx);
28177b8d048SJagan Teki else
28277b8d048SJagan Teki writel(((u8 *)txp)[i], tx);
28377b8d048SJagan Teki
28477b8d048SJagan Teki /*Read: wait for RX containing data (RXS == 1)*/
28577b8d048SJagan Teki start = get_timer(0);
28677b8d048SJagan Teki while (!(readl(&priv->regs->channel[priv->cs].chstat) &
28777b8d048SJagan Teki OMAP3_MCSPI_CHSTAT_RXS)) {
28877b8d048SJagan Teki if (get_timer(start) > SPI_WAIT_TIMEOUT) {
28977b8d048SJagan Teki printf("SPI RXS timed out, status=0x%08x\n",
29077b8d048SJagan Teki readl(&priv->regs->channel[priv->cs].chstat));
29177b8d048SJagan Teki return -1;
29277b8d048SJagan Teki }
29377b8d048SJagan Teki }
29477b8d048SJagan Teki /* Read the data */
29577b8d048SJagan Teki unsigned int *rx = &priv->regs->channel[priv->cs].rx;
29677b8d048SJagan Teki if (priv->wordlen > 16)
29777b8d048SJagan Teki ((u32 *)rxp)[i] = readl(rx);
29877b8d048SJagan Teki else if (priv->wordlen > 8)
29977b8d048SJagan Teki ((u16 *)rxp)[i] = (u16)readl(rx);
30077b8d048SJagan Teki else
30177b8d048SJagan Teki ((u8 *)rxp)[i] = (u8)readl(rx);
30277b8d048SJagan Teki }
30377b8d048SJagan Teki /* Disable the channel */
30477b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
30577b8d048SJagan Teki
30677b8d048SJagan Teki /*if transfer must be terminated disable the channel*/
30777b8d048SJagan Teki if (flags & SPI_XFER_END) {
30877b8d048SJagan Teki chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
30977b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
31077b8d048SJagan Teki }
31177b8d048SJagan Teki
31277b8d048SJagan Teki return 0;
31377b8d048SJagan Teki }
31477b8d048SJagan Teki
_spi_xfer(struct omap3_spi_priv * priv,unsigned int bitlen,const void * dout,void * din,unsigned long flags)31577b8d048SJagan Teki static int _spi_xfer(struct omap3_spi_priv *priv, unsigned int bitlen,
31677b8d048SJagan Teki const void *dout, void *din, unsigned long flags)
31777b8d048SJagan Teki {
31877b8d048SJagan Teki unsigned int len;
31977b8d048SJagan Teki int ret = -1;
32077b8d048SJagan Teki
32177b8d048SJagan Teki if (priv->wordlen < 4 || priv->wordlen > 32) {
32277b8d048SJagan Teki printf("omap3_spi: invalid wordlen %d\n", priv->wordlen);
32377b8d048SJagan Teki return -1;
32477b8d048SJagan Teki }
32577b8d048SJagan Teki
32677b8d048SJagan Teki if (bitlen % priv->wordlen)
32777b8d048SJagan Teki return -1;
32877b8d048SJagan Teki
32977b8d048SJagan Teki len = bitlen / priv->wordlen;
33077b8d048SJagan Teki
33177b8d048SJagan Teki if (bitlen == 0) { /* only change CS */
33277b8d048SJagan Teki int chconf = readl(&priv->regs->channel[priv->cs].chconf);
33377b8d048SJagan Teki
33477b8d048SJagan Teki if (flags & SPI_XFER_BEGIN) {
33577b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_EN);
33677b8d048SJagan Teki chconf |= OMAP3_MCSPI_CHCONF_FORCE;
33777b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
33877b8d048SJagan Teki }
33977b8d048SJagan Teki if (flags & SPI_XFER_END) {
34077b8d048SJagan Teki chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
34177b8d048SJagan Teki omap3_spi_write_chconf(priv, chconf);
34277b8d048SJagan Teki omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
34377b8d048SJagan Teki }
34477b8d048SJagan Teki ret = 0;
34577b8d048SJagan Teki } else {
34677b8d048SJagan Teki if (dout != NULL && din != NULL)
34777b8d048SJagan Teki ret = omap3_spi_txrx(priv, len, dout, din, flags);
34877b8d048SJagan Teki else if (dout != NULL)
34977b8d048SJagan Teki ret = omap3_spi_write(priv, len, dout, flags);
35077b8d048SJagan Teki else if (din != NULL)
35177b8d048SJagan Teki ret = omap3_spi_read(priv, len, din, flags);
35277b8d048SJagan Teki }
35377b8d048SJagan Teki return ret;
35477b8d048SJagan Teki }
35577b8d048SJagan Teki
_omap3_spi_set_speed(struct omap3_spi_priv * priv)35677b8d048SJagan Teki static void _omap3_spi_set_speed(struct omap3_spi_priv *priv)
35777b8d048SJagan Teki {
35877b8d048SJagan Teki uint32_t confr, div = 0;
35977b8d048SJagan Teki
36077b8d048SJagan Teki confr = readl(&priv->regs->channel[priv->cs].chconf);
36177b8d048SJagan Teki
36277b8d048SJagan Teki /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
36377b8d048SJagan Teki if (priv->freq) {
36477b8d048SJagan Teki while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
36577b8d048SJagan Teki > priv->freq)
36677b8d048SJagan Teki div++;
36777b8d048SJagan Teki } else {
36877b8d048SJagan Teki div = 0xC;
36977b8d048SJagan Teki }
37077b8d048SJagan Teki
37177b8d048SJagan Teki /* set clock divisor */
37277b8d048SJagan Teki confr &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
37377b8d048SJagan Teki confr |= div << 2;
37477b8d048SJagan Teki
37577b8d048SJagan Teki omap3_spi_write_chconf(priv, confr);
37677b8d048SJagan Teki }
37777b8d048SJagan Teki
_omap3_spi_set_mode(struct omap3_spi_priv * priv)37877b8d048SJagan Teki static void _omap3_spi_set_mode(struct omap3_spi_priv *priv)
37977b8d048SJagan Teki {
38077b8d048SJagan Teki uint32_t confr;
38177b8d048SJagan Teki
38277b8d048SJagan Teki confr = readl(&priv->regs->channel[priv->cs].chconf);
38377b8d048SJagan Teki
38477b8d048SJagan Teki /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
38577b8d048SJagan Teki * REVISIT: this controller could support SPI_3WIRE mode.
38677b8d048SJagan Teki */
38777b8d048SJagan Teki if (priv->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
38877b8d048SJagan Teki confr &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
38977b8d048SJagan Teki confr |= OMAP3_MCSPI_CHCONF_DPE0;
39077b8d048SJagan Teki } else {
39177b8d048SJagan Teki confr &= ~OMAP3_MCSPI_CHCONF_DPE0;
39277b8d048SJagan Teki confr |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
39377b8d048SJagan Teki }
39477b8d048SJagan Teki
39577b8d048SJagan Teki /* set SPI mode 0..3 */
39677b8d048SJagan Teki confr &= ~(OMAP3_MCSPI_CHCONF_POL | OMAP3_MCSPI_CHCONF_PHA);
39777b8d048SJagan Teki if (priv->mode & SPI_CPHA)
39877b8d048SJagan Teki confr |= OMAP3_MCSPI_CHCONF_PHA;
39977b8d048SJagan Teki if (priv->mode & SPI_CPOL)
40077b8d048SJagan Teki confr |= OMAP3_MCSPI_CHCONF_POL;
40177b8d048SJagan Teki
40277b8d048SJagan Teki /* set chipselect polarity; manage with FORCE */
40377b8d048SJagan Teki if (!(priv->mode & SPI_CS_HIGH))
40477b8d048SJagan Teki confr |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
40577b8d048SJagan Teki else
40677b8d048SJagan Teki confr &= ~OMAP3_MCSPI_CHCONF_EPOL;
40777b8d048SJagan Teki
40877b8d048SJagan Teki /* Transmit & receive mode */
40977b8d048SJagan Teki confr &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
41077b8d048SJagan Teki
41177b8d048SJagan Teki omap3_spi_write_chconf(priv, confr);
41277b8d048SJagan Teki }
41377b8d048SJagan Teki
_omap3_spi_set_wordlen(struct omap3_spi_priv * priv)41477b8d048SJagan Teki static void _omap3_spi_set_wordlen(struct omap3_spi_priv *priv)
41577b8d048SJagan Teki {
41677b8d048SJagan Teki unsigned int confr;
41777b8d048SJagan Teki
41877b8d048SJagan Teki /* McSPI individual channel configuration */
41977b8d048SJagan Teki confr = readl(&priv->regs->channel[priv->wordlen].chconf);
42077b8d048SJagan Teki
42177b8d048SJagan Teki /* wordlength */
42277b8d048SJagan Teki confr &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
42377b8d048SJagan Teki confr |= (priv->wordlen - 1) << 7;
42477b8d048SJagan Teki
42577b8d048SJagan Teki omap3_spi_write_chconf(priv, confr);
42677b8d048SJagan Teki }
42777b8d048SJagan Teki
spi_reset(struct mcspi * regs)42877b8d048SJagan Teki static void spi_reset(struct mcspi *regs)
42977b8d048SJagan Teki {
43077b8d048SJagan Teki unsigned int tmp;
43177b8d048SJagan Teki
43277b8d048SJagan Teki writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, ®s->sysconfig);
43377b8d048SJagan Teki do {
43477b8d048SJagan Teki tmp = readl(®s->sysstatus);
43577b8d048SJagan Teki } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
43677b8d048SJagan Teki
43777b8d048SJagan Teki writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
43877b8d048SJagan Teki OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
43977b8d048SJagan Teki OMAP3_MCSPI_SYSCONFIG_SMARTIDLE, ®s->sysconfig);
44077b8d048SJagan Teki
44177b8d048SJagan Teki writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, ®s->wakeupenable);
44277b8d048SJagan Teki }
44377b8d048SJagan Teki
_omap3_spi_claim_bus(struct omap3_spi_priv * priv)44477b8d048SJagan Teki static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv)
44577b8d048SJagan Teki {
44677b8d048SJagan Teki unsigned int conf;
44777b8d048SJagan Teki
44877b8d048SJagan Teki spi_reset(priv->regs);
44977b8d048SJagan Teki
45077b8d048SJagan Teki /*
45177b8d048SJagan Teki * setup when switching from (reset default) slave mode
45277b8d048SJagan Teki * to single-channel master mode
45377b8d048SJagan Teki */
45477b8d048SJagan Teki conf = readl(&priv->regs->modulctrl);
45577b8d048SJagan Teki conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
45677b8d048SJagan Teki conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
45777b8d048SJagan Teki
45877b8d048SJagan Teki writel(conf, &priv->regs->modulctrl);
45977b8d048SJagan Teki }
46077b8d048SJagan Teki
46177b8d048SJagan Teki #ifndef CONFIG_DM_SPI
46277b8d048SJagan Teki
to_omap3_spi(struct spi_slave * slave)46341bccb81SJagan Teki static inline struct omap3_spi_priv *to_omap3_spi(struct spi_slave *slave)
464682c1723SJagan Teki {
46541bccb81SJagan Teki return container_of(slave, struct omap3_spi_priv, slave);
466682c1723SJagan Teki }
467682c1723SJagan Teki
spi_init(void)46877b8d048SJagan Teki void spi_init(void)
46953736baaSDirk Behme {
47053736baaSDirk Behme /* do nothing */
47153736baaSDirk Behme }
47253736baaSDirk Behme
spi_free_slave(struct spi_slave * slave)47377b8d048SJagan Teki void spi_free_slave(struct spi_slave *slave)
47477b8d048SJagan Teki {
47541bccb81SJagan Teki struct omap3_spi_priv *priv = to_omap3_spi(slave);
47677b8d048SJagan Teki
47741bccb81SJagan Teki free(priv);
47877b8d048SJagan Teki }
47977b8d048SJagan Teki
spi_claim_bus(struct spi_slave * slave)48077b8d048SJagan Teki int spi_claim_bus(struct spi_slave *slave)
48177b8d048SJagan Teki {
48241bccb81SJagan Teki struct omap3_spi_priv *priv = to_omap3_spi(slave);
48341bccb81SJagan Teki
48477b8d048SJagan Teki _omap3_spi_claim_bus(priv);
48577b8d048SJagan Teki _omap3_spi_set_wordlen(priv);
48677b8d048SJagan Teki _omap3_spi_set_mode(priv);
48777b8d048SJagan Teki _omap3_spi_set_speed(priv);
48877b8d048SJagan Teki
48977b8d048SJagan Teki return 0;
49077b8d048SJagan Teki }
49177b8d048SJagan Teki
spi_release_bus(struct spi_slave * slave)49277b8d048SJagan Teki void spi_release_bus(struct spi_slave *slave)
49377b8d048SJagan Teki {
49441bccb81SJagan Teki struct omap3_spi_priv *priv = to_omap3_spi(slave);
49541bccb81SJagan Teki
49677b8d048SJagan Teki /* Reset the SPI hardware */
49777b8d048SJagan Teki spi_reset(priv->regs);
49877b8d048SJagan Teki }
49977b8d048SJagan Teki
spi_setup_slave(unsigned int bus,unsigned int cs,unsigned int max_hz,unsigned int mode)50053736baaSDirk Behme struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
50153736baaSDirk Behme unsigned int max_hz, unsigned int mode)
50253736baaSDirk Behme {
50341bccb81SJagan Teki struct omap3_spi_priv *priv;
504d3504feeSSimon Glass struct mcspi *regs;
50553736baaSDirk Behme
50653736baaSDirk Behme /*
50753736baaSDirk Behme * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
50853736baaSDirk Behme * with different number of chip selects (CS, channels):
50953736baaSDirk Behme * McSPI1 has 4 CS (bus 0, cs 0 - 3)
51053736baaSDirk Behme * McSPI2 has 2 CS (bus 1, cs 0 - 1)
51153736baaSDirk Behme * McSPI3 has 2 CS (bus 2, cs 0 - 1)
51253736baaSDirk Behme * McSPI4 has 1 CS (bus 3, cs 0)
51353736baaSDirk Behme */
51453736baaSDirk Behme
51553736baaSDirk Behme switch (bus) {
51653736baaSDirk Behme case 0:
517d3504feeSSimon Glass regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
51853736baaSDirk Behme break;
5194c0620bfSTom Rini #ifdef OMAP3_MCSPI2_BASE
52053736baaSDirk Behme case 1:
521d3504feeSSimon Glass regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
52253736baaSDirk Behme break;
5234c0620bfSTom Rini #endif
5244c0620bfSTom Rini #ifdef OMAP3_MCSPI3_BASE
52553736baaSDirk Behme case 2:
526d3504feeSSimon Glass regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
52753736baaSDirk Behme break;
5284c0620bfSTom Rini #endif
5294c0620bfSTom Rini #ifdef OMAP3_MCSPI4_BASE
53053736baaSDirk Behme case 3:
531d3504feeSSimon Glass regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
53253736baaSDirk Behme break;
5334c0620bfSTom Rini #endif
53453736baaSDirk Behme default:
53577b8d048SJagan Teki printf("SPI error: unsupported bus %i. Supported busses 0 - 3\n", bus);
53653736baaSDirk Behme return NULL;
53753736baaSDirk Behme }
53853736baaSDirk Behme
53953736baaSDirk Behme if (((bus == 0) && (cs > 3)) ||
54053736baaSDirk Behme ((bus == 1) && (cs > 1)) ||
54153736baaSDirk Behme ((bus == 2) && (cs > 1)) ||
54253736baaSDirk Behme ((bus == 3) && (cs > 0))) {
54377b8d048SJagan Teki printf("SPI error: unsupported chip select %i on bus %i\n", cs, bus);
54453736baaSDirk Behme return NULL;
54553736baaSDirk Behme }
54653736baaSDirk Behme
54753736baaSDirk Behme if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
54853854334SHeinrich Schuchardt printf("SPI error: unsupported frequency %i Hz. Max frequency is 48 MHz\n",
54953854334SHeinrich Schuchardt max_hz);
55053736baaSDirk Behme return NULL;
55153736baaSDirk Behme }
55253736baaSDirk Behme
55353736baaSDirk Behme if (mode > SPI_MODE_3) {
55453736baaSDirk Behme printf("SPI error: unsupported SPI mode %i\n", mode);
55553736baaSDirk Behme return NULL;
55653736baaSDirk Behme }
557d3504feeSSimon Glass
55841bccb81SJagan Teki priv = spi_alloc_slave(struct omap3_spi_priv, bus, cs);
55941bccb81SJagan Teki if (!priv) {
560d3504feeSSimon Glass printf("SPI error: malloc of SPI structure failed\n");
561d3504feeSSimon Glass return NULL;
562d3504feeSSimon Glass }
563d3504feeSSimon Glass
56477b8d048SJagan Teki priv->regs = regs;
56577b8d048SJagan Teki priv->cs = cs;
56677b8d048SJagan Teki priv->freq = max_hz;
56777b8d048SJagan Teki priv->mode = mode;
56841bccb81SJagan Teki priv->wordlen = priv->slave.wordlen;
56925eaa288STom Rini #if 0
57025eaa288STom Rini /* Please migrate to DM_SPI support for this feature. */
57177b8d048SJagan Teki priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
57277b8d048SJagan Teki #endif
57353736baaSDirk Behme
57441bccb81SJagan Teki return &priv->slave;
57553736baaSDirk Behme }
57653736baaSDirk Behme
spi_xfer(struct spi_slave * slave,unsigned int bitlen,const void * dout,void * din,unsigned long flags)57753736baaSDirk Behme int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
57853736baaSDirk Behme const void *dout, void *din, unsigned long flags)
57941bccb81SJagan Teki {
58041bccb81SJagan Teki struct omap3_spi_priv *priv = to_omap3_spi(slave);
58141bccb81SJagan Teki
58241bccb81SJagan Teki return _spi_xfer(priv, bitlen, dout, din, flags);
58341bccb81SJagan Teki }
58477b8d048SJagan Teki
58577b8d048SJagan Teki #else
58677b8d048SJagan Teki
omap3_spi_claim_bus(struct udevice * dev)58777b8d048SJagan Teki static int omap3_spi_claim_bus(struct udevice *dev)
58853736baaSDirk Behme {
58977b8d048SJagan Teki struct udevice *bus = dev->parent;
59077b8d048SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
59177b8d048SJagan Teki struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
59253736baaSDirk Behme
59377b8d048SJagan Teki priv->cs = slave_plat->cs;
59477b8d048SJagan Teki _omap3_spi_claim_bus(priv);
59577b8d048SJagan Teki
59677b8d048SJagan Teki return 0;
5975753d09bSNikita Kiryanov }
5985753d09bSNikita Kiryanov
omap3_spi_release_bus(struct udevice * dev)59977b8d048SJagan Teki static int omap3_spi_release_bus(struct udevice *dev)
60053736baaSDirk Behme {
60177b8d048SJagan Teki struct udevice *bus = dev->parent;
60277b8d048SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
60377b8d048SJagan Teki
60477b8d048SJagan Teki /* Reset the SPI hardware */
60577b8d048SJagan Teki spi_reset(priv->regs);
60677b8d048SJagan Teki
60777b8d048SJagan Teki return 0;
60853736baaSDirk Behme }
60953736baaSDirk Behme
omap3_spi_set_wordlen(struct udevice * dev,unsigned int wordlen)61077b8d048SJagan Teki static int omap3_spi_set_wordlen(struct udevice *dev, unsigned int wordlen)
61153736baaSDirk Behme {
61277b8d048SJagan Teki struct udevice *bus = dev->parent;
61377b8d048SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
61477b8d048SJagan Teki struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
61577b8d048SJagan Teki
61677b8d048SJagan Teki priv->cs = slave_plat->cs;
61777b8d048SJagan Teki priv->wordlen = wordlen;
61877b8d048SJagan Teki _omap3_spi_set_wordlen(priv);
61977b8d048SJagan Teki
62077b8d048SJagan Teki return 0;
62153736baaSDirk Behme }
62253736baaSDirk Behme
omap3_spi_probe(struct udevice * dev)62377b8d048SJagan Teki static int omap3_spi_probe(struct udevice *dev)
62453736baaSDirk Behme {
62577b8d048SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(dev);
62677b8d048SJagan Teki const void *blob = gd->fdt_blob;
627e160f7d4SSimon Glass int node = dev_of_offset(dev);
62877b8d048SJagan Teki
6295f89a15eSMartin Hejnfelt struct omap2_mcspi_platform_config* data =
6305f89a15eSMartin Hejnfelt (struct omap2_mcspi_platform_config*)dev_get_driver_data(dev);
6315f89a15eSMartin Hejnfelt
632a821c4afSSimon Glass priv->regs = (struct mcspi *)(devfdt_get_addr(dev) + data->regs_offset);
633*cafc6911SSjoerd Simons if (fdtdec_get_bool(blob, node, "ti,pindir-d0-out-d1-in"))
634*cafc6911SSjoerd Simons priv->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
635*cafc6911SSjoerd Simons else
636*cafc6911SSjoerd Simons priv->pin_dir = MCSPI_PINDIR_D0_IN_D1_OUT;
63777b8d048SJagan Teki priv->wordlen = SPI_DEFAULT_WORDLEN;
63877b8d048SJagan Teki return 0;
63953736baaSDirk Behme }
64077b8d048SJagan Teki
omap3_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)64177b8d048SJagan Teki static int omap3_spi_xfer(struct udevice *dev, unsigned int bitlen,
64277b8d048SJagan Teki const void *dout, void *din, unsigned long flags)
64377b8d048SJagan Teki {
64477b8d048SJagan Teki struct udevice *bus = dev->parent;
64577b8d048SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
64677b8d048SJagan Teki
64777b8d048SJagan Teki return _spi_xfer(priv, bitlen, dout, din, flags);
64877b8d048SJagan Teki }
64977b8d048SJagan Teki
omap3_spi_set_speed(struct udevice * dev,unsigned int speed)65043e86b9aSJagan Teki static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed)
65177b8d048SJagan Teki {
652226998e3SJagan Teki struct udevice *bus = dev->parent;
653226998e3SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
654226998e3SJagan Teki struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
655226998e3SJagan Teki
656226998e3SJagan Teki priv->cs = slave_plat->cs;
657226998e3SJagan Teki priv->freq = slave_plat->max_hz;
658226998e3SJagan Teki _omap3_spi_set_speed(priv);
659226998e3SJagan Teki
66077b8d048SJagan Teki return 0;
66177b8d048SJagan Teki }
66277b8d048SJagan Teki
omap3_spi_set_mode(struct udevice * dev,uint mode)66343e86b9aSJagan Teki static int omap3_spi_set_mode(struct udevice *dev, uint mode)
66477b8d048SJagan Teki {
665226998e3SJagan Teki struct udevice *bus = dev->parent;
666226998e3SJagan Teki struct omap3_spi_priv *priv = dev_get_priv(bus);
667226998e3SJagan Teki struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
668226998e3SJagan Teki
669226998e3SJagan Teki priv->cs = slave_plat->cs;
670226998e3SJagan Teki priv->mode = slave_plat->mode;
671226998e3SJagan Teki _omap3_spi_set_mode(priv);
672226998e3SJagan Teki
67377b8d048SJagan Teki return 0;
67477b8d048SJagan Teki }
67577b8d048SJagan Teki
67677b8d048SJagan Teki static const struct dm_spi_ops omap3_spi_ops = {
67777b8d048SJagan Teki .claim_bus = omap3_spi_claim_bus,
67877b8d048SJagan Teki .release_bus = omap3_spi_release_bus,
67977b8d048SJagan Teki .set_wordlen = omap3_spi_set_wordlen,
68077b8d048SJagan Teki .xfer = omap3_spi_xfer,
68177b8d048SJagan Teki .set_speed = omap3_spi_set_speed,
68277b8d048SJagan Teki .set_mode = omap3_spi_set_mode,
68377b8d048SJagan Teki /*
68477b8d048SJagan Teki * cs_info is not needed, since we require all chip selects to be
68577b8d048SJagan Teki * in the device tree explicitly
68677b8d048SJagan Teki */
68777b8d048SJagan Teki };
68877b8d048SJagan Teki
6895f89a15eSMartin Hejnfelt static struct omap2_mcspi_platform_config omap2_pdata = {
6905f89a15eSMartin Hejnfelt .regs_offset = 0,
6915f89a15eSMartin Hejnfelt };
6925f89a15eSMartin Hejnfelt
6935f89a15eSMartin Hejnfelt static struct omap2_mcspi_platform_config omap4_pdata = {
6945f89a15eSMartin Hejnfelt .regs_offset = OMAP4_MCSPI_REG_OFFSET,
6955f89a15eSMartin Hejnfelt };
6965f89a15eSMartin Hejnfelt
69777b8d048SJagan Teki static const struct udevice_id omap3_spi_ids[] = {
6985f89a15eSMartin Hejnfelt { .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata },
6995f89a15eSMartin Hejnfelt { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata },
70077b8d048SJagan Teki { }
70177b8d048SJagan Teki };
70277b8d048SJagan Teki
70377b8d048SJagan Teki U_BOOT_DRIVER(omap3_spi) = {
70477b8d048SJagan Teki .name = "omap3_spi",
70577b8d048SJagan Teki .id = UCLASS_SPI,
70677b8d048SJagan Teki .of_match = omap3_spi_ids,
70777b8d048SJagan Teki .probe = omap3_spi_probe,
70877b8d048SJagan Teki .ops = &omap3_spi_ops,
70977b8d048SJagan Teki .priv_auto_alloc_size = sizeof(struct omap3_spi_priv),
71077b8d048SJagan Teki };
71177b8d048SJagan Teki #endif
712