Pull spi updates from Mark Brown: "A few core tweaks this time together with the usual collection of driver specific updates and fixes plus a larger than average selection of new device support: - fix DMA mapping of unaligned vmalloc() buffers - statistics tracking transfer volumes exposed via sysfs - new drivers for Freescale MPC5125, Intel Sunrise Point, Mediatek SoCs, and Netlogic XLP SoCs" * tag 'spi-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits) spi: sh-msiof: Fix FIFO size to 64 word from 256 word spi: fsl-(e)spi: Fix checking return value of devm_ioremap_resource spi: Add DT bindings documentation for Netlogic XLP SPI controller spi/xlp: SPI controller driver for Netlogic XLP SoCs spi: fsl-espi: add runtime PM spi: fsl-(e)spi: simplify cleanup code spi: fsl-(e)spi: migrate to using devm_ functions to simplify cleanup spi: mediatek: fix SPI_CMD_PAUSE_IE macro error spi: check bits_per_word in spi_setup spi: mediatek: replace *_time name spi: mediatek: add PM clk_prepare_enable fail flow spi: mediatek: replace int with u32, delete TAB and define MTK_SPI_PAUSE_INT_STATUS marco spi: mediatek: add linux/io.h include file spi/bcm63xx-hsspi: add support for dual spi read/write spi: dw: Allow interface drivers to limit data I/O to word sizes dt: snps,dw-apb-ssi: Document new I/O data register width property spi: Fall back to master maximum speed if no slave speed specified spi: mediatek: use BIT() to instead of SPI_CMD_*_OFFSET spi: medaitek: revise quirks compatibility style spi: mediatek: fix spi incorrect endian usage ...
Unified · Split
| @@ -6,14 +6,14 @@ PSC in UART mode · 5 unmodified lines | ||
| 6 | 6 | For PSC in UART mode the needed PSC serial devices |
| 7 | 7 | are specified by fsl,mpc5121-psc-uart nodes in the |
| 8 | 8 | fsl,mpc5121-immr SoC node. Additionally the PSC FIFO |
| 9 | −Controller node fsl,mpc5121-psc-fifo is requered there: | |
| 9 | +Controller node fsl,mpc5121-psc-fifo is required there: | |
| 10 | 10 | |
| 11 | −fsl,mpc5121-psc-uart nodes | |
| 11 | +fsl,mpc512x-psc-uart nodes | |
| 12 | 12 | -------------------------- |
| 13 | 13 | |
| 14 | 14 | Required properties : |
| 15 | − - compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc" | |
| 16 | − - cell-index : Index of the PSC in hardware | |
| 15 | + - compatible : Should contain "fsl,<soc>-psc-uart" and "fsl,<soc>-psc" | |
| 16 | + Supported <soc>s: mpc5121, mpc5125 | |
| 17 | 17 | - reg : Offset and length of the register set for the PSC device |
| 18 | 18 | - interrupts : <a b> where a is the interrupt number of the |
| 19 | 19 | PSC FIFO Controller and b is a field that represents an |
| @@ -25,12 +25,21 @@ Recommended properties : · 5 unmodified lines | ||
| 25 | 25 | - fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4) |
| 26 | 26 | - fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4) |
| 27 | 27 | |
| 28 | +PSC in SPI mode | |
| 29 | +--------------- | |
| 28 | 30 | |
| 29 | −fsl,mpc5121-psc-fifo node | |
| 31 | +Similar to the UART mode a PSC can be operated in SPI mode. The compatible used | |
| 32 | +for that is fsl,mpc5121-psc-spi. It requires a fsl,mpc5121-psc-fifo as well. | |
| 33 | +The required and recommended properties are identical to the | |
| 34 | +fsl,mpc5121-psc-uart nodes, just use spi instead of uart in the compatible | |
| 35 | +string. | |
| 36 | + | |
| 37 | +fsl,mpc512x-psc-fifo node | |
| 30 | 38 | ------------------------- |
| 31 | 39 | |
| 32 | 40 | Required properties : |
| 33 | − - compatible : Should be "fsl,mpc5121-psc-fifo" | |
| 41 | + - compatible : Should be "fsl,<soc>-psc-fifo" | |
| 42 | + Supported <soc>s: mpc5121, mpc5125 | |
| 34 | 43 | - reg : Offset and length of the register set for the PSC |
| 35 | 44 | FIFO Controller |
| 36 | 45 | - interrupts : <a b> where a is the interrupt number of the |
| @@ -39,6 +48,9 @@ Required properties : · 2 unmodified lines | ||
| 39 | 48 | - interrupt-parent : the phandle for the interrupt controller that |
| 40 | 49 | services interrupts for this device. |
| 41 | 50 | |
| 51 | +Recommended properties : | |
| 52 | + - clocks : specifies the clock needed to operate the fifo controller | |
| 53 | + - clock-names : name(s) for the clock(s) listed in clocks | |
| 42 | 54 | |
| 43 | 55 | Example for a board using PSC0 and PSC1 devices in serial mode: |
| 44 | 56 | |
| @@ -10,6 +10,8 @@ Required properties: · 9 unmodified lines | ||
| 10 | 10 | Optional properties: |
| 11 | 11 | - cs-gpios : Specifies the gpio pis to be used for chipselects. |
| 12 | 12 | - num-cs : The number of chipselects. If omitted, this will default to 4. |
| 13 | +- reg-io-width : The I/O register width (in bytes) implemented by this | |
| 14 | + device. Supported values are 2 or 4 (the default). | |
| 13 | 15 | |
| 14 | 16 | Child nodes as per the generic SPI binding. |
| 15 | 17 | |
| @@ -12,6 +12,8 @@ Required properties: · 11 unmodified lines | ||
| 12 | 12 | - compatible: |
| 13 | 13 | - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family |
| 14 | 14 | - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family |
| 15 | + - "ti,keystone-spi" for SPI used similar to that on Keystone2 SoC | |
| 16 | + family | |
| 15 | 17 | - reg: Offset and length of SPI controller register space |
| 16 | 18 | - num-cs: Number of chip selects. This includes internal as well as |
| 17 | 19 | GPIO chip selects. |
| @@ -21,6 +21,7 @@ Required properties: · 20 unmodified lines | ||
| 21 | 21 | Optional properties: |
| 22 | 22 | - img,supports-quad-mode: Should be set if the interface supports quad mode |
| 23 | 23 | SPI transfers. |
| 24 | +- spfi-max-frequency: Maximum speed supported by the spfi block. | |
| 24 | 25 | |
| 25 | 26 | Example: |
| 26 | 27 | |
| @@ -0,0 +1,51 @@ | ||
| 1 | +Binding for MTK SPI controller | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | +- compatible: should be one of the following. | |
| 5 | + - mediatek,mt8173-spi: for mt8173 platforms | |
| 6 | + - mediatek,mt8135-spi: for mt8135 platforms | |
| 7 | + - mediatek,mt6589-spi: for mt6589 platforms | |
| 8 | + | |
| 9 | +- #address-cells: should be 1. | |
| 10 | + | |
| 11 | +- #size-cells: should be 0. | |
| 12 | + | |
| 13 | +- reg: Address and length of the register set for the device | |
| 14 | + | |
| 15 | +- interrupts: Should contain spi interrupt | |
| 16 | + | |
| 17 | +- clocks: phandles to input clocks. | |
| 18 | + The first should be <&topckgen CLK_TOP_SPI_SEL>. | |
| 19 | + The second should be one of the following. | |
| 20 | + - <&clk26m>: specify parent clock 26MHZ. | |
| 21 | + - <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ. | |
| 22 | + It's the default one. | |
| 23 | + - <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ. | |
| 24 | + - <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ. | |
| 25 | + - <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ. | |
| 26 | + | |
| 27 | +- clock-names: shall be "spi-clk" for the controller clock, and | |
| 28 | + "parent-clk" for the parent clock. | |
| 29 | + | |
| 30 | +Optional properties: | |
| 31 | +- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi | |
| 32 | + controller used, this value should be 0~3, only required for MT8173. | |
| 33 | + 0: specify GPIO69,70,71,72 for spi pins. | |
| 34 | + 1: specify GPIO102,103,104,105 for spi pins. | |
| 35 | + 2: specify GPIO128,129,130,131 for spi pins. | |
| 36 | + 3: specify GPIO5,6,7,8 for spi pins. | |
| 37 | + | |
| 38 | +Example: | |
| 39 | + | |
| 40 | +- SoC Specific Portion: | |
| 41 | +spi: spi@1100a000 { | |
| 42 | + compatible = "mediatek,mt8173-spi"; | |
| 43 | + #address-cells = <1>; | |
| 44 | + #size-cells = <0>; | |
| 45 | + reg = <0 0x1100a000 0 0x1000>; | |
| 46 | + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>; | |
| 47 | + clocks = <&topckgen CLK_TOP_SPI_SEL>, <&topckgen CLK_TOP_SYSPLL3_D2>; | |
| 48 | + clock-names = "spi-clk", "parent-clk"; | |
| 49 | + mediatek,pad-select = <0>; | |
| 50 | + status = "disabled"; | |
| 51 | +}; | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +SPI Master controller for Netlogic XLP MIPS64 SOCs | |
| 2 | +================================================== | |
| 3 | + | |
| 4 | +Currently this SPI controller driver is supported for the following | |
| 5 | +Netlogic XLP SoCs: | |
| 6 | + XLP832, XLP316, XLP208, XLP980, XLP532 | |
| 7 | + | |
| 8 | +Required properties: | |
| 9 | +- compatible : Should be "netlogic,xlp832-spi". | |
| 10 | +- #address-cells : Number of cells required to define a chip select address | |
| 11 | + on the SPI bus. | |
| 12 | +- #size-cells : Should be zero. | |
| 13 | +- reg : Should contain register location and length. | |
| 14 | +- clocks : Phandle of the spi clock | |
| 15 | +- interrupts : Interrupt number used by this controller. | |
| 16 | +- interrupt-parent : Phandle of the parent interrupt controller. | |
| 17 | + | |
| 18 | +SPI slave nodes must be children of the SPI master node and can contain | |
| 19 | +properties described in Documentation/devicetree/bindings/spi/spi-bus.txt. | |
| 20 | + | |
| 21 | +Example: | |
| 22 | + | |
| 23 | + spi: xlp_spi@3a100 { | |
| 24 | + compatible = "netlogic,xlp832-spi"; | |
| 25 | + #address-cells = <1>; | |
| 26 | + #size-cells = <0>; | |
| 27 | + reg = <0 0x3a100 0x100>; | |
| 28 | + clocks = <&spi_clk>; | |
| 29 | + interrupts = <34>; | |
| 30 | + interrupt-parent = <&pic>; | |
| 31 | + | |
| 32 | + spi_nor@1 { | |
| 33 | + compatible = "spansion,s25sl12801"; | |
| 34 | + #address-cells = <1>; | |
| 35 | + #size-cells = <1>; | |
| 36 | + reg = <1>; /* Chip Select */ | |
| 37 | + spi-max-frequency = <40000000>; | |
| 38 | + }; | |
| 39 | +}; | |
| @@ -1010,11 +1010,13 @@ static struct davinci_spi_platform_data da8xx_spi_pdata[] = { · 1009 unmodified lines | ||
| 1010 | 1010 | .version = SPI_VERSION_2, |
| 1011 | 1011 | .intr_line = 1, |
| 1012 | 1012 | .dma_event_q = EVENTQ_0, |
| 1013 | + .prescaler_limit = 2, | |
| 1013 | 1014 | }, |
| 1014 | 1015 | [1] = { |
| 1015 | 1016 | .version = SPI_VERSION_2, |
| 1016 | 1017 | .intr_line = 1, |
| 1017 | 1018 | .dma_event_q = EVENTQ_0, |
| 1019 | + .prescaler_limit = 2, | |
| 1018 | 1020 | }, |
| 1019 | 1021 | }; |
| 1020 | 1022 | |
| @@ -411,6 +411,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = { · 410 unmodified lines | ||
| 411 | 411 | .num_chipselect = 2, |
| 412 | 412 | .cshold_bug = true, |
| 413 | 413 | .dma_event_q = EVENTQ_1, |
| 414 | + .prescaler_limit = 1, | |
| 414 | 415 | }; |
| 415 | 416 | static struct platform_device dm355_spi0_device = { |
| 416 | 417 | .name = "spi_davinci", |
| @@ -646,6 +646,7 @@ static struct davinci_spi_platform_data dm365_spi0_pdata = { · 645 unmodified lines | ||
| 646 | 646 | .version = SPI_VERSION_1, |
| 647 | 647 | .num_chipselect = 2, |
| 648 | 648 | .dma_event_q = EVENTQ_3, |
| 649 | + .prescaler_limit = 1, | |
| 649 | 650 | }; |
| 650 | 651 | |
| 651 | 652 | static struct resource dm365_spi0_resources[] = { |
| @@ -150,7 +150,10 @@ · 149 unmodified lines | ||
| 150 | 150 | |
| 151 | 151 | /* Structure of the hardware registers */ |
| 152 | 152 | struct mpc52xx_psc { |
| 153 | − u8 mode; /* PSC + 0x00 */ | |
| 153 | + union { | |
| 154 | + u8 mode; /* PSC + 0x00 */ | |
| 155 | + u8 mr2; | |
| 156 | + }; | |
| 154 | 157 | u8 reserved0[3]; |
| 155 | 158 | union { /* PSC + 0x04 */ |
| 156 | 159 | u16 status; |
| @@ -326,6 +326,15 @@ config SPI_MESON_SPIFC · 325 unmodified lines | ||
| 326 | 326 | This enables master mode support for the SPIFC (SPI flash |
| 327 | 327 | controller) available in Amlogic Meson SoCs. |
| 328 | 328 | |
| 329 | +config SPI_MT65XX | |
| 330 | + tristate "MediaTek SPI controller" | |
| 331 | + depends on ARCH_MEDIATEK || COMPILE_TEST | |
| 332 | + help | |
| 333 | + This selects the MediaTek(R) SPI bus driver. | |
| 334 | + If you want to use MediaTek(R) SPI interface, | |
| 335 | + say Y or M here.If you are not sure, say N. | |
| 336 | + SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. | |
| 337 | + | |
| 329 | 338 | config SPI_OC_TINY |
| 330 | 339 | tristate "OpenCores tiny SPI" |
| 331 | 340 | depends on GPIOLIB || COMPILE_TEST |
| @@ -598,6 +607,17 @@ config SPI_XILINX · 266 unmodified lines | ||
| 598 | 607 | |
| 599 | 608 | Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" |
| 600 | 609 | |
| 610 | +config SPI_XLP | |
| 611 | + tristate "Netlogic XLP SPI controller driver" | |
| 612 | + depends on CPU_XLP || COMPILE_TEST | |
| 613 | + help | |
| 614 | + Enable support for the SPI controller on the Netlogic XLP SoCs. | |
| 615 | + Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX | |
| 616 | + and XLP5XX. | |
| 617 | + | |
| 618 | + If you have a Netlogic XLP platform say Y here. | |
| 619 | + If unsure, say N. | |
| 620 | + | |
| 601 | 621 | config SPI_XTENSA_XTFPGA |
| 602 | 622 | tristate "Xtensa SPI controller for xtfpga" |
| 603 | 623 | depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST |
| @@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o · 47 unmodified lines | ||
| 48 | 48 | obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o |
| 49 | 49 | obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o |
| 50 | 50 | obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o |
| 51 | +obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o | |
| 51 | 52 | obj-$(CONFIG_SPI_MXS) += spi-mxs.o |
| 52 | 53 | obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o |
| 53 | 54 | obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o |
| @@ -88,5 +89,6 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o · 34 unmodified lines | ||
| 88 | 89 | obj-$(CONFIG_SPI_TXX9) += spi-txx9.o |
| 89 | 90 | obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o |
| 90 | 91 | obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o |
| 92 | +obj-$(CONFIG_SPI_XLP) += spi-xlp.o | |
| 91 | 93 | obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o |
| 92 | 94 | obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/interrupt.h> |
| 20 | 20 | #include <linux/spi/spi.h> |
| 21 | 21 | #include <linux/slab.h> |
| 22 | −#include <linux/platform_data/atmel.h> | |
| 23 | 22 | #include <linux/platform_data/dma-atmel.h> |
| 24 | 23 | #include <linux/of.h> |
| 25 | 24 | |
| @@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, · 479 unmodified lines | ||
| 480 | 480 | struct spi_device *spi, |
| 481 | 481 | struct spi_transfer *tfr, |
| 482 | 482 | u32 cs, |
| 483 | − unsigned long xfer_time_us) | |
| 483 | + unsigned long long xfer_time_us) | |
| 484 | 484 | { |
| 485 | 485 | struct bcm2835_spi *bs = spi_master_get_devdata(master); |
| 486 | 486 | unsigned long timeout; |
| @@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, · 44 unmodified lines | ||
| 531 | 531 | { |
| 532 | 532 | struct bcm2835_spi *bs = spi_master_get_devdata(master); |
| 533 | 533 | unsigned long spi_hz, clk_hz, cdiv; |
| 534 | − unsigned long spi_used_hz, xfer_time_us; | |
| 534 | + unsigned long spi_used_hz; | |
| 535 | + unsigned long long xfer_time_us; | |
| 535 | 536 | u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); |
| 536 | 537 | |
| 537 | 538 | /* set clock */ |
| @@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, · 15 unmodified lines | ||
| 553 | 554 | spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); |
| 554 | 555 | bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); |
| 555 | 556 | |
| 556 | − /* handle all the modes */ | |
| 557 | + /* handle all the 3-wire mode */ | |
| 557 | 558 | if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) |
| 558 | 559 | cs |= BCM2835_SPI_CS_REN; |
| 559 | − if (spi->mode & SPI_CPOL) | |
| 560 | − cs |= BCM2835_SPI_CS_CPOL; | |
| 561 | − if (spi->mode & SPI_CPHA) | |
| 562 | − cs |= BCM2835_SPI_CS_CPHA; | |
| 560 | + else | |
| 561 | + cs &= ~BCM2835_SPI_CS_REN; | |
| 563 | 562 | |
| 564 | 563 | /* for gpio_cs set dummy CS so that no HW-CS get changed |
| 565 | 564 | * we can not run this in bcm2835_spi_set_cs, as it does |
| @@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, · 9 unmodified lines | ||
| 575 | 574 | bs->rx_len = tfr->len; |
| 576 | 575 | |
| 577 | 576 | /* calculate the estimated time in us the transfer runs */ |
| 578 | − xfer_time_us = tfr->len | |
| 577 | + xfer_time_us = (unsigned long long)tfr->len | |
| 579 | 578 | * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ |
| 580 | − * 1000000 / spi_used_hz; | |
| 579 | + * 1000000; | |
| 580 | + do_div(xfer_time_us, spi_used_hz); | |
| 581 | 581 | |
| 582 | 582 | /* for short requests run polling*/ |
| 583 | 583 | if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) |
| @@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, · 8 unmodified lines | ||
| 592 | 592 | return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); |
| 593 | 593 | } |
| 594 | 594 | |
| 595 | +static int bcm2835_spi_prepare_message(struct spi_master *master, | |
| 596 | + struct spi_message *msg) | |
| 597 | +{ | |
| 598 | + struct spi_device *spi = msg->spi; | |
| 599 | + struct bcm2835_spi *bs = spi_master_get_devdata(master); | |
| 600 | + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); | |
| 601 | + | |
| 602 | + cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); | |
| 603 | + | |
| 604 | + if (spi->mode & SPI_CPOL) | |
| 605 | + cs |= BCM2835_SPI_CS_CPOL; | |
| 606 | + if (spi->mode & SPI_CPHA) | |
| 607 | + cs |= BCM2835_SPI_CS_CPHA; | |
| 608 | + | |
| 609 | + bcm2835_wr(bs, BCM2835_SPI_CS, cs); | |
| 610 | + | |
| 611 | + return 0; | |
| 612 | +} | |
| 613 | + | |
| 595 | 614 | static void bcm2835_spi_handle_err(struct spi_master *master, |
| 596 | 615 | struct spi_message *msg) |
| 597 | 616 | { |
| @@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) · 141 unmodified lines | ||
| 739 | 758 | master->set_cs = bcm2835_spi_set_cs; |
| 740 | 759 | master->transfer_one = bcm2835_spi_transfer_one; |
| 741 | 760 | master->handle_err = bcm2835_spi_handle_err; |
| 761 | + master->prepare_message = bcm2835_spi_prepare_message; | |
| 742 | 762 | master->dev.of_node = pdev->dev.of_node; |
| 743 | 763 | |
| 744 | 764 | bs = spi_master_get_devdata(master); |
| @@ -76,6 +76,7 @@ · 75 unmodified lines | ||
| 76 | 76 | #define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200) |
| 77 | 77 | |
| 78 | 78 | |
| 79 | +#define HSSPI_OP_MULTIBIT BIT(11) | |
| 79 | 80 | #define HSSPI_OP_CODE_SHIFT 13 |
| 80 | 81 | #define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT) |
| 81 | 82 | #define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT) |
| @@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) · 89 unmodified lines | ||
| 171 | 172 | if (opcode != HSSPI_OP_READ) |
| 172 | 173 | step_size -= HSSPI_OPCODE_LEN; |
| 173 | 174 | |
| 174 | − __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT | | |
| 175 | − 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT | | |
| 176 | − 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff, | |
| 175 | + if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) || | |
| 176 | + (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) | |
| 177 | + opcode |= HSSPI_OP_MULTIBIT; | |
| 178 | + | |
| 179 | + __raw_writel(1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT | | |
| 180 | + 1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT | 0xff, | |
| 177 | 181 | bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); |
| 178 | 182 | |
| 179 | 183 | while (pending > 0) { |
| @@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) · 194 unmodified lines | ||
| 374 | 378 | master->num_chipselect = 8; |
| 375 | 379 | master->setup = bcm63xx_hsspi_setup; |
| 376 | 380 | master->transfer_one_message = bcm63xx_hsspi_transfer_one; |
| 377 | − master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | |
| 381 | + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | | |
| 382 | + SPI_RX_DUAL | SPI_TX_DUAL; | |
| 378 | 383 | master->bits_per_word_mask = SPI_BPW_MASK(8); |
| 379 | 384 | master->auto_runtime_pm = true; |
| 380 | 385 | |
| @@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, · 48 unmodified lines | ||
| 49 | 49 | { |
| 50 | 50 | /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ |
| 51 | 51 | |
| 52 | − bool oldbit = !(word & 1); | |
| 52 | + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; | |
| 53 | 53 | /* clock starts at inactive polarity */ |
| 54 | 54 | for (word <<= (32 - bits); likely(bits); bits--) { |
| 55 | 55 | |
| @@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, · 25 unmodified lines | ||
| 81 | 81 | { |
| 82 | 82 | /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ |
| 83 | 83 | |
| 84 | − bool oldbit = !(word & (1 << 31)); | |
| 84 | + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; | |
| 85 | 85 | /* clock starts at inactive polarity */ |
| 86 | 86 | for (word <<= (32 - bits); likely(bits); bits--) { |
| 87 | 87 | |
| @@ -139,6 +139,8 @@ struct davinci_spi { · 138 unmodified lines | ||
| 139 | 139 | u32 (*get_tx)(struct davinci_spi *); |
| 140 | 140 | |
| 141 | 141 | u8 *bytes_per_word; |
| 142 | + | |
| 143 | + u8 prescaler_limit; | |
| 142 | 144 | }; |
| 143 | 145 | |
| 144 | 146 | static struct davinci_spi_config davinci_spi_default_cfg; |
| @@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) · 110 unmodified lines | ||
| 255 | 257 | * This function calculates the prescale value that generates a clock rate |
| 256 | 258 | * less than or equal to the specified maximum. |
| 257 | 259 | * |
| 258 | − * Returns: calculated prescale - 1 for easy programming into SPI registers | |
| 260 | + * Returns: calculated prescale value for easy programming into SPI registers | |
| 259 | 261 | * or negative error number if valid prescalar cannot be updated. |
| 260 | 262 | */ |
| 261 | 263 | static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, |
| @@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, · 1 unmodified line | ||
| 263 | 265 | { |
| 264 | 266 | int ret; |
| 265 | 267 | |
| 266 | − ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz); | |
| 268 | + /* Subtract 1 to match what will be programmed into SPI register. */ | |
| 269 | + ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1; | |
| 267 | 270 | |
| 268 | − if (ret < 1 || ret > 256) | |
| 271 | + if (ret < dspi->prescaler_limit || ret > 255) | |
| 269 | 272 | return -EINVAL; |
| 270 | 273 | |
| 271 | − return ret - 1; | |
| 274 | + return ret; | |
| 272 | 275 | } |
| 273 | 276 | |
| 274 | 277 | /** |
| @@ -832,13 +835,40 @@ rx_dma_failed: · 557 unmodified lines | ||
| 832 | 835 | } |
| 833 | 836 | |
| 834 | 837 | #if defined(CONFIG_OF) |
| 838 | + | |
| 839 | +/* OF SPI data structure */ | |
| 840 | +struct davinci_spi_of_data { | |
| 841 | + u8 version; | |
| 842 | + u8 prescaler_limit; | |
| 843 | +}; | |
| 844 | + | |
| 845 | +static const struct davinci_spi_of_data dm6441_spi_data = { | |
| 846 | + .version = SPI_VERSION_1, | |
| 847 | + .prescaler_limit = 2, | |
| 848 | +}; | |
| 849 | + | |
| 850 | +static const struct davinci_spi_of_data da830_spi_data = { | |
| 851 | + .version = SPI_VERSION_2, | |
| 852 | + .prescaler_limit = 2, | |
| 853 | +}; | |
| 854 | + | |
| 855 | +static const struct davinci_spi_of_data keystone_spi_data = { | |
| 856 | + .version = SPI_VERSION_1, | |
| 857 | + .prescaler_limit = 0, | |
| 858 | +}; | |
| 859 | + | |
| 835 | 860 | static const struct of_device_id davinci_spi_of_match[] = { |
| 836 | 861 | { |
| 837 | 862 | .compatible = "ti,dm6441-spi", |
| 863 | + .data = &dm6441_spi_data, | |
| 838 | 864 | }, |
| 839 | 865 | { |
| 840 | 866 | .compatible = "ti,da830-spi", |
| 841 | − .data = (void *)SPI_VERSION_2, | |
| 867 | + .data = &da830_spi_data, | |
| 868 | + }, | |
| 869 | + { | |
| 870 | + .compatible = "ti,keystone-spi", | |
| 871 | + .data = &keystone_spi_data, | |
| 842 | 872 | }, |
| 843 | 873 | { }, |
| 844 | 874 | }; |
| @@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, · 12 unmodified lines | ||
| 857 | 887 | struct davinci_spi *dspi) |
| 858 | 888 | { |
| 859 | 889 | struct device_node *node = pdev->dev.of_node; |
| 890 | + struct davinci_spi_of_data *spi_data; | |
| 860 | 891 | struct davinci_spi_platform_data *pdata; |
| 861 | 892 | unsigned int num_cs, intr_line = 0; |
| 862 | 893 | const struct of_device_id *match; |
| 863 | 894 | |
| 864 | 895 | pdata = &dspi->pdata; |
| 865 | 896 | |
| 866 | − pdata->version = SPI_VERSION_1; | |
| 867 | 897 | match = of_match_device(davinci_spi_of_match, &pdev->dev); |
| 868 | 898 | if (!match) |
| 869 | 899 | return -ENODEV; |
| 870 | 900 | |
| 871 | − /* match data has the SPI version number for SPI_VERSION_2 */ | |
| 872 | − if (match->data == (void *)SPI_VERSION_2) | |
| 873 | − pdata->version = SPI_VERSION_2; | |
| 901 | + spi_data = (struct davinci_spi_of_data *)match->data; | |
| 874 | 902 | |
| 903 | + pdata->version = spi_data->version; | |
| 904 | + pdata->prescaler_limit = spi_data->prescaler_limit; | |
| 875 | 905 | /* |
| 876 | 906 | * default num_cs is 1 and all chipsel are internal to the chip |
| 877 | 907 | * indicated by chip_sel being NULL or cs_gpios being NULL or |
| @@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev) · 113 unmodified lines | ||
| 991 | 1021 | |
| 992 | 1022 | dspi->bitbang.chipselect = davinci_spi_chipselect; |
| 993 | 1023 | dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; |
| 994 | − | |
| 1024 | + dspi->prescaler_limit = pdata->prescaler_limit; | |
| 995 | 1025 | dspi->version = pdata->version; |
| 996 | 1026 | |
| 997 | 1027 | dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; |
| @@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) · 73 unmodified lines | ||
| 74 | 74 | |
| 75 | 75 | dws->max_freq = clk_get_rate(dwsmmio->clk); |
| 76 | 76 | |
| 77 | + of_property_read_u32(pdev->dev.of_node, "reg-io-width", | |
| 78 | + &dws->reg_io_width); | |
| 79 | + | |
| 77 | 80 | num_cs = 4; |
| 78 | 81 | |
| 79 | 82 | if (pdev->dev.of_node) |
| @@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws) · 193 unmodified lines | ||
| 194 | 194 | else |
| 195 | 195 | txw = *(u16 *)(dws->tx); |
| 196 | 196 | } |
| 197 | − dw_writel(dws, DW_SPI_DR, txw); | |
| 197 | + dw_write_io_reg(dws, DW_SPI_DR, txw); | |
| 198 | 198 | dws->tx += dws->n_bytes; |
| 199 | 199 | } |
| 200 | 200 | } |
| @@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws) · 4 unmodified lines | ||
| 205 | 205 | u16 rxw; |
| 206 | 206 | |
| 207 | 207 | while (max--) { |
| 208 | − rxw = dw_readl(dws, DW_SPI_DR); | |
| 208 | + rxw = dw_read_io_reg(dws, DW_SPI_DR); | |
| 209 | 209 | /* Care rx only if the transfer's original "rx" is not null */ |
| 210 | 210 | if (dws->rx_end - dws->len) { |
| 211 | 211 | if (dws->n_bytes == 1) |
| @@ -109,6 +109,7 @@ struct dw_spi { · 108 unmodified lines | ||
| 109 | 109 | u32 fifo_len; /* depth of the FIFO buffer */ |
| 110 | 110 | u32 max_freq; /* max bus freq supported */ |
| 111 | 111 | |
| 112 | + u32 reg_io_width; /* DR I/O width in bytes */ | |
| 112 | 113 | u16 bus_num; |
| 113 | 114 | u16 num_cs; /* supported slave numbers */ |
| 114 | 115 | |
| @@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset) · 30 unmodified lines | ||
| 145 | 146 | return __raw_readl(dws->regs + offset); |
| 146 | 147 | } |
| 147 | 148 | |
| 149 | +static inline u16 dw_readw(struct dw_spi *dws, u32 offset) | |
| 150 | +{ | |
| 151 | + return __raw_readw(dws->regs + offset); | |
| 152 | +} | |
| 153 | + | |
| 148 | 154 | static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val) |
| 149 | 155 | { |
| 150 | 156 | __raw_writel(val, dws->regs + offset); |
| 151 | 157 | } |
| 152 | 158 | |
| 159 | +static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val) | |
| 160 | +{ | |
| 161 | + __raw_writew(val, dws->regs + offset); | |
| 162 | +} | |
| 163 | + | |
| 164 | +static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset) | |
| 165 | +{ | |
| 166 | + switch (dws->reg_io_width) { | |
| 167 | + case 2: | |
| 168 | + return dw_readw(dws, offset); | |
| 169 | + case 4: | |
| 170 | + default: | |
| 171 | + return dw_readl(dws, offset); | |
| 172 | + } | |
| 173 | +} | |
| 174 | + | |
| 175 | +static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val) | |
| 176 | +{ | |
| 177 | + switch (dws->reg_io_width) { | |
| 178 | + case 2: | |
| 179 | + dw_writew(dws, offset, val); | |
| 180 | + break; | |
| 181 | + case 4: | |
| 182 | + default: | |
| 183 | + dw_writel(dws, offset, val); | |
| 184 | + break; | |
| 185 | + } | |
| 186 | +} | |
| 187 | + | |
| 153 | 188 | static inline void spi_enable_chip(struct dw_spi *dws, int enable) |
| 154 | 189 | { |
| 155 | 190 | dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0)); |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/of_platform.h> |
| 22 | 22 | #include <linux/platform_device.h> |
| 23 | 23 | #include <linux/spi/spi.h> |
| 24 | +#include <linux/pm_runtime.h> | |
| 24 | 25 | #include <sysdev/fsl_soc.h> |
| 25 | 26 | |
| 26 | 27 | #include "spi-fsl-lib.h" |
| @@ -85,6 +86,8 @@ struct fsl_espi_transfer { · 58 unmodified lines | ||
| 85 | 86 | #define SPCOM_TRANLEN(x) ((x) << 0) |
| 86 | 87 | #define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ |
| 87 | 88 | |
| 89 | +#define AUTOSUSPEND_TIMEOUT 2000 | |
| 90 | + | |
| 88 | 91 | static void fsl_espi_change_mode(struct spi_device *spi) |
| 89 | 92 | { |
| 90 | 93 | struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); |
| @@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi) · 394 unmodified lines | ||
| 485 | 488 | mpc8xxx_spi = spi_master_get_devdata(spi->master); |
| 486 | 489 | reg_base = mpc8xxx_spi->reg_base; |
| 487 | 490 | |
| 491 | + pm_runtime_get_sync(mpc8xxx_spi->dev); | |
| 492 | + | |
| 488 | 493 | hw_mode = cs->hw_mode; /* Save original settings */ |
| 489 | 494 | cs->hw_mode = mpc8xxx_spi_read_reg( |
| 490 | 495 | ®_base->csmode[spi->chip_select]); |
| @@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi) · 16 unmodified lines | ||
| 507 | 512 | mpc8xxx_spi_write_reg(®_base->mode, loop_mode); |
| 508 | 513 | |
| 509 | 514 | retval = fsl_espi_setup_transfer(spi, NULL); |
| 515 | + | |
| 516 | + pm_runtime_mark_last_busy(mpc8xxx_spi->dev); | |
| 517 | + pm_runtime_put_autosuspend(mpc8xxx_spi->dev); | |
| 518 | + | |
| 510 | 519 | if (retval < 0) { |
| 511 | 520 | cs->hw_mode = hw_mode; /* Restore settings */ |
| 512 | 521 | return retval; |
| @@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) · 91 unmodified lines | ||
| 604 | 613 | return ret; |
| 605 | 614 | } |
| 606 | 615 | |
| 607 | −static void fsl_espi_remove(struct mpc8xxx_spi *mspi) | |
| 616 | +#ifdef CONFIG_PM | |
| 617 | +static int fsl_espi_runtime_suspend(struct device *dev) | |
| 608 | 618 | { |
| 609 | − iounmap(mspi->reg_base); | |
| 610 | −} | |
| 611 | − | |
| 612 | −static int fsl_espi_suspend(struct spi_master *master) | |
| 613 | −{ | |
| 614 | − struct mpc8xxx_spi *mpc8xxx_spi; | |
| 615 | − struct fsl_espi_reg *reg_base; | |
| 619 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 620 | + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); | |
| 621 | + struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base; | |
| 616 | 622 | u32 regval; |
| 617 | 623 | |
| 618 | − mpc8xxx_spi = spi_master_get_devdata(master); | |
| 619 | − reg_base = mpc8xxx_spi->reg_base; | |
| 620 | − | |
| 621 | 624 | regval = mpc8xxx_spi_read_reg(®_base->mode); |
| 622 | 625 | regval &= ~SPMODE_ENABLE; |
| 623 | 626 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
| @@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master) · 1 unmodified line | ||
| 625 | 628 | return 0; |
| 626 | 629 | } |
| 627 | 630 | |
| 628 | −static int fsl_espi_resume(struct spi_master *master) | |
| 631 | +static int fsl_espi_runtime_resume(struct device *dev) | |
| 629 | 632 | { |
| 630 | − struct mpc8xxx_spi *mpc8xxx_spi; | |
| 631 | − struct fsl_espi_reg *reg_base; | |
| 633 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 634 | + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); | |
| 635 | + struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base; | |
| 632 | 636 | u32 regval; |
| 633 | 637 | |
| 634 | − mpc8xxx_spi = spi_master_get_devdata(master); | |
| 635 | − reg_base = mpc8xxx_spi->reg_base; | |
| 636 | − | |
| 637 | 638 | regval = mpc8xxx_spi_read_reg(®_base->mode); |
| 638 | 639 | regval |= SPMODE_ENABLE; |
| 639 | 640 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
| 640 | 641 | |
| 641 | 642 | return 0; |
| 642 | 643 | } |
| 644 | +#endif | |
| 643 | 645 | |
| 644 | 646 | static struct spi_master * fsl_espi_probe(struct device *dev, |
| 645 | 647 | struct resource *mem, unsigned int irq) |
| @@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev, · 21 unmodified lines | ||
| 667 | 669 | master->setup = fsl_espi_setup; |
| 668 | 670 | master->cleanup = fsl_espi_cleanup; |
| 669 | 671 | master->transfer_one_message = fsl_espi_do_one_msg; |
| 670 | − master->prepare_transfer_hardware = fsl_espi_resume; | |
| 671 | − master->unprepare_transfer_hardware = fsl_espi_suspend; | |
| 672 | + master->auto_runtime_pm = true; | |
| 672 | 673 | |
| 673 | 674 | mpc8xxx_spi = spi_master_get_devdata(master); |
| 674 | − mpc8xxx_spi->spi_remove = fsl_espi_remove; | |
| 675 | 675 | |
| 676 | − mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); | |
| 677 | − if (!mpc8xxx_spi->reg_base) { | |
| 678 | − ret = -ENOMEM; | |
| 676 | + mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem); | |
| 677 | + if (IS_ERR(mpc8xxx_spi->reg_base)) { | |
| 678 | + ret = PTR_ERR(mpc8xxx_spi->reg_base); | |
| 679 | 679 | goto err_probe; |
| 680 | 680 | } |
| 681 | 681 | |
| 682 | 682 | reg_base = mpc8xxx_spi->reg_base; |
| 683 | 683 | |
| 684 | 684 | /* Register for SPI Interrupt */ |
| 685 | − ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq, | |
| 685 | + ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq, | |
| 686 | 686 | 0, "fsl_espi", mpc8xxx_spi); |
| 687 | 687 | if (ret) |
| 688 | − goto free_irq; | |
| 688 | + goto err_probe; | |
| 689 | 689 | |
| 690 | 690 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { |
| 691 | 691 | mpc8xxx_spi->rx_shift = 16; |
| @@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev, · 39 unmodified lines | ||
| 731 | 731 | |
| 732 | 732 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
| 733 | 733 | |
| 734 | − ret = spi_register_master(master); | |
| 734 | + pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT); | |
| 735 | + pm_runtime_use_autosuspend(dev); | |
| 736 | + pm_runtime_set_active(dev); | |
| 737 | + pm_runtime_enable(dev); | |
| 738 | + pm_runtime_get_sync(dev); | |
| 739 | + | |
| 740 | + ret = devm_spi_register_master(dev, master); | |
| 735 | 741 | if (ret < 0) |
| 736 | − goto unreg_master; | |
| 742 | + goto err_pm; | |
| 737 | 743 | |
| 738 | 744 | dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq); |
| 739 | 745 | |
| 746 | + pm_runtime_mark_last_busy(dev); | |
| 747 | + pm_runtime_put_autosuspend(dev); | |
| 748 | + | |
| 740 | 749 | return master; |
| 741 | 750 | |
| 742 | −unreg_master: | |
| 743 | − free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | |
| 744 | −free_irq: | |
| 745 | − iounmap(mpc8xxx_spi->reg_base); | |
| 751 | +err_pm: | |
| 752 | + pm_runtime_put_noidle(dev); | |
| 753 | + pm_runtime_disable(dev); | |
| 754 | + pm_runtime_set_suspended(dev); | |
| 746 | 755 | err_probe: |
| 747 | 756 | spi_master_put(master); |
| 748 | 757 | err: |
| @@ -809,7 +818,9 @@ err: · 60 unmodified lines | ||
| 809 | 818 | |
| 810 | 819 | static int of_fsl_espi_remove(struct platform_device *dev) |
| 811 | 820 | { |
| 812 | − return mpc8xxx_spi_remove(&dev->dev); | |
| 821 | + pm_runtime_disable(&dev->dev); | |
| 822 | + | |
| 823 | + return 0; | |
| 813 | 824 | } |
| 814 | 825 | |
| 815 | 826 | #ifdef CONFIG_PM_SLEEP |
| @@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev) · 8 unmodified lines | ||
| 824 | 835 | return ret; |
| 825 | 836 | } |
| 826 | 837 | |
| 827 | − return fsl_espi_suspend(master); | |
| 838 | + ret = pm_runtime_force_suspend(dev); | |
| 839 | + if (ret < 0) | |
| 840 | + return ret; | |
| 841 | + | |
| 842 | + return 0; | |
| 828 | 843 | } |
| 829 | 844 | |
| 830 | 845 | static int of_fsl_espi_resume(struct device *dev) |
| @@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev) · 3 unmodified lines | ||
| 834 | 849 | struct mpc8xxx_spi *mpc8xxx_spi; |
| 835 | 850 | struct fsl_espi_reg *reg_base; |
| 836 | 851 | u32 regval; |
| 837 | − int i; | |
| 852 | + int i, ret; | |
| 838 | 853 | |
| 839 | 854 | mpc8xxx_spi = spi_master_get_devdata(master); |
| 840 | 855 | reg_base = mpc8xxx_spi->reg_base; |
| @@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev) · 13 unmodified lines | ||
| 854 | 869 | |
| 855 | 870 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
| 856 | 871 | |
| 872 | + ret = pm_runtime_force_resume(dev); | |
| 873 | + if (ret < 0) | |
| 874 | + return ret; | |
| 875 | + | |
| 857 | 876 | return spi_master_resume(master); |
| 858 | 877 | } |
| 859 | 878 | #endif /* CONFIG_PM_SLEEP */ |
| 860 | 879 | |
| 861 | 880 | static const struct dev_pm_ops espi_pm = { |
| 881 | + SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend, | |
| 882 | + fsl_espi_runtime_resume, NULL) | |
| 862 | 883 | SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume) |
| 863 | 884 | }; |
| 864 | 885 | |
| @@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, · 113 unmodified lines | ||
| 114 | 114 | } |
| 115 | 115 | EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe); |
| 116 | 116 | |
| 117 | −int mpc8xxx_spi_remove(struct device *dev) | |
| 118 | −{ | |
| 119 | − struct mpc8xxx_spi *mpc8xxx_spi; | |
| 120 | − struct spi_master *master; | |
| 121 | − | |
| 122 | − master = dev_get_drvdata(dev); | |
| 123 | − mpc8xxx_spi = spi_master_get_devdata(master); | |
| 124 | − | |
| 125 | − spi_unregister_master(master); | |
| 126 | − | |
| 127 | − free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | |
| 128 | − | |
| 129 | − if (mpc8xxx_spi->spi_remove) | |
| 130 | − mpc8xxx_spi->spi_remove(mpc8xxx_spi); | |
| 131 | − | |
| 132 | − return 0; | |
| 133 | −} | |
| 134 | −EXPORT_SYMBOL_GPL(mpc8xxx_spi_remove); | |
| 135 | − | |
| 136 | 117 | int of_mpc8xxx_spi_probe(struct platform_device *ofdev) |
| 137 | 118 | { |
| 138 | 119 | struct device *dev = &ofdev->dev; |
| @@ -54,9 +54,6 @@ struct mpc8xxx_spi { · 53 unmodified lines | ||
| 54 | 54 | void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); |
| 55 | 55 | u32(*get_tx) (struct mpc8xxx_spi *); |
| 56 | 56 | |
| 57 | − /* hooks for different controller driver */ | |
| 58 | − void (*spi_remove) (struct mpc8xxx_spi *mspi); | |
| 59 | − | |
| 60 | 57 | unsigned int count; |
| 61 | 58 | unsigned int irq; |
| 62 | 59 | |
| @@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) · 558 unmodified lines | ||
| 559 | 559 | return ret; |
| 560 | 560 | } |
| 561 | 561 | |
| 562 | −static void fsl_spi_remove(struct mpc8xxx_spi *mspi) | |
| 563 | −{ | |
| 564 | − iounmap(mspi->reg_base); | |
| 565 | − fsl_spi_cpm_free(mspi); | |
| 566 | −} | |
| 567 | − | |
| 568 | 562 | static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) |
| 569 | 563 | { |
| 570 | 564 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); |
| @@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev, · 60 unmodified lines | ||
| 631 | 625 | master->transfer_one_message = fsl_spi_do_one_msg; |
| 632 | 626 | |
| 633 | 627 | mpc8xxx_spi = spi_master_get_devdata(master); |
| 634 | − mpc8xxx_spi->spi_remove = fsl_spi_remove; | |
| 635 | 628 | mpc8xxx_spi->max_bits_per_word = 32; |
| 636 | 629 | mpc8xxx_spi->type = fsl_spi_get_type(dev); |
| 637 | 630 | |
| @@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev, · 1 unmodified line | ||
| 639 | 632 | if (ret) |
| 640 | 633 | goto err_cpm_init; |
| 641 | 634 | |
| 642 | − mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); | |
| 643 | − if (mpc8xxx_spi->reg_base == NULL) { | |
| 644 | − ret = -ENOMEM; | |
| 645 | − goto err_ioremap; | |
| 635 | + mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem); | |
| 636 | + if (IS_ERR(mpc8xxx_spi->reg_base)) { | |
| 637 | + ret = PTR_ERR(mpc8xxx_spi->reg_base); | |
| 638 | + goto err_probe; | |
| 646 | 639 | } |
| 647 | 640 | |
| 648 | 641 | if (mpc8xxx_spi->type == TYPE_GRLIB) |
| @@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev, · 12 unmodified lines | ||
| 661 | 654 | &mpc8xxx_spi->tx_shift, 8, 1); |
| 662 | 655 | |
| 663 | 656 | /* Register for SPI Interrupt */ |
| 664 | − ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, | |
| 665 | − 0, "fsl_spi", mpc8xxx_spi); | |
| 657 | + ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq, | |
| 658 | + 0, "fsl_spi", mpc8xxx_spi); | |
| 666 | 659 | |
| 667 | 660 | if (ret != 0) |
| 668 | − goto free_irq; | |
| 661 | + goto err_probe; | |
| 669 | 662 | |
| 670 | 663 | reg_base = mpc8xxx_spi->reg_base; |
| 671 | 664 | |
| @@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev, · 14 unmodified lines | ||
| 686 | 679 | |
| 687 | 680 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
| 688 | 681 | |
| 689 | − ret = spi_register_master(master); | |
| 682 | + ret = devm_spi_register_master(dev, master); | |
| 690 | 683 | if (ret < 0) |
| 691 | − goto unreg_master; | |
| 684 | + goto err_probe; | |
| 692 | 685 | |
| 693 | 686 | dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base, |
| 694 | 687 | mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); |
| 695 | 688 | |
| 696 | 689 | return master; |
| 697 | 690 | |
| 698 | −unreg_master: | |
| 699 | − free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | |
| 700 | −free_irq: | |
| 701 | − iounmap(mpc8xxx_spi->reg_base); | |
| 702 | −err_ioremap: | |
| 691 | +err_probe: | |
| 703 | 692 | fsl_spi_cpm_free(mpc8xxx_spi); |
| 704 | 693 | err_cpm_init: |
| 705 | 694 | spi_master_put(master); |
| @@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev) · 160 unmodified lines | ||
| 866 | 855 | { |
| 867 | 856 | struct spi_master *master = platform_get_drvdata(ofdev); |
| 868 | 857 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); |
| 869 | − int ret; | |
| 870 | 858 | |
| 871 | − ret = mpc8xxx_spi_remove(&ofdev->dev); | |
| 872 | − if (ret) | |
| 873 | − return ret; | |
| 859 | + fsl_spi_cpm_free(mpc8xxx_spi); | |
| 874 | 860 | if (mpc8xxx_spi->type == TYPE_FSL) |
| 875 | 861 | of_fsl_spi_free_chipselects(&ofdev->dev); |
| 876 | 862 | return 0; |
| @@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) · 39 unmodified lines | ||
| 916 | 902 | |
| 917 | 903 | static int plat_mpc8xxx_spi_remove(struct platform_device *pdev) |
| 918 | 904 | { |
| 919 | − return mpc8xxx_spi_remove(&pdev->dev); | |
| 905 | + struct spi_master *master = platform_get_drvdata(pdev); | |
| 906 | + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); | |
| 907 | + | |
| 908 | + fsl_spi_cpm_free(mpc8xxx_spi); | |
| 909 | + | |
| 910 | + return 0; | |
| 920 | 911 | } |
| 921 | 912 | |
| 922 | 913 | MODULE_ALIAS("platform:mpc8xxx_spi"); |
| @@ -105,6 +105,10 @@ struct img_spfi { · 104 unmodified lines | ||
| 105 | 105 | bool rx_dma_busy; |
| 106 | 106 | }; |
| 107 | 107 | |
| 108 | +struct img_spfi_device_data { | |
| 109 | + bool gpio_requested; | |
| 110 | +}; | |
| 111 | + | |
| 108 | 112 | static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) |
| 109 | 113 | { |
| 110 | 114 | return readl(spfi->regs + reg); |
| @@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master, · 156 unmodified lines | ||
| 267 | 271 | cpu_relax(); |
| 268 | 272 | } |
| 269 | 273 | |
| 270 | − ret = spfi_wait_all_done(spfi); | |
| 271 | − if (ret < 0) | |
| 272 | − return ret; | |
| 273 | − | |
| 274 | 274 | if (rx_bytes > 0 || tx_bytes > 0) { |
| 275 | 275 | dev_err(spfi->dev, "PIO transfer timed out\n"); |
| 276 | 276 | return -ETIMEDOUT; |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | + ret = spfi_wait_all_done(spfi); | |
| 280 | + if (ret < 0) | |
| 281 | + return ret; | |
| 282 | + | |
| 279 | 283 | return 0; |
| 280 | 284 | } |
| 281 | 285 | |
| @@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master, · 158 unmodified lines | ||
| 440 | 444 | |
| 441 | 445 | static int img_spfi_setup(struct spi_device *spi) |
| 442 | 446 | { |
| 443 | − int ret; | |
| 444 | − | |
| 445 | − ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? | |
| 446 | − GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | |
| 447 | − dev_name(&spi->dev)); | |
| 448 | − if (ret) | |
| 449 | − dev_err(&spi->dev, "can't request chipselect gpio %d\n", | |
| 447 | + int ret = -EINVAL; | |
| 448 | + struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi); | |
| 449 | + | |
| 450 | + if (!spfi_data) { | |
| 451 | + spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL); | |
| 452 | + if (!spfi_data) | |
| 453 | + return -ENOMEM; | |
| 454 | + spfi_data->gpio_requested = false; | |
| 455 | + spi_set_ctldata(spi, spfi_data); | |
| 456 | + } | |
| 457 | + if (!spfi_data->gpio_requested) { | |
| 458 | + ret = gpio_request_one(spi->cs_gpio, | |
| 459 | + (spi->mode & SPI_CS_HIGH) ? | |
| 460 | + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | |
| 461 | + dev_name(&spi->dev)); | |
| 462 | + if (ret) | |
| 463 | + dev_err(&spi->dev, "can't request chipselect gpio %d\n", | |
| 450 | 464 | spi->cs_gpio); |
| 451 | − | |
| 465 | + else | |
| 466 | + spfi_data->gpio_requested = true; | |
| 467 | + } else { | |
| 468 | + if (gpio_is_valid(spi->cs_gpio)) { | |
| 469 | + int mode = ((spi->mode & SPI_CS_HIGH) ? | |
| 470 | + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH); | |
| 471 | + | |
| 472 | + ret = gpio_direction_output(spi->cs_gpio, mode); | |
| 473 | + if (ret) | |
| 474 | + dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n", | |
| 475 | + spi->cs_gpio, ret); | |
| 476 | + } | |
| 477 | + } | |
| 452 | 478 | return ret; |
| 453 | 479 | } |
| 454 | 480 | |
| 455 | 481 | static void img_spfi_cleanup(struct spi_device *spi) |
| 456 | 482 | { |
| 457 | − gpio_free(spi->cs_gpio); | |
| 483 | + struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi); | |
| 484 | + | |
| 485 | + if (spfi_data) { | |
| 486 | + if (spfi_data->gpio_requested) | |
| 487 | + gpio_free(spi->cs_gpio); | |
| 488 | + kfree(spfi_data); | |
| 489 | + spi_set_ctldata(spi, NULL); | |
| 490 | + } | |
| 458 | 491 | } |
| 459 | 492 | |
| 460 | 493 | static void img_spfi_config(struct spi_master *master, struct spi_device *spi, |
| @@ -548,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev) · 87 unmodified lines | ||
| 548 | 581 | struct img_spfi *spfi; |
| 549 | 582 | struct resource *res; |
| 550 | 583 | int ret; |
| 584 | + u32 max_speed_hz; | |
| 551 | 585 | |
| 552 | 586 | master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); |
| 553 | 587 | if (!master) |
| @@ -612,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev) · 58 unmodified lines | ||
| 612 | 646 | master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; |
| 613 | 647 | master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; |
| 614 | 648 | |
| 649 | + /* | |
| 650 | + * Maximum speed supported by spfi is limited to the lower value | |
| 651 | + * between 1/4 of the SPFI clock or to "spfi-max-frequency" | |
| 652 | + * defined in the device tree. | |
| 653 | + * If no value is defined in the device tree assume the maximum | |
| 654 | + * speed supported to be 1/4 of the SPFI clock. | |
| 655 | + */ | |
| 656 | + if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency", | |
| 657 | + &max_speed_hz)) { | |
| 658 | + if (master->max_speed_hz > max_speed_hz) | |
| 659 | + master->max_speed_hz = max_speed_hz; | |
| 660 | + } | |
| 661 | + | |
| 615 | 662 | master->setup = img_spfi_setup; |
| 616 | 663 | master->cleanup = img_spfi_cleanup; |
| 617 | 664 | master->transfer_one = img_spfi_transfer_one; |
| @@ -30,11 +30,37 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/gpio.h> |
| 31 | 31 | #include <asm/mpc52xx_psc.h> |
| 32 | 32 | |
| 33 | +enum { | |
| 34 | + TYPE_MPC5121, | |
| 35 | + TYPE_MPC5125, | |
| 36 | +}; | |
| 37 | + | |
| 38 | +/* | |
| 39 | + * This macro abstracts the differences in the PSC register layout between | |
| 40 | + * MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc). | |
| 41 | + */ | |
| 42 | +#define psc_addr(mps, regname) ({ \ | |
| 43 | + void *__ret = NULL; \ | |
| 44 | + switch (mps->type) { \ | |
| 45 | + case TYPE_MPC5121: { \ | |
| 46 | + struct mpc52xx_psc __iomem *psc = mps->psc; \ | |
| 47 | + __ret = &psc->regname; \ | |
| 48 | + }; \ | |
| 49 | + break; \ | |
| 50 | + case TYPE_MPC5125: { \ | |
| 51 | + struct mpc5125_psc __iomem *psc = mps->psc; \ | |
| 52 | + __ret = &psc->regname; \ | |
| 53 | + }; \ | |
| 54 | + break; \ | |
| 55 | + } \ | |
| 56 | + __ret; }) | |
| 57 | + | |
| 33 | 58 | struct mpc512x_psc_spi { |
| 34 | 59 | void (*cs_control)(struct spi_device *spi, bool on); |
| 35 | 60 | |
| 36 | 61 | /* driver internal data */ |
| 37 | − struct mpc52xx_psc __iomem *psc; | |
| 62 | + int type; | |
| 63 | + void __iomem *psc; | |
| 38 | 64 | struct mpc512x_psc_fifo __iomem *fifo; |
| 39 | 65 | unsigned int irq; |
| 40 | 66 | u8 bits_per_word; |
| @@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) · 30 unmodified lines | ||
| 71 | 97 | { |
| 72 | 98 | struct mpc512x_psc_spi_cs *cs = spi->controller_state; |
| 73 | 99 | struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); |
| 74 | − struct mpc52xx_psc __iomem *psc = mps->psc; | |
| 75 | 100 | u32 sicr; |
| 76 | 101 | u32 ccr; |
| 77 | 102 | int speed; |
| 78 | 103 | u16 bclkdiv; |
| 79 | 104 | |
| 80 | − sicr = in_be32(&psc->sicr); | |
| 105 | + sicr = in_be32(psc_addr(mps, sicr)); | |
| 81 | 106 | |
| 82 | 107 | /* Set clock phase and polarity */ |
| 83 | 108 | if (spi->mode & SPI_CPHA) |
| @@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) · 10 unmodified lines | ||
| 94 | 119 | sicr |= 0x10000000; |
| 95 | 120 | else |
| 96 | 121 | sicr &= ~0x10000000; |
| 97 | − out_be32(&psc->sicr, sicr); | |
| 122 | + out_be32(psc_addr(mps, sicr), sicr); | |
| 98 | 123 | |
| 99 | − ccr = in_be32(&psc->ccr); | |
| 124 | + ccr = in_be32(psc_addr(mps, ccr)); | |
| 100 | 125 | ccr &= 0xFF000000; |
| 101 | 126 | speed = cs->speed_hz; |
| 102 | 127 | if (!speed) |
| @@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi) · 1 unmodified line | ||
| 104 | 129 | bclkdiv = (mps->mclk_rate / speed) - 1; |
| 105 | 130 | |
| 106 | 131 | ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); |
| 107 | − out_be32(&psc->ccr, ccr); | |
| 132 | + out_be32(psc_addr(mps, ccr), ccr); | |
| 108 | 133 | mps->bits_per_word = cs->bits_per_word; |
| 109 | 134 | |
| 110 | 135 | if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) |
| @@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, · 204 unmodified lines | ||
| 315 | 340 | static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) |
| 316 | 341 | { |
| 317 | 342 | struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); |
| 318 | − struct mpc52xx_psc __iomem *psc = mps->psc; | |
| 319 | 343 | |
| 320 | 344 | dev_dbg(&master->dev, "%s()\n", __func__); |
| 321 | 345 | |
| 322 | 346 | /* Zero MR2 */ |
| 323 | − in_8(&psc->mode); | |
| 324 | − out_8(&psc->mode, 0x0); | |
| 347 | + in_8(psc_addr(mps, mr2)); | |
| 348 | + out_8(psc_addr(mps, mr2), 0x0); | |
| 325 | 349 | |
| 326 | 350 | /* enable transmitter/receiver */ |
| 327 | − out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); | |
| 351 | + out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); | |
| 328 | 352 | |
| 329 | 353 | return 0; |
| 330 | 354 | } |
| @@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master) · 1 unmodified line | ||
| 332 | 356 | static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master) |
| 333 | 357 | { |
| 334 | 358 | struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); |
| 335 | − struct mpc52xx_psc __iomem *psc = mps->psc; | |
| 336 | 359 | struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; |
| 337 | 360 | |
| 338 | 361 | dev_dbg(&master->dev, "%s()\n", __func__); |
| 339 | 362 | |
| 340 | 363 | /* disable transmitter/receiver and fifo interrupt */ |
| 341 | − out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); | |
| 364 | + out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); | |
| 342 | 365 | out_be32(&fifo->tximr, 0); |
| 343 | 366 | |
| 344 | 367 | return 0; |
| @@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi) · 43 unmodified lines | ||
| 388 | 411 | static int mpc512x_psc_spi_port_config(struct spi_master *master, |
| 389 | 412 | struct mpc512x_psc_spi *mps) |
| 390 | 413 | { |
| 391 | − struct mpc52xx_psc __iomem *psc = mps->psc; | |
| 392 | 414 | struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; |
| 393 | 415 | u32 sicr; |
| 394 | 416 | u32 ccr; |
| @@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, · 1 unmodified line | ||
| 396 | 418 | u16 bclkdiv; |
| 397 | 419 | |
| 398 | 420 | /* Reset the PSC into a known state */ |
| 399 | − out_8(&psc->command, MPC52xx_PSC_RST_RX); | |
| 400 | − out_8(&psc->command, MPC52xx_PSC_RST_TX); | |
| 401 | − out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); | |
| 421 | + out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX); | |
| 422 | + out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX); | |
| 423 | + out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE); | |
| 402 | 424 | |
| 403 | 425 | /* Disable psc interrupts all useful interrupts are in fifo */ |
| 404 | − out_be16(&psc->isr_imr.imr, 0); | |
| 426 | + out_be16(psc_addr(mps, isr_imr.imr), 0); | |
| 405 | 427 | |
| 406 | 428 | /* Disable fifo interrupts, will be enabled later */ |
| 407 | 429 | out_be32(&fifo->tximr, 0); |
| @@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master, · 9 unmodified lines | ||
| 417 | 439 | 0x00004000 | /* MSTR = 1 -- SPI master */ |
| 418 | 440 | 0x00000800; /* UseEOF = 1 -- SS low until EOF */ |
| 419 | 441 | |
| 420 | − out_be32(&psc->sicr, sicr); | |
| 442 | + out_be32(psc_addr(mps, sicr), sicr); | |
| 421 | 443 | |
| 422 | − ccr = in_be32(&psc->ccr); | |
| 444 | + ccr = in_be32(psc_addr(mps, ccr)); | |
| 423 | 445 | ccr &= 0xFF000000; |
| 424 | 446 | speed = 1000000; /* default 1MHz */ |
| 425 | 447 | bclkdiv = (mps->mclk_rate / speed) - 1; |
| 426 | 448 | ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8)); |
| 427 | − out_be32(&psc->ccr, ccr); | |
| 449 | + out_be32(psc_addr(mps, ccr), ccr); | |
| 428 | 450 | |
| 429 | 451 | /* Set 2ms DTL delay */ |
| 430 | − out_8(&psc->ctur, 0x00); | |
| 431 | − out_8(&psc->ctlr, 0x82); | |
| 452 | + out_8(psc_addr(mps, ctur), 0x00); | |
| 453 | + out_8(psc_addr(mps, ctlr), 0x82); | |
| 432 | 454 | |
| 433 | 455 | /* we don't use the alarms */ |
| 434 | 456 | out_be32(&fifo->rxalarm, 0xfff); |
| @@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, · 47 unmodified lines | ||
| 482 | 504 | |
| 483 | 505 | dev_set_drvdata(dev, master); |
| 484 | 506 | mps = spi_master_get_devdata(master); |
| 507 | + mps->type = (int)of_device_get_match_data(dev); | |
| 485 | 508 | mps->irq = irq; |
| 486 | 509 | |
| 487 | 510 | if (pdata == NULL) { |
| @@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op) · 101 unmodified lines | ||
| 589 | 612 | } |
| 590 | 613 | |
| 591 | 614 | static const struct of_device_id mpc512x_psc_spi_of_match[] = { |
| 592 | − { .compatible = "fsl,mpc5121-psc-spi", }, | |
| 615 | + { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 }, | |
| 616 | + { .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 }, | |
| 593 | 617 | {}, |
| 594 | 618 | }; |
| 595 | 619 | |
| @@ -0,0 +1,726 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2015 MediaTek Inc. | |
| 3 | + * Author: Leilk Liu <leilk.liu@mediatek.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 as | |
| 7 | + * published by the Free Software Foundation. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/clk.h> | |
| 16 | +#include <linux/device.h> | |
| 17 | +#include <linux/err.h> | |
| 18 | +#include <linux/interrupt.h> | |
| 19 | +#include <linux/io.h> | |
| 20 | +#include <linux/ioport.h> | |
| 21 | +#include <linux/module.h> | |
| 22 | +#include <linux/of.h> | |
| 23 | +#include <linux/platform_device.h> | |
| 24 | +#include <linux/platform_data/spi-mt65xx.h> | |
| 25 | +#include <linux/pm_runtime.h> | |
| 26 | +#include <linux/spi/spi.h> | |
| 27 | + | |
| 28 | +#define SPI_CFG0_REG 0x0000 | |
| 29 | +#define SPI_CFG1_REG 0x0004 | |
| 30 | +#define SPI_TX_SRC_REG 0x0008 | |
| 31 | +#define SPI_RX_DST_REG 0x000c | |
| 32 | +#define SPI_TX_DATA_REG 0x0010 | |
| 33 | +#define SPI_RX_DATA_REG 0x0014 | |
| 34 | +#define SPI_CMD_REG 0x0018 | |
| 35 | +#define SPI_STATUS0_REG 0x001c | |
| 36 | +#define SPI_PAD_SEL_REG 0x0024 | |
| 37 | + | |
| 38 | +#define SPI_CFG0_SCK_HIGH_OFFSET 0 | |
| 39 | +#define SPI_CFG0_SCK_LOW_OFFSET 8 | |
| 40 | +#define SPI_CFG0_CS_HOLD_OFFSET 16 | |
| 41 | +#define SPI_CFG0_CS_SETUP_OFFSET 24 | |
| 42 | + | |
| 43 | +#define SPI_CFG1_CS_IDLE_OFFSET 0 | |
| 44 | +#define SPI_CFG1_PACKET_LOOP_OFFSET 8 | |
| 45 | +#define SPI_CFG1_PACKET_LENGTH_OFFSET 16 | |
| 46 | +#define SPI_CFG1_GET_TICK_DLY_OFFSET 30 | |
| 47 | + | |
| 48 | +#define SPI_CFG1_CS_IDLE_MASK 0xff | |
| 49 | +#define SPI_CFG1_PACKET_LOOP_MASK 0xff00 | |
| 50 | +#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 | |
| 51 | + | |
| 52 | +#define SPI_CMD_ACT BIT(0) | |
| 53 | +#define SPI_CMD_RESUME BIT(1) | |
| 54 | +#define SPI_CMD_RST BIT(2) | |
| 55 | +#define SPI_CMD_PAUSE_EN BIT(4) | |
| 56 | +#define SPI_CMD_DEASSERT BIT(5) | |
| 57 | +#define SPI_CMD_CPHA BIT(8) | |
| 58 | +#define SPI_CMD_CPOL BIT(9) | |
| 59 | +#define SPI_CMD_RX_DMA BIT(10) | |
| 60 | +#define SPI_CMD_TX_DMA BIT(11) | |
| 61 | +#define SPI_CMD_TXMSBF BIT(12) | |
| 62 | +#define SPI_CMD_RXMSBF BIT(13) | |
| 63 | +#define SPI_CMD_RX_ENDIAN BIT(14) | |
| 64 | +#define SPI_CMD_TX_ENDIAN BIT(15) | |
| 65 | +#define SPI_CMD_FINISH_IE BIT(16) | |
| 66 | +#define SPI_CMD_PAUSE_IE BIT(17) | |
| 67 | + | |
| 68 | +#define MT8173_SPI_MAX_PAD_SEL 3 | |
| 69 | + | |
| 70 | +#define MTK_SPI_PAUSE_INT_STATUS 0x2 | |
| 71 | + | |
| 72 | +#define MTK_SPI_IDLE 0 | |
| 73 | +#define MTK_SPI_PAUSED 1 | |
| 74 | + | |
| 75 | +#define MTK_SPI_MAX_FIFO_SIZE 32 | |
| 76 | +#define MTK_SPI_PACKET_SIZE 1024 | |
| 77 | + | |
| 78 | +struct mtk_spi_compatible { | |
| 79 | + bool need_pad_sel; | |
| 80 | + /* Must explicitly send dummy Tx bytes to do Rx only transfer */ | |
| 81 | + bool must_tx; | |
| 82 | +}; | |
| 83 | + | |
| 84 | +struct mtk_spi { | |
| 85 | + void __iomem *base; | |
| 86 | + u32 state; | |
| 87 | + u32 pad_sel; | |
| 88 | + struct clk *spi_clk, *parent_clk; | |
| 89 | + struct spi_transfer *cur_transfer; | |
| 90 | + u32 xfer_len; | |
| 91 | + struct scatterlist *tx_sgl, *rx_sgl; | |
| 92 | + u32 tx_sgl_len, rx_sgl_len; | |
| 93 | + const struct mtk_spi_compatible *dev_comp; | |
| 94 | +}; | |
| 95 | + | |
| 96 | +static const struct mtk_spi_compatible mt6589_compat; | |
| 97 | +static const struct mtk_spi_compatible mt8135_compat; | |
| 98 | +static const struct mtk_spi_compatible mt8173_compat = { | |
| 99 | + .need_pad_sel = true, | |
| 100 | + .must_tx = true, | |
| 101 | +}; | |
| 102 | + | |
| 103 | +/* | |
| 104 | + * A piece of default chip info unless the platform | |
| 105 | + * supplies it. | |
| 106 | + */ | |
| 107 | +static const struct mtk_chip_config mtk_default_chip_info = { | |
| 108 | + .rx_mlsb = 1, | |
| 109 | + .tx_mlsb = 1, | |
| 110 | +}; | |
| 111 | + | |
| 112 | +static const struct of_device_id mtk_spi_of_match[] = { | |
| 113 | + { .compatible = "mediatek,mt6589-spi", .data = (void *)&mt6589_compat }, | |
| 114 | + { .compatible = "mediatek,mt8135-spi", .data = (void *)&mt8135_compat }, | |
| 115 | + { .compatible = "mediatek,mt8173-spi", .data = (void *)&mt8173_compat }, | |
| 116 | + {} | |
| 117 | +}; | |
| 118 | +MODULE_DEVICE_TABLE(of, mtk_spi_of_match); | |
| 119 | + | |
| 120 | +static void mtk_spi_reset(struct mtk_spi *mdata) | |
| 121 | +{ | |
| 122 | + u32 reg_val; | |
| 123 | + | |
| 124 | + /* set the software reset bit in SPI_CMD_REG. */ | |
| 125 | + reg_val = readl(mdata->base + SPI_CMD_REG); | |
| 126 | + reg_val |= SPI_CMD_RST; | |
| 127 | + writel(reg_val, mdata->base + SPI_CMD_REG); | |
| 128 | + | |
| 129 | + reg_val = readl(mdata->base + SPI_CMD_REG); | |
| 130 | + reg_val &= ~SPI_CMD_RST; | |
| 131 | + writel(reg_val, mdata->base + SPI_CMD_REG); | |
| 132 | +} | |
| 133 | + | |
| 134 | +static void mtk_spi_config(struct mtk_spi *mdata, | |
| 135 | + struct mtk_chip_config *chip_config) | |
| 136 | +{ | |
| 137 | + u32 reg_val; | |
| 138 | + | |
| 139 | + reg_val = readl(mdata->base + SPI_CMD_REG); | |
| 140 | + | |
| 141 | + /* set the mlsbx and mlsbtx */ | |
| 142 | + if (chip_config->tx_mlsb) | |
| 143 | + reg_val |= SPI_CMD_TXMSBF; | |
| 144 | + else | |
| 145 | + reg_val &= ~SPI_CMD_TXMSBF; | |
| 146 | + if (chip_config->rx_mlsb) | |
| 147 | + reg_val |= SPI_CMD_RXMSBF; | |
| 148 | + else | |
| 149 | + reg_val &= ~SPI_CMD_RXMSBF; | |
| 150 | + | |
| 151 | + /* set the tx/rx endian */ | |
| 152 | +#ifdef __LITTLE_ENDIAN | |
| 153 | + reg_val &= ~SPI_CMD_TX_ENDIAN; | |
| 154 | + reg_val &= ~SPI_CMD_RX_ENDIAN; | |
| 155 | +#else | |
| 156 | + reg_val |= SPI_CMD_TX_ENDIAN; | |
| 157 | + reg_val |= SPI_CMD_RX_ENDIAN; | |
| 158 | +#endif | |
| 159 | + | |
| 160 | + /* set finish and pause interrupt always enable */ | |
| 161 | + reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_IE; | |
| 162 | + | |
| 163 | + /* disable dma mode */ | |
| 164 | + reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA); | |
| 165 | + | |
| 166 | + /* disable deassert mode */ | |
| 167 | + reg_val &= ~SPI_CMD_DEASSERT; | |
| 168 | + | |
| 169 | + writel(reg_val, mdata->base + SPI_CMD_REG); | |
| 170 | + | |
| 171 | + /* pad select */ | |
| 172 | + if (mdata->dev_comp->need_pad_sel) | |
| 173 | + writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG); | |
| 174 | +} | |
| 175 | + | |
| 176 | +static int mtk_spi_prepare_hardware(struct spi_master *master) | |
| 177 | +{ | |
| 178 | + struct spi_transfer *trans; | |
| 179 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 180 | + struct spi_message *msg = master->cur_msg; | |
| 181 | + | |
| 182 | + trans = list_first_entry(&msg->transfers, struct spi_transfer, | |
| 183 | + transfer_list); | |
| 184 | + if (!trans->cs_change) { | |
| 185 | + mdata->state = MTK_SPI_IDLE; | |
| 186 | + mtk_spi_reset(mdata); | |
| 187 | + } | |
| 188 | + | |
| 189 | + return 0; | |
| 190 | +} | |
| 191 | + | |
| 192 | +static int mtk_spi_prepare_message(struct spi_master *master, | |
| 193 | + struct spi_message *msg) | |
| 194 | +{ | |
| 195 | + u32 reg_val; | |
| 196 | + u8 cpha, cpol; | |
| 197 | + struct mtk_chip_config *chip_config; | |
| 198 | + struct spi_device *spi = msg->spi; | |
| 199 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 200 | + | |
| 201 | + cpha = spi->mode & SPI_CPHA ? 1 : 0; | |
| 202 | + cpol = spi->mode & SPI_CPOL ? 1 : 0; | |
| 203 | + | |
| 204 | + reg_val = readl(mdata->base + SPI_CMD_REG); | |
| 205 | + if (cpha) | |
| 206 | + reg_val |= SPI_CMD_CPHA; | |
| 207 | + else | |
| 208 | + reg_val &= ~SPI_CMD_CPHA; | |
| 209 | + if (cpol) | |
| 210 | + reg_val |= SPI_CMD_CPOL; | |
| 211 | + else | |
| 212 | + reg_val &= ~SPI_CMD_CPOL; | |
| 213 | + writel(reg_val, mdata->base + SPI_CMD_REG); | |
| 214 | + | |
| 215 | + chip_config = spi->controller_data; | |
| 216 | + if (!chip_config) { | |
| 217 | + chip_config = (void *)&mtk_default_chip_info; | |
| 218 | + spi->controller_data = chip_config; | |
| 219 | + } | |
| 220 | + mtk_spi_config(mdata, chip_config); | |
| 221 | + | |
| 222 | + return 0; | |
| 223 | +} | |
| 224 | + | |
| 225 | +static void mtk_spi_set_cs(struct spi_device *spi, bool enable) | |
| 226 | +{ | |
| 227 | + u32 reg_val; | |
| 228 | + struct mtk_spi *mdata = spi_master_get_devdata(spi->master); | |
| 229 | + | |
| 230 | + reg_val = readl(mdata->base + SPI_CMD_REG); | |
| 231 | + if (!enable) | |
| 232 | + reg_val |= SPI_CMD_PAUSE_EN; | |
| 233 | + else | |
| 234 | + reg_val &= ~SPI_CMD_PAUSE_EN; | |
| 235 | + writel(reg_val, mdata->base + SPI_CMD_REG); | |
| 236 | +} | |
| 237 | + | |
| 238 | +static void mtk_spi_prepare_transfer(struct spi_master *master, | |
| 239 | + struct spi_transfer *xfer) | |
| 240 | +{ | |
| 241 | + u32 spi_clk_hz, div, sck_time, cs_time, reg_val = 0; | |
| 242 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 243 | + | |
| 244 | + spi_clk_hz = clk_get_rate(mdata->spi_clk); | |
| 245 | + if (xfer->speed_hz < spi_clk_hz / 2) | |
| 246 | + div = DIV_ROUND_UP(spi_clk_hz, xfer->speed_hz); | |
| 247 | + else | |
| 248 | + div = 1; | |
| 249 | + | |
| 250 | + sck_time = (div + 1) / 2; | |
| 251 | + cs_time = sck_time * 2; | |
| 252 | + | |
| 253 | + reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_HIGH_OFFSET); | |
| 254 | + reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET); | |
| 255 | + reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); | |
| 256 | + reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET); | |
| 257 | + writel(reg_val, mdata->base + SPI_CFG0_REG); | |
| 258 | + | |
| 259 | + reg_val = readl(mdata->base + SPI_CFG1_REG); | |
| 260 | + reg_val &= ~SPI_CFG1_CS_IDLE_MASK; | |
| 261 | + reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); | |
| 262 | + writel(reg_val, mdata->base + SPI_CFG1_REG); | |
| 263 | +} | |
| 264 | + | |
| 265 | +static void mtk_spi_setup_packet(struct spi_master *master) | |
| 266 | +{ | |
| 267 | + u32 packet_size, packet_loop, reg_val; | |
| 268 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 269 | + | |
| 270 | + packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE); | |
| 271 | + packet_loop = mdata->xfer_len / packet_size; | |
| 272 | + | |
| 273 | + reg_val = readl(mdata->base + SPI_CFG1_REG); | |
| 274 | + reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK); | |
| 275 | + reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; | |
| 276 | + reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; | |
| 277 | + writel(reg_val, mdata->base + SPI_CFG1_REG); | |
| 278 | +} | |
| 279 | + | |
| 280 | +static void mtk_spi_enable_transfer(struct spi_master *master) | |
| 281 | +{ | |
| 282 | + u32 cmd; | |
| 283 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 284 | + | |
| 285 | + cmd = readl(mdata->base + SPI_CMD_REG); | |
| 286 | + if (mdata->state == MTK_SPI_IDLE) | |
| 287 | + cmd |= SPI_CMD_ACT; | |
| 288 | + else | |
| 289 | + cmd |= SPI_CMD_RESUME; | |
| 290 | + writel(cmd, mdata->base + SPI_CMD_REG); | |
| 291 | +} | |
| 292 | + | |
| 293 | +static int mtk_spi_get_mult_delta(u32 xfer_len) | |
| 294 | +{ | |
| 295 | + u32 mult_delta; | |
| 296 | + | |
| 297 | + if (xfer_len > MTK_SPI_PACKET_SIZE) | |
| 298 | + mult_delta = xfer_len % MTK_SPI_PACKET_SIZE; | |
| 299 | + else | |
| 300 | + mult_delta = 0; | |
| 301 | + | |
| 302 | + return mult_delta; | |
| 303 | +} | |
| 304 | + | |
| 305 | +static void mtk_spi_update_mdata_len(struct spi_master *master) | |
| 306 | +{ | |
| 307 | + int mult_delta; | |
| 308 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 309 | + | |
| 310 | + if (mdata->tx_sgl_len && mdata->rx_sgl_len) { | |
| 311 | + if (mdata->tx_sgl_len > mdata->rx_sgl_len) { | |
| 312 | + mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); | |
| 313 | + mdata->xfer_len = mdata->rx_sgl_len - mult_delta; | |
| 314 | + mdata->rx_sgl_len = mult_delta; | |
| 315 | + mdata->tx_sgl_len -= mdata->xfer_len; | |
| 316 | + } else { | |
| 317 | + mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); | |
| 318 | + mdata->xfer_len = mdata->tx_sgl_len - mult_delta; | |
| 319 | + mdata->tx_sgl_len = mult_delta; | |
| 320 | + mdata->rx_sgl_len -= mdata->xfer_len; | |
| 321 | + } | |
| 322 | + } else if (mdata->tx_sgl_len) { | |
| 323 | + mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len); | |
| 324 | + mdata->xfer_len = mdata->tx_sgl_len - mult_delta; | |
| 325 | + mdata->tx_sgl_len = mult_delta; | |
| 326 | + } else if (mdata->rx_sgl_len) { | |
| 327 | + mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len); | |
| 328 | + mdata->xfer_len = mdata->rx_sgl_len - mult_delta; | |
| 329 | + mdata->rx_sgl_len = mult_delta; | |
| 330 | + } | |
| 331 | +} | |
| 332 | + | |
| 333 | +static void mtk_spi_setup_dma_addr(struct spi_master *master, | |
| 334 | + struct spi_transfer *xfer) | |
| 335 | +{ | |
| 336 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 337 | + | |
| 338 | + if (mdata->tx_sgl) | |
| 339 | + writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG); | |
| 340 | + if (mdata->rx_sgl) | |
| 341 | + writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG); | |
| 342 | +} | |
| 343 | + | |
| 344 | +static int mtk_spi_fifo_transfer(struct spi_master *master, | |
| 345 | + struct spi_device *spi, | |
| 346 | + struct spi_transfer *xfer) | |
| 347 | +{ | |
| 348 | + int cnt; | |
| 349 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 350 | + | |
| 351 | + mdata->cur_transfer = xfer; | |
| 352 | + mdata->xfer_len = xfer->len; | |
| 353 | + mtk_spi_prepare_transfer(master, xfer); | |
| 354 | + mtk_spi_setup_packet(master); | |
| 355 | + | |
| 356 | + if (xfer->len % 4) | |
| 357 | + cnt = xfer->len / 4 + 1; | |
| 358 | + else | |
| 359 | + cnt = xfer->len / 4; | |
| 360 | + iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt); | |
| 361 | + | |
| 362 | + mtk_spi_enable_transfer(master); | |
| 363 | + | |
| 364 | + return 1; | |
| 365 | +} | |
| 366 | + | |
| 367 | +static int mtk_spi_dma_transfer(struct spi_master *master, | |
| 368 | + struct spi_device *spi, | |
| 369 | + struct spi_transfer *xfer) | |
| 370 | +{ | |
| 371 | + int cmd; | |
| 372 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 373 | + | |
| 374 | + mdata->tx_sgl = NULL; | |
| 375 | + mdata->rx_sgl = NULL; | |
| 376 | + mdata->tx_sgl_len = 0; | |
| 377 | + mdata->rx_sgl_len = 0; | |
| 378 | + mdata->cur_transfer = xfer; | |
| 379 | + | |
| 380 | + mtk_spi_prepare_transfer(master, xfer); | |
| 381 | + | |
| 382 | + cmd = readl(mdata->base + SPI_CMD_REG); | |
| 383 | + if (xfer->tx_buf) | |
| 384 | + cmd |= SPI_CMD_TX_DMA; | |
| 385 | + if (xfer->rx_buf) | |
| 386 | + cmd |= SPI_CMD_RX_DMA; | |
| 387 | + writel(cmd, mdata->base + SPI_CMD_REG); | |
| 388 | + | |
| 389 | + if (xfer->tx_buf) | |
| 390 | + mdata->tx_sgl = xfer->tx_sg.sgl; | |
| 391 | + if (xfer->rx_buf) | |
| 392 | + mdata->rx_sgl = xfer->rx_sg.sgl; | |
| 393 | + | |
| 394 | + if (mdata->tx_sgl) { | |
| 395 | + xfer->tx_dma = sg_dma_address(mdata->tx_sgl); | |
| 396 | + mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl); | |
| 397 | + } | |
| 398 | + if (mdata->rx_sgl) { | |
| 399 | + xfer->rx_dma = sg_dma_address(mdata->rx_sgl); | |
| 400 | + mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl); | |
| 401 | + } | |
| 402 | + | |
| 403 | + mtk_spi_update_mdata_len(master); | |
| 404 | + mtk_spi_setup_packet(master); | |
| 405 | + mtk_spi_setup_dma_addr(master, xfer); | |
| 406 | + mtk_spi_enable_transfer(master); | |
| 407 | + | |
| 408 | + return 1; | |
| 409 | +} | |
| 410 | + | |
| 411 | +static int mtk_spi_transfer_one(struct spi_master *master, | |
| 412 | + struct spi_device *spi, | |
| 413 | + struct spi_transfer *xfer) | |
| 414 | +{ | |
| 415 | + if (master->can_dma(master, spi, xfer)) | |
| 416 | + return mtk_spi_dma_transfer(master, spi, xfer); | |
| 417 | + else | |
| 418 | + return mtk_spi_fifo_transfer(master, spi, xfer); | |
| 419 | +} | |
| 420 | + | |
| 421 | +static bool mtk_spi_can_dma(struct spi_master *master, | |
| 422 | + struct spi_device *spi, | |
| 423 | + struct spi_transfer *xfer) | |
| 424 | +{ | |
| 425 | + return xfer->len > MTK_SPI_MAX_FIFO_SIZE; | |
| 426 | +} | |
| 427 | + | |
| 428 | +static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) | |
| 429 | +{ | |
| 430 | + u32 cmd, reg_val, cnt; | |
| 431 | + struct spi_master *master = dev_id; | |
| 432 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 433 | + struct spi_transfer *trans = mdata->cur_transfer; | |
| 434 | + | |
| 435 | + reg_val = readl(mdata->base + SPI_STATUS0_REG); | |
| 436 | + if (reg_val & MTK_SPI_PAUSE_INT_STATUS) | |
| 437 | + mdata->state = MTK_SPI_PAUSED; | |
| 438 | + else | |
| 439 | + mdata->state = MTK_SPI_IDLE; | |
| 440 | + | |
| 441 | + if (!master->can_dma(master, master->cur_msg->spi, trans)) { | |
| 442 | + if (trans->rx_buf) { | |
| 443 | + if (mdata->xfer_len % 4) | |
| 444 | + cnt = mdata->xfer_len / 4 + 1; | |
| 445 | + else | |
| 446 | + cnt = mdata->xfer_len / 4; | |
| 447 | + ioread32_rep(mdata->base + SPI_RX_DATA_REG, | |
| 448 | + trans->rx_buf, cnt); | |
| 449 | + } | |
| 450 | + spi_finalize_current_transfer(master); | |
| 451 | + return IRQ_HANDLED; | |
| 452 | + } | |
| 453 | + | |
| 454 | + if (mdata->tx_sgl) | |
| 455 | + trans->tx_dma += mdata->xfer_len; | |
| 456 | + if (mdata->rx_sgl) | |
| 457 | + trans->rx_dma += mdata->xfer_len; | |
| 458 | + | |
| 459 | + if (mdata->tx_sgl && (mdata->tx_sgl_len == 0)) { | |
| 460 | + mdata->tx_sgl = sg_next(mdata->tx_sgl); | |
| 461 | + if (mdata->tx_sgl) { | |
| 462 | + trans->tx_dma = sg_dma_address(mdata->tx_sgl); | |
| 463 | + mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl); | |
| 464 | + } | |
| 465 | + } | |
| 466 | + if (mdata->rx_sgl && (mdata->rx_sgl_len == 0)) { | |
| 467 | + mdata->rx_sgl = sg_next(mdata->rx_sgl); | |
| 468 | + if (mdata->rx_sgl) { | |
| 469 | + trans->rx_dma = sg_dma_address(mdata->rx_sgl); | |
| 470 | + mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl); | |
| 471 | + } | |
| 472 | + } | |
| 473 | + | |
| 474 | + if (!mdata->tx_sgl && !mdata->rx_sgl) { | |
| 475 | + /* spi disable dma */ | |
| 476 | + cmd = readl(mdata->base + SPI_CMD_REG); | |
| 477 | + cmd &= ~SPI_CMD_TX_DMA; | |
| 478 | + cmd &= ~SPI_CMD_RX_DMA; | |
| 479 | + writel(cmd, mdata->base + SPI_CMD_REG); | |
| 480 | + | |
| 481 | + spi_finalize_current_transfer(master); | |
| 482 | + return IRQ_HANDLED; | |
| 483 | + } | |
| 484 | + | |
| 485 | + mtk_spi_update_mdata_len(master); | |
| 486 | + mtk_spi_setup_packet(master); | |
| 487 | + mtk_spi_setup_dma_addr(master, trans); | |
| 488 | + mtk_spi_enable_transfer(master); | |
| 489 | + | |
| 490 | + return IRQ_HANDLED; | |
| 491 | +} | |
| 492 | + | |
| 493 | +static int mtk_spi_probe(struct platform_device *pdev) | |
| 494 | +{ | |
| 495 | + struct spi_master *master; | |
| 496 | + struct mtk_spi *mdata; | |
| 497 | + const struct of_device_id *of_id; | |
| 498 | + struct resource *res; | |
| 499 | + int irq, ret; | |
| 500 | + | |
| 501 | + master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); | |
| 502 | + if (!master) { | |
| 503 | + dev_err(&pdev->dev, "failed to alloc spi master\n"); | |
| 504 | + return -ENOMEM; | |
| 505 | + } | |
| 506 | + | |
| 507 | + master->auto_runtime_pm = true; | |
| 508 | + master->dev.of_node = pdev->dev.of_node; | |
| 509 | + master->mode_bits = SPI_CPOL | SPI_CPHA; | |
| 510 | + | |
| 511 | + master->set_cs = mtk_spi_set_cs; | |
| 512 | + master->prepare_transfer_hardware = mtk_spi_prepare_hardware; | |
| 513 | + master->prepare_message = mtk_spi_prepare_message; | |
| 514 | + master->transfer_one = mtk_spi_transfer_one; | |
| 515 | + master->can_dma = mtk_spi_can_dma; | |
| 516 | + | |
| 517 | + of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); | |
| 518 | + if (!of_id) { | |
| 519 | + dev_err(&pdev->dev, "failed to probe of_node\n"); | |
| 520 | + ret = -EINVAL; | |
| 521 | + goto err_put_master; | |
| 522 | + } | |
| 523 | + | |
| 524 | + mdata = spi_master_get_devdata(master); | |
| 525 | + mdata->dev_comp = of_id->data; | |
| 526 | + if (mdata->dev_comp->must_tx) | |
| 527 | + master->flags = SPI_MASTER_MUST_TX; | |
| 528 | + | |
| 529 | + if (mdata->dev_comp->need_pad_sel) { | |
| 530 | + ret = of_property_read_u32(pdev->dev.of_node, | |
| 531 | + "mediatek,pad-select", | |
| 532 | + &mdata->pad_sel); | |
| 533 | + if (ret) { | |
| 534 | + dev_err(&pdev->dev, "failed to read pad select: %d\n", | |
| 535 | + ret); | |
| 536 | + goto err_put_master; | |
| 537 | + } | |
| 538 | + | |
| 539 | + if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) { | |
| 540 | + dev_err(&pdev->dev, "wrong pad-select: %u\n", | |
| 541 | + mdata->pad_sel); | |
| 542 | + ret = -EINVAL; | |
| 543 | + goto err_put_master; | |
| 544 | + } | |
| 545 | + } | |
| 546 | + | |
| 547 | + platform_set_drvdata(pdev, master); | |
| 548 | + | |
| 549 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 550 | + if (!res) { | |
| 551 | + ret = -ENODEV; | |
| 552 | + dev_err(&pdev->dev, "failed to determine base address\n"); | |
| 553 | + goto err_put_master; | |
| 554 | + } | |
| 555 | + | |
| 556 | + mdata->base = devm_ioremap_resource(&pdev->dev, res); | |
| 557 | + if (IS_ERR(mdata->base)) { | |
| 558 | + ret = PTR_ERR(mdata->base); | |
| 559 | + goto err_put_master; | |
| 560 | + } | |
| 561 | + | |
| 562 | + irq = platform_get_irq(pdev, 0); | |
| 563 | + if (irq < 0) { | |
| 564 | + dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); | |
| 565 | + ret = irq; | |
| 566 | + goto err_put_master; | |
| 567 | + } | |
| 568 | + | |
| 569 | + if (!pdev->dev.dma_mask) | |
| 570 | + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | |
| 571 | + | |
| 572 | + ret = devm_request_irq(&pdev->dev, irq, mtk_spi_interrupt, | |
| 573 | + IRQF_TRIGGER_NONE, dev_name(&pdev->dev), master); | |
| 574 | + if (ret) { | |
| 575 | + dev_err(&pdev->dev, "failed to register irq (%d)\n", ret); | |
| 576 | + goto err_put_master; | |
| 577 | + } | |
| 578 | + | |
| 579 | + mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk"); | |
| 580 | + if (IS_ERR(mdata->spi_clk)) { | |
| 581 | + ret = PTR_ERR(mdata->spi_clk); | |
| 582 | + dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret); | |
| 583 | + goto err_put_master; | |
| 584 | + } | |
| 585 | + | |
| 586 | + mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk"); | |
| 587 | + if (IS_ERR(mdata->parent_clk)) { | |
| 588 | + ret = PTR_ERR(mdata->parent_clk); | |
| 589 | + dev_err(&pdev->dev, "failed to get parent-clk: %d\n", ret); | |
| 590 | + goto err_put_master; | |
| 591 | + } | |
| 592 | + | |
| 593 | + ret = clk_prepare_enable(mdata->spi_clk); | |
| 594 | + if (ret < 0) { | |
| 595 | + dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret); | |
| 596 | + goto err_put_master; | |
| 597 | + } | |
| 598 | + | |
| 599 | + ret = clk_set_parent(mdata->spi_clk, mdata->parent_clk); | |
| 600 | + if (ret < 0) { | |
| 601 | + dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); | |
| 602 | + goto err_disable_clk; | |
| 603 | + } | |
| 604 | + | |
| 605 | + clk_disable_unprepare(mdata->spi_clk); | |
| 606 | + | |
| 607 | + pm_runtime_enable(&pdev->dev); | |
| 608 | + | |
| 609 | + ret = devm_spi_register_master(&pdev->dev, master); | |
| 610 | + if (ret) { | |
| 611 | + dev_err(&pdev->dev, "failed to register master (%d)\n", ret); | |
| 612 | + goto err_put_master; | |
| 613 | + } | |
| 614 | + | |
| 615 | + return 0; | |
| 616 | + | |
| 617 | +err_disable_clk: | |
| 618 | + clk_disable_unprepare(mdata->spi_clk); | |
| 619 | +err_put_master: | |
| 620 | + spi_master_put(master); | |
| 621 | + | |
| 622 | + return ret; | |
| 623 | +} | |
| 624 | + | |
| 625 | +static int mtk_spi_remove(struct platform_device *pdev) | |
| 626 | +{ | |
| 627 | + struct spi_master *master = platform_get_drvdata(pdev); | |
| 628 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 629 | + | |
| 630 | + pm_runtime_disable(&pdev->dev); | |
| 631 | + | |
| 632 | + mtk_spi_reset(mdata); | |
| 633 | + clk_disable_unprepare(mdata->spi_clk); | |
| 634 | + spi_master_put(master); | |
| 635 | + | |
| 636 | + return 0; | |
| 637 | +} | |
| 638 | + | |
| 639 | +#ifdef CONFIG_PM_SLEEP | |
| 640 | +static int mtk_spi_suspend(struct device *dev) | |
| 641 | +{ | |
| 642 | + int ret; | |
| 643 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 644 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 645 | + | |
| 646 | + ret = spi_master_suspend(master); | |
| 647 | + if (ret) | |
| 648 | + return ret; | |
| 649 | + | |
| 650 | + if (!pm_runtime_suspended(dev)) | |
| 651 | + clk_disable_unprepare(mdata->spi_clk); | |
| 652 | + | |
| 653 | + return ret; | |
| 654 | +} | |
| 655 | + | |
| 656 | +static int mtk_spi_resume(struct device *dev) | |
| 657 | +{ | |
| 658 | + int ret; | |
| 659 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 660 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 661 | + | |
| 662 | + if (!pm_runtime_suspended(dev)) { | |
| 663 | + ret = clk_prepare_enable(mdata->spi_clk); | |
| 664 | + if (ret < 0) { | |
| 665 | + dev_err(dev, "failed to enable spi_clk (%d)\n", ret); | |
| 666 | + return ret; | |
| 667 | + } | |
| 668 | + } | |
| 669 | + | |
| 670 | + ret = spi_master_resume(master); | |
| 671 | + if (ret < 0) | |
| 672 | + clk_disable_unprepare(mdata->spi_clk); | |
| 673 | + | |
| 674 | + return ret; | |
| 675 | +} | |
| 676 | +#endif /* CONFIG_PM_SLEEP */ | |
| 677 | + | |
| 678 | +#ifdef CONFIG_PM | |
| 679 | +static int mtk_spi_runtime_suspend(struct device *dev) | |
| 680 | +{ | |
| 681 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 682 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 683 | + | |
| 684 | + clk_disable_unprepare(mdata->spi_clk); | |
| 685 | + | |
| 686 | + return 0; | |
| 687 | +} | |
| 688 | + | |
| 689 | +static int mtk_spi_runtime_resume(struct device *dev) | |
| 690 | +{ | |
| 691 | + struct spi_master *master = dev_get_drvdata(dev); | |
| 692 | + struct mtk_spi *mdata = spi_master_get_devdata(master); | |
| 693 | + int ret; | |
| 694 | + | |
| 695 | + ret = clk_prepare_enable(mdata->spi_clk); | |
| 696 | + if (ret < 0) { | |
| 697 | + dev_err(dev, "failed to enable spi_clk (%d)\n", ret); | |
| 698 | + return ret; | |
| 699 | + } | |
| 700 | + | |
| 701 | + return 0; | |
| 702 | +} | |
| 703 | +#endif /* CONFIG_PM */ | |
| 704 | + | |
| 705 | +static const struct dev_pm_ops mtk_spi_pm = { | |
| 706 | + SET_SYSTEM_SLEEP_PM_OPS(mtk_spi_suspend, mtk_spi_resume) | |
| 707 | + SET_RUNTIME_PM_OPS(mtk_spi_runtime_suspend, | |
| 708 | + mtk_spi_runtime_resume, NULL) | |
| 709 | +}; | |
| 710 | + | |
| 711 | +static struct platform_driver mtk_spi_driver = { | |
| 712 | + .driver = { | |
| 713 | + .name = "mtk-spi", | |
| 714 | + .pm = &mtk_spi_pm, | |
| 715 | + .of_match_table = mtk_spi_of_match, | |
| 716 | + }, | |
| 717 | + .probe = mtk_spi_probe, | |
| 718 | + .remove = mtk_spi_remove, | |
| 719 | +}; | |
| 720 | + | |
| 721 | +module_platform_driver(mtk_spi_driver); | |
| 722 | + | |
| 723 | +MODULE_DESCRIPTION("MTK SPI Controller driver"); | |
| 724 | +MODULE_AUTHOR("Leilk Liu <leilk.liu@mediatek.com>"); | |
| 725 | +MODULE_LICENSE("GPL v2"); | |
| 726 | +MODULE_ALIAS("platform:mtk-spi"); | |
| @@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) · 244 unmodified lines | ||
| 245 | 245 | |
| 246 | 246 | static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) |
| 247 | 247 | { |
| 248 | + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); | |
| 248 | 249 | u32 l; |
| 249 | 250 | |
| 250 | 251 | /* The controller handles the inverted chip selects |
| @@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) · 4 unmodified lines | ||
| 255 | 256 | enable = !enable; |
| 256 | 257 | |
| 257 | 258 | if (spi->controller_state) { |
| 259 | + int err = pm_runtime_get_sync(mcspi->dev); | |
| 260 | + if (err < 0) { | |
| 261 | + dev_err(mcspi->dev, "failed to get sync: %d\n", err); | |
| 262 | + return; | |
| 263 | + } | |
| 264 | + | |
| 258 | 265 | l = mcspi_cached_chconf0(spi); |
| 259 | 266 | |
| 260 | 267 | if (enable) |
| @@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) · 2 unmodified lines | ||
| 263 | 270 | l |= OMAP2_MCSPI_CHCONF_FORCE; |
| 264 | 271 | |
| 265 | 272 | mcspi_write_chconf0(spi, l); |
| 273 | + | |
| 274 | + pm_runtime_mark_last_busy(mcspi->dev); | |
| 275 | + pm_runtime_put_autosuspend(mcspi->dev); | |
| 266 | 276 | } |
| 267 | 277 | } |
| 268 | 278 | |
| @@ -41,6 +41,11 @@ · 40 unmodified lines | ||
| 41 | 41 | #define ORION_SPI_DATA_OUT_REG 0x08 |
| 42 | 42 | #define ORION_SPI_DATA_IN_REG 0x0c |
| 43 | 43 | #define ORION_SPI_INT_CAUSE_REG 0x10 |
| 44 | +#define ORION_SPI_TIMING_PARAMS_REG 0x18 | |
| 45 | + | |
| 46 | +#define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6) | |
| 47 | +#define ORION_SPI_TMISO_SAMPLE_1 (1 << 6) | |
| 48 | +#define ORION_SPI_TMISO_SAMPLE_2 (2 << 6) | |
| 44 | 49 | |
| 45 | 50 | #define ORION_SPI_MODE_CPOL (1 << 11) |
| 46 | 51 | #define ORION_SPI_MODE_CPHA (1 << 12) |
| @@ -70,6 +75,7 @@ struct orion_spi_dev { · 23 unmodified lines | ||
| 70 | 75 | unsigned int min_divisor; |
| 71 | 76 | unsigned int max_divisor; |
| 72 | 77 | u32 prescale_mask; |
| 78 | + bool is_errata_50mhz_ac; | |
| 73 | 79 | }; |
| 74 | 80 | |
| 75 | 81 | struct orion_spi { |
| @@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi) · 119 unmodified lines | ||
| 195 | 201 | writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); |
| 196 | 202 | } |
| 197 | 203 | |
| 204 | +static void | |
| 205 | +orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed) | |
| 206 | +{ | |
| 207 | + u32 reg; | |
| 208 | + struct orion_spi *orion_spi; | |
| 209 | + | |
| 210 | + orion_spi = spi_master_get_devdata(spi->master); | |
| 211 | + | |
| 212 | + /* | |
| 213 | + * Erratum description: (Erratum NO. FE-9144572) The device | |
| 214 | + * SPI interface supports frequencies of up to 50 MHz. | |
| 215 | + * However, due to this erratum, when the device core clock is | |
| 216 | + * 250 MHz and the SPI interfaces is configured for 50MHz SPI | |
| 217 | + * clock and CPOL=CPHA=1 there might occur data corruption on | |
| 218 | + * reads from the SPI device. | |
| 219 | + * Erratum Workaround: | |
| 220 | + * Work in one of the following configurations: | |
| 221 | + * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration | |
| 222 | + * Register". | |
| 223 | + * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1 | |
| 224 | + * Register" before setting the interface. | |
| 225 | + */ | |
| 226 | + reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG)); | |
| 227 | + reg &= ~ORION_SPI_TMISO_SAMPLE_MASK; | |
| 228 | + | |
| 229 | + if (clk_get_rate(orion_spi->clk) == 250000000 && | |
| 230 | + speed == 50000000 && spi->mode & SPI_CPOL && | |
| 231 | + spi->mode & SPI_CPHA) | |
| 232 | + reg |= ORION_SPI_TMISO_SAMPLE_2; | |
| 233 | + else | |
| 234 | + reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */ | |
| 235 | + | |
| 236 | + writel(reg, spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG)); | |
| 237 | +} | |
| 238 | + | |
| 198 | 239 | /* |
| 199 | 240 | * called only when no transfer is active on the bus |
| 200 | 241 | */ |
| @@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) · 15 unmodified lines | ||
| 216 | 257 | |
| 217 | 258 | orion_spi_mode_set(spi); |
| 218 | 259 | |
| 260 | + if (orion_spi->devdata->is_errata_50mhz_ac) | |
| 261 | + orion_spi_50mhz_ac_timing_erratum(spi, speed); | |
| 262 | + | |
| 219 | 263 | rc = orion_spi_baudrate_set(spi, speed); |
| 220 | 264 | if (rc) |
| 221 | 265 | return rc; |
| @@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = { · 191 unmodified lines | ||
| 413 | 457 | .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, |
| 414 | 458 | }; |
| 415 | 459 | |
| 460 | +static const struct orion_spi_dev armada_380_spi_dev_data = { | |
| 461 | + .typ = ARMADA_SPI, | |
| 462 | + .max_hz = 50000000, | |
| 463 | + .max_divisor = 1920, | |
| 464 | + .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, | |
| 465 | + .is_errata_50mhz_ac = true, | |
| 466 | +}; | |
| 467 | + | |
| 416 | 468 | static const struct of_device_id orion_spi_of_match_table[] = { |
| 417 | 469 | { |
| 418 | 470 | .compatible = "marvell,orion-spi", |
| @@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = { · 9 unmodified lines | ||
| 428 | 480 | }, |
| 429 | 481 | { |
| 430 | 482 | .compatible = "marvell,armada-380-spi", |
| 431 | − .data = &armada_xp_spi_dev_data, | |
| 483 | + .data = &armada_380_spi_dev_data, | |
| 432 | 484 | }, |
| 433 | 485 | { |
| 434 | 486 | .compatible = "marvell,armada-390-spi", |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/of_device.h> |
| 8 | 8 | #include <linux/module.h> |
| 9 | 9 | #include <linux/spi/pxa2xx_spi.h> |
| 10 | −#include <linux/clk.h> | |
| 11 | 10 | #include <linux/clk-provider.h> |
| 12 | 11 | |
| 13 | 12 | #include <linux/dmaengine.h> |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/err.h> |
| 22 | 22 | #include <linux/interrupt.h> |
| 23 | 23 | #include <linux/kernel.h> |
| 24 | +#include <linux/pci.h> | |
| 24 | 25 | #include <linux/platform_device.h> |
| 25 | 26 | #include <linux/spi/pxa2xx_spi.h> |
| 26 | 27 | #include <linux/spi/spi.h> |
| @@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = { · 70 unmodified lines | ||
| 97 | 98 | .tx_threshold_lo = 160, |
| 98 | 99 | .tx_threshold_hi = 224, |
| 99 | 100 | }, |
| 101 | + { /* LPSS_SPT_SSP */ | |
| 102 | + .offset = 0x200, | |
| 103 | + .reg_general = -1, | |
| 104 | + .reg_ssp = 0x20, | |
| 105 | + .reg_cs_ctrl = 0x24, | |
| 106 | + .rx_threshold = 1, | |
| 107 | + .tx_threshold_lo = 32, | |
| 108 | + .tx_threshold_hi = 56, | |
| 109 | + }, | |
| 100 | 110 | }; |
| 101 | 111 | |
| 102 | 112 | static inline const struct lpss_config |
| @@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) · 7 unmodified lines | ||
| 110 | 120 | switch (drv_data->ssp_type) { |
| 111 | 121 | case LPSS_LPT_SSP: |
| 112 | 122 | case LPSS_BYT_SSP: |
| 123 | + case LPSS_SPT_SSP: | |
| 113 | 124 | return true; |
| 114 | 125 | default: |
| 115 | 126 | return false; |
| @@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi) · 991 unmodified lines | ||
| 1107 | 1118 | break; |
| 1108 | 1119 | case LPSS_LPT_SSP: |
| 1109 | 1120 | case LPSS_BYT_SSP: |
| 1121 | + case LPSS_SPT_SSP: | |
| 1110 | 1122 | config = lpss_get_config(drv_data); |
| 1111 | 1123 | tx_thres = config->tx_threshold_lo; |
| 1112 | 1124 | tx_hi_thres = config->tx_threshold_hi; |
| @@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { · 163 unmodified lines | ||
| 1276 | 1288 | }; |
| 1277 | 1289 | MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); |
| 1278 | 1290 | |
| 1291 | +/* | |
| 1292 | + * PCI IDs of compound devices that integrate both host controller and private | |
| 1293 | + * integrated DMA engine. Please note these are not used in module | |
| 1294 | + * autoloading and probing in this module but matching the LPSS SSP type. | |
| 1295 | + */ | |
| 1296 | +static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { | |
| 1297 | + /* SPT-LP */ | |
| 1298 | + { PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP }, | |
| 1299 | + { PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP }, | |
| 1300 | + /* SPT-H */ | |
| 1301 | + { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP }, | |
| 1302 | + { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP }, | |
| 1303 | + { }, | |
| 1304 | +}; | |
| 1305 | + | |
| 1306 | +static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param) | |
| 1307 | +{ | |
| 1308 | + struct device *dev = param; | |
| 1309 | + | |
| 1310 | + if (dev != chan->device->dev->parent) | |
| 1311 | + return false; | |
| 1312 | + | |
| 1313 | + return true; | |
| 1314 | +} | |
| 1315 | + | |
| 1279 | 1316 | static struct pxa2xx_spi_master * |
| 1280 | 1317 | pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) |
| 1281 | 1318 | { |
| @@ -1283,16 +1320,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) · 1 unmodified line | ||
| 1283 | 1320 | struct acpi_device *adev; |
| 1284 | 1321 | struct ssp_device *ssp; |
| 1285 | 1322 | struct resource *res; |
| 1286 | − const struct acpi_device_id *id; | |
| 1323 | + const struct acpi_device_id *adev_id = NULL; | |
| 1324 | + const struct pci_device_id *pcidev_id = NULL; | |
| 1287 | 1325 | int devid, type; |
| 1288 | 1326 | |
| 1289 | 1327 | if (!ACPI_HANDLE(&pdev->dev) || |
| 1290 | 1328 | acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) |
| 1291 | 1329 | return NULL; |
| 1292 | 1330 | |
| 1293 | − id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); | |
| 1294 | − if (id) | |
| 1295 | − type = (int)id->driver_data; | |
| 1331 | + if (dev_is_pci(pdev->dev.parent)) | |
| 1332 | + pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, | |
| 1333 | + to_pci_dev(pdev->dev.parent)); | |
| 1334 | + else | |
| 1335 | + adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table, | |
| 1336 | + &pdev->dev); | |
| 1337 | + | |
| 1338 | + if (adev_id) | |
| 1339 | + type = (int)adev_id->driver_data; | |
| 1340 | + else if (pcidev_id) | |
| 1341 | + type = (int)pcidev_id->driver_data; | |
| 1296 | 1342 | else |
| 1297 | 1343 | return NULL; |
| 1298 | 1344 | |
| @@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) · 12 unmodified lines | ||
| 1311 | 1357 | if (IS_ERR(ssp->mmio_base)) |
| 1312 | 1358 | return NULL; |
| 1313 | 1359 | |
| 1360 | + if (pcidev_id) { | |
| 1361 | + pdata->tx_param = pdev->dev.parent; | |
| 1362 | + pdata->rx_param = pdev->dev.parent; | |
| 1363 | + pdata->dma_filter = pxa2xx_spi_idma_filter; | |
| 1364 | + } | |
| 1365 | + | |
| 1314 | 1366 | ssp->clk = devm_clk_get(&pdev->dev, NULL); |
| 1315 | 1367 | ssp->irq = platform_get_irq(pdev, 0); |
| 1316 | 1368 | ssp->type = type; |
| @@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) · 45 unmodified lines | ||
| 1362 | 1414 | return -ENODEV; |
| 1363 | 1415 | } |
| 1364 | 1416 | |
| 1365 | − /* Allocate master with space for drv_data and null dma buffer */ | |
| 1366 | − master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | |
| 1417 | + master = spi_alloc_master(dev, sizeof(struct driver_data)); | |
| 1367 | 1418 | if (!master) { |
| 1368 | 1419 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); |
| 1369 | 1420 | pxa_ssp_free(ssp); |
| @@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 1390 | 1441 | master->auto_runtime_pm = true; |
| 1391 | 1442 | |
| 1392 | 1443 | drv_data->ssp_type = ssp->type; |
| 1393 | − drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT); | |
| 1394 | 1444 | |
| 1395 | 1445 | drv_data->ioaddr = ssp->mmio_base; |
| 1396 | 1446 | drv_data->ssdr_physical = ssp->phys_base + SSDR; |
| @@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) · 27 unmodified lines | ||
| 1424 | 1474 | } |
| 1425 | 1475 | |
| 1426 | 1476 | /* Setup DMA if requested */ |
| 1427 | − drv_data->tx_channel = -1; | |
| 1428 | − drv_data->rx_channel = -1; | |
| 1429 | 1477 | if (platform_info->enable_dma) { |
| 1430 | 1478 | status = pxa2xx_spi_dma_setup(drv_data); |
| 1431 | 1479 | if (status) { |
| @@ -36,11 +36,6 @@ struct driver_data { · 35 unmodified lines | ||
| 36 | 36 | /* PXA hookup */ |
| 37 | 37 | struct pxa2xx_spi_master *master_info; |
| 38 | 38 | |
| 39 | − /* PXA private DMA setup stuff */ | |
| 40 | − int rx_channel; | |
| 41 | − int tx_channel; | |
| 42 | − u32 *null_dma_buf; | |
| 43 | − | |
| 44 | 39 | /* SSP register addresses */ |
| 45 | 40 | void __iomem *ioaddr; |
| 46 | 41 | u32 ssdr_physical; |
| @@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev) · 644 unmodified lines | ||
| 645 | 645 | platform_set_drvdata(pdev, master); |
| 646 | 646 | |
| 647 | 647 | rs = spi_master_get_devdata(master); |
| 648 | − memset(rs, 0, sizeof(struct rockchip_spi)); | |
| 649 | 648 | |
| 650 | 649 | /* Get basic io resource and map it */ |
| 651 | 650 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg) · 382 unmodified lines | ||
| 383 | 383 | rspi_write8(rspi, data, reg); |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | −static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len) | |
| 386 | +static unsigned int qspi_set_send_trigger(struct rspi_data *rspi, | |
| 387 | + unsigned int len) | |
| 387 | 388 | { |
| 388 | 389 | unsigned int n; |
| 389 | 390 | |
| @@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master, · 334 unmodified lines | ||
| 724 | 725 | static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, |
| 725 | 726 | u8 *rx, unsigned int len) |
| 726 | 727 | { |
| 727 | − int i, n, ret; | |
| 728 | − int error; | |
| 728 | + unsigned int i, n; | |
| 729 | + int ret; | |
| 729 | 730 | |
| 730 | 731 | while (len > 0) { |
| 731 | 732 | n = qspi_set_send_trigger(rspi, len); |
| 732 | 733 | qspi_set_receive_trigger(rspi, len); |
| 733 | 734 | if (n == QSPI_BUFFER_SIZE) { |
| 734 | − error = rspi_wait_for_tx_empty(rspi); | |
| 735 | − if (error < 0) { | |
| 735 | + ret = rspi_wait_for_tx_empty(rspi); | |
| 736 | + if (ret < 0) { | |
| 736 | 737 | dev_err(&rspi->master->dev, "transmit timeout\n"); |
| 737 | − return error; | |
| 738 | + return ret; | |
| 738 | 739 | } |
| 739 | 740 | for (i = 0; i < n; i++) |
| 740 | 741 | rspi_write_data(rspi, *tx++); |
| 741 | 742 | |
| 742 | − error = rspi_wait_for_rx_full(rspi); | |
| 743 | − if (error < 0) { | |
| 743 | + ret = rspi_wait_for_rx_full(rspi); | |
| 744 | + if (ret < 0) { | |
| 744 | 745 | dev_err(&rspi->master->dev, "receive timeout\n"); |
| 745 | − return error; | |
| 746 | + return ret; | |
| 746 | 747 | } |
| 747 | 748 | for (i = 0; i < n; i++) |
| 748 | 749 | *rx++ = rspi_read_data(rspi); |
| @@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) · 500 unmodified lines | ||
| 501 | 501 | } |
| 502 | 502 | |
| 503 | 503 | hw = spi_master_get_devdata(master); |
| 504 | − memset(hw, 0, sizeof(struct s3c24xx_spi)); | |
| 505 | 504 | |
| 506 | 505 | hw->master = master; |
| 507 | 506 | hw->pdata = pdata = dev_get_platdata(&pdev->dev); |
| @@ -1191,8 +1191,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) · 1190 unmodified lines | ||
| 1191 | 1191 | |
| 1192 | 1192 | dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", |
| 1193 | 1193 | sdd->port_id, master->num_chipselect); |
| 1194 | − dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n", | |
| 1195 | − mem_res, | |
| 1194 | + dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\tDMA=[Rx-%d, Tx-%d]\n", | |
| 1195 | + mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1, | |
| 1196 | 1196 | sdd->rx_dma.dmach, sdd->tx_dma.dmach); |
| 1197 | 1197 | |
| 1198 | 1198 | return 0; |
| @@ -48,8 +48,8 @@ struct sh_msiof_spi_priv { · 47 unmodified lines | ||
| 48 | 48 | const struct sh_msiof_chipdata *chipdata; |
| 49 | 49 | struct sh_msiof_spi_info *info; |
| 50 | 50 | struct completion done; |
| 51 | − int tx_fifo_size; | |
| 52 | − int rx_fifo_size; | |
| 51 | + unsigned int tx_fifo_size; | |
| 52 | + unsigned int rx_fifo_size; | |
| 53 | 53 | void *tx_dma_page; |
| 54 | 54 | void *rx_dma_page; |
| 55 | 55 | dma_addr_t tx_dma_addr; |
| @@ -95,8 +95,6 @@ struct sh_msiof_spi_priv { · 39 unmodified lines | ||
| 95 | 95 | #define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */ |
| 96 | 96 | #define MDR2_GRPMASK1 0x00000001 /* Group Output Mask 1 (SH, A1) */ |
| 97 | 97 | |
| 98 | −#define MAX_WDLEN 256U | |
| 99 | − | |
| 100 | 98 | /* TSCR and RSCR */ |
| 101 | 99 | #define SCR_BRPS_MASK 0x1f00 /* Prescaler Setting (1-32) */ |
| 102 | 100 | #define SCR_BRPS(i) (((i) - 1) << 8) |
| @@ -850,7 +848,12 @@ static int sh_msiof_transfer_one(struct spi_master *master, · 747 unmodified lines | ||
| 850 | 848 | * DMA supports 32-bit words only, hence pack 8-bit and 16-bit |
| 851 | 849 | * words, with byte resp. word swapping. |
| 852 | 850 | */ |
| 853 | − unsigned int l = min(len, MAX_WDLEN * 4); | |
| 851 | + unsigned int l = 0; | |
| 852 | + | |
| 853 | + if (tx_buf) | |
| 854 | + l = min(len, p->tx_fifo_size * 4); | |
| 855 | + if (rx_buf) | |
| 856 | + l = min(len, p->rx_fifo_size * 4); | |
| 854 | 857 | |
| 855 | 858 | if (bits <= 8) { |
| 856 | 859 | if (l & 3) |
| @@ -963,7 +966,7 @@ static const struct sh_msiof_chipdata sh_data = { · 106 unmodified lines | ||
| 963 | 966 | |
| 964 | 967 | static const struct sh_msiof_chipdata r8a779x_data = { |
| 965 | 968 | .tx_fifo_size = 64, |
| 966 | − .rx_fifo_size = 256, | |
| 969 | + .rx_fifo_size = 64, | |
| 967 | 970 | .master_flags = SPI_MASTER_MUST_TX, |
| 968 | 971 | }; |
| 969 | 972 | |
| @@ -1265,11 +1268,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) · 295 unmodified lines | ||
| 1265 | 1268 | |
| 1266 | 1269 | static const struct platform_device_id spi_driver_ids[] = { |
| 1267 | 1270 | { "spi_sh_msiof", (kernel_ulong_t)&sh_data }, |
| 1268 | − { "spi_r8a7790_msiof", (kernel_ulong_t)&r8a779x_data }, | |
| 1269 | − { "spi_r8a7791_msiof", (kernel_ulong_t)&r8a779x_data }, | |
| 1270 | − { "spi_r8a7792_msiof", (kernel_ulong_t)&r8a779x_data }, | |
| 1271 | − { "spi_r8a7793_msiof", (kernel_ulong_t)&r8a779x_data }, | |
| 1272 | − { "spi_r8a7794_msiof", (kernel_ulong_t)&r8a779x_data }, | |
| 1273 | 1271 | {}, |
| 1274 | 1272 | }; |
| 1275 | 1273 | MODULE_DEVICE_TABLE(platform, spi_driver_ids); |
| @@ -99,6 +99,8 @@ struct ti_qspi { · 98 unmodified lines | ||
| 99 | 99 | #define QSPI_INVAL (4 << 16) |
| 100 | 100 | #define QSPI_WC_CMD_INT_EN (1 << 14) |
| 101 | 101 | #define QSPI_FLEN(n) ((n - 1) << 0) |
| 102 | +#define QSPI_WLEN_MAX_BITS 128 | |
| 103 | +#define QSPI_WLEN_MAX_BYTES 16 | |
| 102 | 104 | |
| 103 | 105 | /* STATUS REGISTER */ |
| 104 | 106 | #define BUSY 0x01 |
| @@ -217,14 +219,16 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi) · 112 unmodified lines | ||
| 217 | 219 | |
| 218 | 220 | static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) |
| 219 | 221 | { |
| 220 | − int wlen, count; | |
| 222 | + int wlen, count, xfer_len; | |
| 221 | 223 | unsigned int cmd; |
| 222 | 224 | const u8 *txbuf; |
| 225 | + u32 data; | |
| 223 | 226 | |
| 224 | 227 | txbuf = t->tx_buf; |
| 225 | 228 | cmd = qspi->cmd | QSPI_WR_SNGL; |
| 226 | 229 | count = t->len; |
| 227 | 230 | wlen = t->bits_per_word >> 3; /* in bytes */ |
| 231 | + xfer_len = wlen; | |
| 228 | 232 | |
| 229 | 233 | while (count) { |
| 230 | 234 | if (qspi_is_busy(qspi)) |
| @@ -234,7 +238,29 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) · 3 unmodified lines | ||
| 234 | 238 | case 1: |
| 235 | 239 | dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n", |
| 236 | 240 | cmd, qspi->dc, *txbuf); |
| 237 | − writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); | |
| 241 | + if (count >= QSPI_WLEN_MAX_BYTES) { | |
| 242 | + u32 *txp = (u32 *)txbuf; | |
| 243 | + | |
| 244 | + data = cpu_to_be32(*txp++); | |
| 245 | + writel(data, qspi->base + | |
| 246 | + QSPI_SPI_DATA_REG_3); | |
| 247 | + data = cpu_to_be32(*txp++); | |
| 248 | + writel(data, qspi->base + | |
| 249 | + QSPI_SPI_DATA_REG_2); | |
| 250 | + data = cpu_to_be32(*txp++); | |
| 251 | + writel(data, qspi->base + | |
| 252 | + QSPI_SPI_DATA_REG_1); | |
| 253 | + data = cpu_to_be32(*txp++); | |
| 254 | + writel(data, qspi->base + | |
| 255 | + QSPI_SPI_DATA_REG); | |
| 256 | + xfer_len = QSPI_WLEN_MAX_BYTES; | |
| 257 | + cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS); | |
| 258 | + } else { | |
| 259 | + writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG); | |
| 260 | + cmd = qspi->cmd | QSPI_WR_SNGL; | |
| 261 | + xfer_len = wlen; | |
| 262 | + cmd |= QSPI_WLEN(wlen); | |
| 263 | + } | |
| 238 | 264 | break; |
| 239 | 265 | case 2: |
| 240 | 266 | dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n", |
| @@ -254,8 +280,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) · 13 unmodified lines | ||
| 254 | 280 | dev_err(qspi->dev, "write timed out\n"); |
| 255 | 281 | return -ETIMEDOUT; |
| 256 | 282 | } |
| 257 | − txbuf += wlen; | |
| 258 | − count -= wlen; | |
| 283 | + txbuf += xfer_len; | |
| 284 | + count -= xfer_len; | |
| 259 | 285 | } |
| 260 | 286 | |
| 261 | 287 | return 0; |
| @@ -237,11 +237,11 @@ static const struct i2c_device_id spi_xcomm_ids[] = { · 236 unmodified lines | ||
| 237 | 237 | { "spi-xcomm" }, |
| 238 | 238 | { }, |
| 239 | 239 | }; |
| 240 | +MODULE_DEVICE_TABLE(i2c, spi_xcomm_ids); | |
| 240 | 241 | |
| 241 | 242 | static struct i2c_driver spi_xcomm_driver = { |
| 242 | 243 | .driver = { |
| 243 | 244 | .name = "spi-xcomm", |
| 244 | − .owner = THIS_MODULE, | |
| 245 | 245 | }, |
| 246 | 246 | .id_table = spi_xcomm_ids, |
| 247 | 247 | .probe = spi_xcomm_probe, |
| @@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) · 248 unmodified lines | ||
| 249 | 249 | xspi->tx_ptr = t->tx_buf; |
| 250 | 250 | xspi->rx_ptr = t->rx_buf; |
| 251 | 251 | remaining_words = t->len / xspi->bytes_per_word; |
| 252 | − reinit_completion(&xspi->done); | |
| 253 | 252 | |
| 254 | 253 | if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { |
| 254 | + u32 isr; | |
| 255 | 255 | use_irq = true; |
| 256 | − xspi->write_fn(XSPI_INTR_TX_EMPTY, | |
| 257 | − xspi->regs + XIPIF_V123B_IISR_OFFSET); | |
| 258 | − /* Enable the global IPIF interrupt */ | |
| 259 | − xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, | |
| 260 | − xspi->regs + XIPIF_V123B_DGIER_OFFSET); | |
| 261 | 256 | /* Inhibit irq to avoid spurious irqs on tx_empty*/ |
| 262 | 257 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); |
| 263 | 258 | xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, |
| 264 | 259 | xspi->regs + XSPI_CR_OFFSET); |
| 260 | + /* ACK old irqs (if any) */ | |
| 261 | + isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); | |
| 262 | + if (isr) | |
| 263 | + xspi->write_fn(isr, | |
| 264 | + xspi->regs + XIPIF_V123B_IISR_OFFSET); | |
| 265 | + /* Enable the global IPIF interrupt */ | |
| 266 | + xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, | |
| 267 | + xspi->regs + XIPIF_V123B_DGIER_OFFSET); | |
| 268 | + reinit_completion(&xspi->done); | |
| 265 | 269 | } |
| 266 | 270 | |
| 267 | 271 | while (remaining_words) { |
| @@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) · 34 unmodified lines | ||
| 302 | 306 | remaining_words -= n_words; |
| 303 | 307 | } |
| 304 | 308 | |
| 305 | − if (use_irq) | |
| 309 | + if (use_irq) { | |
| 306 | 310 | xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); |
| 311 | + xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); | |
| 312 | + } | |
| 307 | 313 | |
| 308 | 314 | return t->len; |
| 309 | 315 | } |
| @@ -0,0 +1,456 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2003-2015 Broadcom Corporation | |
| 3 | + * All Rights Reserved | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License version 2 (GPL v2) | |
| 7 | + * as published by the Free Software Foundation. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + */ | |
| 14 | +#include <linux/clk.h> | |
| 15 | +#include <linux/kernel.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/platform_device.h> | |
| 18 | +#include <linux/spi/spi.h> | |
| 19 | +#include <linux/of.h> | |
| 20 | +#include <linux/interrupt.h> | |
| 21 | + | |
| 22 | +/* SPI Configuration Register */ | |
| 23 | +#define XLP_SPI_CONFIG 0x00 | |
| 24 | +#define XLP_SPI_CPHA BIT(0) | |
| 25 | +#define XLP_SPI_CPOL BIT(1) | |
| 26 | +#define XLP_SPI_CS_POL BIT(2) | |
| 27 | +#define XLP_SPI_TXMISO_EN BIT(3) | |
| 28 | +#define XLP_SPI_TXMOSI_EN BIT(4) | |
| 29 | +#define XLP_SPI_RXMISO_EN BIT(5) | |
| 30 | +#define XLP_SPI_CS_LSBFE BIT(10) | |
| 31 | +#define XLP_SPI_RXCAP_EN BIT(11) | |
| 32 | + | |
| 33 | +/* SPI Frequency Divider Register */ | |
| 34 | +#define XLP_SPI_FDIV 0x04 | |
| 35 | + | |
| 36 | +/* SPI Command Register */ | |
| 37 | +#define XLP_SPI_CMD 0x08 | |
| 38 | +#define XLP_SPI_CMD_IDLE_MASK 0x0 | |
| 39 | +#define XLP_SPI_CMD_TX_MASK 0x1 | |
| 40 | +#define XLP_SPI_CMD_RX_MASK 0x2 | |
| 41 | +#define XLP_SPI_CMD_TXRX_MASK 0x3 | |
| 42 | +#define XLP_SPI_CMD_CONT BIT(4) | |
| 43 | +#define XLP_SPI_XFR_BITCNT_SHIFT 16 | |
| 44 | + | |
| 45 | +/* SPI Status Register */ | |
| 46 | +#define XLP_SPI_STATUS 0x0c | |
| 47 | +#define XLP_SPI_XFR_PENDING BIT(0) | |
| 48 | +#define XLP_SPI_XFR_DONE BIT(1) | |
| 49 | +#define XLP_SPI_TX_INT BIT(2) | |
| 50 | +#define XLP_SPI_RX_INT BIT(3) | |
| 51 | +#define XLP_SPI_TX_UF BIT(4) | |
| 52 | +#define XLP_SPI_RX_OF BIT(5) | |
| 53 | +#define XLP_SPI_STAT_MASK 0x3f | |
| 54 | + | |
| 55 | +/* SPI Interrupt Enable Register */ | |
| 56 | +#define XLP_SPI_INTR_EN 0x10 | |
| 57 | +#define XLP_SPI_INTR_DONE BIT(0) | |
| 58 | +#define XLP_SPI_INTR_TXTH BIT(1) | |
| 59 | +#define XLP_SPI_INTR_RXTH BIT(2) | |
| 60 | +#define XLP_SPI_INTR_TXUF BIT(3) | |
| 61 | +#define XLP_SPI_INTR_RXOF BIT(4) | |
| 62 | + | |
| 63 | +/* SPI FIFO Threshold Register */ | |
| 64 | +#define XLP_SPI_FIFO_THRESH 0x14 | |
| 65 | + | |
| 66 | +/* SPI FIFO Word Count Register */ | |
| 67 | +#define XLP_SPI_FIFO_WCNT 0x18 | |
| 68 | +#define XLP_SPI_RXFIFO_WCNT_MASK 0xf | |
| 69 | +#define XLP_SPI_TXFIFO_WCNT_MASK 0xf0 | |
| 70 | +#define XLP_SPI_TXFIFO_WCNT_SHIFT 4 | |
| 71 | + | |
| 72 | +/* SPI Transmit Data FIFO Register */ | |
| 73 | +#define XLP_SPI_TXDATA_FIFO 0x1c | |
| 74 | + | |
| 75 | +/* SPI Receive Data FIFO Register */ | |
| 76 | +#define XLP_SPI_RXDATA_FIFO 0x20 | |
| 77 | + | |
| 78 | +/* SPI System Control Register */ | |
| 79 | +#define XLP_SPI_SYSCTRL 0x100 | |
| 80 | +#define XLP_SPI_SYS_RESET BIT(0) | |
| 81 | +#define XLP_SPI_SYS_CLKDIS BIT(1) | |
| 82 | +#define XLP_SPI_SYS_PMEN BIT(8) | |
| 83 | + | |
| 84 | +#define SPI_CS_OFFSET 0x40 | |
| 85 | +#define XLP_SPI_TXRXTH 0x80 | |
| 86 | +#define XLP_SPI_FIFO_SIZE 8 | |
| 87 | +#define XLP_SPI_MAX_CS 4 | |
| 88 | +#define XLP_SPI_DEFAULT_FREQ 133333333 | |
| 89 | +#define XLP_SPI_FDIV_MIN 4 | |
| 90 | +#define XLP_SPI_FDIV_MAX 65535 | |
| 91 | +/* | |
| 92 | + * SPI can transfer only 28 bytes properly at a time. So split the | |
| 93 | + * transfer into 28 bytes size. | |
| 94 | + */ | |
| 95 | +#define XLP_SPI_XFER_SIZE 28 | |
| 96 | + | |
| 97 | +struct xlp_spi_priv { | |
| 98 | + struct device dev; /* device structure */ | |
| 99 | + void __iomem *base; /* spi registers base address */ | |
| 100 | + const u8 *tx_buf; /* tx data buffer */ | |
| 101 | + u8 *rx_buf; /* rx data buffer */ | |
| 102 | + int tx_len; /* tx xfer length */ | |
| 103 | + int rx_len; /* rx xfer length */ | |
| 104 | + int txerrors; /* TXFIFO underflow count */ | |
| 105 | + int rxerrors; /* RXFIFO overflow count */ | |
| 106 | + int cs; /* slave device chip select */ | |
| 107 | + u32 spi_clk; /* spi clock frequency */ | |
| 108 | + bool cmd_cont; /* cs active */ | |
| 109 | + struct completion done; /* completion notification */ | |
| 110 | +}; | |
| 111 | + | |
| 112 | +static inline u32 xlp_spi_reg_read(struct xlp_spi_priv *priv, | |
| 113 | + int cs, int regoff) | |
| 114 | +{ | |
| 115 | + return readl(priv->base + regoff + cs * SPI_CS_OFFSET); | |
| 116 | +} | |
| 117 | + | |
| 118 | +static inline void xlp_spi_reg_write(struct xlp_spi_priv *priv, int cs, | |
| 119 | + int regoff, u32 val) | |
| 120 | +{ | |
| 121 | + writel(val, priv->base + regoff + cs * SPI_CS_OFFSET); | |
| 122 | +} | |
| 123 | + | |
| 124 | +static inline void xlp_spi_sysctl_write(struct xlp_spi_priv *priv, | |
| 125 | + int regoff, u32 val) | |
| 126 | +{ | |
| 127 | + writel(val, priv->base + regoff); | |
| 128 | +} | |
| 129 | + | |
| 130 | +/* | |
| 131 | + * Setup global SPI_SYSCTRL register for all SPI channels. | |
| 132 | + */ | |
| 133 | +static void xlp_spi_sysctl_setup(struct xlp_spi_priv *xspi) | |
| 134 | +{ | |
| 135 | + int cs; | |
| 136 | + | |
| 137 | + for (cs = 0; cs < XLP_SPI_MAX_CS; cs++) | |
| 138 | + xlp_spi_sysctl_write(xspi, XLP_SPI_SYSCTRL, | |
| 139 | + XLP_SPI_SYS_RESET << cs); | |
| 140 | + xlp_spi_sysctl_write(xspi, XLP_SPI_SYSCTRL, XLP_SPI_SYS_PMEN); | |
| 141 | +} | |
| 142 | + | |
| 143 | +static int xlp_spi_setup(struct spi_device *spi) | |
| 144 | +{ | |
| 145 | + struct xlp_spi_priv *xspi; | |
| 146 | + u32 fdiv, cfg; | |
| 147 | + int cs; | |
| 148 | + | |
| 149 | + xspi = spi_master_get_devdata(spi->master); | |
| 150 | + cs = spi->chip_select; | |
| 151 | + /* | |
| 152 | + * The value of fdiv must be between 4 and 65535. | |
| 153 | + */ | |
| 154 | + fdiv = DIV_ROUND_UP(xspi->spi_clk, spi->max_speed_hz); | |
| 155 | + if (fdiv > XLP_SPI_FDIV_MAX) | |
| 156 | + fdiv = XLP_SPI_FDIV_MAX; | |
| 157 | + else if (fdiv < XLP_SPI_FDIV_MIN) | |
| 158 | + fdiv = XLP_SPI_FDIV_MIN; | |
| 159 | + | |
| 160 | + xlp_spi_reg_write(xspi, cs, XLP_SPI_FDIV, fdiv); | |
| 161 | + xlp_spi_reg_write(xspi, cs, XLP_SPI_FIFO_THRESH, XLP_SPI_TXRXTH); | |
| 162 | + cfg = xlp_spi_reg_read(xspi, cs, XLP_SPI_CONFIG); | |
| 163 | + if (spi->mode & SPI_CPHA) | |
| 164 | + cfg |= XLP_SPI_CPHA; | |
| 165 | + else | |
| 166 | + cfg &= ~XLP_SPI_CPHA; | |
| 167 | + if (spi->mode & SPI_CPOL) | |
| 168 | + cfg |= XLP_SPI_CPOL; | |
| 169 | + else | |
| 170 | + cfg &= ~XLP_SPI_CPOL; | |
| 171 | + if (!(spi->mode & SPI_CS_HIGH)) | |
| 172 | + cfg |= XLP_SPI_CS_POL; | |
| 173 | + else | |
| 174 | + cfg &= ~XLP_SPI_CS_POL; | |
| 175 | + if (spi->mode & SPI_LSB_FIRST) | |
| 176 | + cfg |= XLP_SPI_CS_LSBFE; | |
| 177 | + else | |
| 178 | + cfg &= ~XLP_SPI_CS_LSBFE; | |
| 179 | + | |
| 180 | + cfg |= XLP_SPI_TXMOSI_EN | XLP_SPI_RXMISO_EN; | |
| 181 | + if (fdiv == 4) | |
| 182 | + cfg |= XLP_SPI_RXCAP_EN; | |
| 183 | + xlp_spi_reg_write(xspi, cs, XLP_SPI_CONFIG, cfg); | |
| 184 | + | |
| 185 | + return 0; | |
| 186 | +} | |
| 187 | + | |
| 188 | +static void xlp_spi_read_rxfifo(struct xlp_spi_priv *xspi) | |
| 189 | +{ | |
| 190 | + u32 rx_data, rxfifo_cnt; | |
| 191 | + int i, j, nbytes; | |
| 192 | + | |
| 193 | + rxfifo_cnt = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_FIFO_WCNT); | |
| 194 | + rxfifo_cnt &= XLP_SPI_RXFIFO_WCNT_MASK; | |
| 195 | + while (rxfifo_cnt) { | |
| 196 | + rx_data = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_RXDATA_FIFO); | |
| 197 | + j = 0; | |
| 198 | + nbytes = min(xspi->rx_len, 4); | |
| 199 | + for (i = nbytes - 1; i >= 0; i--, j++) | |
| 200 | + xspi->rx_buf[i] = (rx_data >> (j * 8)) & 0xff; | |
| 201 | + | |
| 202 | + xspi->rx_len -= nbytes; | |
| 203 | + xspi->rx_buf += nbytes; | |
| 204 | + rxfifo_cnt--; | |
| 205 | + } | |
| 206 | +} | |
| 207 | + | |
| 208 | +static void xlp_spi_fill_txfifo(struct xlp_spi_priv *xspi) | |
| 209 | +{ | |
| 210 | + u32 tx_data, txfifo_cnt; | |
| 211 | + int i, j, nbytes; | |
| 212 | + | |
| 213 | + txfifo_cnt = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_FIFO_WCNT); | |
| 214 | + txfifo_cnt &= XLP_SPI_TXFIFO_WCNT_MASK; | |
| 215 | + txfifo_cnt >>= XLP_SPI_TXFIFO_WCNT_SHIFT; | |
| 216 | + while (xspi->tx_len && (txfifo_cnt < XLP_SPI_FIFO_SIZE)) { | |
| 217 | + j = 0; | |
| 218 | + tx_data = 0; | |
| 219 | + nbytes = min(xspi->tx_len, 4); | |
| 220 | + for (i = nbytes - 1; i >= 0; i--, j++) | |
| 221 | + tx_data |= xspi->tx_buf[i] << (j * 8); | |
| 222 | + | |
| 223 | + xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_TXDATA_FIFO, tx_data); | |
| 224 | + xspi->tx_len -= nbytes; | |
| 225 | + xspi->tx_buf += nbytes; | |
| 226 | + txfifo_cnt++; | |
| 227 | + } | |
| 228 | +} | |
| 229 | + | |
| 230 | +static irqreturn_t xlp_spi_interrupt(int irq, void *dev_id) | |
| 231 | +{ | |
| 232 | + struct xlp_spi_priv *xspi = dev_id; | |
| 233 | + u32 stat; | |
| 234 | + | |
| 235 | + stat = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_STATUS) & | |
| 236 | + XLP_SPI_STAT_MASK; | |
| 237 | + if (!stat) | |
| 238 | + return IRQ_NONE; | |
| 239 | + | |
| 240 | + if (stat & XLP_SPI_TX_INT) { | |
| 241 | + if (xspi->tx_len) | |
| 242 | + xlp_spi_fill_txfifo(xspi); | |
| 243 | + if (stat & XLP_SPI_TX_UF) | |
| 244 | + xspi->txerrors++; | |
| 245 | + } | |
| 246 | + | |
| 247 | + if (stat & XLP_SPI_RX_INT) { | |
| 248 | + if (xspi->rx_len) | |
| 249 | + xlp_spi_read_rxfifo(xspi); | |
| 250 | + if (stat & XLP_SPI_RX_OF) | |
| 251 | + xspi->rxerrors++; | |
| 252 | + } | |
| 253 | + | |
| 254 | + /* write status back to clear interrupts */ | |
| 255 | + xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_STATUS, stat); | |
| 256 | + if (stat & XLP_SPI_XFR_DONE) | |
| 257 | + complete(&xspi->done); | |
| 258 | + | |
| 259 | + return IRQ_HANDLED; | |
| 260 | +} | |
| 261 | + | |
| 262 | +static void xlp_spi_send_cmd(struct xlp_spi_priv *xspi, int xfer_len, | |
| 263 | + int cmd_cont) | |
| 264 | +{ | |
| 265 | + u32 cmd = 0; | |
| 266 | + | |
| 267 | + if (xspi->tx_buf) | |
| 268 | + cmd |= XLP_SPI_CMD_TX_MASK; | |
| 269 | + if (xspi->rx_buf) | |
| 270 | + cmd |= XLP_SPI_CMD_RX_MASK; | |
| 271 | + if (cmd_cont) | |
| 272 | + cmd |= XLP_SPI_CMD_CONT; | |
| 273 | + cmd |= ((xfer_len * 8 - 1) << XLP_SPI_XFR_BITCNT_SHIFT); | |
| 274 | + xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_CMD, cmd); | |
| 275 | +} | |
| 276 | + | |
| 277 | +static int xlp_spi_xfer_block(struct xlp_spi_priv *xs, | |
| 278 | + const unsigned char *tx_buf, | |
| 279 | + unsigned char *rx_buf, int xfer_len, int cmd_cont) | |
| 280 | +{ | |
| 281 | + int timeout; | |
| 282 | + u32 intr_mask = 0; | |
| 283 | + | |
| 284 | + xs->tx_buf = tx_buf; | |
| 285 | + xs->rx_buf = rx_buf; | |
| 286 | + xs->tx_len = (xs->tx_buf == NULL) ? 0 : xfer_len; | |
| 287 | + xs->rx_len = (xs->rx_buf == NULL) ? 0 : xfer_len; | |
| 288 | + xs->txerrors = xs->rxerrors = 0; | |
| 289 | + | |
| 290 | + /* fill TXDATA_FIFO, then send the CMD */ | |
| 291 | + if (xs->tx_len) | |
| 292 | + xlp_spi_fill_txfifo(xs); | |
| 293 | + | |
| 294 | + xlp_spi_send_cmd(xs, xfer_len, cmd_cont); | |
| 295 | + | |
| 296 | + /* | |
| 297 | + * We are getting some spurious tx interrupts, so avoid enabling | |
| 298 | + * tx interrupts when only rx is in process. | |
| 299 | + * Enable all the interrupts in tx case. | |
| 300 | + */ | |
| 301 | + if (xs->tx_len) | |
| 302 | + intr_mask |= XLP_SPI_INTR_TXTH | XLP_SPI_INTR_TXUF | | |
| 303 | + XLP_SPI_INTR_RXTH | XLP_SPI_INTR_RXOF; | |
| 304 | + else | |
| 305 | + intr_mask |= XLP_SPI_INTR_RXTH | XLP_SPI_INTR_RXOF; | |
| 306 | + | |
| 307 | + intr_mask |= XLP_SPI_INTR_DONE; | |
| 308 | + xlp_spi_reg_write(xs, xs->cs, XLP_SPI_INTR_EN, intr_mask); | |
| 309 | + | |
| 310 | + timeout = wait_for_completion_timeout(&xs->done, | |
| 311 | + msecs_to_jiffies(1000)); | |
| 312 | + /* Disable interrupts */ | |
| 313 | + xlp_spi_reg_write(xs, xs->cs, XLP_SPI_INTR_EN, 0x0); | |
| 314 | + if (!timeout) { | |
| 315 | + dev_err(&xs->dev, "xfer timedout!\n"); | |
| 316 | + goto out; | |
| 317 | + } | |
| 318 | + if (xs->txerrors || xs->rxerrors) | |
| 319 | + dev_err(&xs->dev, "Over/Underflow rx %d tx %d xfer %d!\n", | |
| 320 | + xs->rxerrors, xs->txerrors, xfer_len); | |
| 321 | + | |
| 322 | + return xfer_len; | |
| 323 | +out: | |
| 324 | + return -ETIMEDOUT; | |
| 325 | +} | |
| 326 | + | |
| 327 | +static int xlp_spi_txrx_bufs(struct xlp_spi_priv *xs, struct spi_transfer *t) | |
| 328 | +{ | |
| 329 | + int bytesleft, sz; | |
| 330 | + unsigned char *rx_buf; | |
| 331 | + const unsigned char *tx_buf; | |
| 332 | + | |
| 333 | + tx_buf = t->tx_buf; | |
| 334 | + rx_buf = t->rx_buf; | |
| 335 | + bytesleft = t->len; | |
| 336 | + while (bytesleft) { | |
| 337 | + if (bytesleft > XLP_SPI_XFER_SIZE) | |
| 338 | + sz = xlp_spi_xfer_block(xs, tx_buf, rx_buf, | |
| 339 | + XLP_SPI_XFER_SIZE, 1); | |
| 340 | + else | |
| 341 | + sz = xlp_spi_xfer_block(xs, tx_buf, rx_buf, | |
| 342 | + bytesleft, xs->cmd_cont); | |
| 343 | + if (sz < 0) | |
| 344 | + return sz; | |
| 345 | + bytesleft -= sz; | |
| 346 | + if (tx_buf) | |
| 347 | + tx_buf += sz; | |
| 348 | + if (rx_buf) | |
| 349 | + rx_buf += sz; | |
| 350 | + } | |
| 351 | + return bytesleft; | |
| 352 | +} | |
| 353 | + | |
| 354 | +static int xlp_spi_transfer_one(struct spi_master *master, | |
| 355 | + struct spi_device *spi, | |
| 356 | + struct spi_transfer *t) | |
| 357 | +{ | |
| 358 | + struct xlp_spi_priv *xspi = spi_master_get_devdata(master); | |
| 359 | + int ret = 0; | |
| 360 | + | |
| 361 | + xspi->cs = spi->chip_select; | |
| 362 | + xspi->dev = spi->dev; | |
| 363 | + | |
| 364 | + if (spi_transfer_is_last(master, t)) | |
| 365 | + xspi->cmd_cont = 0; | |
| 366 | + else | |
| 367 | + xspi->cmd_cont = 1; | |
| 368 | + | |
| 369 | + if (xlp_spi_txrx_bufs(xspi, t)) | |
| 370 | + ret = -EIO; | |
| 371 | + | |
| 372 | + spi_finalize_current_transfer(master); | |
| 373 | + return ret; | |
| 374 | +} | |
| 375 | + | |
| 376 | +static int xlp_spi_probe(struct platform_device *pdev) | |
| 377 | +{ | |
| 378 | + struct spi_master *master; | |
| 379 | + struct xlp_spi_priv *xspi; | |
| 380 | + struct resource *res; | |
| 381 | + struct clk *clk; | |
| 382 | + int irq, err; | |
| 383 | + | |
| 384 | + xspi = devm_kzalloc(&pdev->dev, sizeof(*xspi), GFP_KERNEL); | |
| 385 | + if (!xspi) | |
| 386 | + return -ENOMEM; | |
| 387 | + | |
| 388 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 389 | + xspi->base = devm_ioremap_resource(&pdev->dev, res); | |
| 390 | + if (IS_ERR(xspi->base)) | |
| 391 | + return PTR_ERR(xspi->base); | |
| 392 | + | |
| 393 | + irq = platform_get_irq(pdev, 0); | |
| 394 | + if (irq < 0) { | |
| 395 | + dev_err(&pdev->dev, "no IRQ resource found\n"); | |
| 396 | + return -EINVAL; | |
| 397 | + } | |
| 398 | + err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0, | |
| 399 | + pdev->name, xspi); | |
| 400 | + if (err) { | |
| 401 | + dev_err(&pdev->dev, "unable to request irq %d\n", irq); | |
| 402 | + return err; | |
| 403 | + } | |
| 404 | + | |
| 405 | + clk = devm_clk_get(&pdev->dev, NULL); | |
| 406 | + if (IS_ERR(clk)) { | |
| 407 | + dev_err(&pdev->dev, "could not get spi clock\n"); | |
| 408 | + return -ENODEV; | |
| 409 | + } | |
| 410 | + xspi->spi_clk = clk_get_rate(clk); | |
| 411 | + | |
| 412 | + master = spi_alloc_master(&pdev->dev, 0); | |
| 413 | + if (!master) { | |
| 414 | + dev_err(&pdev->dev, "could not alloc master\n"); | |
| 415 | + return -ENOMEM; | |
| 416 | + } | |
| 417 | + | |
| 418 | + master->bus_num = 0; | |
| 419 | + master->num_chipselect = XLP_SPI_MAX_CS; | |
| 420 | + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | |
| 421 | + master->setup = xlp_spi_setup; | |
| 422 | + master->transfer_one = xlp_spi_transfer_one; | |
| 423 | + master->dev.of_node = pdev->dev.of_node; | |
| 424 | + | |
| 425 | + init_completion(&xspi->done); | |
| 426 | + spi_master_set_devdata(master, xspi); | |
| 427 | + xlp_spi_sysctl_setup(xspi); | |
| 428 | + | |
| 429 | + /* register spi controller */ | |
| 430 | + err = devm_spi_register_master(&pdev->dev, master); | |
| 431 | + if (err) { | |
| 432 | + dev_err(&pdev->dev, "spi register master failed!\n"); | |
| 433 | + spi_master_put(master); | |
| 434 | + return err; | |
| 435 | + } | |
| 436 | + | |
| 437 | + return 0; | |
| 438 | +} | |
| 439 | + | |
| 440 | +static const struct of_device_id xlp_spi_dt_id[] = { | |
| 441 | + { .compatible = "netlogic,xlp832-spi" }, | |
| 442 | + { }, | |
| 443 | +}; | |
| 444 | + | |
| 445 | +static struct platform_driver xlp_spi_driver = { | |
| 446 | + .probe = xlp_spi_probe, | |
| 447 | + .driver = { | |
| 448 | + .name = "xlp-spi", | |
| 449 | + .of_match_table = xlp_spi_dt_id, | |
| 450 | + }, | |
| 451 | +}; | |
| 452 | +module_platform_driver(xlp_spi_driver); | |
| 453 | + | |
| 454 | +MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>"); | |
| 455 | +MODULE_DESCRIPTION("Netlogic XLP SPI controller driver"); | |
| 456 | +MODULE_LICENSE("GPL v2"); | |
| @@ -67,11 +67,141 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) · 66 unmodified lines | ||
| 67 | 67 | } |
| 68 | 68 | static DEVICE_ATTR_RO(modalias); |
| 69 | 69 | |
| 70 | +#define SPI_STATISTICS_ATTRS(field, file) \ | |
| 71 | +static ssize_t spi_master_##field##_show(struct device *dev, \ | |
| 72 | + struct device_attribute *attr, \ | |
| 73 | + char *buf) \ | |
| 74 | +{ \ | |
| 75 | + struct spi_master *master = container_of(dev, \ | |
| 76 | + struct spi_master, dev); \ | |
| 77 | + return spi_statistics_##field##_show(&master->statistics, buf); \ | |
| 78 | +} \ | |
| 79 | +static struct device_attribute dev_attr_spi_master_##field = { \ | |
| 80 | + .attr = { .name = file, .mode = S_IRUGO }, \ | |
| 81 | + .show = spi_master_##field##_show, \ | |
| 82 | +}; \ | |
| 83 | +static ssize_t spi_device_##field##_show(struct device *dev, \ | |
| 84 | + struct device_attribute *attr, \ | |
| 85 | + char *buf) \ | |
| 86 | +{ \ | |
| 87 | + struct spi_device *spi = container_of(dev, \ | |
| 88 | + struct spi_device, dev); \ | |
| 89 | + return spi_statistics_##field##_show(&spi->statistics, buf); \ | |
| 90 | +} \ | |
| 91 | +static struct device_attribute dev_attr_spi_device_##field = { \ | |
| 92 | + .attr = { .name = file, .mode = S_IRUGO }, \ | |
| 93 | + .show = spi_device_##field##_show, \ | |
| 94 | +} | |
| 95 | + | |
| 96 | +#define SPI_STATISTICS_SHOW_NAME(name, file, field, format_string) \ | |
| 97 | +static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \ | |
| 98 | + char *buf) \ | |
| 99 | +{ \ | |
| 100 | + unsigned long flags; \ | |
| 101 | + ssize_t len; \ | |
| 102 | + spin_lock_irqsave(&stat->lock, flags); \ | |
| 103 | + len = sprintf(buf, format_string, stat->field); \ | |
| 104 | + spin_unlock_irqrestore(&stat->lock, flags); \ | |
| 105 | + return len; \ | |
| 106 | +} \ | |
| 107 | +SPI_STATISTICS_ATTRS(name, file) | |
| 108 | + | |
| 109 | +#define SPI_STATISTICS_SHOW(field, format_string) \ | |
| 110 | + SPI_STATISTICS_SHOW_NAME(field, __stringify(field), \ | |
| 111 | + field, format_string) | |
| 112 | + | |
| 113 | +SPI_STATISTICS_SHOW(messages, "%lu"); | |
| 114 | +SPI_STATISTICS_SHOW(transfers, "%lu"); | |
| 115 | +SPI_STATISTICS_SHOW(errors, "%lu"); | |
| 116 | +SPI_STATISTICS_SHOW(timedout, "%lu"); | |
| 117 | + | |
| 118 | +SPI_STATISTICS_SHOW(spi_sync, "%lu"); | |
| 119 | +SPI_STATISTICS_SHOW(spi_sync_immediate, "%lu"); | |
| 120 | +SPI_STATISTICS_SHOW(spi_async, "%lu"); | |
| 121 | + | |
| 122 | +SPI_STATISTICS_SHOW(bytes, "%llu"); | |
| 123 | +SPI_STATISTICS_SHOW(bytes_rx, "%llu"); | |
| 124 | +SPI_STATISTICS_SHOW(bytes_tx, "%llu"); | |
| 125 | + | |
| 70 | 126 | static struct attribute *spi_dev_attrs[] = { |
| 71 | 127 | &dev_attr_modalias.attr, |
| 72 | 128 | NULL, |
| 73 | 129 | }; |
| 74 | −ATTRIBUTE_GROUPS(spi_dev); | |
| 130 | + | |
| 131 | +static const struct attribute_group spi_dev_group = { | |
| 132 | + .attrs = spi_dev_attrs, | |
| 133 | +}; | |
| 134 | + | |
| 135 | +static struct attribute *spi_device_statistics_attrs[] = { | |
| 136 | + &dev_attr_spi_device_messages.attr, | |
| 137 | + &dev_attr_spi_device_transfers.attr, | |
| 138 | + &dev_attr_spi_device_errors.attr, | |
| 139 | + &dev_attr_spi_device_timedout.attr, | |
| 140 | + &dev_attr_spi_device_spi_sync.attr, | |
| 141 | + &dev_attr_spi_device_spi_sync_immediate.attr, | |
| 142 | + &dev_attr_spi_device_spi_async.attr, | |
| 143 | + &dev_attr_spi_device_bytes.attr, | |
| 144 | + &dev_attr_spi_device_bytes_rx.attr, | |
| 145 | + &dev_attr_spi_device_bytes_tx.attr, | |
| 146 | + NULL, | |
| 147 | +}; | |
| 148 | + | |
| 149 | +static const struct attribute_group spi_device_statistics_group = { | |
| 150 | + .name = "statistics", | |
| 151 | + .attrs = spi_device_statistics_attrs, | |
| 152 | +}; | |
| 153 | + | |
| 154 | +static const struct attribute_group *spi_dev_groups[] = { | |
| 155 | + &spi_dev_group, | |
| 156 | + &spi_device_statistics_group, | |
| 157 | + NULL, | |
| 158 | +}; | |
| 159 | + | |
| 160 | +static struct attribute *spi_master_statistics_attrs[] = { | |
| 161 | + &dev_attr_spi_master_messages.attr, | |
| 162 | + &dev_attr_spi_master_transfers.attr, | |
| 163 | + &dev_attr_spi_master_errors.attr, | |
| 164 | + &dev_attr_spi_master_timedout.attr, | |
| 165 | + &dev_attr_spi_master_spi_sync.attr, | |
| 166 | + &dev_attr_spi_master_spi_sync_immediate.attr, | |
| 167 | + &dev_attr_spi_master_spi_async.attr, | |
| 168 | + &dev_attr_spi_master_bytes.attr, | |
| 169 | + &dev_attr_spi_master_bytes_rx.attr, | |
| 170 | + &dev_attr_spi_master_bytes_tx.attr, | |
| 171 | + NULL, | |
| 172 | +}; | |
| 173 | + | |
| 174 | +static const struct attribute_group spi_master_statistics_group = { | |
| 175 | + .name = "statistics", | |
| 176 | + .attrs = spi_master_statistics_attrs, | |
| 177 | +}; | |
| 178 | + | |
| 179 | +static const struct attribute_group *spi_master_groups[] = { | |
| 180 | + &spi_master_statistics_group, | |
| 181 | + NULL, | |
| 182 | +}; | |
| 183 | + | |
| 184 | +void spi_statistics_add_transfer_stats(struct spi_statistics *stats, | |
| 185 | + struct spi_transfer *xfer, | |
| 186 | + struct spi_master *master) | |
| 187 | +{ | |
| 188 | + unsigned long flags; | |
| 189 | + | |
| 190 | + spin_lock_irqsave(&stats->lock, flags); | |
| 191 | + | |
| 192 | + stats->transfers++; | |
| 193 | + | |
| 194 | + stats->bytes += xfer->len; | |
| 195 | + if ((xfer->tx_buf) && | |
| 196 | + (xfer->tx_buf != master->dummy_tx)) | |
| 197 | + stats->bytes_tx += xfer->len; | |
| 198 | + if ((xfer->rx_buf) && | |
| 199 | + (xfer->rx_buf != master->dummy_rx)) | |
| 200 | + stats->bytes_rx += xfer->len; | |
| 201 | + | |
| 202 | + spin_unlock_irqrestore(&stats->lock, flags); | |
| 203 | +} | |
| 204 | +EXPORT_SYMBOL_GPL(spi_statistics_add_transfer_stats); | |
| 75 | 205 | |
| 76 | 206 | /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, |
| 77 | 207 | * and the sysfs version makes coldplug work too. |
| @@ -249,6 +379,9 @@ struct spi_device *spi_alloc_device(struct spi_master *master) · 171 unmodified lines | ||
| 249 | 379 | spi->dev.bus = &spi_bus_type; |
| 250 | 380 | spi->dev.release = spidev_release; |
| 251 | 381 | spi->cs_gpio = -ENOENT; |
| 382 | + | |
| 383 | + spin_lock_init(&spi->statistics.lock); | |
| 384 | + | |
| 252 | 385 | device_initialize(&spi->dev); |
| 253 | 386 | return spi; |
| 254 | 387 | } |
| @@ -476,21 +609,30 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, · 221 unmodified lines | ||
| 476 | 609 | enum dma_data_direction dir) |
| 477 | 610 | { |
| 478 | 611 | const bool vmalloced_buf = is_vmalloc_addr(buf); |
| 479 | − const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len; | |
| 480 | − const int sgs = DIV_ROUND_UP(len, desc_len); | |
| 612 | + int desc_len; | |
| 613 | + int sgs; | |
| 481 | 614 | struct page *vm_page; |
| 482 | 615 | void *sg_buf; |
| 483 | 616 | size_t min; |
| 484 | 617 | int i, ret; |
| 485 | 618 | |
| 619 | + if (vmalloced_buf) { | |
| 620 | + desc_len = PAGE_SIZE; | |
| 621 | + sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); | |
| 622 | + } else { | |
| 623 | + desc_len = master->max_dma_len; | |
| 624 | + sgs = DIV_ROUND_UP(len, desc_len); | |
| 625 | + } | |
| 626 | + | |
| 486 | 627 | ret = sg_alloc_table(sgt, sgs, GFP_KERNEL); |
| 487 | 628 | if (ret != 0) |
| 488 | 629 | return ret; |
| 489 | 630 | |
| 490 | 631 | for (i = 0; i < sgs; i++) { |
| 491 | − min = min_t(size_t, len, desc_len); | |
| 492 | 632 | |
| 493 | 633 | if (vmalloced_buf) { |
| 634 | + min = min_t(size_t, | |
| 635 | + len, desc_len - offset_in_page(buf)); | |
| 494 | 636 | vm_page = vmalloc_to_page(buf); |
| 495 | 637 | if (!vm_page) { |
| 496 | 638 | sg_free_table(sgt); |
| @@ -499,6 +641,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, · 2 unmodified lines | ||
| 499 | 641 | sg_set_page(&sgt->sgl[i], vm_page, |
| 500 | 642 | min, offset_in_page(buf)); |
| 501 | 643 | } else { |
| 644 | + min = min_t(size_t, len, desc_len); | |
| 502 | 645 | sg_buf = buf; |
| 503 | 646 | sg_set_buf(&sgt->sgl[i], sg_buf, min); |
| 504 | 647 | } |
| @@ -539,8 +682,15 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) · 34 unmodified lines | ||
| 539 | 682 | if (!master->can_dma) |
| 540 | 683 | return 0; |
| 541 | 684 | |
| 542 | − tx_dev = master->dma_tx->device->dev; | |
| 543 | − rx_dev = master->dma_rx->device->dev; | |
| 685 | + if (master->dma_tx) | |
| 686 | + tx_dev = master->dma_tx->device->dev; | |
| 687 | + else | |
| 688 | + tx_dev = &master->dev; | |
| 689 | + | |
| 690 | + if (master->dma_rx) | |
| 691 | + rx_dev = master->dma_rx->device->dev; | |
| 692 | + else | |
| 693 | + rx_dev = &master->dev; | |
| 544 | 694 | |
| 545 | 695 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 546 | 696 | if (!master->can_dma(master, msg->spi, xfer)) |
| @@ -579,8 +729,15 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) · 32 unmodified lines | ||
| 579 | 729 | if (!master->cur_msg_mapped || !master->can_dma) |
| 580 | 730 | return 0; |
| 581 | 731 | |
| 582 | − tx_dev = master->dma_tx->device->dev; | |
| 583 | − rx_dev = master->dma_rx->device->dev; | |
| 732 | + if (master->dma_tx) | |
| 733 | + tx_dev = master->dma_tx->device->dev; | |
| 734 | + else | |
| 735 | + tx_dev = &master->dev; | |
| 736 | + | |
| 737 | + if (master->dma_rx) | |
| 738 | + rx_dev = master->dma_rx->device->dev; | |
| 739 | + else | |
| 740 | + rx_dev = &master->dev; | |
| 584 | 741 | |
| 585 | 742 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 586 | 743 | if (!master->can_dma(master, msg->spi, xfer)) |
| @@ -689,17 +846,29 @@ static int spi_transfer_one_message(struct spi_master *master, · 102 unmodified lines | ||
| 689 | 846 | bool keep_cs = false; |
| 690 | 847 | int ret = 0; |
| 691 | 848 | unsigned long ms = 1; |
| 849 | + struct spi_statistics *statm = &master->statistics; | |
| 850 | + struct spi_statistics *stats = &msg->spi->statistics; | |
| 692 | 851 | |
| 693 | 852 | spi_set_cs(msg->spi, true); |
| 694 | 853 | |
| 854 | + SPI_STATISTICS_INCREMENT_FIELD(statm, messages); | |
| 855 | + SPI_STATISTICS_INCREMENT_FIELD(stats, messages); | |
| 856 | + | |
| 695 | 857 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 696 | 858 | trace_spi_transfer_start(msg, xfer); |
| 697 | 859 | |
| 860 | + spi_statistics_add_transfer_stats(statm, xfer, master); | |
| 861 | + spi_statistics_add_transfer_stats(stats, xfer, master); | |
| 862 | + | |
| 698 | 863 | if (xfer->tx_buf || xfer->rx_buf) { |
| 699 | 864 | reinit_completion(&master->xfer_completion); |
| 700 | 865 | |
| 701 | 866 | ret = master->transfer_one(master, msg->spi, xfer); |
| 702 | 867 | if (ret < 0) { |
| 868 | + SPI_STATISTICS_INCREMENT_FIELD(statm, | |
| 869 | + errors); | |
| 870 | + SPI_STATISTICS_INCREMENT_FIELD(stats, | |
| 871 | + errors); | |
| 703 | 872 | dev_err(&msg->spi->dev, |
| 704 | 873 | "SPI transfer failed: %d\n", ret); |
| 705 | 874 | goto out; |
| @@ -715,6 +884,10 @@ static int spi_transfer_one_message(struct spi_master *master, · 9 unmodified lines | ||
| 715 | 884 | } |
| 716 | 885 | |
| 717 | 886 | if (ms == 0) { |
| 887 | + SPI_STATISTICS_INCREMENT_FIELD(statm, | |
| 888 | + timedout); | |
| 889 | + SPI_STATISTICS_INCREMENT_FIELD(stats, | |
| 890 | + timedout); | |
| 718 | 891 | dev_err(&msg->spi->dev, |
| 719 | 892 | "SPI transfer timed out\n"); |
| 720 | 893 | msg->status = -ETIMEDOUT; |
| @@ -1416,10 +1589,10 @@ static struct class spi_master_class = { · 695 unmodified lines | ||
| 1416 | 1589 | .name = "spi_master", |
| 1417 | 1590 | .owner = THIS_MODULE, |
| 1418 | 1591 | .dev_release = spi_master_release, |
| 1592 | + .dev_groups = spi_master_groups, | |
| 1419 | 1593 | }; |
| 1420 | 1594 | |
| 1421 | 1595 | |
| 1422 | − | |
| 1423 | 1596 | /** |
| 1424 | 1597 | * spi_alloc_master - allocate SPI master controller |
| 1425 | 1598 | * @dev: the controller, possibly using the platform_bus |
| @@ -1585,6 +1758,8 @@ int spi_register_master(struct spi_master *master) · 159 unmodified lines | ||
| 1585 | 1758 | goto done; |
| 1586 | 1759 | } |
| 1587 | 1760 | } |
| 1761 | + /* add statistics */ | |
| 1762 | + spin_lock_init(&master->statistics.lock); | |
| 1588 | 1763 | |
| 1589 | 1764 | mutex_lock(&board_lock); |
| 1590 | 1765 | list_add_tail(&master->list, &spi_master_list); |
| @@ -1740,6 +1915,20 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); · 149 unmodified lines | ||
| 1740 | 1915 | * other core methods are currently defined as inline functions. |
| 1741 | 1916 | */ |
| 1742 | 1917 | |
| 1918 | +static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word) | |
| 1919 | +{ | |
| 1920 | + if (master->bits_per_word_mask) { | |
| 1921 | + /* Only 32 bits fit in the mask */ | |
| 1922 | + if (bits_per_word > 32) | |
| 1923 | + return -EINVAL; | |
| 1924 | + if (!(master->bits_per_word_mask & | |
| 1925 | + SPI_BPW_MASK(bits_per_word))) | |
| 1926 | + return -EINVAL; | |
| 1927 | + } | |
| 1928 | + | |
| 1929 | + return 0; | |
| 1930 | +} | |
| 1931 | + | |
| 1743 | 1932 | /** |
| 1744 | 1933 | * spi_setup - setup SPI mode and clock rate |
| 1745 | 1934 | * @spi: the device whose settings are being modified |
| @@ -1798,6 +1987,9 @@ int spi_setup(struct spi_device *spi) · 52 unmodified lines | ||
| 1798 | 1987 | if (!spi->bits_per_word) |
| 1799 | 1988 | spi->bits_per_word = 8; |
| 1800 | 1989 | |
| 1990 | + if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word)) | |
| 1991 | + return -EINVAL; | |
| 1992 | + | |
| 1801 | 1993 | if (!spi->max_speed_hz) |
| 1802 | 1994 | spi->max_speed_hz = spi->master->max_speed_hz; |
| 1803 | 1995 | |
| @@ -1860,19 +2052,15 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) · 56 unmodified lines | ||
| 1860 | 2052 | |
| 1861 | 2053 | if (!xfer->speed_hz) |
| 1862 | 2054 | xfer->speed_hz = spi->max_speed_hz; |
| 2055 | + if (!xfer->speed_hz) | |
| 2056 | + xfer->speed_hz = master->max_speed_hz; | |
| 1863 | 2057 | |
| 1864 | 2058 | if (master->max_speed_hz && |
| 1865 | 2059 | xfer->speed_hz > master->max_speed_hz) |
| 1866 | 2060 | xfer->speed_hz = master->max_speed_hz; |
| 1867 | 2061 | |
| 1868 | − if (master->bits_per_word_mask) { | |
| 1869 | − /* Only 32 bits fit in the mask */ | |
| 1870 | − if (xfer->bits_per_word > 32) | |
| 1871 | − return -EINVAL; | |
| 1872 | − if (!(master->bits_per_word_mask & | |
| 1873 | − BIT(xfer->bits_per_word - 1))) | |
| 1874 | − return -EINVAL; | |
| 1875 | − } | |
| 2062 | + if (__spi_validate_bits_per_word(master, xfer->bits_per_word)) | |
| 2063 | + return -EINVAL; | |
| 1876 | 2064 | |
| 1877 | 2065 | /* |
| 1878 | 2066 | * SPI transfer length should be multiple of SPI word size |
| @@ -1939,6 +2127,9 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) · 60 unmodified lines | ||
| 1939 | 2127 | |
| 1940 | 2128 | message->spi = spi; |
| 1941 | 2129 | |
| 2130 | + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_async); | |
| 2131 | + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async); | |
| 2132 | + | |
| 1942 | 2133 | trace_spi_message_submit(message); |
| 1943 | 2134 | |
| 1944 | 2135 | return master->transfer(spi, message); |
| @@ -2075,6 +2266,9 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, · 130 unmodified lines | ||
| 2075 | 2266 | message->context = &done; |
| 2076 | 2267 | message->spi = spi; |
| 2077 | 2268 | |
| 2269 | + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync); | |
| 2270 | + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync); | |
| 2271 | + | |
| 2078 | 2272 | if (!bus_locked) |
| 2079 | 2273 | mutex_lock(&master->bus_lock_mutex); |
| 2080 | 2274 | |
| @@ -2102,8 +2296,13 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, · 21 unmodified lines | ||
| 2102 | 2296 | /* Push out the messages in the calling context if we |
| 2103 | 2297 | * can. |
| 2104 | 2298 | */ |
| 2105 | − if (master->transfer == spi_queued_transfer) | |
| 2299 | + if (master->transfer == spi_queued_transfer) { | |
| 2300 | + SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, | |
| 2301 | + spi_sync_immediate); | |
| 2302 | + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, | |
| 2303 | + spi_sync_immediate); | |
| 2106 | 2304 | __spi_pump_messages(master, false); |
| 2305 | + } | |
| 2107 | 2306 | |
| 2108 | 2307 | wait_for_completion(&done); |
| 2109 | 2308 | status = message->status; |
| @@ -602,11 +602,11 @@ static int spidev_open(struct inode *inode, struct file *filp) · 601 unmodified lines | ||
| 602 | 602 | if (!spidev->tx_buffer) { |
| 603 | 603 | spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); |
| 604 | 604 | if (!spidev->tx_buffer) { |
| 605 | − dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); | |
| 606 | − status = -ENOMEM; | |
| 605 | + dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); | |
| 606 | + status = -ENOMEM; | |
| 607 | 607 | goto err_find_dev; |
| 608 | − } | |
| 609 | 608 | } |
| 609 | + } | |
| 610 | 610 | |
| 611 | 611 | if (!spidev->rx_buffer) { |
| 612 | 612 | spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); |
| @@ -709,7 +709,7 @@ static int spidev_probe(struct spi_device *spi) · 96 unmodified lines | ||
| 709 | 709 | |
| 710 | 710 | /* |
| 711 | 711 | * spidev should never be referenced in DT without a specific |
| 712 | − * compatbile string, it is a Linux implementation thing | |
| 712 | + * compatible string, it is a Linux implementation thing | |
| 713 | 713 | * rather than a description of the hardware. |
| 714 | 714 | */ |
| 715 | 715 | if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) { |
| @@ -49,6 +49,7 @@ struct davinci_spi_platform_data { · 48 unmodified lines | ||
| 49 | 49 | u8 num_chipselect; |
| 50 | 50 | u8 intr_line; |
| 51 | 51 | u8 *chip_sel; |
| 52 | + u8 prescaler_limit; | |
| 52 | 53 | bool cshold_bug; |
| 53 | 54 | enum dma_event_q dma_event_q; |
| 54 | 55 | }; |
| @@ -0,0 +1,20 @@ | ||
| 1 | +/* | |
| 2 | + * MTK SPI bus driver definitions | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015 MediaTek Inc. | |
| 5 | + * Author: Leilk Liu <leilk.liu@mediatek.com> | |
| 6 | + * | |
| 7 | + * This program is free software; you can redistribute it and/or modify | |
| 8 | + * it under the terms of the GNU General Public License version 2 as | |
| 9 | + * published by the Free Software Foundation. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H | |
| 13 | +#define ____LINUX_PLATFORM_DATA_SPI_MTK_H | |
| 14 | + | |
| 15 | +/* Board specific platform_data */ | |
| 16 | +struct mtk_chip_config { | |
| 17 | + u32 tx_mlsb; | |
| 18 | + u32 rx_mlsb; | |
| 19 | +}; | |
| 20 | +#endif | |
| @@ -197,6 +197,7 @@ enum pxa_ssp_type { · 196 unmodified lines | ||
| 197 | 197 | QUARK_X1000_SSP, |
| 198 | 198 | LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ |
| 199 | 199 | LPSS_BYT_SSP, |
| 200 | + LPSS_SPT_SSP, | |
| 200 | 201 | }; |
| 201 | 202 | |
| 202 | 203 | struct ssp_device { |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/scatterlist.h> |
| 24 | 24 | |
| 25 | 25 | struct dma_chan; |
| 26 | +struct spi_master; | |
| 27 | +struct spi_transfer; | |
| 26 | 28 | |
| 27 | 29 | /* |
| 28 | 30 | * INTERFACES between SPI master-side drivers and SPI infrastructure. |
| @@ -30,6 +32,59 @@ struct dma_chan; · 1 unmodified line | ||
| 30 | 32 | */ |
| 31 | 33 | extern struct bus_type spi_bus_type; |
| 32 | 34 | |
| 35 | +/** | |
| 36 | + * struct spi_statistics - statistics for spi transfers | |
| 37 | + * @clock: lock protecting this structure | |
| 38 | + * | |
| 39 | + * @messages: number of spi-messages handled | |
| 40 | + * @transfers: number of spi_transfers handled | |
| 41 | + * @errors: number of errors during spi_transfer | |
| 42 | + * @timedout: number of timeouts during spi_transfer | |
| 43 | + * | |
| 44 | + * @spi_sync: number of times spi_sync is used | |
| 45 | + * @spi_sync_immediate: | |
| 46 | + * number of times spi_sync is executed immediately | |
| 47 | + * in calling context without queuing and scheduling | |
| 48 | + * @spi_async: number of times spi_async is used | |
| 49 | + * | |
| 50 | + * @bytes: number of bytes transferred to/from device | |
| 51 | + * @bytes_tx: number of bytes sent to device | |
| 52 | + * @bytes_rx: number of bytes received from device | |
| 53 | + * | |
| 54 | + */ | |
| 55 | +struct spi_statistics { | |
| 56 | + spinlock_t lock; /* lock for the whole structure */ | |
| 57 | + | |
| 58 | + unsigned long messages; | |
| 59 | + unsigned long transfers; | |
| 60 | + unsigned long errors; | |
| 61 | + unsigned long timedout; | |
| 62 | + | |
| 63 | + unsigned long spi_sync; | |
| 64 | + unsigned long spi_sync_immediate; | |
| 65 | + unsigned long spi_async; | |
| 66 | + | |
| 67 | + unsigned long long bytes; | |
| 68 | + unsigned long long bytes_rx; | |
| 69 | + unsigned long long bytes_tx; | |
| 70 | + | |
| 71 | +}; | |
| 72 | + | |
| 73 | +void spi_statistics_add_transfer_stats(struct spi_statistics *stats, | |
| 74 | + struct spi_transfer *xfer, | |
| 75 | + struct spi_master *master); | |
| 76 | + | |
| 77 | +#define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count) \ | |
| 78 | + do { \ | |
| 79 | + unsigned long flags; \ | |
| 80 | + spin_lock_irqsave(&(stats)->lock, flags); \ | |
| 81 | + (stats)->field += count; \ | |
| 82 | + spin_unlock_irqrestore(&(stats)->lock, flags); \ | |
| 83 | + } while (0) | |
| 84 | + | |
| 85 | +#define SPI_STATISTICS_INCREMENT_FIELD(stats, field) \ | |
| 86 | + SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1) | |
| 87 | + | |
| 33 | 88 | /** |
| 34 | 89 | * struct spi_device - Master side proxy for an SPI slave device |
| 35 | 90 | * @dev: Driver model representation of the device. |
| @@ -60,6 +115,8 @@ extern struct bus_type spi_bus_type; · 24 unmodified lines | ||
| 60 | 115 | * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when |
| 61 | 116 | * when not using a GPIO line) |
| 62 | 117 | * |
| 118 | + * @statistics: statistics for the spi_device | |
| 119 | + * | |
| 63 | 120 | * A @spi_device is used to interchange data between an SPI slave |
| 64 | 121 | * (usually a discrete chip) and CPU memory. |
| 65 | 122 | * |
| @@ -98,6 +155,9 @@ struct spi_device { · 32 unmodified lines | ||
| 98 | 155 | char modalias[SPI_NAME_SIZE]; |
| 99 | 156 | int cs_gpio; /* chip select gpio */ |
| 100 | 157 | |
| 158 | + /* the statistics */ | |
| 159 | + struct spi_statistics statistics; | |
| 160 | + | |
| 101 | 161 | /* |
| 102 | 162 | * likely need more hooks for more protocol options affecting how |
| 103 | 163 | * the controller talks to each chip, like: |
| @@ -296,6 +356,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) · 192 unmodified lines | ||
| 296 | 356 | * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS |
| 297 | 357 | * number. Any individual value may be -ENOENT for CS lines that |
| 298 | 358 | * are not GPIOs (driven by the SPI controller itself). |
| 359 | + * @statistics: statistics for the spi_master | |
| 299 | 360 | * @dma_tx: DMA transmit channel |
| 300 | 361 | * @dma_rx: DMA receive channel |
| 301 | 362 | * @dummy_rx: dummy receive buffer for full-duplex devices |
| @@ -452,6 +513,9 @@ struct spi_master { · 150 unmodified lines | ||
| 452 | 513 | /* gpio chip select */ |
| 453 | 514 | int *cs_gpios; |
| 454 | 515 | |
| 516 | + /* statistics */ | |
| 517 | + struct spi_statistics statistics; | |
| 518 | + | |
| 455 | 519 | /* DMA channels for use with core dmaengine helpers */ |
| 456 | 520 | struct dma_chan *dma_tx; |
| 457 | 521 | struct dma_chan *dma_rx; |