Commit 244a60c2 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/armada', 'spi/topic/ath79',...

Merge remote-tracking branches 'spi/topic/armada', 'spi/topic/ath79', 'spi/topic/bcm-qspi' and 'spi/topic/bcm53xx' into spi-next
...@@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI ...@@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI
config SPI_BCM_QSPI config SPI_BCM_QSPI
tristate "Broadcom BSPI and MSPI controller support" tristate "Broadcom BSPI and MSPI controller support"
depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || COMPILE_TEST depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || \
BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Enables support for the Broadcom SPI flash and MSPI controller. Enables support for the Broadcom SPI flash and MSPI controller.
......
...@@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, ...@@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1); val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1);
switch (pin_mode) { switch (pin_mode) {
case 1: case SPI_NBITS_SINGLE:
break; break;
case 2: case SPI_NBITS_DUAL:
val |= A3700_SPI_DATA_PIN0; val |= A3700_SPI_DATA_PIN0;
break; break;
case 4: case SPI_NBITS_QUAD:
val |= A3700_SPI_DATA_PIN1; val |= A3700_SPI_DATA_PIN1;
break; break;
default: default:
...@@ -340,7 +340,6 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id) ...@@ -340,7 +340,6 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id)
spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause); spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause);
/* Wake up the transfer */ /* Wake up the transfer */
if (a3700_spi->wait_mask & cause)
complete(&a3700_spi->done); complete(&a3700_spi->done);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -562,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi) ...@@ -562,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi)
val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG);
if (a3700_spi->buf_len >= 4) { if (a3700_spi->buf_len >= 4) {
u32 data = le32_to_cpu(val); u32 data = le32_to_cpu(val);
memcpy(a3700_spi->rx_buf, &data, 4); memcpy(a3700_spi->rx_buf, &data, 4);
a3700_spi->buf_len -= 4; a3700_spi->buf_len -= 4;
...@@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev) ...@@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
struct a3700_spi *spi = spi_master_get_devdata(master); struct a3700_spi *spi = spi_master_get_devdata(master);
clk_unprepare(spi->clk); clk_unprepare(spi->clk);
spi_master_put(master);
return 0; return 0;
} }
...@@ -909,7 +908,6 @@ static int a3700_spi_remove(struct platform_device *pdev) ...@@ -909,7 +908,6 @@ static int a3700_spi_remove(struct platform_device *pdev)
static struct platform_driver a3700_spi_driver = { static struct platform_driver a3700_spi_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(a3700_spi_dt_ids), .of_match_table = of_match_ptr(a3700_spi_dt_ids),
}, },
.probe = a3700_spi_probe, .probe = a3700_spi_probe,
......
...@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) ...@@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
/* SPI is normally active-low */ /* SPI is normally active-low */
gpio_set_value(spi->cs_gpio, cs_high); gpio_set_value_cansleep(spi->cs_gpio, cs_high);
} else { } else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (cs_high) if (cs_high)
sp->ioc_base |= AR71XX_SPI_IOC_CS0; sp->ioc_base |= cs_bit;
else else
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; sp->ioc_base &= ~cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
...@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
int status; int status;
if (spi->chip_select && !gpio_is_valid(spi->cs_gpio))
return -EINVAL;
status = 0; status = 0;
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
unsigned long flags; unsigned long flags;
flags = GPIOF_DIR_OUT; flags = GPIOF_DIR_OUT;
...@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
status = gpio_request_one(spi->cs_gpio, flags, status = gpio_request_one(spi->cs_gpio, flags,
dev_name(&spi->dev)); dev_name(&spi->dev));
} else { } else {
u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select);
if (spi->mode & SPI_CS_HIGH) if (spi->mode & SPI_CS_HIGH)
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; sp->ioc_base &= ~cs_bit;
else else
sp->ioc_base |= AR71XX_SPI_IOC_CS0; sp->ioc_base |= cs_bit;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
} }
...@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
static void ath79_spi_cleanup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi)
{ {
if (spi->chip_select) { if (gpio_is_valid(spi->cs_gpio)) {
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
} }
} }
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
#define BSPI_BPP_MODE_SELECT_MASK BIT(8) #define BSPI_BPP_MODE_SELECT_MASK BIT(8)
#define BSPI_BPP_ADDR_SELECT_MASK BIT(16) #define BSPI_BPP_ADDR_SELECT_MASK BIT(16)
#define BSPI_READ_LENGTH 256 #define BSPI_READ_LENGTH 512
/* MSPI register offsets */ /* MSPI register offsets */
#define MSPI_SPCR0_LSB 0x000 #define MSPI_SPCR0_LSB 0x000
...@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id { ...@@ -192,9 +192,11 @@ struct bcm_qspi_dev_id {
void *dev; void *dev;
}; };
struct qspi_trans { struct qspi_trans {
struct spi_transfer *trans; struct spi_transfer *trans;
int byte; int byte;
bool mspi_last_trans;
}; };
struct bcm_qspi { struct bcm_qspi {
...@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi) ...@@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi)
return 0; return 0;
} }
static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi,
struct qspi_trans *qt)
{
if (qt->mspi_last_trans &&
spi_transfer_is_last(qspi->master, qt->trans))
return true;
else
return false;
}
static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
struct qspi_trans *qt, int flags) struct qspi_trans *qt, int flags)
{ {
...@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, ...@@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
if (qt->byte >= qt->trans->len) { if (qt->byte >= qt->trans->len) {
/* we're at the end of the spi_transfer */ /* we're at the end of the spi_transfer */
/* in TX mode, need to pause for a delay or CS change */ /* in TX mode, need to pause for a delay or CS change */
if (qt->trans->delay_usecs && if (qt->trans->delay_usecs &&
(flags & TRANS_STATUS_BREAK_DELAY)) (flags & TRANS_STATUS_BREAK_DELAY))
...@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, ...@@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi,
goto done; goto done;
dev_dbg(&qspi->pdev->dev, "advance msg exit\n"); dev_dbg(&qspi->pdev->dev, "advance msg exit\n");
if (spi_transfer_is_last(qspi->master, qt->trans)) if (bcm_qspi_mspi_transfer_is_last(qspi, qt))
ret = TRANS_STATUS_BREAK_EOM; ret = TRANS_STATUS_BREAK_EOM;
else else
ret = TRANS_STATUS_BREAK_NO_BYTES; ret = TRANS_STATUS_BREAK_NO_BYTES;
...@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -813,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
struct spi_flash_read_message *msg) struct spi_flash_read_message *msg)
{ {
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
u32 addr = 0, len, len_words; u32 addr = 0, len, rdlen, len_words;
int ret = 0; int ret = 0;
unsigned long timeo = msecs_to_jiffies(100); unsigned long timeo = msecs_to_jiffies(100);
struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
...@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -826,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
/* /*
* when using flex mode mode we need to send * when using flex mode we need to send
* the upper address byte to bspi * the upper address byte to bspi
*/ */
if (bcm_qspi_bspi_ver_three(qspi) == false) { if (bcm_qspi_bspi_ver_three(qspi) == false) {
...@@ -840,27 +851,33 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -840,27 +851,33 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
else else
addr = msg->from & 0x00ffffff; addr = msg->from & 0x00ffffff;
/* set BSPI RAF buffer max read length */
len = msg->len;
if (len > BSPI_READ_LENGTH)
len = BSPI_READ_LENGTH;
if (bcm_qspi_bspi_ver_three(qspi) == true) if (bcm_qspi_bspi_ver_three(qspi) == true)
addr = (addr + 0xc00000) & 0xffffff; addr = (addr + 0xc00000) & 0xffffff;
/*
* read into the entire buffer by breaking the reads
* into RAF buffer read lengths
*/
len = msg->len;
qspi->bspi_rf_msg_idx = 0;
do {
if (len > BSPI_READ_LENGTH)
rdlen = BSPI_READ_LENGTH;
else
rdlen = len;
reinit_completion(&qspi->bspi_done); reinit_completion(&qspi->bspi_done);
bcm_qspi_enable_bspi(qspi); bcm_qspi_enable_bspi(qspi);
len_words = (len + 3) >> 2; len_words = (rdlen + 3) >> 2;
qspi->bspi_rf_msg = msg; qspi->bspi_rf_msg = msg;
qspi->bspi_rf_msg_status = 0; qspi->bspi_rf_msg_status = 0;
qspi->bspi_rf_msg_idx = 0; qspi->bspi_rf_msg_len = rdlen;
qspi->bspi_rf_msg_len = len; dev_dbg(&qspi->pdev->dev,
dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len); "bspi xfr addr 0x%x len 0x%x", addr, rdlen);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
if (qspi->soc_intc) { if (qspi->soc_intc) {
/* /*
* clear soc MSPI and BSPI interrupts and enable * clear soc MSPI and BSPI interrupts and enable
...@@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, ...@@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,
/* Must flush previous writes before starting BSPI operation */ /* Must flush previous writes before starting BSPI operation */
mb(); mb();
bcm_qspi_bspi_lr_start(qspi); bcm_qspi_bspi_lr_start(qspi);
if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} else { break;
/* set the return length for the caller */
msg->retlen = len;
} }
/* set msg return length */
msg->retlen += rdlen;
addr += rdlen;
len -= rdlen;
} while (len);
return ret;
}
static int bcm_qspi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *trans)
{
struct bcm_qspi *qspi = spi_master_get_devdata(master);
int slots;
unsigned long timeo = msecs_to_jiffies(100);
bcm_qspi_chip_select(qspi, spi->chip_select);
qspi->trans_pos.trans = trans;
qspi->trans_pos.byte = 0;
while (qspi->trans_pos.byte < trans->len) {
reinit_completion(&qspi->mspi_done);
slots = write_to_hw(qspi, spi);
if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
return -ETIMEDOUT;
}
read_from_hw(qspi, slots);
}
return 0;
}
static int bcm_qspi_mspi_flash_read(struct spi_device *spi,
struct spi_flash_read_message *msg)
{
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
struct spi_transfer t[2];
u8 cmd[6];
int ret;
memset(cmd, 0, sizeof(cmd));
memset(t, 0, sizeof(t));
/* tx */
/* opcode is in cmd[0] */
cmd[0] = msg->read_opcode;
cmd[1] = msg->from >> (msg->addr_width * 8 - 8);
cmd[2] = msg->from >> (msg->addr_width * 8 - 16);
cmd[3] = msg->from >> (msg->addr_width * 8 - 24);
cmd[4] = msg->from >> (msg->addr_width * 8 - 32);
t[0].tx_buf = cmd;
t[0].len = msg->addr_width + msg->dummy_bytes + 1;
t[0].bits_per_word = spi->bits_per_word;
t[0].tx_nbits = msg->opcode_nbits;
/* lets mspi know that this is not last transfer */
qspi->trans_pos.mspi_last_trans = false;
ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]);
/* rx */
qspi->trans_pos.mspi_last_trans = true;
if (!ret) {
/* rx */
t[1].rx_buf = msg->buf;
t[1].len = msg->len;
t[1].rx_nbits = msg->data_nbits;
t[1].bits_per_word = spi->bits_per_word;
ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]);
}
if (!ret)
msg->retlen = msg->len;
return ret; return ret;
} }
...@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -918,8 +1008,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
mspi_read = true; mspi_read = true;
if (mspi_read) if (mspi_read)
/* this will make the m25p80 read to fallback to mspi read */ return bcm_qspi_mspi_flash_read(spi, msg);
return -EAGAIN;
io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
addrlen = msg->addr_width; addrlen = msg->addr_width;
...@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -931,33 +1020,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
return ret; return ret;
} }
static int bcm_qspi_transfer_one(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *trans)
{
struct bcm_qspi *qspi = spi_master_get_devdata(master);
int slots;
unsigned long timeo = msecs_to_jiffies(100);
bcm_qspi_chip_select(qspi, spi->chip_select);
qspi->trans_pos.trans = trans;
qspi->trans_pos.byte = 0;
while (qspi->trans_pos.byte < trans->len) {
reinit_completion(&qspi->mspi_done);
slots = write_to_hw(qspi, spi);
if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) {
dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n");
return -ETIMEDOUT;
}
read_from_hw(qspi, slots);
}
return 0;
}
static void bcm_qspi_cleanup(struct spi_device *spi) static void bcm_qspi_cleanup(struct spi_device *spi)
{ {
struct bcm_qspi_parms *xp = spi_get_ctldata(spi); struct bcm_qspi_parms *xp = spi_get_ctldata(spi);
...@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1187,6 +1249,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
qspi->pdev = pdev; qspi->pdev = pdev;
qspi->trans_pos.trans = NULL; qspi->trans_pos.trans = NULL;
qspi->trans_pos.byte = 0; qspi->trans_pos.byte = 0;
qspi->trans_pos.mspi_last_trans = true;
qspi->master = master; qspi->master = master;
master->bus_num = -1; master->bus_num = -1;
...@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev) ...@@ -1345,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev)
{ {
struct bcm_qspi *qspi = platform_get_drvdata(pdev); struct bcm_qspi *qspi = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
bcm_qspi_hw_uninit(qspi); bcm_qspi_hw_uninit(qspi);
clk_disable_unprepare(qspi->clk); clk_disable_unprepare(qspi->clk);
kfree(qspi->dev_ids); kfree(qspi->dev_ids);
......
/*
* Copyright (C) 2014-2016 Rafał Miłecki <rafal@milecki.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -275,10 +283,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi, ...@@ -275,10 +283,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi,
* BCMA * BCMA
**************************************************/ **************************************************/
static struct spi_board_info bcm53xx_info = {
.modalias = "bcm53xxspiflash",
};
static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS),
{}, {},
...@@ -311,6 +315,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) ...@@ -311,6 +315,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
b53spi->bspi = true; b53spi->bspi = true;
bcm53xxspi_disable_bspi(b53spi); bcm53xxspi_disable_bspi(b53spi);
master->dev.of_node = dev->of_node;
master->transfer_one = bcm53xxspi_transfer_one; master->transfer_one = bcm53xxspi_transfer_one;
if (b53spi->mmio_base) if (b53spi->mmio_base)
master->spi_flash_read = bcm53xxspi_flash_read; master->spi_flash_read = bcm53xxspi_flash_read;
...@@ -324,9 +329,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) ...@@ -324,9 +329,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
return err; return err;
} }
/* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
spi_new_device(master, &bcm53xx_info);
return 0; return 0;
} }
...@@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit); ...@@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit);
MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver");
MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>"); MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
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