Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions arch/arm/configs/nanopi2_linux_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1583,8 +1583,8 @@ CONFIG_SPI_PL022_PORT0=y
CONFIG_USE_DMA_PORT0=y
# CONFIG_SPI_PL022_PORT1 is not set
# CONFIG_USE_DMA_PORT1 is not set
# CONFIG_SPI_PL022_PORT2 is not set
# CONFIG_USE_DMA_PORT2 is not set
CONFIG_SPI_PL022_PORT2=y
CONFIG_USE_DMA_PORT2=y
# CONFIG_SPI_PXA2XX_PCI is not set
# CONFIG_SPI_XILINX is not set
# CONFIG_SPI_DESIGNWARE is not set
Expand Down
58 changes: 58 additions & 0 deletions arch/arm/plat-s5p4418/nanopi2/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,51 @@ static struct spi_board_info spi_plat_board[] __initdata = {
};
#endif

#define CFG_SPI2_CS (PAD_GPIO_C + 10)

static void mylcd_cs(u32 chipselect)
{

#if (CFG_SPI2_CS_GPIO_MODE)
nxp_soc_gpio_set_out_value( CFG_SPI2_CS , chipselect);
#else
;
#endif
}

struct pl022_config_chip mylcd_info = {
/* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
.com_mode = CFG_SPI2_COM_MODE,
.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 = 1,
.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_8,
.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 = mylcd_cs,
.clkdelay = SSP_FEEDBACK_CLK_DELAY_1T,
};

static struct spi_board_info spi2_plat_board[] __initdata = {
[0] = {
.modalias = "my_spilcd", /* fixup */
.max_speed_hz = 50000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 2, /* Note> set bus num, must be smaller than ARRAY_SIZE(spi_plat_device) */
.chip_select = 0, /* Note> set chip select num, must be smaller than spi cs_num */
.controller_data = &mylcd_info,
.mode = SPI_MODE_0,
},
};


/*------------------------------------------------------------------------------
* DW MMC board config
*/
Expand Down Expand Up @@ -1943,6 +1988,19 @@ void __init nxp_board_devices_register(void)
printk("plat: register spidev\n");
#endif

nxp_soc_gpio_set_io_func(PAD_GPIO_C + 9, NX_GPIO_PADFUNC_2);
#if (CFG_SPI2_CS_GPIO_MODE)
nxp_soc_gpio_set_io_func(PAD_GPIO_C + 10, NX_GPIO_PADFUNC_1);
nxp_soc_gpio_set_io_dir( CFG_SPI2_CS, 1);
#else
nxp_soc_gpio_set_io_func(PAD_GPIO_C + 10, NX_GPIO_PADFUNC_2);
#endif
nxp_soc_gpio_set_io_func(PAD_GPIO_C + 11, NX_GPIO_PADFUNC_2);
nxp_soc_gpio_set_io_func(PAD_GPIO_C + 12, NX_GPIO_PADFUNC_2);
spi_register_board_info(spi2_plat_board, ARRAY_SIZE(spi2_plat_board));
printk("plat: register mylcd\n");


#if defined(CONFIG_TOUCHSCREEN_GSLX680)
printk("plat: add touch(gslX680) device\n");
i2c_register_board_info(GSLX680_I2C_BUS, &gslX680_i2c_bdi, 1);
Expand Down
15 changes: 8 additions & 7 deletions arch/arm/plat-s5p4418/nanopi2/include/cfg_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,20 @@
/*------------------------------------------------------------------------------
* SPI
*/
#define CFG_SPI0_CLK (10000000*5) // spiclk = CFG_SPI0_CLK / 2
#define CFG_SPI1_CLK 10000000
#define CFG_SPI2_CLK 10000000
#define CFG_SPI0_CLK (10000000*10) // spiclk = CFG_SPI0_CLK / 2
#define CFG_SPI1_CLK (10000000*10)
#define CFG_SPI2_CLK (10000000*10)

#define CFG_SPI0_COM_MODE 0 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */
#define CFG_SPI1_COM_MODE 1 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */
#define CFG_SPI2_COM_MODE 1 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */
#define CFG_SPI0_COM_MODE 2 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */
#define CFG_SPI1_COM_MODE 2 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */
#define CFG_SPI2_COM_MODE 2 /* available 0: INTERRUPT_TRANSFER, 1: POLLING_TRANSFER, 2: DMA_TRANSFER */

#define CFG_SPI0_CS_GPIO_MODE 1 /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */
#define CFG_SPI1_CS_GPIO_MODE 1 /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */
#define CFG_SPI2_CS_GPIO_MODE 0 /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */
#define CFG_SPI2_CS_GPIO_MODE 1 /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */

#define CFG_SPI0_CS (PAD_GPIO_C + 30) /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */
#define CFG_SPI2_CS (PAD_GPIO_C + 10) /* 0 FSS CONTROL, 1: CS CONTRO GPIO MODE */

/*------------------------------------------------------------------------------
* MPEGTSIF
Expand Down
68 changes: 68 additions & 0 deletions drivers/dma/amba-pl08x.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ struct pl08x_lli {
u32 cctl;
};

struct ssp_monitor {
int index;
struct timer_list timer;
spinlock_t ssp_lock;
};

/**
* struct pl08x_driver_data - the local state holder for the PL08x
* @slave: slave engine for this instance
Expand Down Expand Up @@ -146,6 +152,7 @@ struct pl08x_driver_data {
u8 lli_buses;
u8 mem_buses;
spinlock_t lock;
struct ssp_monitor ssp_monitor[3];
};

/*
Expand Down Expand Up @@ -2099,10 +2106,57 @@ static void pl08x_tasklet(unsigned long data)
}
}


static void pl08x_ssp_timer(unsigned long data)
{
struct ssp_monitor *monitor = (struct ssp_monitor *)data;
struct pl08x_driver_data *pl08x = container_of(monitor,
struct pl08x_driver_data, ssp_monitor[monitor->index]);
unsigned long flags, ch_id, val;
struct pl08x_phy_chan *phychan = &pl08x->phy_chans[0];
int i, num_req;

ch_id = DMA_PERIPHERAL_ID_SSP0_RX + 2 * monitor->index;

spin_lock_irqsave(&monitor->ssp_lock, flags);
for(i = 0; i < pl08x->vd->channels; i++) {
if(phychan->serving->cd->min_signal == ch_id)
break;
phychan++;
}
num_req = readl(phychan->base + PL080_CH_CONTROL) & 0xFFF;
val = 1 << ch_id;
for(i = 0; i < DIV_ROUND_UP(num_req, 4); i++)
writel(val, pl08x->base + PL080_SOFT_BREQ);
spin_unlock_irqrestore(&monitor->ssp_lock, flags);
}

void prevent_abnormal_ssp_task(struct pl08x_driver_data *pl08x, u16 ssp_tc)
{
int i = 0;

for(i = 0; i < 3; i++) {
int bit = DMA_PERIPHERAL_ID_SSP0_TX + 2 * i;
int spi_tx = 0, spi_rx = 0;

spi_tx = ssp_tc & (1 << bit);
spi_rx = ssp_tc & (1 << (bit + 1));

if(spi_tx && !spi_rx) {
mod_timer(&pl08x->ssp_monitor[i].timer,jiffies + msecs_to_jiffies(8));
}

if(!spi_tx && spi_rx) {
del_timer(&pl08x->ssp_monitor[i].timer);
}
}
}

static irqreturn_t pl08x_irq(int irq, void *dev)
{
struct pl08x_driver_data *pl08x = dev;
u32 mask = 0, err, tc, i;
u16 ssp_tc_record_bit = 0;

/* check & clear - ERR & TC interrupts */
err = readl(pl08x->base + PL080_ERR_STATUS);
Expand Down Expand Up @@ -2131,6 +2185,11 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
continue;
}

/* Only DMAC0 contains SPI. */
if(pl08x->slave.chancnt == 16){
ssp_tc_record_bit |= (1 << plchan->cd->min_signal);
}

/* Schedule tasklet on this channel */
#if !defined(CONFIG_AMBA_PL08X_USE_ISR)
tasklet_schedule(&plchan->tasklet);
Expand All @@ -2140,6 +2199,8 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
mask |= (1 << i);
}
}
if(ssp_tc_record_bit)
prevent_abnormal_ssp_task(pl08x, ssp_tc_record_bit);

return mask ? IRQ_HANDLED : IRQ_NONE;
}
Expand Down Expand Up @@ -2388,6 +2449,13 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
pm_runtime_set_active(&adev->dev);
pm_runtime_enable(&adev->dev);

for(i = 0; i < 3; i++){
pl08x->ssp_monitor[i].index = i;
spin_lock_init(&pl08x->ssp_monitor[i].ssp_lock);
setup_timer(&pl08x->ssp_monitor[i].timer,
pl08x_ssp_timer, (unsigned long)&pl08x->ssp_monitor[i]);
}

/* Initialize memcpy engine */
dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
pl08x->memcpy.dev = &adev->dev;
Expand Down
3 changes: 2 additions & 1 deletion drivers/spi/spi-pl022.c
Original file line number Diff line number Diff line change
Expand Up @@ -1408,8 +1408,9 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
}
/* If we're using DMA, set up DMA here */

if (pl022->cur_chip->enable_dma && !(pl022->cur_transfer->len % 4) && (pl022->cur_transfer->len < 4096)) { //bok add
// if (pl022->cur_chip->enable_dma && !(pl022->cur_transfer->len % 4) && (pl022->cur_transfer->len < 4096)) { //bok add
// if (pl022->cur_chip->enable_dma) {
if (pl022->cur_chip->enable_dma && !(pl022->cur_transfer->len % 4)) {
/* Configure DMA transfer */
if (configure_dma(pl022)) {
dev_dbg(&pl022->adev->dev,
Expand Down