2009-08-14 17:59:05 +08:00
|
|
|
/*
|
|
|
|
* arch/arm/mach-u300/spi.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 ST-Ericsson AB
|
|
|
|
* License terms: GNU General Public License (GPL) version 2
|
|
|
|
*
|
|
|
|
* Author: Linus Walleij <linus.walleij@stericsson.com>
|
|
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/amba/bus.h>
|
|
|
|
#include <linux/spi/spi.h>
|
|
|
|
#include <linux/amba/pl022.h>
|
|
|
|
#include <linux/err.h>
|
2010-08-13 17:31:59 +08:00
|
|
|
#include <mach/coh901318.h>
|
|
|
|
#include <mach/dma_channels.h>
|
|
|
|
|
2009-08-14 17:59:05 +08:00
|
|
|
#include "padmux.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The following is for the actual devices on the SSP/SPI bus
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_MACH_U300_SPIDUMMY
|
|
|
|
static void select_dummy_chip(u32 chipselect)
|
|
|
|
{
|
|
|
|
pr_debug("CORE: %s called with CS=0x%x (%s)\n",
|
|
|
|
__func__,
|
|
|
|
chipselect,
|
|
|
|
chipselect ? "unselect chip" : "select chip");
|
|
|
|
/*
|
|
|
|
* Here you would write the chip select value to the GPIO pins if
|
|
|
|
* this was a real chip (but this is a loopback dummy).
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pl022_config_chip dummy_chip_info = {
|
2010-08-13 17:31:59 +08:00
|
|
|
/* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
|
|
|
|
.com_mode = DMA_TRANSFER,
|
2009-08-14 17:59:05 +08:00
|
|
|
.iface = SSP_INTERFACE_MOTOROLA_SPI,
|
|
|
|
/* We can only act as master but SSP_SLAVE is possible in theory */
|
|
|
|
.hierarchy = SSP_MASTER,
|
|
|
|
/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
|
|
|
|
.slave_tx_disable = 0,
|
2011-06-16 15:28:28 +08:00
|
|
|
.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
|
|
|
|
.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
|
2009-08-14 17:59:05 +08:00
|
|
|
.ctrl_len = SSP_BITS_12,
|
|
|
|
.wait_state = SSP_MWIRE_WAIT_ZERO,
|
|
|
|
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
|
|
|
|
/*
|
|
|
|
* This is where you insert a call to a function to enable CS
|
|
|
|
* (usually GPIO) for a certain chip.
|
|
|
|
*/
|
|
|
|
.cs_control = select_dummy_chip,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct spi_board_info u300_spi_devices[] = {
|
|
|
|
#ifdef CONFIG_MACH_U300_SPIDUMMY
|
|
|
|
{
|
|
|
|
/* A dummy chip used for loopback tests */
|
|
|
|
.modalias = "spi-dummy",
|
|
|
|
/* Really dummy, pass in additional chip config here */
|
|
|
|
.platform_data = NULL,
|
|
|
|
/* This defines how the controller shall handle the device */
|
|
|
|
.controller_data = &dummy_chip_info,
|
|
|
|
/* .irq - no external IRQ routed from this device */
|
|
|
|
.max_speed_hz = 1000000,
|
|
|
|
.bus_num = 0, /* Only one bus on this chip */
|
|
|
|
.chip_select = 0,
|
|
|
|
/* Means SPI_CS_HIGH, change if e.g low CS */
|
2010-10-22 03:05:25 +08:00
|
|
|
.mode = SPI_MODE_1 | SPI_LOOP,
|
2009-08-14 17:59:05 +08:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct pl022_ssp_controller ssp_platform_data = {
|
|
|
|
/* If you have several SPI buses this varies, we have only bus 0 */
|
|
|
|
.bus_id = 0,
|
|
|
|
/*
|
|
|
|
* On the APP CPU GPIO 4, 5 and 6 are connected as generic
|
|
|
|
* chip selects for SPI. (Same on U330, U335 and U365.)
|
|
|
|
* TODO: make sure the GPIO driver can select these properly
|
|
|
|
* and do padmuxing accordingly too.
|
|
|
|
*/
|
|
|
|
.num_chipselect = 3,
|
2010-08-13 17:31:59 +08:00
|
|
|
#ifdef CONFIG_COH901318
|
|
|
|
.enable_dma = 1,
|
|
|
|
.dma_filter = coh901318_filter_id,
|
|
|
|
.dma_rx_param = (void *) U300_DMA_SPI_RX,
|
|
|
|
.dma_tx_param = (void *) U300_DMA_SPI_TX,
|
|
|
|
#else
|
|
|
|
.enable_dma = 0,
|
|
|
|
#endif
|
2009-08-14 17:59:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void __init u300_spi_init(struct amba_device *adev)
|
|
|
|
{
|
|
|
|
struct pmx *pmx;
|
|
|
|
|
|
|
|
adev->dev.platform_data = &ssp_platform_data;
|
|
|
|
/*
|
|
|
|
* Setup padmuxing for SPI. Since this must always be
|
|
|
|
* compiled into the kernel, pmx is never released.
|
|
|
|
*/
|
|
|
|
pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING);
|
|
|
|
|
|
|
|
if (IS_ERR(pmx))
|
|
|
|
dev_warn(&adev->dev, "Could not get padmux handle\n");
|
|
|
|
else {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = pmx_activate(&adev->dev, pmx);
|
|
|
|
if (IS_ERR_VALUE(ret))
|
|
|
|
dev_warn(&adev->dev, "Could not activate padmuxing\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-08-13 17:31:59 +08:00
|
|
|
|
2009-08-14 17:59:05 +08:00
|
|
|
void __init u300_spi_register_board_devices(void)
|
|
|
|
{
|
|
|
|
/* Register any SPI devices */
|
|
|
|
spi_register_board_info(u300_spi_devices, ARRAY_SIZE(u300_spi_devices));
|
|
|
|
}
|