aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEthan Xia <xiasb@marvell.com>2016-03-25 10:28:44 +0800
committerEthan Xia <xiasb@marvell.com>2016-03-29 07:19:24 +0000
commitd7a980c93f98be1779452e59fb21ca76dc6b4d5c (patch)
treef55ddaf4aeb2ee52fe44f91c44d926f136a854c5
parentd4cb1394128f6e3e837167f0bda345a608f7df4d (diff)
downloadpxa-v3.14-master.tar.gz
VENDOR: Marvell: abox_edge: Enable SPI controller driverHEADmastermain
1. Enable Marvell SPI controller and MTD m25p80 driver in kernel config 2. Add SPI pin configuration in dts file 3. Support setting the SPI controller clock dynamically 4. Use GPIO to control the #CS signal of SPI BUG: 27844484 Change-Id: I3691f37e869dc43599417ed734ea9b9dd4db2944
-rwxr-xr-xarch/arm/configs/abox_edge_defconfig21
-rw-r--r--arch/arm64/boot/dts/pxa1908-board-common.dtsi58
-rw-r--r--arch/arm64/boot/dts/pxa1908.dtsi33
-rw-r--r--arch/arm64/mach/helanx-dt.c3
-rw-r--r--drivers/clk/mmp/clk-pxa1U88.c3
-rw-r--r--drivers/mtd/devices/m25p80.c1
-rw-r--r--drivers/spi/spi-pxa2xx.c66
-rw-r--r--drivers/spi/spi-pxa2xx.h2
8 files changed, 151 insertions, 36 deletions
diff --git a/arch/arm/configs/abox_edge_defconfig b/arch/arm/configs/abox_edge_defconfig
index 30eacdc78ce..2dc93653b2c 100755
--- a/arch/arm/configs/abox_edge_defconfig
+++ b/arch/arm/configs/abox_edge_defconfig
@@ -316,6 +316,7 @@ CONFIG_ARCH_MMP=y
# CONFIG_GPIO_PCA953X is not set
# CONFIG_KEYBOARD_GPIO_POLLED is not set
# CONFIG_MACH_TAVOREVB is not set
+CONFIG_PXA_SSP=y
#
# Marvell PXA168/910/MMP2 Implmentations
@@ -1046,6 +1047,7 @@ CONFIG_FW_LOADER_USER_HELPER=y
# CONFIG_HAVE_CPU_AUTOPROBE is not set
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_DMA_SHARED_BUFFER=y
@@ -1068,7 +1070,14 @@ CONFIG_DYNAMIC_TOPOLOGY_SYSFS=y
#
# CONFIG_ARM_CCI is not set
# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_M25P80=y
CONFIG_DTC=y
CONFIG_OF=y
@@ -1083,6 +1092,7 @@ CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_NET=y
CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -1307,6 +1317,7 @@ CONFIG_NET_VENDOR_MARVELL=y
CONFIG_NET_VENDOR_MICREL=y
# CONFIG_KS8842 is not set
# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
CONFIG_NET_VENDOR_NATSEMI=y
CONFIG_NET_VENDOR_8390=y
# CONFIG_AX88796 is not set
@@ -1647,7 +1658,11 @@ CONFIG_I2C_PXA=y
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_PXA2XX_DMA=y
+CONFIG_SPI_PXA2XX=y
# CONFIG_HSI is not set
#
@@ -2238,6 +2253,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_MMP_DISP=y
CONFIG_MMP_DISP_CONTROLLER=y
CONFIG_MMP_DISP_DFC=y
+CONFIG_MMP_DISP_SPI=y
# CONFIG_MMP_VIRTUAL_RESOLUTION is not set
# CONFIG_MMP_PANEL_HX8394_IPS3P5071 is not set
CONFIG_MMP_PANEL_R63311=y
@@ -2312,6 +2328,7 @@ CONFIG_SND_DRIVERS=y
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=y
# CONFIG_SND_USB_UA101 is not set
diff --git a/arch/arm64/boot/dts/pxa1908-board-common.dtsi b/arch/arm64/boot/dts/pxa1908-board-common.dtsi
index 5c76d332432..2c0c546e2c8 100644
--- a/arch/arm64/boot/dts/pxa1908-board-common.dtsi
+++ b/arch/arm64/boot/dts/pxa1908-board-common.dtsi
@@ -407,6 +407,7 @@
&range 55 55 0 /* GPIO0 ~ GPIO54 */
&range 110 32 0 /* GPIO67 ~ GPIO98 */
&range 52 1 0 /* GPIO124 */
+ &range 6 1 0 /* GPIO65 */
>;
pinctrl-names = "default";
pinctrl-0 = <&mfp_pins_group_0 &mfp_pins_group_1>;
@@ -426,10 +427,6 @@
mfp_pins_group_0: mfp_pins_group_0 {
pinctrl-single,pins = <
/* DF_IO8 AF0 */
- DF_IO9 AF0
- DF_IO10 AF0
- DF_IO11 AF0
- DF_IO12 AF0
DF_IO13 AF0
DF_IO15 AF0
>;
@@ -650,21 +647,21 @@
};
spi0_pmx_func: spi0_pmx_func {
- pinctrl-single,pins = <
- GPIO33 AF2 /* GPIO33 SSP0_CLK */
- GPIO34 AF2 /* GPIO34 SSP0_FRM */
- GPIO35 AF2 /* GPIO35 SSP0_RX */
- GPIO36 AF2 /* GPIO36 SSP0_TX */
+ pinctrl-single,pins = <
+ GPIO33 AF2 /* GPIO33 SSP0_CLK */
+ GPIO34 AF2 /* GPIO34 SSP0_FRM */
+ GPIO35 AF2 /* GPIO35 SSP0_RX */
+ GPIO36 AF2 /* GPIO36 SSP0_TX */
>;
MFP_DEFAULT;
};
- spi1_pmx_func: spi1_pmx_func {
- pinctrl-single,pins = <
- DF_IO9 AF2 /* GPIO66 SSP2_CLK */
- DF_IO10 AF2 /* GPIO65 SSP2_FRM */
- DF_IO11 AF2 /* GPIO64 SSP2_TX */
- DF_IO12 AF2 /* GPIO63 SSP2_RX */
+ spi2_pmx_func: spi2_pmx_func {
+ pinctrl-single,pins = <
+ DF_IO9 AF2 /* GPIO66 SSP2_CLK */
+ DF_IO10 AF1 /* GPIO65 SSP2_FRM */
+ DF_IO11 AF2 /* GPIO64 SSP2_TX */
+ DF_IO12 AF2 /* GPIO63 SSP2_RX */
>;
MFP_DEFAULT;
};
@@ -1065,6 +1062,37 @@
};
};
+ spi_0: ssp@d401b000 {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pmx_func>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spidev {
+ spi-max-frequency = <52000000>;
+ reg = <0>;
+ compatible = "rohm,dh2228fv";
+ status = "okay";
+ };
+ };
+
+ spi_2: ssp@d401c000 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pmx_func>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "sst,sst25wf040b";
+ spi-max-frequency = <40000000>;
+ reg = <0>;
+ };
+ };
+
/* SSPA port 0 */
sspa0: sspa@d128dc00 {
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/pxa1908.dtsi b/arch/arm64/boot/dts/pxa1908.dtsi
index dd9a824f6f8..987bff725fe 100644
--- a/arch/arm64/boot/dts/pxa1908.dtsi
+++ b/arch/arm64/boot/dts/pxa1908.dtsi
@@ -601,7 +601,7 @@
gcb2: gpio@d4019008 {
reg-offset = <0x8>;
- gpio-ranges = <&pmx 3 110 29>;
+ gpio-ranges = <&pmx 1 6 1 &pmx 3 110 29>;
};
gcb3: gpio@d4019100 {
@@ -633,6 +633,37 @@
status = "disabled";
};
+ spi_0: ssp@d401b000 {
+ compatible = "marvell,pxa910-spi";
+ marvell,ssp-enhancement;
+ reg = <0xd401b000 0x90>;
+ ssp-id = <0>;
+ interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>;
+ /* dma engineer, DRCMR offset, user_do_qos */
+ dmas = <&pdma0 52 1
+ &pdma0 53 1>;
+ dma-names = "rx", "tx";
+ lpm-qos = <PM_QOS_CPUIDLE_BLOCK_AXI>;
+ clocks = <&soc_clocks PXA1U88_CLK_SSP0>;
+ status = "disabled";
+ };
+
+ spi_2: ssp@d401c000 {
+ compatible = "marvell,pxa910-spi";
+ marvell,ssp-enhancement;
+ marvell,ssp-nor-flash;
+ reg = <0xd401c000 0x90>;
+ ssp-id = <2>;
+ interrupts = <0 1 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&pdma0 60 1
+ &pdma0 61 1>;
+ dma-names = "rx", "tx";
+ lpm-qos = <PM_QOS_CPUIDLE_BLOCK_AXI>;
+ clocks = <&soc_clocks PXA1U88_CLK_SSP2>;
+ cs-gpios = <&gpio 65 0>;
+ status = "disabled";
+ };
+
sspa0: sspa@d128dc00 {
compatible = "mrvl,mmp-sspa-dai";
reg = <0xd128dc00 0x100>;
diff --git a/arch/arm64/mach/helanx-dt.c b/arch/arm64/mach/helanx-dt.c
index 2f0b5bcccc0..80939cee0f0 100644
--- a/arch/arm64/mach/helanx-dt.c
+++ b/arch/arm64/mach/helanx-dt.c
@@ -68,6 +68,9 @@ static const struct of_dev_auxdata helanx_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("regulator-leds", 0, "leds-regulator",
&keypad_backlight),
#endif
+#ifdef CONFIG_SPI_PXA2XX
+ OF_DEV_AUXDATA("marvell,pxa910-spi", 0xd401c000, "pxa910-ssp.2", NULL),
+#endif
{}
};
diff --git a/drivers/clk/mmp/clk-pxa1U88.c b/drivers/clk/mmp/clk-pxa1U88.c
index 48d825beb81..7475a04decf 100644
--- a/drivers/clk/mmp/clk-pxa1U88.c
+++ b/drivers/clk/mmp/clk-pxa1U88.c
@@ -519,7 +519,7 @@ static void pxa1U88_apb_periph_clk_init(struct pxa1U88_clk_unit *pxa_unit)
ARRAY_SIZE(ssp_parent_names), 0,
pxa_unit->apbc_base + APBC_SSP2, 4, 3, 0, NULL);
clk = mmp_clk_register_gate(NULL, "ssp2_clk", "ssp2_mux",
- 0,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apbc_base + APBC_SSP2,
0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_SSP2, clk);
@@ -1494,7 +1494,6 @@ static void __init pxa1U88_misc_init(struct pxa1U88_clk_unit *pxa_unit)
val = __raw_readl(pxa_unit->apmu_base + APMU_DVC_DFC_DEBUG);
val |= (1 << 5);
__raw_writel(val, pxa_unit->apmu_base + APMU_DVC_DFC_DEBUG);
-
}
static void __init pxa1U88_clk_init(struct device_node *np)
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index ad191390970..4a7c796379d 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -977,6 +977,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) },
{ "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) },
{ "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) },
+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
/* ST Microelectronics -- newer production may have feature updates */
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 98eca261273..b37f657fb7d 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -593,8 +593,9 @@ static irqreturn_t pxa2xx_spi_int(int irq, void *dev_id)
return IRQ_NONE;
if (!drv_data->cur_msg) {
-
+ /* Disable SSPx port */
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ /* Disable TXFIFO/RXFIFO/RX-Timeout interrupt */
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
@@ -777,8 +778,10 @@ static void pump_transfers(unsigned long data)
SSCR2_RD_ENDIAN_16BITS;
bits = 32;
drv_data->n_bytes = 4;
- drv_data->read = u32_reader;
- drv_data->write = u32_writer;
+ drv_data->read = drv_data->read != null_reader ?
+ u32_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u32_writer : null_writer;
if (chip->enable_dma) {
if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
@@ -802,7 +805,6 @@ static void pump_transfers(unsigned long data)
if (pxa2xx_spi_dma_is_possible(drv_data->len))
drv_data->dma_mapped = pxa2xx_spi_map_dma_buffers(drv_data);
if (drv_data->dma_mapped) {
-
/* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
@@ -829,6 +831,7 @@ static void pump_transfers(unsigned long data)
write_SSITF(chip->lpss_tx_threshold, reg);
}
+
/* see if we need to reload the config registers */
if ((read_SSCR0(reg) != cr0)
|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
@@ -933,6 +936,7 @@ static int setup(struct spi_device *spi)
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
unsigned int clk_div;
uint tx_thres, tx_hi_thres, rx_thres;
+ int ret = 0;
if (is_lpss_ssp(drv_data)) {
tx_thres = LPSS_TX_LOTHRESH_DFLT;
@@ -961,10 +965,14 @@ static int setup(struct spi_device *spi)
kfree(chip);
return -EINVAL;
}
-
chip->frm = spi->chip_select;
- } else
+ } else if (drv_data->ssp_nor_flash) {
+ chip->gpio_cs = spi->cs_gpio;
+ chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
+ }
+ else
chip->gpio_cs = -1;
+
chip->enable_dma = 0;
chip->timeout = TIMOUT_DFLT;
}
@@ -1013,8 +1021,13 @@ static int setup(struct spi_device *spi)
}
}
- /* clk_div represent to Bit17-8 bits of CS0 */
+ /* clk_div represent to Bit19-8 bits of CS0 */
clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
+
+ /* Clock rate setting not in SSCR0 for Marvell SSP2 */
+ if (drv_data->ssp_nor_flash)
+ clk_set_rate(drv_data->clk, spi->max_speed_hz);
+
chip->speed_hz = spi->max_speed_hz;
chip->cr0 = clk_div
@@ -1030,8 +1043,12 @@ static int setup(struct spi_device *spi)
if (spi->mode & SPI_LOOP)
chip->cr1 |= SSCR1_LBM;
+ if (drv_data->ssp_nor_flash)
+ dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
+ clk_get_rate(drv_data->clk),
+ chip->enable_dma ? "DMA" : "PIO");
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
- if (!pxa25x_ssp_comp(drv_data))
+ else if (!pxa25x_ssp_comp(drv_data))
dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
drv_data->max_clk_rate
/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
@@ -1042,7 +1059,6 @@ static int setup(struct spi_device *spi)
/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO");
-
/* Enable rx fifo auto full control */
if (drv_data->ssp_enhancement)
chip->cr2 = SSCR2_RX_FULL_CTRL;
@@ -1066,7 +1082,21 @@ static int setup(struct spi_device *spi)
spi_set_ctldata(spi, chip);
if (drv_data->ssp_type == CE4100_SSP)
- return 0;
+ return ret;
+
+ /* Configure SSP2_FRM as GPIO for SPI #CS */
+ if (drv_data->ssp_nor_flash && gpio_is_valid(chip->gpio_cs)) {
+ ret = gpio_request(chip->gpio_cs, dev_name(&spi->dev));
+ if (ret) {
+ dev_err(&spi->dev, "failed to request chip select GPIO%d\n",
+ chip->gpio_cs);
+ return ret;
+ }
+
+ ret = gpio_direction_output(chip->gpio_cs,
+ !chip->gpio_cs_inverted);
+ return ret;
+ }
return setup_cs(spi, chip, chip_info);
}
@@ -1228,6 +1258,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
/* Receive FIFO auto full ctrl enable */
if (of_get_property(np, "marvell,ssp-enhancement", NULL))
drv_data->ssp_enhancement = 1;
+
+ /* Use SSP2 port for SPI Nor flash */
+ if (of_get_property(np, "marvell,ssp-nor-flash", NULL))
+ drv_data->ssp_nor_flash = 1;
+
/*
* the null DMA buf should malloc form DMA_ZONE
* and align of DMA_ALIGNMENT
@@ -1267,7 +1302,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->bus_num = bus_num;
drv_data->ssdr_physical = iores->start + SSDR;
drv_data->clk = devm_clk_get(dev, NULL);
-
#else
ssp = pxa_ssp_request(pdev->id, pdev->name);
if (!ssp)
@@ -1356,6 +1390,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
tasklet_init(&drv_data->pump_transfers, pump_transfers,
(unsigned long)drv_data);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
/* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data);
status = devm_spi_register_master(&pdev->dev, master);
@@ -1364,11 +1403,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
goto out_error_clock_enabled;
}
- pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
return status;
out_error_clock_enabled:
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 3c9788acd9e..7fa576a0bf8 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -98,6 +98,8 @@ struct driver_data {
int irq;
/* Support RX FIFO auto full control and endian swap */
unsigned int ssp_enhancement;
+ /* Use SSP2 for SPI Nor flash chip */
+ unsigned int ssp_nor_flash;
#endif
};