Commit 96836edc authored by Pablo Bitton's avatar Pablo Bitton Committed by James Toy

Add support for SPI in DaVinci DM6446 (and try to keep support for

DM355/DM365/DM6467 and DA8xx).  Mostly the same as the patch by Sandeep
Paulraj.

This has been tested on the DM6446 by defining a spidev device and using a
scope (to check correctness) and a hardware loopback.

This was NOT tested on DM355, DM365 and DM6467 - in fact, it will probably
not work "as is" because its default mode is CS low-inactive (default mode
of SPI in kernel) - need to set CS_HIGH mode to work as in the previous
patch.

Changes from the patch by Sandeep Paulraj:

Bug fixes:
 * Additional word written with chip select up after each transfer.
   Particulary problematic with NO_CS mode where this word can't be
   distiguished from correct words. Problem was in davinci_chip_select.
 * setup() for one chip select may interfere with transfer for another
 * Small nitpicks (bits that can be changed only on VERSION_2)

Features added:
 * Support DM6446
 * Support CS_HIGH mode (using SPIDEF register). Note that CS low is default.

Other:
 * Less accesses to registers used.
 * Once-per-device configuration is done only in probe(), not each transfer.

Uglyness still there:
 * VERSION_X definitions for different SPI controllers - added VERSION_3
   for the dm6446, which is ugly.

NOTE:
This patch is based on following patches:

SPI: DaVinci: Adding SPI driver for DM3xx/DM6467/DA8xx

 The patch adds support for SPI in DaVinci
 DM355/DM365/DM6467 and DA8xx.

 This has been tested on the DM355, DM365 and DM6467 EVMs using
 the EEPROM connected to SPI0
Signed-off-by: default avatarSandeep Paulraj <s-paulraj@ti.com>

DaVinci: DM646x: Adding Support for SPI

 The patch does the following

 1) Adds a clock for SPI
 2) Defines resources specific to DM646x SOC
Signed-off-by: default avatarSandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: default avatarPablo Bitton <pablo.bitton@gmail.com>
Cc: Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 95140a3a
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include <mach/serial.h> #include <mach/serial.h>
#include <mach/common.h> #include <mach/common.h>
#include <mach/asp.h> #include <mach/asp.h>
#include <mach/spi.h>
#include "clock.h" #include "clock.h"
#include "mux.h" #include "mux.h"
...@@ -306,7 +308,7 @@ struct davinci_clk dm644x_clks[] = { ...@@ -306,7 +308,7 @@ struct davinci_clk dm644x_clks[] = {
CLK("palm_bk3710", NULL, &ide_clk), CLK("palm_bk3710", NULL, &ide_clk),
CLK("davinci-asp", NULL, &asp_clk), CLK("davinci-asp", NULL, &asp_clk),
CLK("davinci_mmc.0", NULL, &mmcsd_clk), CLK("davinci_mmc.0", NULL, &mmcsd_clk),
CLK(NULL, "spi", &spi_clk), CLK("spi_davinci.0", NULL, &spi_clk),
CLK(NULL, "gpio", &gpio_clk), CLK(NULL, "gpio", &gpio_clk),
CLK(NULL, "usb", &usb_clk), CLK(NULL, "usb", &usb_clk),
CLK(NULL, "vlynq", &vlynq_clk), CLK(NULL, "vlynq", &vlynq_clk),
...@@ -320,6 +322,52 @@ struct davinci_clk dm644x_clks[] = { ...@@ -320,6 +322,52 @@ struct davinci_clk dm644x_clks[] = {
CLK(NULL, NULL, NULL), CLK(NULL, NULL, NULL),
}; };
static u64 dm644x_spi_dma_mask = DMA_BIT_MASK(32);
static struct davinci_spi_platform_data dm644x_spi_pdata = {
.version = SPI_VERSION_3,
.num_chipselect = 2,
.clk_internal = 1,
.cs_hold = 0,
.intr_level = 0,
.poll_mode = 1,
.c2tdelay = 8,
.t2cdelay = 8,
};
static struct resource dm644x_spi_resources[] = {
{
.start = 0x01c66800,
.end = 0x01c66fff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_SPINT0,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device dm644x_spi_device = {
.name = "spi_davinci",
.id = 0,
.dev = {
.dma_mask = &dm644x_spi_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &dm644x_spi_pdata,
},
.num_resources = ARRAY_SIZE(dm644x_spi_resources),
.resource = dm644x_spi_resources,
};
void __init dm644x_init_spi(struct spi_board_info *info, unsigned len)
{
spi_register_board_info(info, len);
platform_device_register(&dm644x_spi_device);
}
static struct emac_platform_data dm644x_emac_pdata = { static struct emac_platform_data dm644x_emac_pdata = {
.ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET,
.ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include <mach/serial.h> #include <mach/serial.h>
#include <mach/common.h> #include <mach/common.h>
#include <mach/asp.h> #include <mach/asp.h>
#include <mach/spi.h>
#include "clock.h" #include "clock.h"
#include "mux.h" #include "mux.h"
...@@ -262,6 +264,12 @@ static struct clk emac_clk = { ...@@ -262,6 +264,12 @@ static struct clk emac_clk = {
.lpsc = DM646X_LPSC_EMAC, .lpsc = DM646X_LPSC_EMAC,
}; };
static struct clk spi0_clk = {
.name = "spi0",
.parent = &pll1_sysclk3,
.lpsc = DM646X_LPSC_SPI,
};
static struct clk pwm0_clk = { static struct clk pwm0_clk = {
.name = "pwm0", .name = "pwm0",
.parent = &pll1_sysclk3, .parent = &pll1_sysclk3,
...@@ -347,6 +355,7 @@ struct davinci_clk dm646x_clks[] = { ...@@ -347,6 +355,7 @@ struct davinci_clk dm646x_clks[] = {
CLK("davinci-mcasp.1", NULL, &mcasp1_clk), CLK("davinci-mcasp.1", NULL, &mcasp1_clk),
CLK(NULL, "aemif", &aemif_clk), CLK(NULL, "aemif", &aemif_clk),
CLK("davinci_emac.1", NULL, &emac_clk), CLK("davinci_emac.1", NULL, &emac_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
CLK(NULL, "pwm0", &pwm0_clk), CLK(NULL, "pwm0", &pwm0_clk),
CLK(NULL, "pwm1", &pwm1_clk), CLK(NULL, "pwm1", &pwm1_clk),
CLK(NULL, "timer0", &timer0_clk), CLK(NULL, "timer0", &timer0_clk),
...@@ -358,6 +367,50 @@ struct davinci_clk dm646x_clks[] = { ...@@ -358,6 +367,50 @@ struct davinci_clk dm646x_clks[] = {
CLK(NULL, NULL, NULL), CLK(NULL, NULL, NULL),
}; };
static u64 dm646x_spi0_dma_mask = DMA_BIT_MASK(32);
static struct davinci_spi_platform_data dm646x_spi0_pdata = {
.version = SPI_VERSION_1,
.num_chipselect = 2,
.clk_internal = 1,
.cs_hold = 1,
.intr_level = 0,
.poll_mode = 1,
.c2tdelay = 8,
.t2cdelay = 8,
};
static struct resource dm646x_spi0_resources[] = {
{
.start = 0x01c66800,
.end = 0x01c66fff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_DM646X_SPINT0,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device dm646x_spi0_device = {
.name = "spi_davinci",
.id = 0,
.dev = {
.dma_mask = &dm646x_spi0_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &dm646x_spi0_pdata,
},
.num_resources = ARRAY_SIZE(dm646x_spi0_resources),
.resource = dm646x_spi0_resources,
};
void __init dm646x_init_spi0(struct spi_board_info *info, unsigned len)
{
spi_register_board_info(info, len);
platform_device_register(&dm646x_spi0_device);
}
static struct emac_platform_data dm646x_emac_pdata = { static struct emac_platform_data dm646x_emac_pdata = {
.ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET,
.ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET,
......
...@@ -38,5 +38,7 @@ ...@@ -38,5 +38,7 @@
void __init dm644x_init(void); void __init dm644x_init(void);
void __init dm644x_init_asp(struct snd_platform_data *pdata); void __init dm644x_init_asp(struct snd_platform_data *pdata);
void dm644x_set_vpfe_config(struct vpfe_config *cfg); void dm644x_set_vpfe_config(struct vpfe_config *cfg);
struct spi_board_info;
void __init dm644x_init_spi(struct spi_board_info *info, unsigned len);
#endif /* __ASM_ARCH_DM644X_H */ #endif /* __ASM_ARCH_DM644X_H */
...@@ -28,6 +28,8 @@ void __init dm646x_init(void); ...@@ -28,6 +28,8 @@ void __init dm646x_init(void);
void __init dm646x_init_ide(void); void __init dm646x_init_ide(void);
void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
void __init dm646x_init_mcasp1(struct snd_platform_data *pdata); void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);
struct spi_board_info;
void dm646x_init_spi0(struct spi_board_info *info, unsigned len);
void dm646x_video_init(void); void dm646x_video_init(void);
......
/*
* Copyright 2009 Texas Instruments.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ARCH_ARM_DAVINCI_SPI_H
#define __ARCH_ARM_DAVINCI_SPI_H
#define SPI_INTERN_CS 0xFF
enum {
SPI_VERSION_1 = 0, /* For DM355/DM365/DM6467*/
SPI_VERSION_2, /* For DA8xx */
SPI_VERSION_3, /* For DM6446 */
};
struct davinci_spi_platform_data {
u8 version;
u16 num_chipselect;
u32 wdelay;
u32 odd_parity;
u32 parity_enable;
u32 wait_enable;
u32 timer_disable;
u32 clk_internal;
u32 cs_hold;
u32 intr_level;
u32 poll_mode;
u8 c2tdelay;
u8 t2cdelay;
};
#endif /* __ARCH_ARM_DAVINCI_SPI_H */
...@@ -77,6 +77,13 @@ config SPI_AU1550 ...@@ -77,6 +77,13 @@ config SPI_AU1550
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called au1550_spi. will be called au1550_spi.
config SPI_DAVINCI
tristate "SPI controller driver for DaVinci/DA8xx SoC's"
depends on SPI_MASTER && ARCH_DAVINCI
select SPI_BITBANG
help
SPI master controller for DaVinci and DA8xx SPI modules.
config SPI_BITBANG config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters" tristate "Utilities for Bitbanging SPI masters"
help help
......
...@@ -32,6 +32,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o ...@@ -32,6 +32,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
obj-$(CONFIG_SPI_TXX9) += spi_txx9.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
# ... add above this line ... # ... add above this line ...
# SPI protocol drivers (device/link on bus) # SPI protocol drivers (device/link on bus)
......
This diff is collapsed.
/*
* Copyright (C) 2009 Texas Instruments.
*
* 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
*/
#ifndef __DAVINCI_SPI_H
#define __DAVINCI_SPI_H
#define SPI_MAX_CHIPSELECT 2
#define CS_DEFAULT 0xFF
#define SCS0_SELECT 0x01
#define SCS1_SELECT 0x02
#define SCS2_SELECT 0x04
#define SCS3_SELECT 0x08
#define SCS4_SELECT 0x10
#define SCS5_SELECT 0x20
#define SCS6_SELECT 0x40
#define SCS7_SELECT 0x80
#define SPIFMT_PHASE_MASK BIT(16)
#define SPIFMT_POLARITY_MASK BIT(17)
#define SPIFMT_DISTIMER_MASK BIT(18)
#define SPIFMT_SHIFTDIR_MASK BIT(20)
#define SPIFMT_WAITENA_MASK BIT(21)
#define SPIFMT_PARITYENA_MASK BIT(22)
#define SPIFMT_ODD_PARITY_MASK BIT(23)
#define SPIFMT_WDELAY_MASK 0x3f000000u
#define SPIFMT_WDELAY_SHIFT 24
#define SPIFMT_CHARLEN_MASK 0x0000001Fu
/* SPIGCR1 */
#define SPIGCR1_SPIENA_MASK 0x01000000u
#define SPIGCR1_CLKMOD_MASK BIT(1)
#define SPIGCR1_MASTER_MASK BIT(0)
#define SPIGCR1_LOOPBACK_MASK BIT(16)
/* SPIPC0 */
#define SPIPC0_DIFUN_MASK BIT(11) /* MISO */
#define SPIPC0_DOFUN_MASK BIT(10) /* MOSI */
#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
#define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */
#define SPIPC0_EN1FUN_MASK BIT(1)
#define SPIPC0_EN0FUN_MASK BIT(0)
#define SPIINT_MASKALL 0x0101035F
#define SPI_INTLVL_1 0x000001FFu
#define SPI_INTLVL_0 0x00000000u
/* SPIDAT1 */
#define SPIDAT1_CSHOLD_MASK BIT(28)
#define SPIDAT1_CSHOLD_SHIFT 28
#define SPIDAT1_CSNR_MASK (BIT(17 | BIT(16))
#define SPIDAT1_CSNR_SHIFT 16
#define SPIDAT1_DFSEL_MASK (BIT(24 | BIT(25))
#define SPIDAT1_DFSEL_SHIFT 24
/* SPIBUF */
#define SPIBUF_TXFULL_MASK BIT(29)
#define SPIBUF_RXEMPTY_MASK BIT(31)
/* Error Masks */
#define SPIFLG_DLEN_ERR_MASK BIT(0)
#define SPIFLG_TIMEOUT_MASK BIT(1)
#define SPIFLG_PARERR_MASK BIT(2)
#define SPIFLG_DESYNC_MASK BIT(3)
#define SPIFLG_BITERR_MASK BIT(4)
#define SPIFLG_OVRRUN_MASK BIT(6)
#define SPIFLG_RX_INTR_MASK BIT(8)
#define SPIFLG_TX_INTR_MASK BIT(9)
#define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24)
#define SPIFLG_MASK (SPIFLG_DLEN_ERR_MASK \
| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
| SPIFLG_OVRRUN_MASK | SPIFLG_RX_INTR_MASK \
| SPIFLG_TX_INTR_MASK \
| SPIFLG_BUF_INIT_ACTIVE_MASK)
#define SPIFLG_VERSION_1 (SPIFLG_TIMEOUT_MASK | SPIFLG_DESYNC_MASK \
| SPIFLG_BITERR_MASK | SPIFLG_RX_INTR_MASK)
#define SPIFLG_VERSION_2 (SPIFLG_DLEN_ERR_MASK | SPIFLG_TIMEOUT_MASK \
| SPIFLG_PARERR_MASK | SPIFLG_DESYNC_MASK \
| SPIFLG_BITERR_MASK | SPIFLG_DESYNC_MASK \
| SPIFLG_RX_INTR_MASK | SPIFLG_TX_INTR_MASK \
| SPIFLG_BUF_INIT_ACTIVE_MASK)
#define SPIFLG_VERSION_3 (SPIFLG_BITERR_MASK | SPIFLG_OVRRUN_MASK \
| SPIFLG_RX_INTR_MASK)
#define SPIINT_DLEN_ERR_INTR BIT(0)
#define SPIINT_TIMEOUT_INTR BIT(1)
#define SPIINT_PARERR_INTR BIT(2)
#define SPIINT_DESYNC_INTR BIT(3)
#define SPIINT_BITERR_INTR BIT(4)
#define SPIINT_OVRRUN_INTR BIT(6)
#define SPIINT_RX_INTR BIT(8)
#define SPIINT_TX_INTR BIT(9)
#define SPIINT_DMA_REQ_EN BIT(16)
#define SPIINT_ENABLE_HIGHZ BIT(24)
#define SPI_T2CDELAY_SHIFT 16
#define SPI_C2TDELAY_SHIFT 24
/* SPI Controller registers */
#define SPIGCR0 0x00
#define SPIGCR1 0x04
#define SPIINT 0x08
#define SPILVL 0x0c
#define SPIFLG 0x10
#define SPIPC0 0x14
#define SPIPC1 0x18
#define SPIPC2 0x1c
#define SPIPC3 0x20
#define SPIPC4 0x24
#define SPIPC5 0x28
#define SPIPC6 0x2c
#define SPIPC7 0x30
#define SPIPC8 0x34
#define SPIDAT0 0x38
#define SPIDAT1 0x3c
#define SPIBUF 0x40
#define SPIEMU 0x44
#define SPIDELAY 0x48
#define SPIDEF 0x4c
#define SPIFMT0 0x50
#define SPIFMT1 0x54
#define SPIFMT2 0x58
#define SPIFMT3 0x5c
#define TGINTVEC0 0x60
#define TGINTVEC1 0x64
struct davinci_spi_slave {
u32 cmd_to_write;
u32 clk_ctrl_to_write;
u32 bytes_per_word;
u8 active_cs;
};
/* SPI Controller driver's private data. */
struct davinci_spi {
struct spi_bitbang bitbang;
struct clk *clk;
u8 version;
resource_size_t pbase;
void __iomem *base;
size_t region_size;
u32 irq;
struct completion done;
const void *tx;
void *rx;
int count;
struct davinci_spi_platform_data *pdata;
void (*get_rx)(u32 rx_data, struct davinci_spi *);
u32 (*get_tx)(struct davinci_spi *);
struct davinci_spi_slave slave[SPI_MAX_CHIPSELECT];
};
#endif /* __DAVINCI_SPI_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment