firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-spi-spi-pl022.c....

382 lines
11 KiB
Diff

--- linux-4.9.37/drivers/spi/spi-pl022.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/spi/spi-pl022.c 2021-06-07 13:01:34.000000000 +0300
@@ -43,6 +43,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/of_address.h>
/*
* This macro is used to define some register default values.
@@ -136,6 +137,18 @@
/* This one is only in the PL023 variant */
#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
+#ifdef CONFIG_ARCH_GOKE
+/*
+ * The Goke version of this block adds some bits
+ * in SSP_CR1
+ */
+#define SSP_CR1_MASK_BIGEND_GOKE (0x1UL << 4)
+#define SSP_CR1_MASK_ALTASENS_GOKE (0x1UL << 6)
+
+#define SSP_TX_FIFO_CR(r) (r + 0x28)
+#define SSP_RX_FIFO_CR(r) (r + 0x2C)
+#endif
+
/*
* SSP Status Register - SSP_SR
*/
@@ -296,6 +309,10 @@
#define SPI_POLLING_TIMEOUT 1000
+#ifdef CONFIG_ARCH_GOKE
+#define PL022_IDS_INDEX_GOKE 4
+#endif
+
/*
* The type of reading going on on this chip
*/
@@ -337,6 +354,15 @@
bool internal_cs_ctrl;
};
+#ifdef CONFIG_ARCH_GOKE
+struct cs_data {
+ struct resource res;
+ void __iomem *virt_addr;
+ unsigned int cs_sb;
+ unsigned int cs_mask_bit;
+};
+#endif
+
/**
* struct pl022 - This is the private SSP driver data structure
* @adev: AMBA device model hookup
@@ -346,6 +372,13 @@
* @clk: outgoing clock "SPICLK" for the SPI bus
* @master: SPI framework hookup
* @master_info: controller-specific data from machine setup
+ * @kworker: thread struct for message pump
+ * @kworker_task: pointer to task for message pump kworker thread
+ * @pump_messages: work struct for scheduling work to the message pump
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
+ * @busy: message pump is busy
+ * @running: message pump is running
* @pump_transfers: Tasklet used in Interrupt Transfer mode
* @cur_msg: Pointer to current spi_message being processed
* @cur_transfer: Pointer to current spi_transfer
@@ -403,6 +436,9 @@
#endif
int cur_cs;
int *chipselects;
+#ifdef CONFIG_ARCH_GOKE
+ struct cs_data *cs_data;
+#endif
};
/**
@@ -459,13 +495,41 @@
static void internal_cs_control(struct pl022 *pl022, u32 command)
{
u32 tmp;
-
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+
+ if (pl022->vendor->extended_cr && (adev->periphid ==
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+ if (pl022->cs_data) {
+ tmp = readl(pl022->cs_data->virt_addr);
+ tmp &= ~(pl022->cs_data->cs_mask_bit);
+ tmp |= ((u32)pl022->cur_cs) << pl022->cs_data->cs_sb;
+ writel(tmp, pl022->cs_data->virt_addr);
+ }
+
+ if (command == SSP_CHIP_SELECT)
+ /* Enable SSP */
+ writew((readw(SSP_CR1(pl022->virtbase)) |
+ SSP_CR1_MASK_SSE),
+ SSP_CR1(pl022->virtbase));
+ else
+ /* disable SSP */
+ writew((readw(SSP_CR1(pl022->virtbase)) &
+ (~SSP_CR1_MASK_SSE)),
+ SSP_CR1(pl022->virtbase));
+ } else {
+#endif
tmp = readw(SSP_CSR(pl022->virtbase));
if (command == SSP_CHIP_SELECT)
- tmp &= ~BIT(pl022->cur_cs);
+ tmp &= ~BIT((u32)pl022->cur_cs);
else
- tmp |= BIT(pl022->cur_cs);
+ tmp |= BIT((u32)pl022->cur_cs);
writew(tmp, SSP_CSR(pl022->virtbase));
+#ifdef CONFIG_ARCH_GOKE
+ }
+#endif
}
static void pl022_cs_control(struct pl022 *pl022, u32 command)
@@ -566,8 +630,16 @@
static void restore_state(struct pl022 *pl022)
{
struct chip_data *chip = pl022->cur_chip;
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+ if (pl022->vendor->extended_cr && (adev->periphid !=
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id))
+#else
if (pl022->vendor->extended_cr)
+#endif
writel(chip->cr0, SSP_CR0(pl022->virtbase));
else
writew(chip->cr0, SSP_CR0(pl022->virtbase));
@@ -640,6 +712,15 @@
GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
)
+#ifdef CONFIG_ARCH_GOKE
+/* Goke versions extend this register to use all 16 bits */
+#define DEFAULT_SSP_REG_CR1_GOKE ( \
+ DEFAULT_SSP_REG_CR1 | \
+ GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_BIGEND_GOKE, 4) | \
+ GEN_MASK_BITS(0x0, SSP_CR1_MASK_ALTASENS_GOKE, 6) \
+)
+#endif
+
#define DEFAULT_SSP_REG_CPSR ( \
GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
)
@@ -659,8 +740,22 @@
writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
} else if (pl022->vendor->extended_cr) {
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+
+ if (adev->periphid == adrv->id_table[PL022_IDS_INDEX_GOKE].id) {
+ writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
+ writew(DEFAULT_SSP_REG_CR1_GOKE,
+ SSP_CR1(pl022->virtbase));
+ } else {
+#endif
writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
+#ifdef CONFIG_ARCH_GOKE
+ }
+#endif
} else {
writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase));
@@ -1803,7 +1898,7 @@
.com_mode = POLLING_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
.hierarchy = SSP_SLAVE,
- .slave_tx_disable = DO_NOT_DRIVE_TX,
+ .slave_tx_disable = DRIVE_TX,
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_8,
@@ -1835,6 +1930,13 @@
unsigned int bits = spi->bits_per_word;
u32 tmp;
struct device_node *np = spi->dev.of_node;
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+ writel(0, SSP_TX_FIFO_CR(pl022->virtbase));
+ writel(0, SSP_RX_FIFO_CR(pl022->virtbase));
+#endif
if (!spi->max_speed_hz)
return -EINVAL;
@@ -1856,8 +1958,10 @@
if (chip_info == NULL) {
if (np) {
chip_info_dt = pl022_default_chip_info;
-
- chip_info_dt.hierarchy = SSP_MASTER;
+ if(pl022->master->slave)
+ chip_info_dt.hierarchy = SSP_SLAVE;
+ else
+ chip_info_dt.hierarchy = SSP_MASTER;
of_property_read_u32(np, "pl022,interface",
&chip_info_dt.iface);
of_property_read_u32(np, "pl022,com-mode",
@@ -1977,7 +2081,12 @@
chip->cpsr = clk_freq.cpsdvsr;
/* Special setup for the ST micro extended control registers */
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->vendor->extended_cr && (adev->periphid !=
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+#else
if (pl022->vendor->extended_cr) {
+#endif
u32 etx;
if (pl022->vendor->pl023) {
@@ -2011,6 +2120,22 @@
SSP_CR1_MASK_RXIFLSEL_ST, 7);
SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
SSP_CR1_MASK_TXIFLSEL_ST, 10);
+#ifdef CONFIG_ARCH_GOKE
+ } else if (pl022->vendor->extended_cr && (adev->periphid ==
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+ SSP_WRITE_BITS(chip->cr0, bits - 1,
+ SSP_CR0_MASK_DSS, 0);
+ SSP_WRITE_BITS(chip->cr0, chip_info->iface,
+ SSP_CR0_MASK_FRF, 4);
+
+ if (spi->mode & SPI_LSB_FIRST)
+ tmp = !!SPI_LSB_FIRST;
+ else
+ tmp = !SPI_LSB_FIRST;
+
+ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_BIGEND_GOKE, 4);
+ SSP_WRITE_BITS(chip->cr1, 0x0, SSP_CR1_MASK_ALTASENS_GOKE, 6);
+#endif
} else {
SSP_WRITE_BITS(chip->cr0, bits - 1,
SSP_CR0_MASK_DSS, 0);
@@ -2099,11 +2224,14 @@
static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
struct pl022_ssp_controller *platform_info =
dev_get_platdata(&adev->dev);
struct spi_master *master;
struct pl022 *pl022 = NULL; /*Data for this driver */
struct device_node *np = adev->dev.of_node;
+ unsigned int slave_mode;
int status = 0, i, num_cs;
dev_info(&adev->dev,
@@ -2156,12 +2284,62 @@
master->rt = platform_info->rt;
master->dev.of_node = dev->of_node;
+ if (of_property_read_u32(np, "pl022,slave_mode",
+ &slave_mode) == 0) {
+ if (slave_mode == 1){
+ master->slave = true;
+ } else if (slave_mode == 0) {
+ master->slave = false;
+ } else {
+ dev_err(&adev->dev, "spi Master/Slave mode err!!!\n");
+ goto err_no_gpio;
+ }
+
+ }
+
if (platform_info->num_chipselect && platform_info->chipselects) {
for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = platform_info->chipselects[i];
} else if (pl022->vendor->internal_cs_ctrl) {
for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = i;
+
+#ifdef CONFIG_ARCH_GOKE
+ if ((adev->periphid == adrv->id_table[PL022_IDS_INDEX_GOKE].id)
+ && pl022->vendor->extended_cr
+ && (num_cs > 1)) {
+ pl022->cs_data = devm_kzalloc(dev,
+ sizeof(struct cs_data),
+ GFP_KERNEL);
+ if (!pl022->cs_data) {
+ status = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ if (of_address_to_resource(np, 1,
+ &pl022->cs_data->res)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ if (of_property_read_u32(np, "spi_cs_sb",
+ &pl022->cs_data->cs_sb)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ if (of_property_read_u32(np, "spi_cs_mask_bit",
+ &pl022->cs_data->cs_mask_bit)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ pl022->cs_data->virt_addr = devm_ioremap(dev,
+ pl022->cs_data->res.start,
+ resource_size(&adev->res));
+ } else
+ pl022->cs_data = NULL;
+#endif
} else if (IS_ENABLED(CONFIG_OF)) {
for (i = 0; i < num_cs; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
@@ -2288,6 +2466,11 @@
err_no_ioremap:
amba_release_regions(adev);
err_no_ioregion:
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->cs_data)
+ release_mem_region(pl022->cs_data->res.start,
+ resource_size(&pl022->cs_data->res));
+#endif
err_no_gpio:
err_no_mem:
spi_master_put(master);
@@ -2314,6 +2497,11 @@
clk_disable_unprepare(pl022->clk);
amba_release_regions(adev);
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->cs_data)
+ release_mem_region(pl022->cs_data->res.start,
+ resource_size(&pl022->cs_data->res));
+#endif
tasklet_disable(&pl022->pump_transfers);
return 0;
}
@@ -2390,13 +2578,13 @@
};
static struct vendor_data vendor_arm = {
- .fifodepth = 8,
+ .fifodepth = 256,
.max_bpw = 16,
.unidir = false,
- .extended_cr = false,
+ .extended_cr = true,
.pl023 = false,
.loopback = true,
- .internal_cs_ctrl = false,
+ .internal_cs_ctrl = true,
};
static struct vendor_data vendor_st = {
@@ -2433,7 +2621,7 @@
{
/*
* ARM PL022 variant, this has a 16bit wide
- * and 8 locations deep TX/RX FIFO
+ * and 256 locations deep TX/RX FIFO
*/
.id = 0x00041022,
.mask = 0x000fffff,